X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsp-gradient.cpp;h=d5a733b4ff4c452b796e2508c928116ec2d533b0;hb=724821145d62dee9f97465c706952582da6e432d;hp=c2b0b32a3cb881169f6562a13d5ef59e649f38ea;hpb=f951374eef04129c6a0d213e7ab4d9ed2095ca69;p=inkscape.git diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index c2b0b32a3..d5a733b4f 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -26,9 +26,12 @@ #include #include "libnr/nr-scale-translate-ops.h" +#include +#include #include "display/nr-gradient-gpl.h" #include "svg/svg.h" +#include "svg/svg-color.h" #include "svg/css-ostringstream.h" #include "attributes.h" #include "document-private.h" @@ -181,7 +184,7 @@ sp_stop_set(SPObject *object, unsigned key, gchar const *value) } case SP_ATTR_OFFSET: { stop->offset = sp_svg_read_percentage(value, 0.0); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); break; } default: { @@ -201,9 +204,16 @@ sp_stop_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) SPStop *stop = SP_STOP(object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = sp_repr_new("svg:stop"); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object)); + repr = xml_doc->createElement("svg:stop"); } + if (((SPObjectClass *) stop_parent_class)->write) + (* ((SPObjectClass *) stop_parent_class)->write)(object, repr, flags); + + // Since we do a hackish style setting here (because SPStyle does not support stop-color and + // stop-opacity), we must do it AFTER calling the parent write method; otherwise + // sp_object_write would clear our style= attribute (bug 1695287) Inkscape::CSSOStringStream os; os << "stop-color:"; @@ -222,9 +232,6 @@ sp_stop_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) /* strictly speaking, offset an SVG rather than a CSS one, but exponents make no sense * for offset proportions. */ - if (((SPObjectClass *) stop_parent_class)->write) - (* ((SPObjectClass *) stop_parent_class)->write)(object, repr, flags); - return repr; } @@ -301,6 +308,9 @@ static void sp_gradient_rebuild_vector(SPGradient *gr); static void gradient_ref_changed(SPObject *old_ref, SPObject *ref, SPGradient *gradient); +SPGradientSpread sp_gradient_get_spread(SPGradient *gradient); +SPGradientUnits sp_gradient_get_units(SPGradient *gradient); + static SPPaintServerClass *gradient_parent_class; /** @@ -376,6 +386,8 @@ sp_gradient_init(SPGradient *gr) gr->vector.stops.clear(); gr->color = NULL; + + new (&gr->modified_connection) sigc::connection(); } /** @@ -424,9 +436,7 @@ sp_gradient_release(SPObject *object) } if (gradient->ref) { - if (gradient->ref->getObject()) { - sp_signal_disconnect_by_data(gradient->ref->getObject(), gradient); - } + gradient->modified_connection.disconnect(); gradient->ref->detach(); delete gradient->ref; gradient->ref = NULL; @@ -437,6 +447,8 @@ sp_gradient_release(SPObject *object) gradient->color = NULL; } + gradient->modified_connection.~connection(); + if (((SPObjectClass *) gradient_parent_class)->release) ((SPObjectClass *) gradient_parent_class)->release(object); } @@ -517,13 +529,23 @@ static void gradient_ref_changed(SPObject *old_ref, SPObject *ref, SPGradient *gr) { if (old_ref) { - sp_signal_disconnect_by_data(old_ref, gr); + gr->modified_connection.disconnect(); } if ( SP_IS_GRADIENT(ref) && ref != gr ) { - g_signal_connect(G_OBJECT(ref), "modified", G_CALLBACK(gradient_ref_modified), gr); + gr->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&gradient_ref_modified), gr)); } + + // Per SVG, all unset attributes must be inherited from linked gradient. + // So, as we're now (re)linked, we assign linkee's values to this gradient if they are not yet set - + // but without setting the _set flags. + // FIXME: do the same for gradientTransform too + if (!gr->units_set) + gr->units = sp_gradient_get_units (gr); + if (!gr->spread_set) + gr->spread = sp_gradient_get_spread (gr); + /// \todo Fixme: what should the flags (second) argument be? */ gradient_ref_modified(ref, 0, gr); } @@ -588,6 +610,10 @@ sp_gradient_modified(SPObject *object, guint flags) sp_gradient_invalidate_vector(gr); } + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + sp_gradient_ensure_colors(gr); + } + if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; flags &= SP_OBJECT_MODIFIED_CASCADE; @@ -651,12 +677,9 @@ sp_gradient_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) } if ((flags & SP_OBJECT_WRITE_ALL) || gr->gradientTransform_set) { - gchar c[256]; - if (sp_svg_transform_write(c, 256, gr->gradientTransform)) { - repr->setAttribute("gradientTransform", c); - } else { - repr->setAttribute("gradientTransform", NULL); - } + gchar *c=sp_svg_transform_write(gr->gradientTransform); + repr->setAttribute("gradientTransform", c); + g_free(c); } if ((flags & SP_OBJECT_WRITE_ALL) || gr->spread_set) { @@ -781,6 +804,15 @@ has_spread_set(SPGradient const *gr) return gr->spread_set; } +/** + * True if gradient has units set. + */ +static bool +has_units_set(SPGradient const *gr) +{ + return gr->units_set; +} + /** * Returns private vector of given gradient (the gradient at the end of the href chain which has @@ -817,6 +849,23 @@ sp_gradient_get_spread(SPGradient *gradient) : SP_GRADIENT_SPREAD_PAD ); // pad is the default } +/** + * Returns the effective units of given gradient (climbing up the refs chain if needed). + * + * \pre SP_IS_GRADIENT(gradient). + */ +SPGradientUnits +sp_gradient_get_units(SPGradient *gradient) +{ + g_return_val_if_fail(SP_IS_GRADIENT(gradient), SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX); + + SPGradient const *src = chase_hrefs(gradient, has_units_set); + return ( src + ? src->units + : SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ); // bbox is the default +} + + /** * Clears the gradient's svg:stop children from its repr. */ @@ -853,6 +902,7 @@ sp_gradient_repr_write_vector(SPGradient *gr) g_return_if_fail(gr != NULL); g_return_if_fail(SP_IS_GRADIENT(gr)); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(gr)); Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); /* We have to be careful, as vector may be our own, so construct repr list at first */ @@ -860,7 +910,7 @@ sp_gradient_repr_write_vector(SPGradient *gr) for (guint i = 0; i < gr->vector.stops.size(); i++) { Inkscape::CSSOStringStream os; - Inkscape::XML::Node *child = sp_repr_new("svg:stop"); + Inkscape::XML::Node *child = xml_doc->createElement("svg:stop"); sp_repr_set_css_double(child, "offset", gr->vector.stops[i].offset); /* strictly speaking, offset an SVG rather than a CSS one, but exponents make no * sense for offset proportions. */ @@ -1229,7 +1279,7 @@ sp_gradient_set_gs2d_matrix(SPGradient *gr, NR::Matrix const &ctm, NR::Rect const &bbox, NR::Matrix const &gs2d) { gr->gradientTransform = gs2d / ctm; - if ( gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ) { + if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ) { gr->gradientTransform = ( gr->gradientTransform / NR::translate(bbox.min()) / NR::scale(bbox.dimensions()) ); @@ -1382,7 +1432,8 @@ sp_lineargradient_write(SPObject *object, Inkscape::XML::Node *repr, guint flags SPLinearGradient *lg = SP_LINEARGRADIENT(object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = sp_repr_new("svg:linearGradient"); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object)); + repr = xml_doc->createElement("svg:linearGradient"); } if ((flags & SP_OBJECT_WRITE_ALL) || lg->x1._set) @@ -1683,7 +1734,8 @@ sp_radialgradient_write(SPObject *object, Inkscape::XML::Node *repr, guint flags SPRadialGradient *rg = SP_RADIALGRADIENT(object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = sp_repr_new("svg:radialGradient"); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object)); + repr = xml_doc->createElement("svg:radialGradient"); } if ((flags & SP_OBJECT_WRITE_ALL) || rg->cx._set) sp_repr_set_svg_double(repr, "cx", rg->cx.computed);