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