Code

new command: relink clone to copied object
[inkscape.git] / src / gradient-chemistry.cpp
index 486d38167f5e0e55bdbe8ff10aec94f8725f3718..9fade37ecdcb042f5b430aad95b9989a6ccfc84d 100644 (file)
 #include "sp-text.h"
 #include "sp-tspan.h"
 #include <libnr/nr-matrix-fns.h>
+#include <libnr/nr-point-fns.h>
 #include "xml/repr.h"
 #include "svg/svg.h"
 #include "svg/svg-color.h"
 #include "svg/css-ostringstream.h"
+#include "prefs-utils.h"
 
 
 // Terminology:
@@ -73,7 +75,7 @@ sp_gradient_ensure_vector_normalized(SPGradient *gr)
     /* If gr hrefs some other gradient, remove the href */
     if (gr->ref->getObject()) {
         /* We are hrefing someone, so require flattening */
-        SP_OBJECT(gr)->updateRepr(((SPObject *) gr)->repr, SP_OBJECT_WRITE_EXT | SP_OBJECT_WRITE_ALL);
+        SP_OBJECT(gr)->updateRepr(SP_OBJECT_WRITE_EXT | SP_OBJECT_WRITE_ALL);
         sp_gradient_repr_set_link(SP_OBJECT_REPR(gr), NULL);
     }
 
@@ -234,6 +236,10 @@ sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector,
 SPGradient *
 sp_gradient_fork_vector_if_necessary (SPGradient *gr)
 {
+    // Some people actually prefer their gradient vectors to be shared...
+    if (prefs_get_int_attribute("options.forkgradientvectors", "value", 1) == 0)
+        return gr;
+
     if (SP_OBJECT_HREFCOUNT(gr) > 1) {
         SPDocument *doc = SP_OBJECT_DOCUMENT(gr);
         Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
@@ -361,7 +367,7 @@ sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar const *prop
          *   transformation from bounding box space to user space.
          */
         NR::Matrix skew = bbox2user;
-        double exp = skew.expansion();
+        double exp = NR::expansion(skew);
         skew[0] /= exp;
         skew[1] /= exp;
         skew[2] /= exp;
@@ -392,7 +398,7 @@ sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar const *prop
             // converted points in userspace coords
             NR::Point c_u = c_b * point_convert;
             NR::Point f_u = f_b * point_convert;
-            double r_u = r_b * point_convert.expansion();
+            double r_u = r_b * NR::expansion(point_convert);
 
             sp_repr_set_svg_double(repr, "cx", c_u[NR::X]);
             sp_repr_set_svg_double(repr, "cy", c_u[NR::Y]);
@@ -549,6 +555,12 @@ SPStop*
 sp_get_stop_i(SPGradient *gradient, guint stop_i)
 {            
     SPStop *stop = sp_first_stop (gradient);
+
+    // if this is valid but weird gradient without an offset-zero stop element,  
+    // inkscape has created a handle for the start of gradient anyway,
+    // so when it asks for stop N that corresponds to stop element N-1
+    if (stop->offset != 0)
+        stop_i --;
   
     for (guint i=0; i < stop_i; i++) {
         if (!stop) return NULL;  
@@ -798,21 +810,6 @@ sp_item_gradient_reverse_vector (SPItem *item, bool fill_or_stroke)
 }
 
 
-// FIXME: make general global function
-static double
-get_offset_between_points (NR::Point p, NR::Point begin, NR::Point end)
-{
-    double length = NR::L2(end - begin);
-    NR::Point be = (end - begin) / length;
-    double r = NR::dot(p - begin, be);
-        
-    if (r < 0.0) return 0.0;
-    if (r > length) return 1.0;    
-    
-    return (r / length);
-}
-
-
 /**
 Set the position of point point_type of the gradient applied to item (either fill_or_stroke) to
 p_w (in desktop coordinates). Write_repr if you want the change to become permanent.
@@ -827,7 +824,7 @@ sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, NR::
 
     gradient = sp_gradient_convert_to_userspace (gradient, item, fill_or_stroke? "fill" : "stroke");
 
-    NR::Matrix i2d = sp_item_i2d_affine (item);
+    NR::Matrix i2d = from_2geom(sp_item_i2d_affine (item));
     NR::Point p = p_w * i2d.inverse();
     p *= (gradient->gradientTransform).inverse();
     // now p is in gradient's original coordinates
@@ -1104,7 +1101,7 @@ sp_item_gradient_get_coords (SPItem *item, guint point_type, guint point_i, bool
                             bbox->min()[NR::X], bbox->min()[NR::Y]);
         }
     }
-    p *= NR::Matrix(gradient->gradientTransform) * sp_item_i2d_affine(item);
+    p *= NR::Matrix(gradient->gradientTransform) * from_2geom(sp_item_i2d_affine(item));
     return p;
 }