style.cpp revision be395c0b0e020f2695dad4287d44cb9047e94b7b
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof/**
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * @file
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * SVG stylesheets implementation.
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof */
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof/* Authors:
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Lauris Kaplinski <lauris@kaplinski.com>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Peter Moulder <pmoulder@mail.csse.monash.edu.au>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * bulia byak <buliabyak@users.sf.net>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Abhishek Sharma
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Tavmjong Bah <tavmjong@free.fr>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Kris De Gussem <Kris.DeGussem@gmail.com>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof *
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof * Copyright (C) 2001-2002 Lauris Kaplinski
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof * Copyright (C) 2001 Ximian, Inc.
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof * Copyright (C) 2005 Monash University
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Copyright (C) 2012 Kris De Gussem
81db7808fbee540434bcc6c7198579b95a6a2d88Jabiertxof * Copyright (C) 2014-2015 Tavmjong Bah
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof *
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof * Released under GNU GPL, read the file 'COPYING' for more information
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof */
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#ifdef HAVE_CONFIG_H
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof# include "config.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#endif
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include <cstring>
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include <string>
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include <algorithm>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include "libcroco/cr-sel-eng.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "xml/croco-node-iface.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include "svg/svg.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "svg/svg-color.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "svg/svg-icc-color.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "display/canvas-bpath.h"
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include "attributes.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "document.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "extract-uri.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "uri-references.h"
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include "uri.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "sp-paint-server.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "streq.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "strneq.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "style.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "svg/css-ostringstream.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "xml/repr.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "xml/simple-document.h"
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include "util/units.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "macros.h"
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof#include "preferences.h"
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof#include "sp-filter-reference.h"
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include <sigc++/functors/ptr_fun.h>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include <sigc++/adaptors/bind.h>
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include <2geom/math-utils.h>
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#include <glibmm/regex.h>
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxofusing Inkscape::CSSOStringStream;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxofusing std::vector;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#define BMAX 8192
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof#define SP_CSS_FONT_SIZE_DEFAULT 12.0;
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxofstruct SPStyleEnum;
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxofint SPStyle::_count = 0;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof/*#########################
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof## FORWARD DECLARATIONS
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#########################*/
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxofvoid sp_style_filter_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxofvoid sp_style_fill_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
2ce2003d5713154f99c32af18fb904a1af109031Jabiertxofvoid sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxofstatic void sp_style_object_release(SPObject *object, SPStyle *style);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxofstatic CRSelEng *sp_repr_sel_eng();
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
2ce2003d5713154f99c32af18fb904a1af109031Jabiertxof//SPPropMap SPStyle::_propmap;
2ce2003d5713154f99c32af18fb904a1af109031Jabiertxof
2ce2003d5713154f99c32af18fb904a1af109031Jabiertxof// C++11 allows one constructor to call another... might be useful. The original C code
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof// had separate calls to create SPStyle, one with only SPDocument and the other with only
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof// SPObject as parameters.
ccbee7d45f91658e83a602a9a28ee26162a261f9JabiertxofSPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Unimplemented SVG 1.1: alignment-baseline, clip, clip-path, color-profile, cursor,
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // dominant-baseline, flood-color, flood-opacity, font-size-adjust,
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // glyph-orientation-horizontal, glyph-orientation-vertical, kerning, lighting-color,
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // pointer-events, stop-color, stop-opacity, unicode-bidi
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // For enums: property( name, enumeration, default value , inherits = true );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // For scale24: property( name, default value = 0, inherits = true );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // 'font', 'font-size', and 'font-family' must come first as other properties depend on them
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // for calculated values (through 'em' and 'ex'). ('ex' is currently not read.)
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // The following properties can depend on 'em' and 'ex':
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // baseline-shift, kerning, letter-spacing, stroke-dash-offset, stroke-width, word-spacing,
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Non-SVG 1.1: text-indent, line-spacing
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // Hidden in SPIFontStyle: (to be refactored)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // font-family
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // font-specification
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // Font related properties and 'font' shorthand
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof font_style( "font-style", enum_font_style, SP_CSS_FONT_STYLE_NORMAL ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof font_variant( "font-variant", enum_font_variant, SP_CSS_FONT_VARIANT_NORMAL ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof font_weight( "font-weight", enum_font_weight, SP_CSS_FONT_WEIGHT_NORMAL, SP_CSS_FONT_WEIGHT_400 ),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof font_stretch( "font-stretch", enum_font_stretch, SP_CSS_FONT_STRETCH_NORMAL ),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof font_size(),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof line_height( "line-height", 1.0 ), // SPILengthOrNormal
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof font_family( "font-family", "sans-serif" ), // SPIString w/default
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof font(), // SPIFont
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof font_specification( "-inkscape-font-specification" ), // SPIString
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
de641d2613f4eea940ba6eb6c52ea9bcda516ba2Jabiertxof // Font variants
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof font_variant_ligatures( "font-variant-ligatures", enum_font_variant_ligatures ),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof font_variant_position( "font-variant-position", enum_font_variant_position, SP_CSS_FONT_VARIANT_POSITION_NORMAL ),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof font_variant_caps( "font-variant-caps", enum_font_variant_caps, SP_CSS_FONT_VARIANT_CAPS_NORMAL ),
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof font_variant_numeric( "font-variant-numeric", enum_font_variant_numeric ),
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof font_variant_alternates("font-variant-alternates", enum_font_variant_alternates, SP_CSS_FONT_VARIANT_ALTERNATES_NORMAL ),
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof font_variant_east_asian("font-variant-east_asian", enum_font_variant_east_asian, SP_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof font_feature_settings( "font-feature-settings", "normal" ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Text related properties
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof text_indent( "text-indent", 0.0 ), // SPILength
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof text_align( "text-align", enum_text_align, SP_CSS_TEXT_ALIGN_START ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof letter_spacing( "letter-spacing", 0.0 ), // SPILengthOrNormal
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof word_spacing( "word-spacing", 0.0 ), // SPILengthOrNormal
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof text_transform( "text-transform", enum_text_transform, SP_CSS_TEXT_TRANSFORM_NONE ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof direction( "direction", enum_direction, SP_CSS_DIRECTION_LTR ),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof block_progression("block-progression", enum_block_progression, SP_CSS_BLOCK_PROGRESSION_TB),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof writing_mode( "writing-mode", enum_writing_mode, SP_CSS_WRITING_MODE_LR_TB ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof baseline_shift(),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof text_anchor( "text-anchor", enum_text_anchor, SP_CSS_TEXT_ANCHOR_START ),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof white_space( "white-space", enum_white_space, SP_CSS_WHITE_SPACE_NORMAL ),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // SVG 2 Text Wrapping
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof shape_inside( "shape-inside" ), // SPIString
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof //shape_outside( "shape-outside" ), // SPIString
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof shape_padding( "shape-padding", 0.0 ), // SPILength for now
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof //shape_margin( "shape-margin", 0.0 ), // SPILength for now
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof text_decoration(),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof text_decoration_line(),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof text_decoration_style(),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof text_decoration_color( "text-decoration-color" ), // SPIColor
0b159142b0b5738b20883b411fe8233657cf8b4fJabiertxof
0b159142b0b5738b20883b411fe8233657cf8b4fJabiertxof // General visual properties
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof clip_rule( "clip-rule", enum_clip_rule, SP_WIND_RULE_NONZERO ),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof display( "display", enum_display, SP_CSS_DISPLAY_INLINE, false ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof overflow( "overflow", enum_overflow, SP_CSS_OVERFLOW_VISIBLE, false ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof visibility( "visibility", enum_visibility, SP_CSS_VISIBILITY_VISIBLE ),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof opacity( "opacity", SP_SCALE24_MAX, false ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof isolation( "isolation", enum_isolation, SP_CSS_ISOLATION_AUTO ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof mix_blend_mode( "mix-blend-mode", enum_blend_mode, SP_CSS_BLEND_NORMAL ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof paint_order(), // SPIPaintOrder
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Color properties
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof color( "color" ), // SPIColor
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof color_interpolation( "color-interpolation", enum_color_interpolation, SP_CSS_COLOR_INTERPOLATION_SRGB),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof color_interpolation_filters("color-interpolation-filters", enum_color_interpolation, SP_CSS_COLOR_INTERPOLATION_LINEARRGB),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Solid color properties
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof solid_color( "solid-color" ), // SPIColor
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof solid_opacity( "solid-opacity", SP_SCALE24_MAX ),
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Fill properties
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof fill( "fill" ), // SPIPaint
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof fill_opacity( "fill-opacity", SP_SCALE24_MAX ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof fill_rule( "fill-rule", enum_fill_rule, SP_WIND_RULE_NONZERO ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Stroke properites
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof stroke( "stroke" ), // SPIPaint
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof stroke_width( "stroke-width", 1.0 ), // SPILength
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof stroke_linecap( "stroke-linecap", enum_stroke_linecap, SP_STROKE_LINECAP_BUTT ),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof stroke_linejoin( "stroke-linejoin", enum_stroke_linejoin, SP_STROKE_LINEJOIN_MITER ),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof stroke_miterlimit("stroke-miterlimit", 4 ), // SPIFloat (only use of float!)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof stroke_dasharray(), // SPIDashArray
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof stroke_dashoffset("stroke-dashoffset", 0.0 ), // SPILength for now
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof stroke_opacity( "stroke-opacity", SP_SCALE24_MAX ),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof marker( "marker" ), // SPIString
a0623d30f399827fa8c9cf5edad86bbc8e72c063Jabiertxof marker_start( "marker-start" ), // SPIString
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof marker_mid( "marker-mid" ), // SPIString
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof marker_end( "marker-end" ), // SPIString
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // Filter properties
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof filter(),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof filter_blend_mode("filter-blend-mode", enum_blend_mode, SP_CSS_BLEND_NORMAL),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof filter_gaussianBlur_deviation( "filter-gaussianBlur-deviation", 0.0 ), // SPILength
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof enable_background("enable-background", enum_enable_background, SP_CSS_BACKGROUND_ACCUMULATE, false),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // Rendering hint properties
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof color_rendering( "color-rendering", enum_color_rendering, SP_CSS_COLOR_RENDERING_AUTO),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof image_rendering( "image-rendering", enum_image_rendering, SP_CSS_IMAGE_RENDERING_AUTO),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof shape_rendering( "shape-rendering", enum_shape_rendering, SP_CSS_SHAPE_RENDERING_AUTO),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof text_rendering( "text-rendering", enum_text_rendering, SP_CSS_TEXT_RENDERING_AUTO )
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // std::cout << "SPStyle::SPStyle( SPDocument ): Entrance: (" << _count << ")" << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " Document: " << (document_in?"present":"null") << std::endl;
0b159142b0b5738b20883b411fe8233657cf8b4fJabiertxof // std::cout << " Object: "
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // << (object_in?(object_in->getId()?object_in->getId():"id null"):"object null") << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // static bool first = true;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // if( first ) {
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // std::cout << "Size of SPStyle: " << sizeof(SPStyle) << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " SPIBase: " << sizeof(SPIBase) << std::endl;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // std::cout << " SPIFloat: " << sizeof(SPIFloat) << std::endl;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // std::cout << " SPIScale24: " << sizeof(SPIScale24) << std::endl;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // std::cout << " SPILength: " << sizeof(SPILength) << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " SPILengthOrNormal: " << sizeof(SPILengthOrNormal) << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " SPIColor: " << sizeof(SPIColor) << std::endl;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // std::cout << " SPIPaint: " << sizeof(SPIPaint) << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " SPITextDecorationLine" << sizeof(SPITextDecorationLine) << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " Glib::ustring:" << sizeof(Glib::ustring) << std::endl;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // std::cout << " SPColor: " << sizeof(SPColor) << std::endl;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // first = false;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof ++_count; // Poor man's memory leak detector
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _refcount = 1;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof cloned = false;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof object = object_in;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof if( object ) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof g_assert( SP_IS_OBJECT(object) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof document = object->document;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof release_connection =
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_style_object_release), this));
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof cloned = object->cloned;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof } else {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof document = document_in;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
a0623d30f399827fa8c9cf5edad86bbc8e72c063Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // 'font' shorthand requires access to included properties.
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof font.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // Properties that depend on 'font-size' for calculating lengths.
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof baseline_shift.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof text_indent.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof line_height.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof letter_spacing.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof word_spacing.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof stroke_width.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof stroke_dashoffset.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof shape_padding.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // Properties that depend on 'color'
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof text_decoration_color.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof fill.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof stroke.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // color.setStylePointer( this ); // Doen't need reference to self
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // 'text_decoration' shorthand requires access to included properties.
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof text_decoration.setStylePointer( this );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // SPIPaint, SPIFilter needs access to 'this' (SPStyle)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // for setting up signals... 'fill', 'stroke' already done
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof filter.setStylePointer( this );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // Used to iterate over markers
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof marker_ptrs[SP_MARKER_LOC] = &marker;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof marker_ptrs[SP_MARKER_LOC_START] = &marker_start;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof marker_ptrs[SP_MARKER_LOC_MID] = &marker_mid;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof marker_ptrs[SP_MARKER_LOC_END] = &marker_end;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // This might be too resource hungary... but for now it possible to loop over properties
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // 'color' must be before 'fill', 'stroke', 'text-decoration-color', ...
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &color );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // 'font-size'/'font' must be before properties that need to know em, ex size (SPILength,
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // SPILenghtOrNormal)
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font_style );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font_variant );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font_weight );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font_stretch );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof _properties.push_back( &font_size );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &line_height );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font_family );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &font_specification );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // Font variants
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_variant_ligatures );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_variant_position );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_variant_caps );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_variant_numeric );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_variant_alternates );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_variant_east_asian );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &font_feature_settings );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_indent );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_align );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_decoration );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_decoration_line );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_decoration_style );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_decoration_color );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &letter_spacing );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &word_spacing );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof _properties.push_back( &text_transform );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &direction );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &block_progression );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &writing_mode );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &baseline_shift );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &text_anchor );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &white_space );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &shape_inside );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &shape_padding );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &clip_rule );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &display );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &overflow );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &visibility );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &opacity );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &isolation );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &mix_blend_mode );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &color_interpolation );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &color_interpolation_filters );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &solid_color );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &solid_opacity );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &fill );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &fill_opacity );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &fill_rule );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke_width );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke_linecap );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke_linejoin );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke_miterlimit );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke_dasharray );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &stroke_dashoffset );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof _properties.push_back( &stroke_opacity );
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński _properties.push_back( &marker );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof _properties.push_back( &marker_start );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &marker_mid );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &marker_end );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof _properties.push_back( &paint_order );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &filter );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &filter_blend_mode );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &filter_gaussianBlur_deviation );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof _properties.push_back( &color_rendering );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof _properties.push_back( &image_rendering );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof _properties.push_back( &shape_rendering );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof _properties.push_back( &text_rendering );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof _properties.push_back( &enable_background );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // MAP -------------------------------------------
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // if( _propmap.size() == 0 ) {
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // // 'color' must be before 'fill', 'stroke', 'text-decoration-color', ...
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // _propmap.insert( std::make_pair( color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // // 'font-size' must be before properties that need to know em, ex size (SPILength, SPILenghtOrNormal)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( font_style.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_style ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( font_variant.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_variant ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( font_weight.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_weight ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( font_stretch.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_stretch ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( font_size.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_size ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( line_height.name, reinterpret_cast<SPIBasePtr>(&SPStyle::line_height ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( font_family.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_family ) ) );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // _propmap.insert( std::make_pair( font.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( font_specification.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_specification ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // font_variant_ligatures );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // font_variant_position );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // font_variant_caps );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // font_variant_numeric );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // font_variant_alternates );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // font_variant_east_asian );
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof // font_feature_settings );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( text_indent.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_indent ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( text_align.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_align ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( text_decoration.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( text_decoration_line.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_line ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( text_decoration_style.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_style ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( text_decoration_color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_color ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( letter_spacing.name, reinterpret_cast<SPIBasePtr>(&SPStyle::letter_spacing ) ) );
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof // _propmap.insert( std::make_pair( word_spacing.name, reinterpret_cast<SPIBasePtr>(&SPStyle::word_spacing ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( text_transform.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_transform ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( direction.name, reinterpret_cast<SPIBasePtr>(&SPStyle::direction ) ) );
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof // _propmap.insert( std::make_pair( block_progression.name, reinterpret_cast<SPIBasePtr>(&SPStyle::block_progression ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( writing_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::writing_mode ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( baseline_shift.name, reinterpret_cast<SPIBasePtr>(&SPStyle::baseline_shift ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( text_anchor.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_anchor ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( white_space.name, reinterpret_cast<SPIBasePtr>(&SPStyle::white_space ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( shape_inside.name, reinterpret_cast<SPIBasePtr>(&SPStyle::shape_inside ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( shape_padding.name, reinterpret_cast<SPIBasePtr>(&SPStyle::shape_padding ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( clip_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::clip_rule ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( display.name, reinterpret_cast<SPIBasePtr>(&SPStyle::display ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( overflow.name, reinterpret_cast<SPIBasePtr>(&SPStyle::overflow ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( visibility.name, reinterpret_cast<SPIBasePtr>(&SPStyle::visibility ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // _propmap.insert( std::make_pair( opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::opacity ) ) );
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
// _propmap.insert( std::make_pair( isolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::isolation ) ) );
// _propmap.insert( std::make_pair( mix_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::mix_blend_mode ) ) );
// _propmap.insert( std::make_pair( color_interpolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation ) ) );
// _propmap.insert( std::make_pair( color_interpolation_filters.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation_filters ) ) );
// _propmap.insert( std::make_pair( solid_color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::solid_color ) ) );
// _propmap.insert( std::make_pair( solid_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::solid_opacity ) ) );
// _propmap.insert( std::make_pair( fill.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill ) ) );
// _propmap.insert( std::make_pair( fill_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill_opacity ) ) );
// _propmap.insert( std::make_pair( fill_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill_rule ) ) );
// _propmap.insert( std::make_pair( stroke.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke ) ) );
// _propmap.insert( std::make_pair( stroke_width.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_width ) ) );
// _propmap.insert( std::make_pair( stroke_linecap.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_linecap ) ) );
// _propmap.insert( std::make_pair( stroke_linejoin.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_linejoin ) ) );
// _propmap.insert( std::make_pair( stroke_miterlimit.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_miterlimit ) ) );
// _propmap.insert( std::make_pair( stroke_dasharray.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_dasharray ) ) );
// _propmap.insert( std::make_pair( stroke_dashoffset.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_dashoffset ) ) );
// _propmap.insert( std::make_pair( stroke_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_opacity ) ) );
// _propmap.insert( std::make_pair( marker.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker ) ) );
// _propmap.insert( std::make_pair( marker_start.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_start ) ) );
// _propmap.insert( std::make_pair( marker_mid.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_mid ) ) );
// _propmap.insert( std::make_pair( marker_end.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_end ) ) );
// _propmap.insert( std::make_pair( paint_order.name, reinterpret_cast<SPIBasePtr>(&SPStyle::paint_order ) ) );
// _propmap.insert( std::make_pair( filter.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter ) ) );
// _propmap.insert( std::make_pair( filter_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter_blend_mode ) ) );
// _propmap.insert( std::make_pair( filter_gaussianBlur_deviation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter_gaussianBlur_deviation ) ) );
// _propmap.insert( std::make_pair( color_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_rendering ) ) );
// _propmap.insert( std::make_pair( image_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::image_rendering ) ) );
// _propmap.insert( std::make_pair( shape_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::shape_rendering ) ) );
// _propmap.insert( std::make_pair( text_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_rendering ) ) );
// _propmap.insert( std::make_pair( enable_background.name, reinterpret_cast<SPIBasePtr>(&SPStyle::enable_background ) ) );
// }
}
SPStyle::~SPStyle() {
// std::cout << "SPStyle::~SPStyle" << std::endl;
--_count; // Poor man's memory leak detector.
// Remove connections
release_connection.disconnect();
fill_ps_changed_connection.disconnect();
stroke_ps_changed_connection.disconnect();
// The following shoud be moved into SPIPaint and SPIFilter
if (fill.value.href) {
fill_ps_modified_connection.disconnect();
}
if (stroke.value.href) {
stroke_ps_modified_connection.disconnect();
}
if (filter.href) {
filter_modified_connection.disconnect();
}
_properties.clear();
// Conjecture: all this SPStyle ref counting is not needed. SPObject creates an instance of
// SPStyle when it is constructed and deletes it when it is destructed. The refcount is
// incremented and decremented only in the files: display/drawing-item.cpp,
// display/nr-filter-primitive.cpp, and libnrtype/Layout-TNG-Input.cpp.
if( _refcount > 1 ) {
std::cerr << "SPStyle::~SPStyle: ref count greater than 1! " << _refcount << std::endl;
}
// std::cout << "SPStyle::~SPStyle(): Exit\n" << std::endl;
}
// Used in SPStyle::clear()
void clear_property( SPIBase* p ) {
p->clear();
}
// Matches void sp_style_clear();
void
SPStyle::clear() {
for_each( _properties.begin(), _properties.end(), clear_property );
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).clear();
// }
// Release connection to object, created in constructor.
release_connection.disconnect();
// href->detach() called in fill->clear()...
fill_ps_modified_connection.disconnect();
if (fill.value.href) {
delete fill.value.href;
fill.value.href = NULL;
}
stroke_ps_modified_connection.disconnect();
if (stroke.value.href) {
delete stroke.value.href;
stroke.value.href = NULL;
}
filter_modified_connection.disconnect();
if (filter.href) {
delete filter.href;
filter.href = NULL;
}
if (document) {
filter.href = new SPFilterReference(document);
filter.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), this));
fill.value.href = new SPPaintServerReference(document);
fill_ps_changed_connection = fill.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), this));
stroke.value.href = new SPPaintServerReference(document);
stroke_ps_changed_connection = stroke.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), this));
}
cloned = false;
}
// Matches void sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
void
SPStyle::read( SPObject *object, Inkscape::XML::Node *repr ) {
// std::cout << "SPstyle::read( SPObject, Inkscape::XML::Node ): Entrance: "
// << (object?(object->getId()?object->getId():"id null"):"object null") << " "
// << (repr?(repr->name()?repr->name():"no name"):"repr null")
// << std::endl;
g_assert(repr != NULL);
g_assert(!object || (object->getRepr() == repr));
// // Uncomment to verify that we don't need to call clear.
// std::cout << " Creating temp style for testing" << std::endl;
// SPStyle *temp = new SPStyle();
// if( !(*temp == *this ) ) std::cout << "SPStyle::read: Need to clear" << std::endl;
// delete temp;
clear(); // FIXME, If this isn't here, gradient editing stops working. Why?
if (object && object->cloned) {
cloned = true;
}
/* 1. Style attribute */
// std::cout << " MERGING STYLE ATTRIBUTE" << std::endl;
gchar const *val = repr->attribute("style");
if( val != NULL && *val ) {
_mergeString( val );
}
/* 2 Style sheet */
// std::cout << " MERGING OBJECT STYLESHEET" << std::endl;
if (object) {
_mergeObjectStylesheet( object );
} else {
// std::cerr << "SPStyle::read: No object! Can not read style sheet" << std::endl;
}
/* 3 Presentation attributes */
// std::cout << " MERGING PRESENTATION ATTRIBUTES" << std::endl;
for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
// Shorthands are not allowed as presentation properites. Note: text-decoration and
// font-variant are converted to shorthands in CSS 3 but can still be read as a
// non-shorthand for compatability with older renders, so they should not be in this list.
// We could add a flag to SPIBase to avoid string comparison.
if( _properties[i]->name.compare( "font" ) != 0 &&
_properties[i]->name.compare( "marker" ) != 0 ) {
_properties[i]->readAttribute( repr );
}
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).readAttribute( repr );
// }
/* 4 Cascade from parent */
// std::cout << " CASCADING FROM PARENT" << std::endl;
if( object ) {
if( object->parent ) {
cascade( object->parent->style );
}
} else {
// When does this happen?
// std::cout << "SPStyle::read(): reading via repr->parent()" << std::endl;
if( repr->parent() ) {
SPStyle *parent = new SPStyle();
parent->read( NULL, repr->parent() );
cascade( parent );
delete parent;
}
}
}
/**
* Read style properties from object's repr.
*
* 1. Reset existing object style
* 2. Load current effective object style
* 3. Load i attributes from immediate parent (which has to be up-to-date)
*/
void
SPStyle::readFromObject( SPObject *object ) {
// std::cout << "SPStyle::readFromObject: "<< (object->getId()?object->getId():"null")<< std::endl;
g_return_if_fail(object != NULL);
g_return_if_fail(SP_IS_OBJECT(object));
Inkscape::XML::Node *repr = object->getRepr();
g_return_if_fail(repr != NULL);
read( object, repr );
}
/**
* Read style properties from preferences.
* @param path Preferences directory from which the style should be read
*/
void
SPStyle::readFromPrefs(Glib::ustring const &path) {
g_return_if_fail(!path.empty());
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
// not optimal: we reconstruct the node based on the prefs, then pass it to
// sp_style_read for actual processing.
Inkscape::XML::SimpleDocument *tempdoc = new Inkscape::XML::SimpleDocument;
Inkscape::XML::Node *tempnode = tempdoc->createElement("prefs");
std::vector<Inkscape::Preferences::Entry> attrs = prefs->getAllEntries(path);
for (std::vector<Inkscape::Preferences::Entry>::iterator i = attrs.begin(); i != attrs.end(); ++i) {
tempnode->setAttribute(i->getEntryName().data(), i->getString().data());
}
read( NULL, tempnode );
Inkscape::GC::release(tempnode);
Inkscape::GC::release(tempdoc);
delete tempdoc;
}
// Matches sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
void
SPStyle::readIfUnset( gint id, gchar const *val ) {
// std::cout << "SPStyle::readIfUnset: Entrance: " << (val?val:"null") << std::endl;
// To Do: If it is not too slow, use std::map instead of std::vector inorder to remove switch()
// (looking up SP_PROP_xxxx already uses a hash).
g_return_if_fail(val != NULL);
switch (id) {
case SP_PROP_INKSCAPE_FONT_SPEC:
font_specification.readIfUnset( val );
break;
case SP_PROP_FONT_FAMILY:
font_family.readIfUnset( val );
break;
case SP_PROP_FONT_SIZE:
font_size.readIfUnset( val );
break;
case SP_PROP_FONT_SIZE_ADJUST:
if (strcmp(val, "none") != 0) {
g_warning("Unimplemented style property id SP_PROP_FONT_SIZE_ADJUST: value: %s", val);
}
break;
case SP_PROP_FONT_STYLE:
font_style.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT:
font_variant.readIfUnset( val );
break;
case SP_PROP_FONT_WEIGHT:
font_weight.readIfUnset( val );
break;
case SP_PROP_FONT_STRETCH:
font_stretch.readIfUnset( val );
break;
case SP_PROP_FONT:
font.readIfUnset( val );
break;
/* Font Variants CSS 3 */
case SP_PROP_FONT_VARIANT_LIGATURES:
font_variant_ligatures.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT_POSITION:
font_variant_position.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT_CAPS:
font_variant_caps.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT_NUMERIC:
font_variant_numeric.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT_ALTERNATES:
font_variant_alternates.readIfUnset( val );
break;
case SP_PROP_FONT_VARIANT_EAST_ASIAN:
font_variant_east_asian.readIfUnset( val );
break;
case SP_PROP_FONT_FEATURE_SETTINGS:
font_feature_settings.readIfUnset( val );
break;
/* Text */
case SP_PROP_TEXT_INDENT:
text_indent.readIfUnset( val );
break;
case SP_PROP_TEXT_ALIGN:
text_align.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION:
text_decoration.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION_LINE:
text_decoration_line.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION_STYLE:
text_decoration_style.readIfUnset( val );
break;
case SP_PROP_TEXT_DECORATION_COLOR:
text_decoration_color.readIfUnset( val );
break;
case SP_PROP_LINE_HEIGHT:
line_height.readIfUnset( val );
break;
case SP_PROP_LETTER_SPACING:
letter_spacing.readIfUnset( val );
break;
case SP_PROP_WORD_SPACING:
word_spacing.readIfUnset( val );
break;
case SP_PROP_TEXT_TRANSFORM:
text_transform.readIfUnset( val );
break;
/* Text (css3) */
case SP_PROP_DIRECTION:
direction.readIfUnset( val );
break;
case SP_PROP_BLOCK_PROGRESSION:
block_progression.readIfUnset( val );
break;
case SP_PROP_WRITING_MODE:
writing_mode.readIfUnset( val );
break;
case SP_PROP_TEXT_ANCHOR:
text_anchor.readIfUnset( val );
break;
case SP_PROP_WHITE_SPACE:
white_space.readIfUnset( val );
break;
case SP_PROP_SHAPE_INSIDE:
shape_inside.readIfUnset( val );
break;
case SP_PROP_SHAPE_PADDING:
shape_padding.readIfUnset( val );
break;
case SP_PROP_BASELINE_SHIFT:
baseline_shift.readIfUnset( val );
break;
case SP_PROP_TEXT_RENDERING:
text_rendering.readIfUnset( val );
break;
case SP_PROP_ALIGNMENT_BASELINE:
g_warning("Unimplemented style property SP_PROP_ALIGNMENT_BASELINE: value: %s", val);
break;
case SP_PROP_DOMINANT_BASELINE:
g_warning("Unimplemented style property SP_PROP_DOMINANT_BASELINE: value: %s", val);
break;
case SP_PROP_GLYPH_ORIENTATION_HORIZONTAL:
g_warning("Unimplemented style property SP_PROP_ORIENTATION_HORIZONTAL: value: %s", val);
break;
case SP_PROP_GLYPH_ORIENTATION_VERTICAL:
g_warning("Unimplemented style property SP_PROP_ORIENTATION_VERTICAL: value: %s", val);
break;
case SP_PROP_KERNING:
g_warning("Unimplemented style property SP_PROP_KERNING: value: %s", val);
break;
/* Misc */
case SP_PROP_CLIP:
g_warning("Unimplemented style property SP_PROP_CLIP: value: %s", val);
break;
case SP_PROP_COLOR:
color.readIfUnset( val );
break;
case SP_PROP_CURSOR:
g_warning("Unimplemented style property SP_PROP_CURSOR: value: %s", val);
break;
case SP_PROP_DISPLAY:
display.readIfUnset( val );
break;
case SP_PROP_OVERFLOW:
overflow.readIfUnset( val );
break;
case SP_PROP_VISIBILITY:
visibility.readIfUnset( val );
break;
case SP_PROP_ISOLATION:
isolation.readIfUnset( val );
break;
case SP_PROP_MIX_BLEND_MODE:
mix_blend_mode.readIfUnset( val );
break;
/* SVG */
/* Clip/Mask */
case SP_PROP_CLIP_PATH:
/** \todo
* This is a workaround. Inkscape only supports 'clip-path' as SVG attribute, not as
* style property. By having both CSS and SVG attribute set, editing of clip-path
* will fail, since CSS always overwrites SVG attributes.
* Fixes Bug #324849
*/
g_warning("attribute 'clip-path' given as CSS");
//XML Tree being directly used here.
this->object->getRepr()->setAttribute("clip-path", val);
break;
case SP_PROP_CLIP_RULE:
clip_rule.readIfUnset( val );
break;
case SP_PROP_MASK:
/** \todo
* See comment for SP_PROP_CLIP_PATH
*/
g_warning("attribute 'mask' given as CSS");
//XML Tree being directly used here.
this->object->getRepr()->setAttribute("mask", val);
break;
case SP_PROP_OPACITY:
opacity.readIfUnset( val );
break;
case SP_PROP_ENABLE_BACKGROUND:
enable_background.readIfUnset( val );
break;
/* Filter */
case SP_PROP_FILTER:
if( !filter.inherit ) filter.readIfUnset( val );
break;
case SP_PROP_FLOOD_COLOR:
g_warning("Unimplemented style property SP_PROP_FLOOD_COLOR: value: %s", val);
break;
case SP_PROP_FLOOD_OPACITY:
g_warning("Unimplemented style property SP_PROP_FLOOD_OPACITY: value: %s", val);
break;
case SP_PROP_LIGHTING_COLOR:
g_warning("Unimplemented style property SP_PROP_LIGHTING_COLOR: value: %s", val);
break;
/* Gradient */
case SP_PROP_STOP_COLOR:
g_warning("Unimplemented style property SP_PROP_STOP_COLOR: value: %s", val);
break;
case SP_PROP_STOP_OPACITY:
g_warning("Unimplemented style property SP_PROP_STOP_OPACITY: value: %s", val);
break;
/* Interactivity */
case SP_PROP_POINTER_EVENTS:
g_warning("Unimplemented style property SP_PROP_POINTER_EVENTS: value: %s", val);
break;
/* Paint */
case SP_PROP_COLOR_INTERPOLATION:
// We read it but issue warning
color_interpolation.readIfUnset( val );
if( color_interpolation.value != SP_CSS_COLOR_INTERPOLATION_SRGB ) {
g_warning("Inkscape currently only supports color-interpolation = sRGB");
}
break;
case SP_PROP_COLOR_INTERPOLATION_FILTERS:
color_interpolation_filters.readIfUnset( val );
break;
case SP_PROP_COLOR_PROFILE:
g_warning("Unimplemented style property SP_PROP_COLOR_PROFILE: value: %s", val);
break;
case SP_PROP_COLOR_RENDERING:
color_rendering.readIfUnset( val );
break;
case SP_PROP_SOLID_COLOR:
solid_color.readIfUnset( val );
break;
case SP_PROP_SOLID_OPACITY:
solid_opacity.readIfUnset( val );
break;
case SP_PROP_FILL:
fill.readIfUnset( val );
break;
case SP_PROP_FILL_OPACITY:
fill_opacity.readIfUnset( val );
break;
case SP_PROP_FILL_RULE:
fill_rule.readIfUnset( val );
break;
case SP_PROP_IMAGE_RENDERING:
image_rendering.readIfUnset( val );
break;
case SP_PROP_MARKER:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
marker.readIfUnset( val );
break;
case SP_PROP_MARKER_START:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
marker_start.readIfUnset( val );
break;
case SP_PROP_MARKER_MID:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
marker_mid.readIfUnset( val );
break;
case SP_PROP_MARKER_END:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
marker_end.readIfUnset( val );
break;
case SP_PROP_SHAPE_RENDERING:
shape_rendering.readIfUnset( val );
break;
case SP_PROP_STROKE:
stroke.readIfUnset( val );
break;
case SP_PROP_STROKE_WIDTH:
stroke_width.readIfUnset( val );
break;
case SP_PROP_STROKE_DASHARRAY:
stroke_dasharray.readIfUnset( val );
break;
case SP_PROP_STROKE_DASHOFFSET:
stroke_dashoffset.readIfUnset( val );
break;
case SP_PROP_STROKE_LINECAP:
stroke_linecap.readIfUnset( val );
break;
case SP_PROP_STROKE_LINEJOIN:
stroke_linejoin.readIfUnset( val );
break;
case SP_PROP_STROKE_MITERLIMIT:
stroke_miterlimit.readIfUnset( val );
break;
case SP_PROP_STROKE_OPACITY:
stroke_opacity.readIfUnset( val );
break;
case SP_PROP_PAINT_ORDER:
paint_order.readIfUnset( val );
break;
default:
g_warning("SPIStyle::readIfUnset(): Invalid style property id: %d value: %s", id, val);
break;
}
}
/**
* Outputs the style to a CSS string.
*
* Use with SP_STYLE_FLAG_ALWAYS for copying an object's complete cascaded style to
* style_clipboard.
*
* Use with SP_STYLE_FLAG_IFDIFF and a pointer to the parent class when you need a CSS string for
* an object in the document tree.
*
* \pre flags in {IFSET, ALWAYS, IFDIFF}.
* \pre base.
* \post ret != NULL.
*/
Glib::ustring
SPStyle::write( guint const flags, SPStyle const *const base ) const {
// std::cout << "SPStyle::write" << std::endl;
Glib::ustring style_string;
for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
if( base != NULL ) {
style_string += _properties[i]->write( flags, base->_properties[i] );
} else {
style_string += _properties[i]->write( flags, NULL );
}
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// if( base != NULL ) {
// style_string += (this->*(i->second)).write( flags, &(base->*(i->second)) );
// } else {
// style_string += (this->*(i->second)).write( flags, NULL );
// }
// }
// Remove trailing ';'
if( style_string.size() > 0 ) {
style_string.erase( style_string.size() - 1 );
}
return style_string;
}
// Corresponds to sp_style_merge_from_parent()
/**
* Sets computed values in \a style, which may involve inheriting from (or in some other way
* calculating from) corresponding computed values of \a parent.
*
* References: http://www.w3.org/TR/SVG11/propidx.html shows what properties inherit by default.
* http://www.w3.org/TR/SVG11/styling.html#Inheritance gives general rules as to what it means to
* inherit a value. http://www.w3.org/TR/REC-CSS2/cascade.html#computed-value is more precise
* about what the computed value is (not obvious for lengths).
*
* \pre \a parent's computed values are already up-to-date.
*/
void
SPStyle::cascade( SPStyle const *const parent ) {
// std::cout << "SPStyle::cascade: " << (object->getId()?object->getId():"null") << std::endl;
for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
_properties[i]->cascade( parent->_properties[i] );
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).cascade( &(parent->*(i->second)) );
// }
}
// Corresponds to sp_style_merge_from_dying_parent()
/**
* Combine \a style and \a parent style specifications into a single style specification that
* preserves (as much as possible) the effect of the existing \a style being a child of \a parent.
*
* Called when the parent repr is to be removed (e.g. the parent is a \<use\> element that is being
* unlinked), in which case we copy/adapt property values that are explicitly set in \a parent,
* trying to retain the same visual appearance once the parent is removed. Interesting cases are
* when there is unusual interaction with the parent's value (opacity, display) or when the value
* can be specified as relative to the parent computed value (font-size, font-weight etc.).
*
* Doesn't update computed values of \a style. For correctness, you should subsequently call
* sp_style_merge_from_parent against the new parent (presumably \a parent's parent) even if \a
* style was previously up-to-date wrt \a parent.
*
* \pre \a parent's computed values are already up-to-date.
* (\a style's computed values needn't be up-to-date.)
*/
void
SPStyle::merge( SPStyle const *const parent ) {
// std::cout << "SPStyle::merge" << std::endl;
for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
_properties[i]->merge( parent->_properties[i] );
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).cascade( &(parent->*(i->second)) );
// }
}
/**
* Parses a style="..." string and merges it with an existing SPStyle.
*/
void
SPStyle::mergeString( gchar const *const p ) {
_mergeString( p );
}
// Mostly for unit testing
bool
SPStyle::operator==(const SPStyle& rhs) {
// Uncomment for testing
// for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
// if( *_properties[i] != *rhs._properties[i])
// std::cout << _properties[i]->name << ": "
// << _properties[i]->write(SP_STYLE_FLAG_ALWAYS,NULL) << " "
// << rhs._properties[i]->write(SP_STYLE_FLAG_ALWAYS,NULL)
// << (*_properties[i] == *rhs._properties[i]) << std::endl;
// }
for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
if( *_properties[i] != *rhs._properties[i]) return false;
}
return true;
}
void
SPStyle::_mergeString( gchar const *const p ) {
// std::cout << "SPStyle::_mergeString: " << (p?p:"null") << std::endl;
CRDeclaration *const decl_list
= cr_declaration_parse_list_from_buf(reinterpret_cast<guchar const *>(p), CR_UTF_8);
if (decl_list) {
_mergeDeclList( decl_list );
cr_declaration_destroy(decl_list);
}
}
void
SPStyle::_mergeDeclList( CRDeclaration const *const decl_list ) {
// std::cout << "SPStyle::_mergeDeclList" << std::endl;
// In reverse order, as later declarations to take precedence over earlier ones.
// (Properties are only set if not previously set. See:
// Ref: http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order point 4.)
if (decl_list->next) {
_mergeDeclList( decl_list->next );
}
_mergeDecl( decl_list );
}
void
SPStyle::_mergeDecl( CRDeclaration const *const decl ) {
// std::cout << "SPStyle::_mergeDecl" << std::endl;
unsigned const prop_idx = sp_attribute_lookup(decl->property->stryng->str);
if (prop_idx != SP_ATTR_INVALID) {
/** \todo
* effic: Test whether the property is already set before trying to
* convert to string. Alternatively, set from CRTerm directly rather
* than converting to string.
*/
guchar *const str_value_unsigned = cr_term_to_string(decl->value);
gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned);
readIfUnset( prop_idx, str_value );
g_free(str_value);
}
}
void
SPStyle::_mergeProps( CRPropList *const props ) {
// std::cout << "SPStyle::_mergeProps" << std::endl;
// In reverse order, as later declarations to take precedence over earlier ones.
if (props) {
_mergeProps( cr_prop_list_get_next( props ) );
CRDeclaration *decl = NULL;
cr_prop_list_get_decl(props, &decl);
_mergeDecl( decl );
}
}
void
SPStyle::_mergeObjectStylesheet( SPObject const *const object ) {
// std::cout << "SPStyle::_mergeObjectStylesheet: " << (object->getId()?object->getId():"null") << std::endl;
static CRSelEng *sel_eng = NULL;
if (!sel_eng) {
sel_eng = sp_repr_sel_eng();
}
CRPropList *props = NULL;
//XML Tree being directly used here while it shouldn't be.
CRStatus status = cr_sel_eng_get_matched_properties_from_cascade(sel_eng,
object->document->style_cascade,
object->getRepr(),
&props);
g_return_if_fail(status == CR_OK);
/// \todo Check what errors can occur, and handle them properly.
if (props) {
_mergeProps(props);
cr_prop_list_destroy(props);
}
}
// Internal
/**
* Release callback.
*/
static void
sp_style_object_release(SPObject *object, SPStyle *style)
{
(void)object; // TODO
style->object = NULL;
}
// Internal
/**
* Emit style modified signal on style's object if the filter changed.
*/
static void
sp_style_filter_ref_modified(SPObject *obj, guint flags, SPStyle *style)
{
(void)flags; // TODO
SPFilter *filter=static_cast<SPFilter *>(obj);
if (style->getFilter() == filter)
{
if (style->object) {
style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
}
}
// Internal
/**
* Gets called when the filter is (re)attached to the style
*/
void
sp_style_filter_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
{
if (old_ref) {
(dynamic_cast<SPFilter *>( old_ref ))->_refcount--;
style->filter_modified_connection.disconnect();
}
if ( SP_IS_FILTER(ref))
{
(dynamic_cast<SPFilter *>( ref ))->_refcount++;
style->filter_modified_connection =
ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_filter_ref_modified), style));
}
sp_style_filter_ref_modified(ref, 0, style);
}
/**
* Emit style modified signal on style's object if server is style's fill
* or stroke paint server.
*/
static void
sp_style_paint_server_ref_modified(SPObject *obj, guint flags, SPStyle *style)
{
(void)flags; // TODO
SPPaintServer *server = static_cast<SPPaintServer *>(obj);
if ((style->fill.isPaintserver())
&& style->getFillPaintServer() == server)
{
if (style->object) {
/** \todo
* fixme: I do not know, whether it is optimal - we are
* forcing reread of everything (Lauris)
*/
/** \todo
* fixme: We have to use object_modified flag, because parent
* flag is only available downstreams.
*/
style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
} else if ((style->stroke.isPaintserver())
&& style->getStrokePaintServer() == server)
{
if (style->object) {
/// \todo fixme:
style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
} else if (server) {
g_assert_not_reached();
}
}
/**
* Gets called when the paintserver is (re)attached to the style
*/
void
sp_style_fill_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
{
if (old_ref) {
style->fill_ps_modified_connection.disconnect();
}
if (SP_IS_PAINT_SERVER(ref)) {
style->fill_ps_modified_connection =
ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_paint_server_ref_modified), style));
}
style->signal_fill_ps_changed.emit(old_ref, ref);
sp_style_paint_server_ref_modified(ref, 0, style);
}
/**
* Gets called when the paintserver is (re)attached to the style
*/
void
sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
{
if (old_ref) {
style->stroke_ps_modified_connection.disconnect();
}
if (SP_IS_PAINT_SERVER(ref)) {
style->stroke_ps_modified_connection =
ref->connectModified(sigc::bind(sigc::ptr_fun(&sp_style_paint_server_ref_modified), style));
}
style->signal_stroke_ps_changed.emit(old_ref, ref);
sp_style_paint_server_ref_modified(ref, 0, style);
}
// Called in display/drawing-item.cpp, display/nr-filter-primitive.cpp, libnrtype/Layout-TNG-Input.cpp
/**
* Increase refcount of style.
*/
SPStyle *
sp_style_ref(SPStyle *style)
{
g_return_val_if_fail(style != NULL, NULL);
style->style_ref(); // Increase ref count
return style;
}
// Called in display/drawing-item.cpp, display/nr-filter-primitive.cpp, libnrtype/Layout-TNG-Input.cpp
/**
* Decrease refcount of style with possible destruction.
*/
SPStyle *
sp_style_unref(SPStyle *style)
{
g_return_val_if_fail(style != NULL, NULL);
if (style->style_unref() < 1) {
delete style;
return NULL;
}
return style;
}
static CRSelEng *
sp_repr_sel_eng()
{
CRSelEng *const ret = cr_sel_eng_new();
cr_sel_eng_set_node_iface(ret, &Inkscape::XML::croco_node_iface);
/** \todo
* Check whether we need to register any pseudo-class handlers.
* libcroco has its own default handlers for first-child and lang.
*
* We probably want handlers for link and arguably visited (though
* inkscape can't visit links at the time of writing). hover etc.
* more useful in inkview than the editor inkscape.
*
* http://www.w3.org/TR/SVG11/styling.html#StylingWithCSS says that
* the following should be honoured, at least by inkview:
* :hover, :active, :focus, :visited, :link.
*/
g_assert(ret);
return ret;
}
/** Indexed by SP_CSS_FONT_SIZE_blah. These seem a bit small */
static float const font_size_table[] = {6.0, 8.0, 10.0, 12.0, 14.0, 18.0, 24.0};
// The following functions should be incorporated into SPIPaint. FIXME
// Called in: style.cpp, style-internal.cpp
void
sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI *uri, SPDocument *document)
{
// std::cout << "sp_style_set_ipaint_to_uri: Entrance: " << uri << " " << (void*)document << std::endl;
// it may be that this style's SPIPaint has not yet created its URIReference;
// now that we have a document, we can create it here
if (!paint->value.href && document) {
paint->value.href = new SPPaintServerReference(document);
if (paint == &style->fill) {
style->fill_ps_changed_connection = paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), style));
} else {
style->stroke_ps_changed_connection = paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), style));
}
}
if (paint->value.href){
if (paint->value.href->getObject()){
paint->value.href->detach();
}
try {
paint->value.href->attach(*uri);
} catch (Inkscape::BadURIException &e) {
g_warning("%s", e.what());
paint->value.href->detach();
}
}
}
// Called in: style.cpp, style-internal.cpp
void
sp_style_set_ipaint_to_uri_string (SPStyle *style, SPIPaint *paint, const gchar *uri)
{
try {
const Inkscape::URI IURI(uri);
sp_style_set_ipaint_to_uri(style, paint, &IURI, style->document);
} catch (...) {
g_warning("URI failed to parse: %s", uri);
}
}
// Called in: desktop-style.cpp
void
sp_style_set_to_uri_string (SPStyle *style, bool isfill, const gchar *uri)
{
sp_style_set_ipaint_to_uri_string (style, isfill? &style->fill : &style->stroke, uri);
}
// Called in: widgets/font-selector.cpp, widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
gchar const *
sp_style_get_css_unit_string(int unit)
{
// specify px by default, see inkscape bug 1221626, mozilla bug 234789
switch (unit) {
case SP_CSS_UNIT_NONE: return "px";
case SP_CSS_UNIT_PX: return "px";
case SP_CSS_UNIT_PT: return "pt";
case SP_CSS_UNIT_PC: return "pc";
case SP_CSS_UNIT_MM: return "mm";
case SP_CSS_UNIT_CM: return "cm";
case SP_CSS_UNIT_IN: return "in";
case SP_CSS_UNIT_EM: return "em";
case SP_CSS_UNIT_EX: return "ex";
case SP_CSS_UNIT_PERCENT: return "%";
default: return "px";
}
return "px";
}
// Called in: style-internal.cpp, widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
/*
* Convert a size in pixels into another CSS unit size
*/
double
sp_style_css_size_px_to_units(double size, int unit)
{
double unit_size = size;
switch (unit) {
case SP_CSS_UNIT_NONE: unit_size = size; break;
case SP_CSS_UNIT_PX: unit_size = size; break;
case SP_CSS_UNIT_PT: unit_size = Inkscape::Util::Quantity::convert(size, "px", "pt"); break;
case SP_CSS_UNIT_PC: unit_size = Inkscape::Util::Quantity::convert(size, "px", "pc"); break;
case SP_CSS_UNIT_MM: unit_size = Inkscape::Util::Quantity::convert(size, "px", "mm"); break;
case SP_CSS_UNIT_CM: unit_size = Inkscape::Util::Quantity::convert(size, "px", "cm"); break;
case SP_CSS_UNIT_IN: unit_size = Inkscape::Util::Quantity::convert(size, "px", "in"); break;
case SP_CSS_UNIT_EM: unit_size = size / SP_CSS_FONT_SIZE_DEFAULT; break;
case SP_CSS_UNIT_EX: unit_size = size * 2.0 / SP_CSS_FONT_SIZE_DEFAULT ; break;
case SP_CSS_UNIT_PERCENT: unit_size = size * 100.0 / SP_CSS_FONT_SIZE_DEFAULT; break;
default:
g_warning("sp_style_get_css_font_size_units conversion to %d not implemented.", unit);
break;
}
return unit_size;
}
// Called in: widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
/*
* Convert a size in a CSS unit size to pixels
*/
double
sp_style_css_size_units_to_px(double size, int unit)
{
if (unit == SP_CSS_UNIT_PX) {
return size;
}
//g_message("sp_style_css_size_units_to_px %f %d = %f px", size, unit, out);
return size * (size / sp_style_css_size_px_to_units(size, unit));;
}
// FIXME: Everything below this line belongs in a different file - css-chemistry?
void
sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive)
{
Inkscape::XML::Node *repr = item->getRepr();
if (repr == NULL) return;
SPCSSAttr *css = sp_repr_css_attr_new();
if (linked) {
gchar *val = g_strdup_printf("url(#%s)", linked->getId());
sp_repr_css_set_property(css, property, val);
g_free(val);
} else {
sp_repr_css_unset_property(css, "filter");
}
if (recursive) {
sp_repr_css_change_recursive(repr, css, "style");
} else {
sp_repr_css_change(repr, css, "style");
}
sp_repr_css_attr_unref(css);
}
// Called in sp-object.cpp
/**
* Clear all style property attributes in object.
*/
void
sp_style_unset_property_attrs(SPObject *o)
{
if (!o) {
return;
}
SPStyle *style = o->style;
if (!style) {
return;
}
Inkscape::XML::Node *repr = o->getRepr();
if (!repr) {
return;
}
if (style->opacity.set) {
repr->setAttribute("opacity", NULL);
}
if (style->color.set) {
repr->setAttribute("color", NULL);
}
if (style->color_interpolation.set) {
repr->setAttribute("color-interpolation", NULL);
}
if (style->color_interpolation_filters.set) {
repr->setAttribute("color-interpolation-filters", NULL);
}
if (style->solid_color.set) {
repr->setAttribute("solid-color", NULL);
}
if (style->solid_opacity.set) {
repr->setAttribute("solid-opacity", NULL);
}
if (style->fill.set) {
repr->setAttribute("fill", NULL);
}
if (style->fill_opacity.set) {
repr->setAttribute("fill-opacity", NULL);
}
if (style->fill_rule.set) {
repr->setAttribute("fill-rule", NULL);
}
if (style->stroke.set) {
repr->setAttribute("stroke", NULL);
}
if (style->stroke_width.set) {
repr->setAttribute("stroke-width", NULL);
}
if (style->stroke_linecap.set) {
repr->setAttribute("stroke-linecap", NULL);
}
if (style->stroke_linejoin.set) {
repr->setAttribute("stroke-linejoin", NULL);
}
if (style->marker.set) {
repr->setAttribute("marker", NULL);
}
if (style->marker_start.set) {
repr->setAttribute("marker-start", NULL);
}
if (style->marker_mid.set) {
repr->setAttribute("marker-mid", NULL);
}
if (style->marker_end.set) {
repr->setAttribute("marker-end", NULL);
}
if (style->stroke_opacity.set) {
repr->setAttribute("stroke-opacity", NULL);
}
if (style->stroke_dasharray.set) {
repr->setAttribute("stroke-dasharray", NULL);
}
if (style->stroke_dashoffset.set) {
repr->setAttribute("stroke-dashoffset", NULL);
}
if (style->paint_order.set) {
repr->setAttribute("paint-order", NULL);
}
if (style->font_specification.set) {
repr->setAttribute("-inkscape-font-specification", NULL);
}
if (style->font_family.set) {
repr->setAttribute("font-family", NULL);
}
if (style->text_anchor.set) {
repr->setAttribute("text-anchor", NULL);
}
if (style->white_space.set) {
repr->setAttribute("white_space", NULL);
}
if (style->shape_inside.set) {
repr->setAttribute("shape_inside", NULL);
}
if (style->shape_padding.set) {
repr->setAttribute("shape_padding", NULL);
}
if (style->writing_mode.set) {
repr->setAttribute("writing_mode", NULL);
}
if (style->filter.set) {
repr->setAttribute("filter", NULL);
}
if (style->enable_background.set) {
repr->setAttribute("enable-background", NULL);
}
if (style->clip_rule.set) {
repr->setAttribute("clip-rule", NULL);
}
if (style->color_rendering.set) {
repr->setAttribute("color-rendering", NULL);
}
if (style->image_rendering.set) {
repr->setAttribute("image-rendering", NULL);
}
if (style->shape_rendering.set) {
repr->setAttribute("shape-rendering", NULL);
}
if (style->text_rendering.set) {
repr->setAttribute("text-rendering", NULL);
}
}
/**
* \pre style != NULL.
* \pre flags in {IFSET, ALWAYS}.
*/
SPCSSAttr *
sp_css_attr_from_style(SPStyle const *const style, guint const flags)
{
g_return_val_if_fail(style != NULL, NULL);
g_return_val_if_fail(((flags == SP_STYLE_FLAG_IFSET) ||
(flags == SP_STYLE_FLAG_ALWAYS) ),
NULL);
Glib::ustring style_str = style->write(flags);
SPCSSAttr *css = sp_repr_css_attr_new();
sp_repr_css_attr_add_from_string(css, style_str.c_str());
return css;
}
// Called in: selection-chemistry.cpp, widgets/stroke-marker-selector.cpp, widgets/stroke-style.cpp,
// ui/tools/freehand-base.cpp
/**
* \pre object != NULL
* \pre flags in {IFSET, ALWAYS}.
*/
SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint const flags)
{
g_return_val_if_fail(((flags == SP_STYLE_FLAG_IFSET) ||
(flags == SP_STYLE_FLAG_ALWAYS) ),
NULL);
SPCSSAttr * result = 0;
if (object->style) {
result = sp_css_attr_from_style(object->style, flags);
}
return result;
}
// Called in: selection-chemistry.cpp, ui/dialog/inkscape-preferences.cpp
/**
* Unset any text-related properties
*/
SPCSSAttr *
sp_css_attr_unset_text(SPCSSAttr *css)
{
sp_repr_css_set_property(css, "font", NULL);
sp_repr_css_set_property(css, "-inkscape-font-specification", NULL);
sp_repr_css_set_property(css, "font-size", NULL);
sp_repr_css_set_property(css, "font-size-adjust", NULL); // not implemented yet
sp_repr_css_set_property(css, "font-style", NULL);
sp_repr_css_set_property(css, "font-variant", NULL);
sp_repr_css_set_property(css, "font-weight", NULL);
sp_repr_css_set_property(css, "font-stretch", NULL);
sp_repr_css_set_property(css, "font-family", NULL);
sp_repr_css_set_property(css, "text-indent", NULL);
sp_repr_css_set_property(css, "text-align", NULL);
sp_repr_css_set_property(css, "line-height", NULL);
sp_repr_css_set_property(css, "letter-spacing", NULL);
sp_repr_css_set_property(css, "word-spacing", NULL);
sp_repr_css_set_property(css, "text-transform", NULL);
sp_repr_css_set_property(css, "direction", NULL);
sp_repr_css_set_property(css, "block-progression", NULL);
sp_repr_css_set_property(css, "writing-mode", NULL);
sp_repr_css_set_property(css, "text-anchor", NULL);
sp_repr_css_set_property(css, "white-space", NULL);
sp_repr_css_set_property(css, "shape-inside", NULL);
sp_repr_css_set_property(css, "shape-padding", NULL);
sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet
sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "baseline-shift", NULL);
sp_repr_css_set_property(css, "text-decoration", NULL);
sp_repr_css_set_property(css, "text-decoration-line", NULL);
sp_repr_css_set_property(css, "text-decoration-color", NULL);
sp_repr_css_set_property(css, "text-decoration-style", NULL);
sp_repr_css_set_property(css, "font-variant-ligatures", NULL);
sp_repr_css_set_property(css, "font-variant-position", NULL);
sp_repr_css_set_property(css, "font-variant-caps", NULL);
sp_repr_css_set_property(css, "font-variant-numeric", NULL);
sp_repr_css_set_property(css, "font-variant-alternates", NULL);
sp_repr_css_set_property(css, "font-variant-east-asian", NULL);
sp_repr_css_set_property(css, "font-feature-settings", NULL);
return css;
}
// ui/dialog/inkscape-preferences.cpp
/**
* Unset properties that should not be set for default tool style.
* This list needs to be reviewed.
*/
SPCSSAttr *
sp_css_attr_unset_blacklist(SPCSSAttr *css)
{
sp_repr_css_set_property(css, "color", NULL);
sp_repr_css_set_property(css, "clip-rule", NULL);
sp_repr_css_set_property(css, "display", NULL);
sp_repr_css_set_property(css, "overflow", NULL);
sp_repr_css_set_property(css, "visibility", NULL);
sp_repr_css_set_property(css, "isolation", NULL);
sp_repr_css_set_property(css, "mix-blend-mode", NULL);
sp_repr_css_set_property(css, "color-interpolation", NULL);
sp_repr_css_set_property(css, "color-interpolation-filters", NULL);
sp_repr_css_set_property(css, "solid-color", NULL);
sp_repr_css_set_property(css, "solid-opacity", NULL);
sp_repr_css_set_property(css, "fill-rule", NULL);
sp_repr_css_set_property(css, "filter-blend-mode", NULL);
sp_repr_css_set_property(css, "filter-gaussianBlur-deviation", NULL);
sp_repr_css_set_property(css, "color-rendering", NULL);
sp_repr_css_set_property(css, "image-rendering", NULL);
sp_repr_css_set_property(css, "shape-rendering", NULL);
sp_repr_css_set_property(css, "text-rendering", NULL);
sp_repr_css_set_property(css, "enable-background", NULL);
return css;
}
// Called in style.cpp
static bool
is_url(char const *p)
{
if (p == NULL)
return false;
/** \todo
* FIXME: I'm not sure if this applies to SVG as well, but CSS2 says any URIs
* in property values must start with 'url('.
*/
return (g_ascii_strncasecmp(p, "url(", 4) == 0);
}
// Called in: ui/dialog/inkscape-preferences.cpp, ui/tools/tweek-tool.cpp
/**
* Unset any properties that contain URI values.
*
* Used for storing style that will be reused across documents when carrying
* the referenced defs is impractical.
*/
SPCSSAttr *
sp_css_attr_unset_uris(SPCSSAttr *css)
{
// All properties that may hold <uri> or <paint> according to SVG 1.1
if (is_url(sp_repr_css_property(css, "clip-path", NULL))) sp_repr_css_set_property(css, "clip-path", NULL);
if (is_url(sp_repr_css_property(css, "color-profile", NULL))) sp_repr_css_set_property(css, "color-profile", NULL);
if (is_url(sp_repr_css_property(css, "cursor", NULL))) sp_repr_css_set_property(css, "cursor", NULL);
if (is_url(sp_repr_css_property(css, "filter", NULL))) sp_repr_css_set_property(css, "filter", NULL);
if (is_url(sp_repr_css_property(css, "marker", NULL))) sp_repr_css_set_property(css, "marker", NULL);
if (is_url(sp_repr_css_property(css, "marker-start", NULL))) sp_repr_css_set_property(css, "marker-start", NULL);
if (is_url(sp_repr_css_property(css, "marker-mid", NULL))) sp_repr_css_set_property(css, "marker-mid", NULL);
if (is_url(sp_repr_css_property(css, "marker-end", NULL))) sp_repr_css_set_property(css, "marker-end", NULL);
if (is_url(sp_repr_css_property(css, "mask", NULL))) sp_repr_css_set_property(css, "mask", NULL);
if (is_url(sp_repr_css_property(css, "fill", NULL))) sp_repr_css_set_property(css, "fill", NULL);
if (is_url(sp_repr_css_property(css, "stroke", NULL))) sp_repr_css_set_property(css, "stroke", NULL);
return css;
}
// Called in style.cpp
/**
* Scale a single-value property.
*/
static void
sp_css_attr_scale_property_single(SPCSSAttr *css, gchar const *property,
double ex, bool only_with_units = false)
{
gchar const *w = sp_repr_css_property(css, property, NULL);
if (w) {
gchar *units = NULL;
double wd = g_ascii_strtod(w, &units) * ex;
if (w == units) {// nothing converted, non-numeric value
return;
}
if (only_with_units && (units == NULL || *units == '\0' || *units == '%')) {
// only_with_units, but no units found, so do nothing.
return;
}
Inkscape::CSSOStringStream os;
os << wd << units; // reattach units
sp_repr_css_set_property(css, property, os.str().c_str());
}
}
// Called in style.cpp for stroke-dasharray
/**
* Scale a list-of-values property.
*/
static void
sp_css_attr_scale_property_list(SPCSSAttr *css, gchar const *property, double ex)
{
gchar const *string = sp_repr_css_property(css, property, NULL);
if (string) {
Inkscape::CSSOStringStream os;
gchar **a = g_strsplit(string, ",", 10000);
bool first = true;
for (gchar **i = a; i != NULL; i++) {
gchar *w = *i;
if (w == NULL)
break;
gchar *units = NULL;
double wd = g_ascii_strtod(w, &units) * ex;
if (w == units) {// nothing converted, non-numeric value ("none" or "inherit"); do nothing
g_strfreev(a);
return;
}
if (!first) {
os << ",";
}
os << wd << units; // reattach units
first = false;
}
sp_repr_css_set_property(css, property, os.str().c_str());
g_strfreev(a);
}
}
// Called in: text-editing.cpp,
/**
* Scale any properties that may hold <length> by ex.
*/
SPCSSAttr *
sp_css_attr_scale(SPCSSAttr *css, double ex)
{
sp_css_attr_scale_property_single(css, "baseline-shift", ex);
sp_css_attr_scale_property_single(css, "stroke-width", ex);
sp_css_attr_scale_property_list (css, "stroke-dasharray", ex);
sp_css_attr_scale_property_single(css, "stroke-dashoffset", ex);
sp_css_attr_scale_property_single(css, "font-size", ex);
sp_css_attr_scale_property_single(css, "kerning", ex);
sp_css_attr_scale_property_single(css, "letter-spacing", ex);
sp_css_attr_scale_property_single(css, "word-spacing", ex);
sp_css_attr_scale_property_single(css, "line-height", ex, true);
return css;
}
/**
* Quote and/or escape string for writing to CSS, changing strings in place.
* See: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
*/
void
css_quote(Glib::ustring &val)
{
Glib::ustring out;
bool quote = false;
// Can't wait for C++11!
for( Glib::ustring::iterator it = val.begin(); it != val.end(); ++it) {
if(g_ascii_isalnum(*it) || *it=='-' || *it=='_' || *it > 0xA0) {
out += *it;
} else if (*it == '\'') {
// Single quotes require escaping and quotes.
out += '\\';
out += *it;
quote = true;
} else {
// Quote everything else including spaces.
// (CSS Fonts Level 3 recommends quoting with spaces.)
out += *it;
quote = true;
}
if( it == val.begin() && !g_ascii_isalpha(*it) ) {
// A non-ASCII/non-alpha initial value on any indentifier needs quotes.
// (Actually it's a bit more complicated but as it never hurts to quote...)
quote = true;
}
}
if( quote ) {
out.insert( out.begin(), '\'' );
out += '\'';
}
val = out;
}
/**
* Quote font names in font-family lists, changing string in place.
* We use unquoted names internally but some need to be quoted in CSS.
*/
void
css_font_family_quote(Glib::ustring &val)
{
std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", val );
val.erase();
for( unsigned i=0; i < tokens.size(); ++i ) {
css_quote( tokens[i] );
val += tokens[i] + ", ";
}
if( val.size() > 1 )
val.erase( val.size() - 2 ); // Remove trailing ", "
}
// Called in style-internal.cpp, xml/repr-css.cpp
/**
* Remove paired single and double quotes from a string, changing string in place.
*/
void
css_unquote(Glib::ustring &val)
{
if( val.size() > 1 &&
( (val[0] == '"' && val[val.size()-1] == '"' ) ||
(val[0] == '\'' && val[val.size()-1] == '\'' ) ) ) {
val.erase( 0, 1 );
val.erase( val.size()-1 );
}
}
// Called in style-internal.cpp, text-toolbar.cpp
/**
* Remove paired single and double quotes from font names in font-family lists,
* changing string in place.
* We use unquoted family names internally but CSS sometimes uses quoted names.
*/
void
css_font_family_unquote(Glib::ustring &val)
{
std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", val );
val.erase();
for( unsigned i=0; i < tokens.size(); ++i ) {
css_unquote( tokens[i] );
val += tokens[i] + ", ";
}
if( val.size() > 1 )
val.erase( val.size() - 2 ); // Remove trailing ", "
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :