Code

Node tool: fix handle retraction with non-cusp nodes
[inkscape.git] / src / style.h
1 #ifndef SEEN_SP_STYLE_H
2 #define SEEN_SP_STYLE_H
4 /** \file
5  * SPStyle - a style object for SPItem objects
6  */
7 /* Authors:
8  *   Lauris Kaplinski <lauris@kaplinski.com>
9  *   Jon A. Cruz <jon@joncruz.org>
10  *
11  * Copyright (C) 2010 Jon A. Cruz
12  * Copyright (C) 2001-2002 Lauris Kaplinski
13  * Copyright (C) 2001 Ximian, Inc.
14  *
15  * Released under GNU GPL, read the file 'COPYING' for more information
16  */
18 #include "color.h"
19 #include "forward.h"
20 #include "sp-marker-loc.h"
21 #include "sp-filter.h"
22 #include "sp-filter-reference.h"
23 #include "uri-references.h"
24 #include "uri.h"
25 #include "sp-paint-server.h"
27 #include <sigc++/connection.h>
29 namespace Inkscape {
30 namespace XML {
31 class Node;
32 }
33 }
35 class SPCSSAttr;
37 class SPIFloat;
38 class SPIScale24;
39 class SPIInt;
40 class SPIShort;
41 class SPIEnum;
42 class SPIString;
43 class SPILength;
44 class SPIPaint;
45 class SPIFontSize;
46 class SPIBaselineShift;
48 /// Float type internal to SPStyle.
49 struct SPIFloat {
50     unsigned set : 1;
51     unsigned inherit : 1;
52     unsigned data : 30;
53     float value;
54 };
56 /*
57  * One might think that the best value for SP_SCALE24_MAX would be ((1<<24)-1), which allows the
58  * greatest possible precision for fitting [0, 1] fractions into 24 bits.
59  *
60  * However, in practice, that gives a problem with 0.5, which falls half way between two fractions
61  * of ((1<<24)-1).  What's worse is that casting double(1<<23) / ((1<<24)-1) to float on x86
62  * produces wrong rounding behaviour, resulting in a fraction of ((1<<23)+2.0f) / (1<<24) rather
63  * than ((1<<23)+1.0f) / (1<<24) as one would expect, let alone ((1<<23)+0.0f) / (1<<24) as one
64  * would ideally like for this example.
65  *
66  * The value (1<<23) is thus best if one considers float conversions alone.
67  *
68  * The value 0xff0000 can exactly represent all 8-bit alpha channel values,
69  * and can exactly represent all multiples of 0.1.  I haven't yet tested whether
70  * rounding bugs still get in the way of conversions to & from float, but my instinct is that
71  * it's fairly safe because 0xff fits three times inside float's significand.
72  *
73  * We should probably use the value 0xffff00 once we support 16 bits per channel and/or LittleCMS,
74  * though that might need to be accompanied by greater use of double instead of float for
75  * colours and opacities, to be safe from rounding bugs.
76  */
77 #define SP_SCALE24_MAX (0xff0000)
78 #define SP_SCALE24_TO_FLOAT(v) ((double) (v) / SP_SCALE24_MAX)
79 #define SP_SCALE24_FROM_FLOAT(v) unsigned(((v) * SP_SCALE24_MAX) + .5)
81 /** Returns a scale24 for the product of two scale24 values. */
82 #define SP_SCALE24_MUL(_v1, _v2) unsigned((double)(_v1) * (_v2) / SP_SCALE24_MAX + .5)
84 /// 24 bit data type internal to SPStyle.
85 struct SPIScale24 {
86     unsigned set : 1;
87     unsigned inherit : 1;
88     unsigned value : 24;
89 };
91 /// Int type internal to SPStyle.
92 struct SPIInt {
93     unsigned set : 1;
94     unsigned inherit : 1;
95     unsigned data : 30;
96     int value;
97 };
99 /// Short type internal to SPStyle.
100 struct SPIShort {
101     unsigned set : 1;
102     unsigned inherit : 1;
103     unsigned data : 14;
104     int value : 16;
105 };
107 /// Enum type internal to SPStyle.
108 struct SPIEnum {
109     unsigned set : 1;
110     unsigned inherit : 1;
111     unsigned value : 8;
112     unsigned computed : 8;
113 };
115 /// String type internal to SPStyle.
116 struct SPIString {
117     unsigned set : 1;
118     unsigned inherit : 1;
119     unsigned data : 30;
120     gchar *value;
121 };
123 enum {
124     SP_CSS_UNIT_NONE,
125     SP_CSS_UNIT_PX,
126     SP_CSS_UNIT_PT,
127     SP_CSS_UNIT_PC,
128     SP_CSS_UNIT_MM,
129     SP_CSS_UNIT_CM,
130     SP_CSS_UNIT_IN,
131     SP_CSS_UNIT_EM,
132     SP_CSS_UNIT_EX,
133     SP_CSS_UNIT_PERCENT
134 };
136 /// Length type internal to SPStyle.
137 struct SPILength {
138     unsigned set : 1;
139     unsigned inherit : 1;
140     unsigned unit : 4;
141     float value;
142     float computed;
143 };
145 #define SP_STYLE_FILL_SERVER(s) (((SPStyle *) (s))->getFillPaintServer())
146 #define SP_STYLE_STROKE_SERVER(s) (((SPStyle *) (s))->getStrokePaintServer())
148 class SVGICCColor;
150 /// Paint type internal to SPStyle.
151 struct SPIPaint {
152     unsigned set : 1;
153     unsigned inherit : 1;
154     unsigned currentcolor : 1;
155     unsigned int colorSet : 1;
156     unsigned int noneSet : 1;
157     struct {
158          SPPaintServerReference *href;
159          SPColor color;
160     } value;
162     SPIPaint();
164     bool isSet() const { return true; /* set || colorSet*/}
165     bool isSameType( SPIPaint const & other ) const {return (isPaintserver() == other.isPaintserver()) && (colorSet == other.colorSet) && (currentcolor == other.currentcolor);}
167     bool isNoneSet() const {return noneSet;}
169     bool isNone() const {return !currentcolor && !colorSet && !isPaintserver();} // TODO refine
170     bool isColor() const {return colorSet && !isPaintserver();}
171     bool isPaintserver() const {return value.href && value.href->getObject();}
173     void clear();
175     void setColor( float r, float g, float b ) {value.color.set( r, g, b ); colorSet = true;}
176     void setColor( guint32 val ) {value.color.set( val ); colorSet = true;}
177     void setColor( SPColor const& color ) {value.color = color; colorSet = true;}
179     void read( gchar const *str, SPStyle &tyle, SPDocument *document = 0);
181     // Win32 is a temp work-around until the emf extension is fixed:
182 #ifndef WIN32
183 private:
184     SPIPaint(SPIPaint const&);
185     SPIPaint &operator=(SPIPaint const &);
186 #endif // WIN32
187 };
189 /// Filter type internal to SPStyle
190 struct SPIFilter {
191     unsigned set : 1;
192     unsigned inherit : 1;
193     SPFilterReference *href;
194 };
196 enum {
197     SP_FONT_SIZE_LITERAL,
198     SP_FONT_SIZE_LENGTH,
199     SP_FONT_SIZE_PERCENTAGE
200 };
202 enum {
203     SP_BASELINE_SHIFT_LITERAL,
204     SP_BASELINE_SHIFT_LENGTH,
205     SP_BASELINE_SHIFT_PERCENTAGE
206 };
208 #define SP_FONT_SIZE ((1 << 24) - 1)
210 #define SP_F8_16_TO_FLOAT(v) ((gdouble) (v) / (1 << 16))
211 #define SP_F8_16_FROM_FLOAT(v) ((int) ((v) * ((1 << 16) + 0.9999)))
213 #define SP_STYLE_FLAG_IFSET (1 << 0)
214 #define SP_STYLE_FLAG_IFDIFF (1 << 1)
215 #define SP_STYLE_FLAG_ALWAYS (1 << 2)
217 /// Fontsize type internal to SPStyle.
218 struct SPIFontSize {
219     unsigned set : 1;
220     unsigned inherit : 1;
221     unsigned type : 2;
222     unsigned value : 24;
223     float computed;
224 };
226 /// Baseline shift type internal to SPStyle.
227 struct SPIBaselineShift {
228     unsigned set : 1;
229     unsigned inherit : 1;
230     unsigned type : 2;
231     unsigned unit : 4;
232     unsigned literal: 2;
233     float value; // Can be negative
234     float computed;
235 };
237 /// Text decoration type internal to SPStyle.
238 struct SPITextDecoration {
239     unsigned set : 1;
240     unsigned inherit : 1;
241     unsigned underline : 1;
242     unsigned overline : 1;
243     unsigned line_through : 1;
244     unsigned blink : 1;    // "Conforming user agents are not required to support this value." yay!
245 };
247 /// Extended length type internal to SPStyle.
248 struct SPILengthOrNormal {
249     unsigned set : 1;
250     unsigned inherit : 1;
251     unsigned normal : 1;
252     unsigned unit : 4;
253     float value;
254     float computed;
255 };
257 class SPTextStyle;
259 /// Stroke dash details.
260 class NRVpathDash {
261 public:
262     double offset;
263     int n_dash;
264     double *dash;
265 };
267 /// An SVG style object.
268 struct SPStyle {
269     int refcount;
271     /** Object we are attached to */
272     SPObject *object;
273     /** Document we are associated with */
274     SPDocument *document;
276     /** Our text style component */
277     SPTextStyle *text;
278     unsigned text_private : 1;
280     /* CSS2 */
281     /* Font */
282     /** Size of the font */
283     SPIFontSize font_size;
284     /** Style of the font */
285     SPIEnum font_style;
286     /** Which substyle of the font */
287     SPIEnum font_variant;
288     /** Weight of the font */
289     SPIEnum font_weight;
290     /** Stretch of the font */
291     SPIEnum font_stretch;
293     /** First line indent of paragraphs (css2 16.1) */
294     SPILength text_indent;
295     /** text alignment (css2 16.2) (not to be confused with text-anchor) */
296     SPIEnum text_align;
297     /** text decoration (css2 16.3.1) */
298     SPITextDecoration text_decoration;
299     // 16.3.2 is text-shadow. That's complicated.
300     /** Line spacing (css2 10.8.1) */
301     SPILengthOrNormal line_height;
302     /** letter spacing (css2 16.4) */
303     SPILengthOrNormal letter_spacing;
304     /** word spacing (also css2 16.4) */
305     SPILengthOrNormal word_spacing;
306     /** capitalization (css2 16.5) */
307     SPIEnum text_transform;
309     /* CSS3 Text */
310     /** text direction (css3 text 3.2) */
311     SPIEnum direction;
312     /** block progression (css3 text 3.2) */
313     SPIEnum block_progression;
314     /** Writing mode (css3 text 3.2 and svg1.1 10.7.2) */
315     SPIEnum writing_mode;
316     /** Baseline shift (svg1.1 10.9.2) */
317     SPIBaselineShift baseline_shift;
319     /* SVG */
320     /** Anchor of the text (svg1.1 10.9.1) */
321     SPIEnum text_anchor;
323     /* Misc attributes */
324     unsigned clip_set : 1;
325     unsigned color_set : 1;
326     unsigned cursor_set : 1;
327     unsigned overflow_set : 1;
328     unsigned clip_path_set : 1;
329     unsigned clip_rule_set : 1;
330     unsigned mask_set : 1;
332     /** display */
333     SPIEnum display;
335     /** overflow */
336     SPIEnum overflow;
338     /** visibility */
339     SPIEnum visibility;
341     /** opacity */
342     SPIScale24 opacity;
344     /** color */
345     SPIPaint color;
347     /** fill */
348     SPIPaint fill;
349     /** fill-opacity */
350     SPIScale24 fill_opacity;
351     /** fill-rule: 0 nonzero, 1 evenodd */
352     SPIEnum fill_rule;
354     /** stroke */
355     SPIPaint stroke;
356     /** stroke-width */
357     SPILength stroke_width;
358     /** stroke-linecap */
359     SPIEnum stroke_linecap;
360     /** stroke-linejoin */
361     SPIEnum stroke_linejoin;
362     /** stroke-miterlimit */
363     SPIFloat stroke_miterlimit;
364     /** stroke-dash* */
365     NRVpathDash stroke_dash;
366     unsigned stroke_dasharray_set : 1;
367     unsigned stroke_dasharray_inherit : 1;
368     unsigned stroke_dashoffset_set : 1;
369     unsigned stroke_dashoffset_inherit : 1;
370     /** stroke-opacity */
371     SPIScale24 stroke_opacity;
373     /** Marker list */
374     SPIString marker[SP_MARKER_LOC_QTY];
376     /** Filter effect */
377     SPIFilter filter;
379     SPIEnum filter_blend_mode;
381    /** normally not used, but duplicates the Gaussian blur deviation (if any) from the attached
382         filter when the style is used for querying */
383     SPILength filter_gaussianBlur_deviation;
385     /** enable-background, used for defining where filter effects get
386      * their background image */
387     SPIEnum enable_background;
389     /// style belongs to a cloned object
390     bool cloned;
392     sigc::connection release_connection;
394     sigc::connection filter_modified_connection;
395     sigc::connection fill_ps_modified_connection;
396     sigc::connection stroke_ps_modified_connection;
398     SPObject *getFilter() { return (filter.href) ? filter.href->getObject() : 0; }
399     SPObject const *getFilter() const { return (filter.href) ? filter.href->getObject() : 0; }
400     gchar const *getFilterURI() const { return (filter.href) ? filter.href->getURI()->toString() : 0; }
402     SPPaintServer *getFillPaintServer() { return (fill.value.href) ? fill.value.href->getObject() : 0; }
403     SPPaintServer const *getFillPaintServer() const { return (fill.value.href) ? fill.value.href->getObject() : 0; }
404     gchar const *getFillURI() const { return (fill.value.href) ? fill.value.href->getURI()->toString() : 0; }
406     SPPaintServer *getStrokePaintServer() { return (stroke.value.href) ? stroke.value.href->getObject() : 0; }
407     SPPaintServer const *getStrokePaintServer() const { return (stroke.value.href) ? stroke.value.href->getObject() : 0; }
408     gchar const  *getStrokeURI() const { return (stroke.value.href) ? stroke.value.href->getURI()->toString() : 0; }
409 };
411 SPStyle *sp_style_new(SPDocument *document);
413 SPStyle *sp_style_new_from_object(SPObject *object);
415 SPStyle *sp_style_ref(SPStyle *style);
417 SPStyle *sp_style_unref(SPStyle *style);
419 void sp_style_read_from_object(SPStyle *style, SPObject *object);
421 void sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path);
423 void sp_style_merge_from_style_string(SPStyle *style, gchar const *p);
425 void sp_style_merge_from_parent(SPStyle *style, SPStyle const *parent);
427 void sp_style_merge_from_dying_parent(SPStyle *style, SPStyle const *parent);
429 gchar *sp_style_write_string(SPStyle const *style, guint flags = SP_STYLE_FLAG_IFSET);
431 gchar *sp_style_write_difference(SPStyle const *from, SPStyle const *to);
433 void sp_style_set_to_uri_string (SPStyle *style, bool isfill, const gchar *uri);
435 /* SPTextStyle */
437 enum SPCSSFontSize {
438     SP_CSS_FONT_SIZE_XX_SMALL,
439     SP_CSS_FONT_SIZE_X_SMALL,
440     SP_CSS_FONT_SIZE_SMALL,
441     SP_CSS_FONT_SIZE_MEDIUM,
442     SP_CSS_FONT_SIZE_LARGE,
443     SP_CSS_FONT_SIZE_X_LARGE,
444     SP_CSS_FONT_SIZE_XX_LARGE,
445     SP_CSS_FONT_SIZE_SMALLER,
446     SP_CSS_FONT_SIZE_LARGER
447 };
449 enum SPCSSFontStyle {
450     SP_CSS_FONT_STYLE_NORMAL,
451     SP_CSS_FONT_STYLE_ITALIC,
452     SP_CSS_FONT_STYLE_OBLIQUE
453 };
455 enum SPCSSFontVariant {
456     SP_CSS_FONT_VARIANT_NORMAL,
457     SP_CSS_FONT_VARIANT_SMALL_CAPS
458 };
460 enum SPCSSFontWeight {
461     SP_CSS_FONT_WEIGHT_100,
462     SP_CSS_FONT_WEIGHT_200,
463     SP_CSS_FONT_WEIGHT_300,
464     SP_CSS_FONT_WEIGHT_400,
465     SP_CSS_FONT_WEIGHT_500,
466     SP_CSS_FONT_WEIGHT_600,
467     SP_CSS_FONT_WEIGHT_700,
468     SP_CSS_FONT_WEIGHT_800,
469     SP_CSS_FONT_WEIGHT_900,
470     SP_CSS_FONT_WEIGHT_NORMAL,
471     SP_CSS_FONT_WEIGHT_BOLD,
472     SP_CSS_FONT_WEIGHT_LIGHTER,
473     SP_CSS_FONT_WEIGHT_BOLDER
474 };
476 enum SPCSSFontStretch {
477     SP_CSS_FONT_STRETCH_ULTRA_CONDENSED,
478     SP_CSS_FONT_STRETCH_EXTRA_CONDENSED,
479     SP_CSS_FONT_STRETCH_CONDENSED,
480     SP_CSS_FONT_STRETCH_SEMI_CONDENSED,
481     SP_CSS_FONT_STRETCH_NORMAL,
482     SP_CSS_FONT_STRETCH_SEMI_EXPANDED,
483     SP_CSS_FONT_STRETCH_EXPANDED,
484     SP_CSS_FONT_STRETCH_EXTRA_EXPANDED,
485     SP_CSS_FONT_STRETCH_ULTRA_EXPANDED,
486     SP_CSS_FONT_STRETCH_NARROWER,
487     SP_CSS_FONT_STRETCH_WIDER
488 };
490 enum SPCSSTextAlign {
491     SP_CSS_TEXT_ALIGN_START,
492     SP_CSS_TEXT_ALIGN_END,
493     SP_CSS_TEXT_ALIGN_LEFT,
494     SP_CSS_TEXT_ALIGN_RIGHT,
495     SP_CSS_TEXT_ALIGN_CENTER,
496     SP_CSS_TEXT_ALIGN_JUSTIFY
497     // also <string> is allowed, but only within table calls
498 };
500 enum SPCSSTextTransform {
501     SP_CSS_TEXT_TRANSFORM_CAPITALIZE,
502     SP_CSS_TEXT_TRANSFORM_UPPERCASE,
503     SP_CSS_TEXT_TRANSFORM_LOWERCASE,
504     SP_CSS_TEXT_TRANSFORM_NONE
505 };
507 enum SPCSSDirection {
508     SP_CSS_DIRECTION_LTR,
509     SP_CSS_DIRECTION_RTL
510 };
512 enum SPCSSBlockProgression {
513     SP_CSS_BLOCK_PROGRESSION_TB,
514     SP_CSS_BLOCK_PROGRESSION_RL,
515     SP_CSS_BLOCK_PROGRESSION_LR
516 };
518 enum SPCSSWritingMode {
519     SP_CSS_WRITING_MODE_LR_TB,
520     SP_CSS_WRITING_MODE_RL_TB,
521     SP_CSS_WRITING_MODE_TB_RL,
522     SP_CSS_WRITING_MODE_TB_LR
523 };
525 enum SPTextAnchor {
526     SP_CSS_TEXT_ANCHOR_START,
527     SP_CSS_TEXT_ANCHOR_MIDDLE,
528     SP_CSS_TEXT_ANCHOR_END
529 };
531 enum SPCSSBaselineShift {
532   SP_CSS_BASELINE_SHIFT_BASELINE,
533   SP_CSS_BASELINE_SHIFT_SUB,
534   SP_CSS_BASELINE_SHIFT_SUPER
535 };
537 enum SPVisibility {
538     SP_CSS_VISIBILITY_HIDDEN,
539     SP_CSS_VISIBILITY_COLLAPSE,
540     SP_CSS_VISIBILITY_VISIBLE
541 };
543 enum SPOverflow {
544     SP_CSS_OVERFLOW_VISIBLE,
545     SP_CSS_OVERFLOW_HIDDEN,
546     SP_CSS_OVERFLOW_SCROLL,
547     SP_CSS_OVERFLOW_AUTO
548 };
550 /// \todo more display types
551 enum SPCSSDisplay {
552     SP_CSS_DISPLAY_NONE,
553     SP_CSS_DISPLAY_INLINE,
554     SP_CSS_DISPLAY_BLOCK,
555     SP_CSS_DISPLAY_LIST_ITEM,
556     SP_CSS_DISPLAY_RUN_IN,
557     SP_CSS_DISPLAY_COMPACT,
558     SP_CSS_DISPLAY_MARKER,
559     SP_CSS_DISPLAY_TABLE,
560     SP_CSS_DISPLAY_INLINE_TABLE,
561     SP_CSS_DISPLAY_TABLE_ROW_GROUP,
562     SP_CSS_DISPLAY_TABLE_HEADER_GROUP,
563     SP_CSS_DISPLAY_TABLE_FOOTER_GROUP,
564     SP_CSS_DISPLAY_TABLE_ROW,
565     SP_CSS_DISPLAY_TABLE_COLUMN_GROUP,
566     SP_CSS_DISPLAY_TABLE_COLUMN,
567     SP_CSS_DISPLAY_TABLE_CELL,
568     SP_CSS_DISPLAY_TABLE_CAPTION
569 };
571 enum SPEnableBackground {
572     SP_CSS_BACKGROUND_ACCUMULATE,
573     SP_CSS_BACKGROUND_NEW
574 };
576 /// An SPTextStyle has a refcount, a font family, and a font name.
577 struct SPTextStyle {
578     int refcount;
580     /* CSS font properties */
581     SPIString font_family;
583     /* Full font name, as font_factory::ConstructFontSpecification would give */
584     SPIString font_specification;
586     /** \todo fixme: The 'font' property is ugly, and not working (lauris) */
587     SPIString font;
588 };
590 SPCSSAttr *sp_css_attr_from_style (SPStyle const *const style, guint flags);
591 SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint flags = SP_STYLE_FLAG_IFSET);
592 SPCSSAttr *sp_css_attr_unset_text(SPCSSAttr *css);
593 SPCSSAttr *sp_css_attr_unset_uris(SPCSSAttr *css);
594 SPCSSAttr *sp_css_attr_scale(SPCSSAttr *css, double ex);
596 void sp_style_unset_property_attrs(SPObject *o);
598 void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive);
600 gchar *attribute_unquote(gchar const *val);
601 gchar *css2_escape_quote(gchar const *val);
603 #endif // SEEN_SP_STYLE_H
606 /*
607   Local Variables:
608   mode:c++
609   c-file-style:"stroustrup"
610   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
611   indent-tabs-mode:nil
612   fill-column:99
613   End:
614 */
615 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :