X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fstyle.cpp;h=dd81692823123f0b45c055ebe1da5f0cb3af22ca;hb=411c17ba01c3d854de288448bbbfdd14c9035afa;hp=a50fedf6b673ec6abcb842c92d0d518abb5d020a;hpb=e2cb7cee0660082e1650f1725bb5c54c7b75cd50;p=inkscape.git diff --git a/src/style.cpp b/src/style.cpp index a50fedf6b..dd8169282 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -1,9 +1,9 @@ #define __SP_STYLE_C__ -/** \file - * SVG stylesheets implementation. - * - * Authors: +/** @file + * @brief SVG stylesheets implementation. + */ +/* Authors: * Lauris Kaplinski * Peter Moulder * bulia byak @@ -41,9 +41,11 @@ #include "style.h" #include "svg/css-ostringstream.h" #include "xml/repr.h" +#include "xml/simple-document.h" #include "unit-constants.h" -#include "isnan.h" +#include "2geom/isnan.h" #include "macros.h" +#include "preferences.h" #include "sp-filter-reference.h" @@ -790,15 +792,33 @@ sp_style_read_from_object(SPStyle *style, SPObject *object) /** - * Read style properties from repr only. + * Read style properties from preferences. + * @param style The style to write to + * @param path Preferences directory from which the style should be read */ void -sp_style_read_from_repr(SPStyle *style, Inkscape::XML::Node *repr) +sp_style_read_from_prefs(SPStyle *style, Glib::ustring const &path) { g_return_if_fail(style != NULL); - g_return_if_fail(repr != NULL); + g_return_if_fail(path != ""); + + 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("temp"); + + std::vector attrs = prefs->getAllEntries(path); + for (std::vector::iterator i = attrs.begin(); i != attrs.end(); ++i) { + tempnode->setAttribute(i->getEntryName().data(), i->getString().data()); + } - sp_style_read(style, NULL, repr); + sp_style_read(style, NULL, tempnode); + + Inkscape::GC::release(tempnode); + Inkscape::GC::release(tempdoc); + delete tempdoc; } @@ -974,13 +994,24 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) /* SVG */ /* Clip/Mask */ case SP_PROP_CLIP_PATH: - g_warning("Unimplemented style property SP_PROP_CLIP_PATH: value: %s", val); + /** \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"); + style->object->repr->setAttribute("clip-path", val); break; case SP_PROP_CLIP_RULE: g_warning("Unimplemented style property SP_PROP_CLIP_RULE: value: %s", val); break; case SP_PROP_MASK: - g_warning("Unimplemented style property SP_PROP_MASK: value: %s", val); + /** \todo + * See comment for SP_PROP_CLIP_PATH + */ + g_warning("attribute 'mask' given as CSS"); + style->object->repr->setAttribute("mask", val); break; case SP_PROP_OPACITY: if (!style->opacity.set) { @@ -1582,7 +1613,7 @@ sp_style_merge_paint_prop_from_dying_parent(SPStyle *style, * I haven't given this much attention. See comments below about * currentColor, colorProfile, and relative URIs. */ - if (!child.set || child.inherit || child.currentcolor) { + if (!child.set || child.inherit) { sp_style_merge_ipaint(style, &child, &parent); child.set = parent.set; child.inherit = parent.inherit; @@ -1672,7 +1703,7 @@ sp_style_merge_length_prop_from_dying_parent(LengthT &child, LengthT const &pare * fixme: Have separate ex ratio parameter. * Get x height from libnrtype or pango. */ - if (!isFinite(child.value)) { + if (!IS_FINITE(child.value)) { child.value = child.computed; child.unit = SP_CSS_UNIT_NONE; } @@ -2016,9 +2047,6 @@ sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const pare if (!style->filter.set || style->filter.inherit) { - // FIXME: - // instead of just copying over, we need to _really merge_ the two filters by combining their - // filter primitives sp_style_merge_ifilter(style, &parent->filter); } @@ -2108,8 +2136,12 @@ sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI static void sp_style_set_ipaint_to_uri_string (SPStyle *style, SPIPaint *paint, const gchar *uri) { - const Inkscape::URI IURI(uri); - sp_style_set_ipaint_to_uri(style, paint, &IURI, style->document); + 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); + } } void @@ -2125,7 +2157,9 @@ static void sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent) { if ((paint->set && paint->currentcolor) || parent->currentcolor) { + bool isset = paint->set; paint->clear(); + paint->set = isset; paint->currentcolor = TRUE; paint->setColor(style->color.value.color); return; @@ -2140,6 +2174,8 @@ sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent) } } else if ( parent->isColor() ) { paint->setColor( parent->value.color ); + } else if ( parent->isNoneSet() ) { + paint->noneSet = TRUE; } else if ( parent->isNone() ) { // } else { @@ -2155,6 +2191,10 @@ sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent) static void sp_style_merge_ifilter(SPStyle *style, SPIFilter const *parent) { + // FIXME: + // instead of just copying over, we need to _really merge_ the two filters by combining their + // filter primitives + sp_style_filter_clear(style); style->filter.set = parent->set; style->filter.inherit = parent->inherit; @@ -2162,7 +2202,13 @@ sp_style_merge_ifilter(SPStyle *style, SPIFilter const *parent) if (style->filter.href && style->filter.href->getObject()) style->filter.href->detach(); - if (style->filter.href && parent->href) { + // it may be that this style has not yet created its SPFilterReference + if (!style->filter.href && style->object && SP_OBJECT_DOCUMENT(style->object)) { + style->filter.href = new SPFilterReference(SP_OBJECT_DOCUMENT(style->object)); + style->filter.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style)); + } + + if (style->filter.href && parent->href && parent->href->getObject()) { try { style->filter.href->attach(*parent->href->getURI()); } catch (Inkscape::BadURIException &e) { @@ -2219,8 +2265,14 @@ sp_style_write_string(SPStyle const *const style, guint const flags) p += sp_style_write_ienum(p, c + BMAX - p, "text-anchor", enum_text_anchor, &style->text_anchor, NULL, flags); /// \todo fixme: Per type methods need default flag too (lauris) - p += sp_style_write_iscale24(p, c + BMAX - p, "opacity", &style->opacity, NULL, flags); - p += sp_style_write_ipaint(p, c + BMAX - p, "color", &style->color, NULL, flags); + + if (style->opacity.value != SP_SCALE24_MAX) { + p += sp_style_write_iscale24(p, c + BMAX - p, "opacity", &style->opacity, NULL, flags); + } + + if (!style->color.noneSet) { // CSS does not permit "none" for color + p += sp_style_write_ipaint(p, c + BMAX - p, "color", &style->color, NULL, flags); + } p += sp_style_write_ipaint(p, c + BMAX - p, "fill", &style->fill, NULL, flags); // if fill:none, skip writing fill properties @@ -2231,9 +2283,17 @@ sp_style_write_string(SPStyle const *const style, guint const flags) p += sp_style_write_ipaint(p, c + BMAX - p, "stroke", &style->stroke, NULL, flags); + // stroke width affects markers, so write it if there's stroke OR any markers + if (!style->stroke.noneSet || + style->marker[SP_MARKER_LOC].set || + style->marker[SP_MARKER_LOC_START].set || + style->marker[SP_MARKER_LOC_MID].set || + style->marker[SP_MARKER_LOC_END].set) { + p += sp_style_write_ilength(p, c + BMAX - p, "stroke-width", &style->stroke_width, NULL, flags); + } + // if stroke:none, skip writing stroke properties if (!style->stroke.noneSet) { - p += sp_style_write_ilength(p, c + BMAX - p, "stroke-width", &style->stroke_width, NULL, flags); p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linecap", enum_stroke_linecap, &style->stroke_linecap, NULL, flags); p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linejoin", enum_stroke_linejoin, &style->stroke_linejoin, NULL, flags); p += sp_style_write_ifloat(p, c + BMAX - p, "stroke-miterlimit", &style->stroke_miterlimit, NULL, flags); @@ -2274,24 +2334,30 @@ sp_style_write_string(SPStyle const *const style, guint const flags) } } + bool marker_none = false; + gchar *master = style->marker[SP_MARKER_LOC].value; if (style->marker[SP_MARKER_LOC].set) { p += g_snprintf(p, c + BMAX - p, "marker:%s;", style->marker[SP_MARKER_LOC].value); } else if (flags == SP_STYLE_FLAG_ALWAYS) { p += g_snprintf(p, c + BMAX - p, "marker:none;"); + marker_none = true; } - if (style->marker[SP_MARKER_LOC_START].set) { + if (style->marker[SP_MARKER_LOC_START].set + && (!master || strcmp(master, style->marker[SP_MARKER_LOC_START].value))) { p += g_snprintf(p, c + BMAX - p, "marker-start:%s;", style->marker[SP_MARKER_LOC_START].value); - } else if (flags == SP_STYLE_FLAG_ALWAYS) { + } else if (flags == SP_STYLE_FLAG_ALWAYS && !marker_none) { p += g_snprintf(p, c + BMAX - p, "marker-start:none;"); } - if (style->marker[SP_MARKER_LOC_MID].set) { + if (style->marker[SP_MARKER_LOC_MID].set + && (!master || strcmp(master, style->marker[SP_MARKER_LOC_MID].value))) { p += g_snprintf(p, c + BMAX - p, "marker-mid:%s;", style->marker[SP_MARKER_LOC_MID].value); - } else if (flags == SP_STYLE_FLAG_ALWAYS) { + } else if (flags == SP_STYLE_FLAG_ALWAYS && !marker_none) { p += g_snprintf(p, c + BMAX - p, "marker-mid:none;"); } - if (style->marker[SP_MARKER_LOC_END].set) { + if (style->marker[SP_MARKER_LOC_END].set + && (!master || strcmp(master, style->marker[SP_MARKER_LOC_END].value))) { p += g_snprintf(p, c + BMAX - p, "marker-end:%s;", style->marker[SP_MARKER_LOC_END].value); - } else if (flags == SP_STYLE_FLAG_ALWAYS) { + } else if (flags == SP_STYLE_FLAG_ALWAYS && !marker_none) { p += g_snprintf(p, c + BMAX - p, "marker-end:none;"); } @@ -2362,7 +2428,10 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to) if (from->opacity.set && from->opacity.value != SP_SCALE24_MAX) { p += sp_style_write_iscale24(p, c + BMAX - p, "opacity", &from->opacity, &to->opacity, SP_STYLE_FLAG_IFSET); } - p += sp_style_write_ipaint(p, c + BMAX - p, "color", &from->color, &to->color, SP_STYLE_FLAG_IFSET); + + if (!from->color.noneSet) { // CSS does not permit "none" for color + p += sp_style_write_ipaint(p, c + BMAX - p, "color", &from->color, &to->color, SP_STYLE_FLAG_IFSET); + } p += sp_style_write_ipaint(p, c + BMAX - p, "fill", &from->fill, &to->fill, SP_STYLE_FLAG_IFDIFF); // if fill:none, skip writing fill properties @@ -2372,9 +2441,18 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to) } p += sp_style_write_ipaint(p, c + BMAX - p, "stroke", &from->stroke, &to->stroke, SP_STYLE_FLAG_IFDIFF); + + // stroke width affects markers, so write it if there's stroke OR any markers + if (!from->stroke.noneSet || + from->marker[SP_MARKER_LOC].set || + from->marker[SP_MARKER_LOC_START].set || + from->marker[SP_MARKER_LOC_MID].set || + from->marker[SP_MARKER_LOC_END].set) { + p += sp_style_write_ilength(p, c + BMAX - p, "stroke-width", &from->stroke_width, &to->stroke_width, SP_STYLE_FLAG_IFDIFF); + } + // if stroke:none, skip writing stroke properties if (!from->stroke.noneSet) { - p += sp_style_write_ilength(p, c + BMAX - p, "stroke-width", &from->stroke_width, &to->stroke_width, SP_STYLE_FLAG_IFDIFF); p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linecap", enum_stroke_linecap, &from->stroke_linecap, &to->stroke_linecap, SP_STYLE_FLAG_IFDIFF); p += sp_style_write_ienum(p, c + BMAX - p, "stroke-linejoin", enum_stroke_linejoin, @@ -2408,16 +2486,17 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to) } /* markers */ - if (from->marker[SP_MARKER_LOC].value != NULL) { - p += g_snprintf(p, c + BMAX - p, "marker:%s;", from->marker[SP_MARKER_LOC].value); + gchar *master = from->marker[SP_MARKER_LOC].value; + if (master != NULL) { + p += g_snprintf(p, c + BMAX - p, "marker:%s;", master); } - if (from->marker[SP_MARKER_LOC_START].value != NULL) { + if (from->marker[SP_MARKER_LOC_START].value != NULL && (!master || strcmp(master, from->marker[SP_MARKER_LOC_START].value))) { p += g_snprintf(p, c + BMAX - p, "marker-start:%s;", from->marker[SP_MARKER_LOC_START].value); } - if (from->marker[SP_MARKER_LOC_MID].value != NULL) { + if (from->marker[SP_MARKER_LOC_MID].value != NULL && (!master || strcmp(master, from->marker[SP_MARKER_LOC_MID].value))) { p += g_snprintf(p, c + BMAX - p, "marker-mid:%s;", from->marker[SP_MARKER_LOC_MID].value); } - if (from->marker[SP_MARKER_LOC_END].value != NULL) { + if (from->marker[SP_MARKER_LOC_END].value != NULL && (!master || strcmp(master, from->marker[SP_MARKER_LOC_END].value))) { p += g_snprintf(p, c + BMAX - p, "marker-end:%s;", from->marker[SP_MARKER_LOC_END].value); } @@ -2463,12 +2542,18 @@ sp_style_clear(SPStyle *style) style->stroke.clear(); sp_style_filter_clear(style); - if (style->fill.value.href) + if (style->fill.value.href) { delete style->fill.value.href; - if (style->stroke.value.href) + style->fill.value.href = NULL; + } + if (style->stroke.value.href) { delete style->stroke.value.href; - if (style->filter.href) + style->stroke.value.href = NULL; + } + if (style->filter.href) { delete style->filter.href; + style->filter.href = NULL; + } if (style->stroke_dash.dash) { g_free(style->stroke_dash.dash); @@ -3016,6 +3101,7 @@ sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume guint32 const rgb0 = sp_svg_read_color(str, 0xff); if (rgb0 != 0xff) { paint->setColor(rgb0); + paint->set = TRUE; paint->inherit = FALSE; } } @@ -3361,8 +3447,10 @@ sp_style_write_istring(gchar *p, gint const len, gchar const *const key, return g_snprintf(p, len, "%s:inherit;", key); } else { gchar *val_quoted = css2_escape_quote(val->value); - return g_snprintf(p, len, "%s:%s;", key, val_quoted); - g_free (val_quoted); + if (val_quoted) { + return g_snprintf(p, len, "%s:%s;", key, val_quoted); + g_free (val_quoted); + } } } return 0; @@ -3626,7 +3714,7 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key, css << "currentColor"; } - if ( paint->colorSet ) { + if ( paint->colorSet && !paint->currentcolor ) { if ( !css.str().empty() ) { css << " "; } @@ -3635,7 +3723,7 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key, css << color_buf; } - if (paint->value.color.icc) { + if (paint->value.color.icc && !paint->currentcolor) { if ( !css.str().empty() ) { css << " "; } @@ -3772,13 +3860,15 @@ sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *link if (repr == NULL) return; - g_return_if_fail(linked != NULL); - - gchar *val = g_strdup_printf("url(#%s)", SP_OBJECT_ID(linked)); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, property, val); - g_free(val); + if (linked) { + gchar *val = g_strdup_printf("url(#%s)", SP_OBJECT_ID(linked)); + 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 { @@ -3965,6 +4055,7 @@ sp_css_attr_unset_uris(SPCSSAttr *css) 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);