From 37e32e5ce4110ec15974e0e9c225a334056c19ee Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Jul 2010 02:34:22 -0700 Subject: [PATCH] Create only single-stop gradients when using Fill-n-Stroke to convert solid to a swatch. Preserve CMS colors. --- src/desktop-style.cpp | 26 +++++++++++-- src/gradient-chemistry.cpp | 75 ++++++++++++++++---------------------- src/gradient-chemistry.h | 5 +-- src/widgets/fill-style.cpp | 18 +++++---- 4 files changed, 67 insertions(+), 57 deletions(-) diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index 26f29d172..e11fa1493 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -436,6 +436,20 @@ stroke_average_width (GSList const *objects) return avgwidth / (g_slist_length ((GSList *) objects) - n_notstroked); } +static bool vectorsClose( std::vector const &lhs, std::vector const &rhs ) +{ + static double epsilon = 1e-6; + bool isClose = false; + if ( lhs.size() == rhs.size() ) { + isClose = true; + for ( size_t i = 0; (i < lhs.size()) && isClose; ++i ) { + isClose = fabs(lhs[i] - rhs[i]) < epsilon; + } + } + return isClose; +} + + /** * Write to style_res the average fill or stroke of list of objects, if applicable. */ @@ -536,11 +550,15 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill iccColor = paint->value.color.icc; iccSeen = true; } else { - if (same_color && (prev[0] != d[0] || prev[1] != d[1] || prev[2] != d[2])) + if (same_color && (prev[0] != d[0] || prev[1] != d[1] || prev[2] != d[2])) { same_color = false; - if ( iccSeen ) { - if(paint->value.color.icc) { - // TODO fix this + iccColor = 0; + } + if ( iccSeen && iccColor ) { + if ( !paint->value.color.icc + || (iccColor->colorProfile != paint->value.color.icc->colorProfile) + || !vectorsClose(iccColor->colors, paint->value.color.icc->colors) ) { + same_color = false; iccColor = 0; } } diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 979b53f1b..4df25aab4 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -1144,15 +1144,29 @@ static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *lin } } + +static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gint opacity, gchar const *offset ) +{ + Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); + { + gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%d;", color.c_str(), opacity ); + stop->setAttribute( "style", tmp ); + g_free(tmp); + } + + stop->setAttribute( "offset", offset ); + + parent->appendChild(stop); + Inkscape::GC::release(stop); +} + /* * Get default normalized gradient vector of document, create if there is none */ - -SPGradient * -sp_document_default_gradient_vector(SPDocument *document, guint32 color) +SPGradient *sp_document_default_gradient_vector( SPDocument *document, SPColor const &color, bool singleStop ) { - SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document); - Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document); + SPDefs *defs = static_cast(SP_DOCUMENT_DEFS(document)); + Inkscape::XML::Document *xml_doc = document->rdoc; Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient"); @@ -1162,41 +1176,17 @@ sp_document_default_gradient_vector(SPDocument *document, guint32 color) // (1) here, search gradients by color and return what is found without duplication // (2) in fill & stroke, show only one copy of each gradient in list - Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); - - gchar b[64]; - sp_svg_write_color(b, sizeof(b), color); - - { - gchar *t = g_strdup_printf("stop-color:%s;stop-opacity:1;", b); - stop->setAttribute("style", t); - g_free(t); + Glib::ustring colorStr = color.toString(); + addStop( repr, colorStr, 1, "0" ); + if ( !singleStop ) { + addStop( repr, colorStr, 0, "1" ); } - stop->setAttribute("offset", "0"); - - repr->appendChild(stop); - Inkscape::GC::release(stop); - - stop = xml_doc->createElement("svg:stop"); - - { - gchar *t = g_strdup_printf("stop-color:%s;stop-opacity:0;", b); - stop->setAttribute("style", t); - g_free(t); - } - - stop->setAttribute("offset", "1"); - - repr->appendChild(stop); - Inkscape::GC::release(stop); - SP_OBJECT_REPR(defs)->addChild(repr, NULL); Inkscape::GC::release(repr); /* fixme: This does not look like nice */ - SPGradient *gr; - gr = (SPGradient *) document->getObjectByRepr(repr); + SPGradient *gr = static_cast(document->getObjectByRepr(repr)); g_assert(gr != NULL); g_assert(SP_IS_GRADIENT(gr)); /* fixme: Maybe add extra sanity check here */ @@ -1209,13 +1199,12 @@ sp_document_default_gradient_vector(SPDocument *document, guint32 color) Return the preferred vector for \a o, made from (in order of preference) its current vector, current fill or stroke color, or from desktop style if \a o is NULL or doesn't have style. */ -SPGradient * -sp_gradient_vector_for_object(SPDocument *const doc, SPDesktop *const desktop, - SPObject *const o, bool const is_fill) +SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *const desktop, + SPObject *const o, bool const is_fill, bool singleStop ) { - guint32 rgba = 0; + SPColor color; if (o == NULL || SP_OBJECT_STYLE(o) == NULL) { - rgba = sp_desktop_get_color(desktop, is_fill); + color = sp_desktop_get_color(desktop, is_fill); } else { // take the color of the object SPStyle const &style = *SP_OBJECT_STYLE(o); @@ -1227,17 +1216,17 @@ sp_gradient_vector_for_object(SPDocument *const doc, SPDesktop *const desktop, if (SP_IS_GRADIENT (server)) { return SP_GRADIENT(server)->getVector(true); } else { - rgba = sp_desktop_get_color(desktop, is_fill); + color = sp_desktop_get_color(desktop, is_fill); } } else if (paint.isColor()) { - rgba = paint.value.color.toRGBA32( 0xff ); + color = paint.value.color; } else { // if o doesn't use flat color, then take current color of the desktop. - rgba = sp_desktop_get_color(desktop, is_fill); + color = sp_desktop_get_color(desktop, is_fill); } } - return sp_document_default_gradient_vector(doc, rgba); + return sp_document_default_gradient_vector( doc, color, singleStop ); } diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h index 3f72fa394..0c8d0afe7 100644 --- a/src/gradient-chemistry.h +++ b/src/gradient-chemistry.h @@ -42,9 +42,8 @@ SPGradient *sp_item_set_gradient (SPItem *item, SPGradient *gr, SPGradientType t /* * Get default normalized gradient vector of document, create if there is none */ - -SPGradient *sp_document_default_gradient_vector (SPDocument *document, guint32 color = 0); -SPGradient *sp_gradient_vector_for_object (SPDocument *doc, SPDesktop *desktop, SPObject *o, bool is_fill); +SPGradient *sp_document_default_gradient_vector( SPDocument *document, SPColor const &color, bool singleStop ); +SPGradient *sp_gradient_vector_for_object( SPDocument *doc, SPDesktop *desktop, SPObject *o, bool is_fill, bool singleStop = false ); void sp_object_ensure_fill_gradient_normalized (SPObject *object); void sp_object_ensure_stroke_gradient_normalized (SPObject *object); diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index f1342f3de..19b8448c6 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -523,6 +523,7 @@ void FillNStroke::updateFromPaint() SPGradientType const gradient_type = ( psel->mode != SPPaintSelector::MODE_GRADIENT_RADIAL ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL ); + bool createSwatch = (psel->mode == SPPaintSelector::MODE_SWATCH); SPCSSAttr *css = 0; if (kind == FILL) { @@ -537,15 +538,18 @@ void FillNStroke::updateFromPaint() SPStyle *query = sp_style_new(desktop->doc()); int result = objects_query_fillstroke(const_cast(items), query, kind == FILL); - SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; - guint32 common_rgb = 0; if (result == QUERY_STYLE_MULTIPLE_SAME) { + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; + SPColor common; if (!targPaint.isColor()) { - common_rgb = sp_desktop_get_color(desktop, kind == FILL); + common = sp_desktop_get_color(desktop, kind == FILL); } else { - common_rgb = targPaint.value.color.toRGBA32( 0xff ); + common = targPaint.value.color; + } + vector = sp_document_default_gradient_vector( document, common, createSwatch ); + if ( vector && createSwatch ) { + vector->setSwatch(); } - vector = sp_document_default_gradient_vector(document, common_rgb); } sp_style_unref(query); @@ -556,8 +560,8 @@ void FillNStroke::updateFromPaint() } if (!vector) { - SPGradient *gr = sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL); - if ( gr && (psel->mode == SPPaintSelector::MODE_SWATCH) ) { + SPGradient *gr = sp_gradient_vector_for_object( document, desktop, SP_OBJECT(i->data), kind == FILL, createSwatch ); + if ( gr && createSwatch ) { gr->setSwatch(); } sp_item_set_gradient(SP_ITEM(i->data), -- 2.30.2