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())
147 #define SP_OBJECT_STYLE_FILL_SERVER(o) (SP_OBJECT (o)->style->getFillPaintServer())
148 #define SP_OBJECT_STYLE_STROKE_SERVER(o) (SP_OBJECT (o)->style->getStrokePaintServer())
150 class SVGICCColor;
152 /// Paint type internal to SPStyle.
153 struct SPIPaint {
154 unsigned set : 1;
155 unsigned inherit : 1;
156 unsigned currentcolor : 1;
157 unsigned int colorSet : 1;
158 unsigned int noneSet : 1;
159 struct {
160 SPPaintServerReference *href;
161 SPColor color;
162 } value;
165 bool isSet() const { return true; /* set || colorSet*/}
166 bool isSameType( SPIPaint const & other ) const {return (isPaintserver() == other.isPaintserver()) && (colorSet == other.colorSet) && (currentcolor == other.currentcolor);}
168 bool isNoneSet() const {return noneSet;}
170 bool isNone() const {return !currentcolor && !colorSet && !isPaintserver();} // TODO refine
171 bool isColor() const {return colorSet && !isPaintserver();}
172 bool isPaintserver() const {return value.href && value.href->getObject();}
174 void clear();
176 void setColor( float r, float g, float b ) {value.color.set( r, g, b ); colorSet = true;}
177 void setColor( guint32 val ) {value.color.set( val ); colorSet = true;}
178 void setColor( SPColor const& color ) {value.color = color; colorSet = true;}
179 };
181 /// Filter type internal to SPStyle
182 struct SPIFilter {
183 unsigned set : 1;
184 unsigned inherit : 1;
185 SPFilterReference *href;
186 };
188 enum {
189 SP_FONT_SIZE_LITERAL,
190 SP_FONT_SIZE_LENGTH,
191 SP_FONT_SIZE_PERCENTAGE
192 };
194 enum {
195 SP_BASELINE_SHIFT_LITERAL,
196 SP_BASELINE_SHIFT_LENGTH,
197 SP_BASELINE_SHIFT_PERCENTAGE
198 };
200 #define SP_FONT_SIZE ((1 << 24) - 1)
202 #define SP_F8_16_TO_FLOAT(v) ((gdouble) (v) / (1 << 16))
203 #define SP_F8_16_FROM_FLOAT(v) ((int) ((v) * ((1 << 16) + 0.9999)))
205 #define SP_STYLE_FLAG_IFSET (1 << 0)
206 #define SP_STYLE_FLAG_IFDIFF (1 << 1)
207 #define SP_STYLE_FLAG_ALWAYS (1 << 2)
209 /// Fontsize type internal to SPStyle.
210 struct SPIFontSize {
211 unsigned set : 1;
212 unsigned inherit : 1;
213 unsigned type : 2;
214 unsigned value : 24;
215 float computed;
216 };
218 /// Baseline shift type internal to SPStyle.
219 struct SPIBaselineShift {
220 unsigned set : 1;
221 unsigned inherit : 1;
222 unsigned type : 2;
223 unsigned unit : 4;
224 unsigned literal: 2;
225 float value; // Can be negative
226 float computed;
227 };
229 /// Text decoration type internal to SPStyle.
230 struct SPITextDecoration {
231 unsigned set : 1;
232 unsigned inherit : 1;
233 unsigned underline : 1;
234 unsigned overline : 1;
235 unsigned line_through : 1;
236 unsigned blink : 1; // "Conforming user agents are not required to support this value." yay!
237 };
239 /// Extended length type internal to SPStyle.
240 struct SPILengthOrNormal {
241 unsigned set : 1;
242 unsigned inherit : 1;
243 unsigned normal : 1;
244 unsigned unit : 4;
245 float value;
246 float computed;
247 };
249 class SPTextStyle;
251 /// Stroke dash details.
252 class NRVpathDash {
253 public:
254 double offset;
255 int n_dash;
256 double *dash;
257 };
259 /// An SVG style object.
260 struct SPStyle {
261 int refcount;
263 /** Object we are attached to */
264 SPObject *object;
265 /** Document we are associated with */
266 SPDocument *document;
268 /** Our text style component */
269 SPTextStyle *text;
270 unsigned text_private : 1;
272 /* CSS2 */
273 /* Font */
274 /** Size of the font */
275 SPIFontSize font_size;
276 /** Style of the font */
277 SPIEnum font_style;
278 /** Which substyle of the font */
279 SPIEnum font_variant;
280 /** Weight of the font */
281 SPIEnum font_weight;
282 /** Stretch of the font */
283 SPIEnum font_stretch;
285 /** First line indent of paragraphs (css2 16.1) */
286 SPILength text_indent;
287 /** text alignment (css2 16.2) (not to be confused with text-anchor) */
288 SPIEnum text_align;
289 /** text decoration (css2 16.3.1) */
290 SPITextDecoration text_decoration;
291 // 16.3.2 is text-shadow. That's complicated.
292 /** Line spacing (css2 10.8.1) */
293 SPILengthOrNormal line_height;
294 /** letter spacing (css2 16.4) */
295 SPILengthOrNormal letter_spacing;
296 /** word spacing (also css2 16.4) */
297 SPILengthOrNormal word_spacing;
298 /** capitalization (css2 16.5) */
299 SPIEnum text_transform;
301 /* CSS3 Text */
302 /** text direction (css3 text 3.2) */
303 SPIEnum direction;
304 /** block progression (css3 text 3.2) */
305 SPIEnum block_progression;
306 /** Writing mode (css3 text 3.2 and svg1.1 10.7.2) */
307 SPIEnum writing_mode;
308 /** Baseline shift (svg1.1 10.9.2) */
309 SPIBaselineShift baseline_shift;
311 /* SVG */
312 /** Anchor of the text (svg1.1 10.9.1) */
313 SPIEnum text_anchor;
315 /* Misc attributes */
316 unsigned clip_set : 1;
317 unsigned color_set : 1;
318 unsigned cursor_set : 1;
319 unsigned overflow_set : 1;
320 unsigned clip_path_set : 1;
321 unsigned clip_rule_set : 1;
322 unsigned mask_set : 1;
324 /** display */
325 SPIEnum display;
327 /** overflow */
328 SPIEnum overflow;
330 /** visibility */
331 SPIEnum visibility;
333 /** opacity */
334 SPIScale24 opacity;
336 /** color */
337 SPIPaint color;
339 /** fill */
340 SPIPaint fill;
341 /** fill-opacity */
342 SPIScale24 fill_opacity;
343 /** fill-rule: 0 nonzero, 1 evenodd */
344 SPIEnum fill_rule;
346 /** stroke */
347 SPIPaint stroke;
348 /** stroke-width */
349 SPILength stroke_width;
350 /** stroke-linecap */
351 SPIEnum stroke_linecap;
352 /** stroke-linejoin */
353 SPIEnum stroke_linejoin;
354 /** stroke-miterlimit */
355 SPIFloat stroke_miterlimit;
356 /** stroke-dash* */
357 NRVpathDash stroke_dash;
358 unsigned stroke_dasharray_set : 1;
359 unsigned stroke_dasharray_inherit : 1;
360 unsigned stroke_dashoffset_set : 1;
361 unsigned stroke_dashoffset_inherit : 1;
362 /** stroke-opacity */
363 SPIScale24 stroke_opacity;
365 /** Marker list */
366 SPIString marker[SP_MARKER_LOC_QTY];
368 /** Filter effect */
369 SPIFilter filter;
371 SPIEnum filter_blend_mode;
373 /** normally not used, but duplicates the Gaussian blur deviation (if any) from the attached
374 filter when the style is used for querying */
375 SPILength filter_gaussianBlur_deviation;
377 /** enable-background, used for defining where filter effects get
378 * their background image */
379 SPIEnum enable_background;
381 /// style belongs to a cloned object
382 bool cloned;
384 sigc::connection release_connection;
386 sigc::connection filter_modified_connection;
387 sigc::connection fill_ps_modified_connection;
388 sigc::connection stroke_ps_modified_connection;
390 SPObject *getFilter() { return (filter.href) ? filter.href->getObject() : 0; }
391 SPObject const *getFilter() const { return (filter.href) ? filter.href->getObject() : 0; }
392 gchar const *getFilterURI() const { return (filter.href) ? filter.href->getURI()->toString() : 0; }
394 SPPaintServer *getFillPaintServer() { return (fill.value.href) ? fill.value.href->getObject() : 0; }
395 SPPaintServer const *getFillPaintServer() const { return (fill.value.href) ? fill.value.href->getObject() : 0; }
396 gchar const *getFillURI() const { return (fill.value.href) ? fill.value.href->getURI()->toString() : 0; }
398 SPPaintServer *getStrokePaintServer() { return (stroke.value.href) ? stroke.value.href->getObject() : 0; }
399 SPPaintServer const *getStrokePaintServer() const { return (stroke.value.href) ? stroke.value.href->getObject() : 0; }
400 gchar const *getStrokeURI() const { return (stroke.value.href) ? stroke.value.href->getURI()->toString() : 0; }
401 };
403 SPStyle *sp_style_new(SPDocument *document);
405 SPStyle *sp_style_new_from_object(SPObject *object);
407 SPStyle *sp_style_ref(SPStyle *style);
409 SPStyle *sp_style_unref(SPStyle *style);
411 void sp_style_read_from_object(SPStyle *style, SPObject *object);
413 void sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path);
415 void sp_style_merge_from_style_string(SPStyle *style, gchar const *p);
417 void sp_style_merge_from_parent(SPStyle *style, SPStyle const *parent);
419 void sp_style_merge_from_dying_parent(SPStyle *style, SPStyle const *parent);
421 gchar *sp_style_write_string(SPStyle const *style, guint flags = SP_STYLE_FLAG_IFSET);
423 gchar *sp_style_write_difference(SPStyle const *from, SPStyle const *to);
425 void sp_style_set_to_uri_string (SPStyle *style, bool isfill, const gchar *uri);
427 /* SPTextStyle */
429 enum SPCSSFontSize {
430 SP_CSS_FONT_SIZE_XX_SMALL,
431 SP_CSS_FONT_SIZE_X_SMALL,
432 SP_CSS_FONT_SIZE_SMALL,
433 SP_CSS_FONT_SIZE_MEDIUM,
434 SP_CSS_FONT_SIZE_LARGE,
435 SP_CSS_FONT_SIZE_X_LARGE,
436 SP_CSS_FONT_SIZE_XX_LARGE,
437 SP_CSS_FONT_SIZE_SMALLER,
438 SP_CSS_FONT_SIZE_LARGER
439 };
441 enum SPCSSFontStyle {
442 SP_CSS_FONT_STYLE_NORMAL,
443 SP_CSS_FONT_STYLE_ITALIC,
444 SP_CSS_FONT_STYLE_OBLIQUE
445 };
447 enum SPCSSFontVariant {
448 SP_CSS_FONT_VARIANT_NORMAL,
449 SP_CSS_FONT_VARIANT_SMALL_CAPS
450 };
452 enum SPCSSFontWeight {
453 SP_CSS_FONT_WEIGHT_100,
454 SP_CSS_FONT_WEIGHT_200,
455 SP_CSS_FONT_WEIGHT_300,
456 SP_CSS_FONT_WEIGHT_400,
457 SP_CSS_FONT_WEIGHT_500,
458 SP_CSS_FONT_WEIGHT_600,
459 SP_CSS_FONT_WEIGHT_700,
460 SP_CSS_FONT_WEIGHT_800,
461 SP_CSS_FONT_WEIGHT_900,
462 SP_CSS_FONT_WEIGHT_NORMAL,
463 SP_CSS_FONT_WEIGHT_BOLD,
464 SP_CSS_FONT_WEIGHT_LIGHTER,
465 SP_CSS_FONT_WEIGHT_BOLDER
466 };
468 enum SPCSSFontStretch {
469 SP_CSS_FONT_STRETCH_ULTRA_CONDENSED,
470 SP_CSS_FONT_STRETCH_EXTRA_CONDENSED,
471 SP_CSS_FONT_STRETCH_CONDENSED,
472 SP_CSS_FONT_STRETCH_SEMI_CONDENSED,
473 SP_CSS_FONT_STRETCH_NORMAL,
474 SP_CSS_FONT_STRETCH_SEMI_EXPANDED,
475 SP_CSS_FONT_STRETCH_EXPANDED,
476 SP_CSS_FONT_STRETCH_EXTRA_EXPANDED,
477 SP_CSS_FONT_STRETCH_ULTRA_EXPANDED,
478 SP_CSS_FONT_STRETCH_NARROWER,
479 SP_CSS_FONT_STRETCH_WIDER
480 };
482 enum SPCSSTextAlign {
483 SP_CSS_TEXT_ALIGN_START,
484 SP_CSS_TEXT_ALIGN_END,
485 SP_CSS_TEXT_ALIGN_LEFT,
486 SP_CSS_TEXT_ALIGN_RIGHT,
487 SP_CSS_TEXT_ALIGN_CENTER,
488 SP_CSS_TEXT_ALIGN_JUSTIFY
489 // also <string> is allowed, but only within table calls
490 };
492 enum SPCSSTextTransform {
493 SP_CSS_TEXT_TRANSFORM_CAPITALIZE,
494 SP_CSS_TEXT_TRANSFORM_UPPERCASE,
495 SP_CSS_TEXT_TRANSFORM_LOWERCASE,
496 SP_CSS_TEXT_TRANSFORM_NONE
497 };
499 enum SPCSSDirection {
500 SP_CSS_DIRECTION_LTR,
501 SP_CSS_DIRECTION_RTL
502 };
504 enum SPCSSBlockProgression {
505 SP_CSS_BLOCK_PROGRESSION_TB,
506 SP_CSS_BLOCK_PROGRESSION_RL,
507 SP_CSS_BLOCK_PROGRESSION_LR
508 };
510 enum SPCSSWritingMode {
511 SP_CSS_WRITING_MODE_LR_TB,
512 SP_CSS_WRITING_MODE_RL_TB,
513 SP_CSS_WRITING_MODE_TB_RL,
514 SP_CSS_WRITING_MODE_TB_LR
515 };
517 enum SPTextAnchor {
518 SP_CSS_TEXT_ANCHOR_START,
519 SP_CSS_TEXT_ANCHOR_MIDDLE,
520 SP_CSS_TEXT_ANCHOR_END
521 };
523 enum SPCSSBaselineShift {
524 SP_CSS_BASELINE_SHIFT_BASELINE,
525 SP_CSS_BASELINE_SHIFT_SUB,
526 SP_CSS_BASELINE_SHIFT_SUPER
527 };
529 enum SPVisibility {
530 SP_CSS_VISIBILITY_HIDDEN,
531 SP_CSS_VISIBILITY_COLLAPSE,
532 SP_CSS_VISIBILITY_VISIBLE
533 };
535 enum SPOverflow {
536 SP_CSS_OVERFLOW_VISIBLE,
537 SP_CSS_OVERFLOW_HIDDEN,
538 SP_CSS_OVERFLOW_SCROLL,
539 SP_CSS_OVERFLOW_AUTO
540 };
542 /// \todo more display types
543 enum SPCSSDisplay {
544 SP_CSS_DISPLAY_NONE,
545 SP_CSS_DISPLAY_INLINE,
546 SP_CSS_DISPLAY_BLOCK,
547 SP_CSS_DISPLAY_LIST_ITEM,
548 SP_CSS_DISPLAY_RUN_IN,
549 SP_CSS_DISPLAY_COMPACT,
550 SP_CSS_DISPLAY_MARKER,
551 SP_CSS_DISPLAY_TABLE,
552 SP_CSS_DISPLAY_INLINE_TABLE,
553 SP_CSS_DISPLAY_TABLE_ROW_GROUP,
554 SP_CSS_DISPLAY_TABLE_HEADER_GROUP,
555 SP_CSS_DISPLAY_TABLE_FOOTER_GROUP,
556 SP_CSS_DISPLAY_TABLE_ROW,
557 SP_CSS_DISPLAY_TABLE_COLUMN_GROUP,
558 SP_CSS_DISPLAY_TABLE_COLUMN,
559 SP_CSS_DISPLAY_TABLE_CELL,
560 SP_CSS_DISPLAY_TABLE_CAPTION
561 };
563 enum SPEnableBackground {
564 SP_CSS_BACKGROUND_ACCUMULATE,
565 SP_CSS_BACKGROUND_NEW
566 };
568 /// An SPTextStyle has a refcount, a font family, and a font name.
569 struct SPTextStyle {
570 int refcount;
572 /* CSS font properties */
573 SPIString font_family;
575 /* Full font name, as font_factory::ConstructFontSpecification would give */
576 SPIString font_specification;
578 /** \todo fixme: The 'font' property is ugly, and not working (lauris) */
579 SPIString font;
580 };
582 SPCSSAttr *sp_css_attr_from_style (SPStyle const *const style, guint flags);
583 SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint flags = SP_STYLE_FLAG_IFSET);
584 SPCSSAttr *sp_css_attr_unset_text(SPCSSAttr *css);
585 SPCSSAttr *sp_css_attr_unset_uris(SPCSSAttr *css);
586 SPCSSAttr *sp_css_attr_scale(SPCSSAttr *css, double ex);
588 void sp_style_unset_property_attrs(SPObject *o);
590 void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive);
592 gchar *attribute_unquote(gchar const *val);
593 gchar *css2_escape_quote(gchar const *val);
595 #endif // SEEN_SP_STYLE_H
598 /*
599 Local Variables:
600 mode:c++
601 c-file-style:"stroustrup"
602 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
603 indent-tabs-mode:nil
604 fill-column:99
605 End:
606 */
607 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :