Code

Fix by Johan for 436304.
[inkscape.git] / src / splivarot.cpp
index dc19ac761f6e5be1184d347b793236da3712a8bb..feba2cab6b0ee522b2cd5f02f8f4e5699520c082 100644 (file)
@@ -41,7 +41,7 @@
 #include "display/canvas-bpath.h"
 #include "display/curve.h"
 #include <glibmm/i18n.h>
-#include "prefs-utils.h"
+#include "preferences.h"
 
 #include "xml/repr.h"
 #include "xml/repr-sorting.h"
@@ -127,8 +127,8 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
     }
 
     if (g_slist_length(il) > 2) {
-        if (bop == bool_op_diff || bop == bool_op_symdiff || bop == bool_op_cut || bop == bool_op_slice ) {
-            desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>exactly 2 paths</b> to perform difference, XOR, division, or path cut."));
+        if (bop == bool_op_diff || bop == bool_op_cut || bop == bool_op_slice ) {
+            desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>exactly 2 paths</b> to perform difference, division, or path cut."));
             return;
         }
     }
@@ -138,8 +138,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
     // topmost object (differences, cuts)
     bool reverseOrderForOp = false;
 
-    // mettre les elements de la liste dans l'ordre pour ces operations
-    if (bop == bool_op_diff || bop == bool_op_symdiff || bop == bool_op_cut || bop == bool_op_slice) {
+    if (bop == bool_op_diff || bop == bool_op_cut || bop == bool_op_slice) {
         // check in the tree to find which element of the selection list is topmost (for 2-operand commands only)
         Inkscape::XML::Node *a = SP_OBJECT_REPR(il->data);
         Inkscape::XML::Node *b = SP_OBJECT_REPR(il->next->data);
@@ -431,7 +430,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
 
     // get the source path object
     SPObject *source;
-    if ( bop == bool_op_diff || bop == bool_op_symdiff || bop == bool_op_cut || bop == bool_op_slice ) {
+    if ( bop == bool_op_diff || bop == bool_op_cut || bop == bool_op_slice ) {
         if (reverseOrderForOp) {
              source = SP_OBJECT(il->data);
         } else {
@@ -452,11 +451,11 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
     // adjust style properties that depend on a possible transform in the source object in order
     // to get a correct style attribute for the new path
     SPItem* item_source = SP_ITEM(source);
-    NR::Matrix i2root(sp_item_i2root_affine(item_source));
-    sp_item_adjust_stroke(item_source, i2root.descrim());
-    sp_item_adjust_pattern(item_source, i2root);
-    sp_item_adjust_gradient(item_source, i2root);
-    sp_item_adjust_livepatheffect(item_source, i2root);
+    Geom::Matrix i2doc(sp_item_i2doc_affine(item_source));
+    sp_item_adjust_stroke(item_source, i2doc.descrim());
+    sp_item_adjust_pattern(item_source, i2doc);
+    sp_item_adjust_gradient(item_source, i2doc);
+    sp_item_adjust_livepatheffect(item_source, i2doc);
 
     Inkscape::XML::Node *repr_source = SP_OBJECT_REPR(source);
 
@@ -485,7 +484,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
 
     // premultiply by the inverse of parent's repr
     SPItem *parent_item = SP_ITEM(sp_desktop_document(desktop)->getObjectByRepr(parent));
-    NR::Matrix local (sp_item_i2doc_affine(parent_item));
+    Geom::Matrix local (sp_item_i2doc_affine(parent_item));
     gchar *transform = sp_svg_transform_write(local.inverse());
 
     // now that we have the result, add it on the canvas
@@ -685,7 +684,7 @@ sp_selected_path_outline(SPDesktop *desktop)
             sp_repr_css_unset_property(ncss, "marker-end");
         }
 
-        NR::Matrix const transform(item->transform);
+        Geom::Matrix const transform(item->transform);
         float const scale = transform.descrim();
         gchar const *mask = SP_OBJECT_REPR(item)->attribute("mask");
         gchar const *clip_path = SP_OBJECT_REPR(item)->attribute("clip-path");
@@ -858,46 +857,52 @@ sp_selected_path_outline(SPDesktop *desktop)
 
                 Geom::PathVector const & pathv = curve->get_pathvector();
                 for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) {
-                    if ( SPObject *marker_obj = shape->marker[SP_MARKER_LOC_START] ) {
-                        Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front()));
-                        sp_selected_path_outline_add_marker( marker_obj, m,
-                                                             Geom::Scale(i_style->stroke_width.computed), transform,
-                                                             g_repr, xml_doc, doc );
+                    for (int i = 0; i < 2; i++) {  // SP_MARKER_LOC and SP_MARKER_LOC_START
+                        if ( SPObject *marker_obj = shape->marker[i] ) {
+                            Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front()));
+                            sp_selected_path_outline_add_marker( marker_obj, m,
+                                                                 Geom::Scale(i_style->stroke_width.computed), transform,
+                                                                 g_repr, xml_doc, doc );
+                        }
                     }
 
-                    SPObject *midmarker_obj = shape->marker[SP_MARKER_LOC_MID];
-                    if ( midmarker_obj && (path_it->size_default() > 1) ) {
-                        Geom::Path::const_iterator curve_it1 = path_it->begin();      // incoming curve
-                        Geom::Path::const_iterator curve_it2 = ++(path_it->begin());  // outgoing curve
-                        while (curve_it2 != path_it->end_default())
-                        {
-                            /* Put marker between curve_it1 and curve_it2.
-                             * Loop to end_default (so including closing segment), because when a path is closed,
-                             * there should be a midpoint marker between last segment and closing straight line segment
-                             */
-                            Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
-                            sp_selected_path_outline_add_marker(midmarker_obj, m,
-                                                                Geom::Scale(i_style->stroke_width.computed), transform,
-                                                                g_repr, xml_doc, doc);
-
-                            ++curve_it1;
-                            ++curve_it2;
+                    for (int i = 0; i < 3; i += 2) {  // SP_MARKER_LOC and SP_MARKER_LOC_MID
+                        SPObject *midmarker_obj = shape->marker[i];
+                        if ( midmarker_obj && (path_it->size_default() > 1) ) {
+                            Geom::Path::const_iterator curve_it1 = path_it->begin();      // incoming curve
+                            Geom::Path::const_iterator curve_it2 = ++(path_it->begin());  // outgoing curve
+                            while (curve_it2 != path_it->end_default())
+                            {
+                                /* Put marker between curve_it1 and curve_it2.
+                                 * Loop to end_default (so including closing segment), because when a path is closed,
+                                 * there should be a midpoint marker between last segment and closing straight line segment
+                                 */
+                                Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+                                sp_selected_path_outline_add_marker(midmarker_obj, m,
+                                                                    Geom::Scale(i_style->stroke_width.computed), transform,
+                                                                    g_repr, xml_doc, doc);
+
+                                ++curve_it1;
+                                ++curve_it2;
+                            }
                         }
                     }
 
-                    if ( SPObject *marker_obj = shape->marker[SP_MARKER_LOC_END] ) {
-                        /* Get reference to last curve in the path.
-                         * For moveto-only path, this returns the "closing line segment". */
-                        unsigned int index = path_it->size_default();
-                        if (index > 0) {
-                            index--;
-                        }
-                        Geom::Curve const &lastcurve = (*path_it)[index];
+                    for (int i = 0; i < 4; i += 3) {  // SP_MARKER_LOC and SP_MARKER_LOC_END
+                        if ( SPObject *marker_obj = shape->marker[i] ) {
+                            /* Get reference to last curve in the path.
+                             * For moveto-only path, this returns the "closing line segment". */
+                            unsigned int index = path_it->size_default();
+                            if (index > 0) {
+                                index--;
+                            }
+                            Geom::Curve const &lastcurve = (*path_it)[index];
 
-                        Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
-                        sp_selected_path_outline_add_marker( marker_obj, m,
-                                                             Geom::Scale(i_style->stroke_width.computed), transform,
-                                                             g_repr, xml_doc, doc );
+                            Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+                            sp_selected_path_outline_add_marker( marker_obj, m,
+                                                                 Geom::Scale(i_style->stroke_width.computed), transform,
+                                                                 g_repr, xml_doc, doc );
+                        }
                     }
                 }
 
@@ -958,14 +963,16 @@ sp_selected_path_outline(SPDesktop *desktop)
 void
 sp_selected_path_offset(SPDesktop *desktop)
 {
-    double prefOffset = prefs_get_double_attribute("options.defaultoffsetwidth", "value", 1.0);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    double prefOffset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0);
 
     sp_selected_path_do_offset(desktop, true, prefOffset);
 }
 void
 sp_selected_path_inset(SPDesktop *desktop)
 {
-    double prefOffset = prefs_get_double_attribute("options.defaultoffsetwidth", "value", 1.0);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    double prefOffset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0);
 
     sp_selected_path_do_offset(desktop, false, prefOffset);
 }
@@ -1046,7 +1053,7 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat
             return;
     }
 
-    NR::Matrix const transform(item->transform);
+    Geom::Matrix const transform(item->transform);
 
     sp_item_write_transform(item, SP_OBJECT_REPR(item), Geom::identity());
 
@@ -1090,9 +1097,8 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat
         }
 
         {
-            double prefOffset = 1.0;
-            prefOffset = prefs_get_double_attribute("options.defaultoffsetwidth", "value", prefOffset);
-            o_width = prefOffset;
+            Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+            o_width = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0);
         }
 
         if (o_width < 0.01)
@@ -1272,7 +1278,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset)
                 continue;
         }
 
-        NR::Matrix const transform(item->transform);
+        Geom::Matrix const transform(item->transform);
 
         sp_item_write_transform(item, SP_OBJECT_REPR(item), Geom::identity());
 
@@ -1515,8 +1521,11 @@ sp_selected_path_simplify_item(SPDesktop *desktop,
             return false;
     }
 
+    // correct virtual size by full transform (bug #166937)
+    size /= sp_item_i2doc_affine(item).descrim();
+
     // save the transform, to re-apply it after simplification
-    NR::Matrix const transform(item->transform);
+    Geom::Matrix const transform(item->transform);
 
     /*
        reset the transform, effectively transforming the item by transform.inverse();
@@ -1580,6 +1589,9 @@ sp_selected_path_simplify_item(SPDesktop *desktop,
         g_free(clip_path);
     }
 
+    // restore path effect
+    repr->setAttribute("inkscape:path-effect", patheffect);
+
     // path
     gchar *str = orig->svg_dump_path();
     if (patheffect)
@@ -1602,9 +1614,6 @@ sp_selected_path_simplify_item(SPDesktop *desktop,
     // reapply the transform
     sp_item_write_transform(newitem, repr, transform);
 
-    // restore path effect
-    repr->setAttribute("inkscape:path-effect", patheffect);
-    
     // restore title & description
     if (title) {
        newitem->setTitle(title);
@@ -1635,65 +1644,66 @@ sp_selected_path_simplify_items(SPDesktop *desktop,
                                 float angleLimit, bool breakableAngles,
                                 bool modifySelection)
 {
-  bool simplifyIndividualPaths =
-    (bool) prefs_get_int_attribute("options.simplifyindividualpaths", "value", 0);
-  
-  gchar *simplificationType;
-  if (simplifyIndividualPaths) {
-      simplificationType = _("Simplifying paths (separately):");
-  } else {
-      simplificationType = _("Simplifying paths:");
-  }
-
-  bool didSomething = false;
-
-  boost::optional<Geom::Rect> selectionBbox = selection->bounds();
-  if (!selectionBbox) {
-    return false;
-  }
-  gdouble selectionSize  = L2(selectionBbox->dimensions());
-
-  gdouble simplifySize  = selectionSize;
-  
-  int pathsSimplified = 0;
-  int totalPathCount  = g_slist_length(items);
-  
-  // set "busy" cursor
-  desktop->setWaitingCursor();
-  
-  for (; items != NULL; items = items->next) {
-      SPItem *item = (SPItem *) items->data;
-      
-      if (!(SP_IS_GROUP(item) || SP_IS_SHAPE(item) || SP_IS_TEXT(item)))
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    bool simplifyIndividualPaths = prefs->getBool("/options/simplifyindividualpaths/value");
+
+    gchar *simplificationType;
+    if (simplifyIndividualPaths) {
+        simplificationType = _("Simplifying paths (separately):");
+    } else {
+        simplificationType = _("Simplifying paths:");
+    }
+
+    bool didSomething = false;
+
+    Geom::OptRect selectionBbox = selection->bounds();
+    if (!selectionBbox) {
+        return false;
+    }
+    gdouble selectionSize  = L2(selectionBbox->dimensions());
+
+    gdouble simplifySize  = selectionSize;
+
+    int pathsSimplified = 0;
+    int totalPathCount  = g_slist_length(items);
+
+    // set "busy" cursor
+    desktop->setWaitingCursor();
+
+    for (; items != NULL; items = items->next) {
+        SPItem *item = (SPItem *) items->data;
+
+        if (!(SP_IS_GROUP(item) || SP_IS_SHAPE(item) || SP_IS_TEXT(item)))
           continue;
 
-      if (simplifyIndividualPaths) {
-          boost::optional<Geom::Rect> itemBbox = item->getBounds(sp_item_i2d_affine(item));
-          if (itemBbox) {
-              simplifySize      = L2(itemBbox->dimensions());
-          } else {
-              simplifySize      = 0;
-          }
-      }
-
-      pathsSimplified++;
-
-      if (pathsSimplified % 20 == 0) {
-        gchar *message = g_strdup_printf(_("%s <b>%d</b> of <b>%d</b> paths simplified..."), simplificationType, pathsSimplified, totalPathCount);
-        desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, message);
-      }
-
-      didSomething |= sp_selected_path_simplify_item(desktop, selection, item,
-                          threshold, justCoalesce, angleLimit, breakableAngles, simplifySize, modifySelection);
-  }
-
-  desktop->clearWaitingCursor();
-
-  if (pathsSimplified > 20) {
-    desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, g_strdup_printf(_("<b>%d</b> paths simplified."), pathsSimplified));
-  }
-  
-  return didSomething;
+        if (simplifyIndividualPaths) {
+            Geom::OptRect itemBbox = item->getBounds(sp_item_i2d_affine(item));
+            if (itemBbox) {
+                simplifySize      = L2(itemBbox->dimensions());
+            } else {
+                simplifySize      = 0;
+            }
+        }
+
+        pathsSimplified++;
+
+        if (pathsSimplified % 20 == 0) {
+            gchar *message = g_strdup_printf(_("%s <b>%d</b> of <b>%d</b> paths simplified..."),
+                simplificationType, pathsSimplified, totalPathCount);
+            desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, message);
+        }
+
+        didSomething |= sp_selected_path_simplify_item(desktop, selection, item,
+            threshold, justCoalesce, angleLimit, breakableAngles, simplifySize, modifySelection);
+    }
+
+    desktop->clearWaitingCursor();
+
+    if (pathsSimplified > 20) {
+        desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, g_strdup_printf(_("<b>%d</b> paths simplified."), pathsSimplified));
+    }
+
+    return didSomething;
 }
 
 void
@@ -1732,10 +1742,10 @@ static gdouble simplifyMultiply = 1.0;
 void
 sp_selected_path_simplify(SPDesktop *desktop)
 {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     gdouble simplifyThreshold =
-        prefs_get_double_attribute("options.simplifythreshold", "value", 0.003);
-    bool simplifyJustCoalesce =
-        (bool) prefs_get_int_attribute("options.simplifyjustcoalesce", "value", 0);
+        prefs->getDouble("/options/simplifythreshold/value", 0.003);
+    bool simplifyJustCoalesce = prefs->getBool("/options/simplifyjustcoalesce/value", 0);
 
     //Get the current time
     GTimeVal currentTimeVal;
@@ -1848,16 +1858,16 @@ SPCurve* curve_for_item(SPItem *item)
     return curve; // do not forget to unref the curve at some point!
 }
 
-boost::optional<Path::cut_position> get_nearest_position_on_Path(Path *path, NR::Point p, unsigned seg)
+boost::optional<Path::cut_position> get_nearest_position_on_Path(Path *path, Geom::Point p, unsigned seg)
 {
     //get nearest position on path
     Path::cut_position pos = path->PointToCurvilignPosition(p, seg);
     return pos;
 }
 
-NR::Point get_point_on_Path(Path *path, int piece, double t)
+Geom::Point get_point_on_Path(Path *path, int piece, double t)
 {
-    NR::Point p;
+    Geom::Point p;
     path->PointAt(piece, t, p);
     return p;
 }