X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fstyle.cpp;h=2a0a30bd165b91fb4b12171307aa3bb3463b90da;hb=2c9c6838241516364d68db0d30520e18f70fc70d;hp=3baa1678be88fc24c5b326cd551f1ddf60175287;hpb=bc0b620d60a93261a2faa0fc1a383f9c16b71c0b;p=inkscape.git diff --git a/src/style.cpp b/src/style.cpp index 3baa1678b..2a0a30bd1 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -24,6 +24,7 @@ #include "svg/svg.h" #include "svg/svg-color.h" +#include "svg/svg-icc-color.h" #include "display/canvas-bpath.h" #include "attributes.h" @@ -40,6 +41,9 @@ #include "unit-constants.h" #include "isnan.h" +using Inkscape::CSSOStringStream; +using std::vector; + namespace Inkscape { /** @@ -148,7 +152,7 @@ static gint sp_style_write_itextdecoration(gchar *p, gint const len, gchar const static void css2_unescape_unquote(SPIString *val); -static void sp_style_paint_clear(SPStyle *style, SPIPaint *paint, unsigned hunref, unsigned unset); +static void sp_style_paint_clear(SPStyle *style, SPIPaint *paint); #define SPS_READ_IENUM_IF_UNSET(v,s,d,i) if (!(v)->set) {sp_style_read_ienum((v), (s), (d), (i));} #define SPS_READ_PENUM_IF_UNSET(v,r,k,d,i) if (!(v)->set) {sp_style_read_penum((v), (r), (k), (d), (i));} @@ -390,8 +394,12 @@ sp_style_new() sp_style_clear(style); style->cloned = false; - style->hreffed = false; - style->listening = false; + + style->fill_hreffed = false; + style->stroke_hreffed = false; + + style->fill_listening = false; + style->stroke_listening = false; return style; } @@ -449,8 +457,8 @@ sp_style_unref(SPStyle *style) g_signal_handlers_disconnect_matched(G_OBJECT(style->object), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, style); if (style->text) sp_text_style_unref(style->text); - sp_style_paint_clear(style, &style->fill, TRUE, FALSE); - sp_style_paint_clear(style, &style->stroke, TRUE, FALSE); + sp_style_paint_clear(style, &style->fill); + sp_style_paint_clear(style, &style->stroke); g_free(style->stroke_dash.dash); g_free(style); } @@ -1930,13 +1938,13 @@ sp_style_paint_server_release(SPPaintServer *server, SPStyle *style) if ((style->fill.type == SP_PAINT_TYPE_PAINTSERVER) && (server == style->fill.value.paint.server)) { - sp_style_paint_clear(style, &style->fill, TRUE, FALSE); + sp_style_paint_clear(style, &style->fill); } if ((style->stroke.type == SP_PAINT_TYPE_PAINTSERVER) && (server == style->stroke.value.paint.server)) { - sp_style_paint_clear(style, &style->stroke, TRUE, FALSE); + sp_style_paint_clear(style, &style->stroke); } } @@ -1984,7 +1992,7 @@ sp_style_paint_server_modified(SPPaintServer *server, guint flags, SPStyle *styl static void sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent) { - sp_style_paint_clear(style, paint, TRUE, FALSE); + sp_style_paint_clear(style, paint); if ((paint->set && paint->currentcolor) || parent->currentcolor) { paint->currentcolor = TRUE; @@ -2003,15 +2011,25 @@ sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent) paint->value.paint.uri = parent->value.paint.uri; if (paint->value.paint.server) { if (style->object && !style->cloned) { // href paintserver for style of non-clones only - style->hreffed = true; sp_object_href(SP_OBJECT(paint->value.paint.server), style); + if (paint == &style->fill) { + style->fill_hreffed = true; + } else { + assert(paint == &style->stroke); + style->stroke_hreffed = true; + } } if (style->object || style->cloned) { // connect to signals for style of real objects or clones (this excludes temp styles) g_signal_connect(G_OBJECT(paint->value.paint.server), "release", G_CALLBACK(sp_style_paint_server_release), style); g_signal_connect(G_OBJECT(paint->value.paint.server), "modified", G_CALLBACK(sp_style_paint_server_modified), style); - style->listening = true; + if (paint == &style->fill) { + style->fill_listening = true; + } else { + assert(paint == &style->stroke); + style->stroke_listening = true; + } } } break; @@ -2288,8 +2306,8 @@ sp_style_clear(SPStyle *style) { g_return_if_fail(style != NULL); - sp_style_paint_clear(style, &style->fill, TRUE, FALSE); - sp_style_paint_clear(style, &style->stroke, TRUE, FALSE); + sp_style_paint_clear(style, &style->fill); + sp_style_paint_clear(style, &style->stroke); if (style->stroke_dash.dash) { g_free(style->stroke_dash.dash); } @@ -2820,6 +2838,8 @@ sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume /** * Set SPIPaint object from string. + * + * \pre paint == \&style.fill || paint == \&style.stroke. */ static void sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document) @@ -2832,16 +2852,16 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume paint->set = TRUE; paint->inherit = TRUE; paint->currentcolor = FALSE; - } else if (streq(str, "currentColor")) { + } else if (streq(str, "currentColor") && paint != &style->color) { paint->set = TRUE; paint->inherit = FALSE; paint->currentcolor = TRUE; - } else if (streq(str, "none")) { + } else if (streq(str, "none") && paint != &style->color) { paint->type = SP_PAINT_TYPE_NONE; paint->set = TRUE; paint->inherit = FALSE; paint->currentcolor = FALSE; - } else if (strneq(str, "url", 3)) { + } else if (strneq(str, "url", 3) && paint != &style->color) { // this is alloc'd uri, but seems to be shared with a parent // potentially, so it's not any easy g_free case... paint->value.paint.uri = extract_uri(str); @@ -2859,27 +2879,49 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume paint->value.paint.server = SP_PAINT_SERVER(ps); if (style->object && !style->cloned) { sp_object_href(SP_OBJECT(paint->value.paint.server), style); - style->hreffed = true; + if (paint == &style->fill) { + style->fill_hreffed = true; + } else { + assert(paint == &style->stroke); + style->stroke_hreffed = true; + } } if (style->object || style->cloned) { g_signal_connect(G_OBJECT(paint->value.paint.server), "release", G_CALLBACK(sp_style_paint_server_release), style); g_signal_connect(G_OBJECT(paint->value.paint.server), "modified", G_CALLBACK(sp_style_paint_server_modified), style); - style->listening = true; + if (paint == &style->fill) { + style->fill_listening = true; + } else { + assert(paint == &style->stroke); + style->stroke_listening = true; + } } } else { paint->value.paint.server = NULL; } } } else { - guint32 const rgb0 = sp_svg_read_color(str, 0xff); + guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff); if (rgb0 != 0xff) { paint->type = SP_PAINT_TYPE_COLOR; sp_color_set_rgb_rgba32(&paint->value.color, rgb0); paint->set = TRUE; paint->inherit = FALSE; paint->currentcolor = FALSE; + + while (g_ascii_isspace(*str)) { + ++str; + } + if (strneq(str, "icc-color(", 10)) { + SVGICCColor* tmp = new SVGICCColor(); + if ( ! sp_svg_read_icc_color( str, &str, tmp ) ) { + delete tmp; + tmp = 0; + } + paint->iccColor = tmp; + } } } } @@ -3299,7 +3341,13 @@ sp_paint_differ(SPIPaint const *const a, SPIPaint const *const b) if (a->type != b->type) return true; if (a->type == SP_PAINT_TYPE_COLOR) - return !sp_color_is_equal(&a->value.color, &b->value.color); + return !(sp_color_is_equal(&a->value.color, &b->value.color) + && ((a->iccColor == b->iccColor) + || (a->iccColor && b->iccColor + && (a->iccColor->colorProfile == b->iccColor->colorProfile) + && (a->iccColor->colors == b->iccColor->colors)))); + /* todo: Allow for epsilon differences in iccColor->colors, e.g. changes small enough not to show up + * in the string representation. */ if (a->type == SP_PAINT_TYPE_PAINTSERVER) return (a->value.paint.server != b->value.paint.server); return false; @@ -3325,12 +3373,25 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key, return g_snprintf(b, len, "%s:currentColor;", key); } else { switch (paint->type) { - case SP_PAINT_TYPE_COLOR: - return g_snprintf(b, len, "%s:#%06x;", key, sp_color_get_rgba32_falpha(&paint->value.color, 0.0) >> 8); - break; + case SP_PAINT_TYPE_COLOR: { + char color_buf[8]; + sp_svg_write_color(color_buf, sizeof(color_buf), sp_color_get_rgba32_ualpha(&paint->value.color, 0)); + if (paint->iccColor) { + CSSOStringStream css; + css << color_buf << " icc-color(" << paint->iccColor->colorProfile; + for (vector::const_iterator i(paint->iccColor->colors.begin()), + iEnd(paint->iccColor->colors.end()); + i != iEnd; ++i) { + css << ", " << *i; + } + css << ')'; + return g_snprintf(b, len, "%s:%s;", key, css.gcharp()); + } else { + return g_snprintf(b, len, "%s:%s;", key, color_buf); + } + } case SP_PAINT_TYPE_PAINTSERVER: return g_snprintf(b, len, "%s:url(%s);", key, paint->value.paint.uri); - break; default: break; } @@ -3396,31 +3457,41 @@ sp_style_write_ifontsize(gchar *p, gint const len, gchar const *key, /** - * Clear paint object; conditionally disconnect style from paintserver. + * Clear paint object, and disconnect style from paintserver (if present). */ static void -sp_style_paint_clear(SPStyle *style, SPIPaint *paint, - unsigned hunref, unsigned unset) +sp_style_paint_clear(SPStyle *style, SPIPaint *paint) { - if (hunref && (paint->type == SP_PAINT_TYPE_PAINTSERVER) && paint->value.paint.server) { - if (style->hreffed) { - sp_object_hunref(SP_OBJECT(paint->value.paint.server), style); - style->hreffed = false; - } - if (style->listening) { - g_signal_handlers_disconnect_matched(G_OBJECT(paint->value.paint.server), + if ((paint->type == SP_PAINT_TYPE_PAINTSERVER) && paint->value.paint.server) { + if (paint == &style->fill) { + if (style->fill_hreffed) { + sp_object_hunref(SP_OBJECT(paint->value.paint.server), style); + style->fill_hreffed = false; + } + if (style->fill_listening) { + g_signal_handlers_disconnect_matched(G_OBJECT(paint->value.paint.server), + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, style); + style->fill_listening = false; + } + } else { + assert(paint == &style->stroke); // Only fill & stroke can have a paint server. + if (style->stroke_hreffed) { + sp_object_hunref(SP_OBJECT(paint->value.paint.server), style); + style->stroke_hreffed = false; + } + if (style->stroke_listening) { + g_signal_handlers_disconnect_matched(G_OBJECT(paint->value.paint.server), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, style); - style->listening = false; + style->stroke_listening = false; + } } - paint->value.paint.server = NULL; - paint->value.paint.uri = NULL; - paint->type = SP_PAINT_TYPE_NONE; - } - if (unset) { - paint->set = FALSE; - paint->inherit = FALSE; + paint->value.paint.server = NULL; } + paint->value.paint.uri = NULL; + paint->type = SP_PAINT_TYPE_NONE; + delete paint->iccColor; + paint->iccColor = NULL; } /**