Code

Create only single-stop gradients when using Fill-n-Stroke to convert solid to a...
authorJon A. Cruz <jon@joncruz.org>
Sat, 3 Jul 2010 09:34:22 +0000 (02:34 -0700)
committerJon A. Cruz <jon@joncruz.org>
Sat, 3 Jul 2010 09:34:22 +0000 (02:34 -0700)
src/desktop-style.cpp
src/gradient-chemistry.cpp
src/gradient-chemistry.h
src/widgets/fill-style.cpp

index 26f29d172067639d0ed610f78b7e8fe90992c611..e11fa14939204e7efb06b2e4e846a93bc96a1c26 100644 (file)
@@ -436,6 +436,20 @@ stroke_average_width (GSList const *objects)
     return avgwidth / (g_slist_length ((GSList *) objects) - n_notstroked);
 }
 
+static bool vectorsClose( std::vector<double> const &lhs, std::vector<double> 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;
                     }
                 }
index 979b53f1b9a1babf0f434646b176587bf90b6c41..4df25aab4e03936ae5727fea8ed91c58f5f77ffa 100644 (file)
@@ -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<SPDefs *>(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<SPGradient *>(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 );
 }
 
 
index 3f72fa394d0ab0ec8c34777c7baeeb9a095f426d..0c8d0afe7bfa55547518d60dd1fcd58e75574f3d 100644 (file)
@@ -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);
index f1342f3de3374d47c14ee64b32eb166c5b315288..19b8448c6043c00fd56aafe1988abf7c7a63c293 100644 (file)
@@ -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<GSList *>(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),