Code

Block display of named color icc profiles.
[inkscape.git] / src / sp-shape.cpp
index 3064341b66238b48b2842c7514771033183f0eb3..4bbfbc1e12fcbc728be7c8330d213942a0bcb418 100644 (file)
@@ -24,6 +24,7 @@
 #include <2geom/transforms.h>
 #include <2geom/pathvector.h>
 #include <2geom/path-intersection.h>
+#include <2geom/exception.h>
 #include "helper/geom.h"
 #include "helper/geom-nodetype.h"
 
@@ -410,7 +411,9 @@ sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai)
     // position arguments to sp_marker_show_instance, basically counts the amount of markers.
     int counter[4] = {0};
 
+    if (!shape->curve) return;
     Geom::PathVector const & pathv = shape->curve->get_pathvector();
+    if (pathv.empty()) return;
 
     // the first vertex should get a start marker, the last an end marker, and all the others a mid marker
     // see bug 456148
@@ -585,7 +588,7 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &
                     }
 
                     // Union with bboxes of the markers, if any
-                    if (sp_shape_has_markers (shape)) {
+                    if (sp_shape_has_markers (shape) && !shape->curve->get_pathvector().empty()) {
                         /** \todo make code prettier! */
                         Geom::PathVector const & pathv = shape->curve->get_pathvector();
                         // START marker
@@ -767,6 +770,9 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
 
     if (!shape->curve) return;
 
+    Geom::PathVector const & pathv = shape->curve->get_pathvector();
+    if (pathv.empty()) return;
+
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         gint add_comments = prefs->getBool("/printing/debug/add-label-comments");
         if (add_comments) {
@@ -788,15 +794,14 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
     SPStyle* style = SP_OBJECT_STYLE (item);
 
     if (!style->fill.isNone()) {
-        sp_print_fill (ctx, shape->curve->get_pathvector(), &i2d, style, &pbox, &dbox, &bbox);
+        sp_print_fill (ctx, pathv, &i2d, style, &pbox, &dbox, &bbox);
     }
 
     if (!style->stroke.isNone()) {
-        sp_print_stroke (ctx, shape->curve->get_pathvector(), &i2d, style, &pbox, &dbox, &bbox);
+        sp_print_stroke (ctx, pathv, &i2d, style, &pbox, &dbox, &bbox);
     }
 
     /** \todo make code prettier */
-    Geom::PathVector const & pathv = shape->curve->get_pathvector();
     // START marker
     for (int i = 0; i < 2; i++) {  // SP_MARKER_LOC and SP_MARKER_LOC_START    
         if ( shape->marker[i] ) {
@@ -1208,49 +1213,55 @@ static void sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::SnapCa
 
     for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) {
         if (snapprefs->getSnapToItemNode()) {
+            // Add the first point of the path
             p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP));
         }
 
         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_closed())
+        while (curve_it1 != path_it->end_default())
         {
-            /* Test whether to add the node between curve_it1 and curve_it2.
-             * Loop to end_closed (so always including closing segment); the last node to be added
-             * is the node between the closing segment and the segment before that, regardless
-             * of the path being closed or not. If the path is closed, the final point was already added by
-             * adding the initial point. */
-
-            Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2);
-
-            bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE);
-            bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM);
-
-            if (c1 || c2) {
-                Inkscape::SnapSourceType sst;
-                Inkscape::SnapTargetType stt;
-                switch (nodetype) {
-                case Geom::NODE_CUSP:
-                    sst = Inkscape::SNAPSOURCE_NODE_CUSP;
-                    stt = Inkscape::SNAPTARGET_NODE_CUSP;
-                    break;
-                case Geom::NODE_SMOOTH:
-                case Geom::NODE_SYMM:
-                    sst = Inkscape::SNAPSOURCE_NODE_SMOOTH;
-                    stt = Inkscape::SNAPTARGET_NODE_SMOOTH;
-                    break;
-                default:
-                    sst = Inkscape::SNAPSOURCE_UNDEFINED;
-                    stt = Inkscape::SNAPTARGET_UNDEFINED;
-                    break;
+            // For each path: consider midpoints of line segments for snapping
+            if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping)
+                if (Geom::LineSegment const* line_segment = dynamic_cast<Geom::LineSegment const*>(&(*curve_it1))) {
+                    p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT));
                 }
-                p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt));
             }
 
-            // Consider midpoints of line segments for snapping
-            if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping)
-                if (Geom::LineSegment const* line_segment = dynamic_cast<Geom::LineSegment const*>(&(*curve_it1))) {
-                    p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT));
+            if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop
+                if (snapprefs->getSnapToItemNode() && !path_it->closed()) {
+                    // Add the last point of the path, but only for open paths
+                    // (for closed paths the first and last point will coincide)
+                    p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP));
+                }
+            } else {
+                /* Test whether to add the node between curve_it1 and curve_it2.
+                 * Loop to end_default (so only iterating through the stroked part); */
+
+                Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2);
+
+                bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE);
+                bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM);
+
+                if (c1 || c2) {
+                    Inkscape::SnapSourceType sst;
+                    Inkscape::SnapTargetType stt;
+                    switch (nodetype) {
+                    case Geom::NODE_CUSP:
+                        sst = Inkscape::SNAPSOURCE_NODE_CUSP;
+                        stt = Inkscape::SNAPTARGET_NODE_CUSP;
+                        break;
+                    case Geom::NODE_SMOOTH:
+                    case Geom::NODE_SYMM:
+                        sst = Inkscape::SNAPSOURCE_NODE_SMOOTH;
+                        stt = Inkscape::SNAPTARGET_NODE_SMOOTH;
+                        break;
+                    default:
+                        sst = Inkscape::SNAPSOURCE_UNDEFINED;
+                        stt = Inkscape::SNAPTARGET_UNDEFINED;
+                        break;
+                    }
+                    p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt));
                 }
             }
 
@@ -1262,13 +1273,19 @@ static void sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::SnapCa
         // (using "Method 1" as described in Inkscape::ObjectSnapper::_collectNodes())
         if (snapprefs->getSnapIntersectionCS()) {
             Geom::Crossings cs;
-            cs = self_crossings(*path_it);
-            if (cs.size() > 0) { // There might be multiple intersections...
-                for (Geom::Crossings::const_iterator i = cs.begin(); i != cs.end(); i++) {
-                    Geom::Point p_ix = (*path_it).pointAt((*i).ta);
-                    p.push_back(Inkscape::SnapCandidatePoint(p_ix * i2d, Inkscape::SNAPSOURCE_PATH_INTERSECTION, Inkscape::SNAPTARGET_PATH_INTERSECTION));
+            try {
+                cs = self_crossings(*path_it);
+                if (cs.size() > 0) { // There might be multiple intersections...
+                    for (Geom::Crossings::const_iterator i = cs.begin(); i != cs.end(); i++) {
+                        Geom::Point p_ix = (*path_it).pointAt((*i).ta);
+                        p.push_back(Inkscape::SnapCandidatePoint(p_ix * i2d, Inkscape::SNAPSOURCE_PATH_INTERSECTION, Inkscape::SNAPTARGET_PATH_INTERSECTION));
+                    }
                 }
+            } catch (Geom::RangeError &e) {
+                // do nothing
+                // The exception could be Geom::InfiniteSolutions: then no snappoints should be added
             }
+
         }
     }
 
@@ -1283,4 +1300,4 @@ static void sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::SnapCa
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :