Code

fix marker behavior for moveto-only paths
authorjohanengelen <johanengelen@users.sourceforge.net>
Fri, 8 Aug 2008 21:26:52 +0000 (21:26 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Fri, 8 Aug 2008 21:26:52 +0000 (21:26 +0000)
src/extension/internal/cairo-renderer.cpp
src/sp-shape.cpp
src/splivarot.cpp

index 3a4748b8aebd14fa3550a5f473c02cf50995c157..914a543f2846e2fea35a0f5defc6b0259163f8f8 100644 (file)
@@ -204,7 +204,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
             marker_item->transform = old_tr;
         }
 
-        if ( shape->marker[SP_MARKER_LOC_MID] ) {
+        if ( shape->marker[SP_MARKER_LOC_MID] && (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())
@@ -238,7 +238,15 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
             SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_END]);
             SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_END]));
 
-            NR::Matrix tr(sp_shape_marker_get_transform_at_end(path_it->back_default()));
+            /* 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];
+
+            NR::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
 
             if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
                 tr = NR::scale(style->stroke_width.computed) * tr;
index 96b52fd46aff2f19573562578fb59a24412d4dfc..7c1cd20eae45dfda33a7206a22367c69257d4f71 100644 (file)
@@ -362,23 +362,37 @@ Geom::Matrix
 sp_shape_marker_get_transform_at_start(Geom::Curve const & c)
 {
     Geom::Point p = c.pointAt(0);
-    Geom::Point tang = c.unitTangentAt(0);
-
-    double const angle = Geom::atan2(tang);
+    Geom::Matrix ret = Geom::Translate(p);
+
+    if ( !c.isDegenerate() ) {
+        Geom::Point tang = c.unitTangentAt(0);
+        double const angle = Geom::atan2(tang);
+        ret = Geom::Rotate(angle) * Geom::Translate(p);
+    } else {
+        /* FIXME: the svg spec says to search for a better alternative than zero angle directionality:
+         * http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes */
+    }
 
-    return Geom::Rotate(angle) * Geom::Translate(p);
+    return ret;
 }
 Geom::Matrix
 sp_shape_marker_get_transform_at_end(Geom::Curve const & c)
 {
     Geom::Point p = c.pointAt(1);
-    Geom::Curve * c_reverse = c.reverse();
-    Geom::Point tang = - c_reverse->unitTangentAt(0);
-    delete c_reverse;
-
-    double const angle = Geom::atan2(tang);
+    Geom::Matrix ret = Geom::Translate(p);
+
+    if ( !c.isDegenerate() ) {
+        Geom::Curve * c_reverse = c.reverse();
+        Geom::Point tang = - c_reverse->unitTangentAt(0);
+        delete c_reverse;
+        double const angle = Geom::atan2(tang);
+        ret = Geom::Rotate(angle) * Geom::Translate(p);
+    } else {
+        /* FIXME: the svg spec says to search for a better alternative than zero angle directionality:
+         * http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes */
+    }
 
-    return Geom::Rotate(angle) * Geom::Translate(p);
+    return ret;
 }
 
 /**
@@ -410,7 +424,7 @@ sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai)
              start_pos++;
         }
 
-        if ( shape->marker[SP_MARKER_LOC_MID] ) {
+        if ( shape->marker[SP_MARKER_LOC_MID] && (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())
@@ -431,7 +445,15 @@ sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai)
         }
 
         if ( shape->marker[SP_MARKER_LOC_END] ) {
-            Geom::Matrix const m (sp_shape_marker_get_transform_at_end(path_it->back_default()));
+            /* 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_marker_show_instance ((SPMarker* ) shape->marker[SP_MARKER_LOC_END], ai,
                                      NR_ARENA_ITEM_GET_KEY(ai) + SP_MARKER_LOC_END, end_pos, m,
                                      style->stroke_width.computed);
@@ -518,7 +540,7 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &tr
                         nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
                     }
 
-                    if ( shape->marker[SP_MARKER_LOC_MID] ) {
+                    if ( shape->marker[SP_MARKER_LOC_MID] && (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())
@@ -554,7 +576,15 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &tr
                         SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_END]);
                         SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_END]));
 
-                        NR::Matrix tr(sp_shape_marker_get_transform_at_end(path_it->back_default()));
+                        /* 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];
+
+                        NR::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
 
                         if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
                             tr = NR::scale(style->stroke_width.computed) * tr;
@@ -641,7 +671,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
             marker_item->transform = old_tr;
         }
 
-        if ( shape->marker[SP_MARKER_LOC_MID] ) {
+        if ( shape->marker[SP_MARKER_LOC_MID] && (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())
@@ -675,7 +705,15 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
             SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_END]);
             SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_END]));
 
-            NR::Matrix tr(sp_shape_marker_get_transform_at_end(path_it->back_default()));
+            /* 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];
+
+            NR::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
 
             if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
                 tr = NR::scale(style->stroke_width.computed) * tr;
index 47051be2be132a954340c3d8ee223dccc8e1b068..e66bc6a689581a95f436b44f5e56683f1eabfc0d 100644 (file)
@@ -855,7 +855,8 @@ sp_selected_path_outline()
                                                              g_repr, xml_doc, doc );
                     }
 
-                    if ( SPObject *marker_obj = shape->marker[SP_MARKER_LOC_MID] ) {
+                    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())
@@ -865,7 +866,7 @@ sp_selected_path_outline()
                              * 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( marker_obj, m,
+                            sp_selected_path_outline_add_marker( midmarker_obj, m,
                                                                  NR::scale(i_style->stroke_width.computed), transform,
                                                                  g_repr, xml_doc, doc );
 
@@ -875,7 +876,15 @@ sp_selected_path_outline()
                     }
 
                     if ( SPObject *marker_obj = shape->marker[SP_MARKER_LOC_END] ) {
-                        Geom::Matrix const m (sp_shape_marker_get_transform_at_end(path_it->back_default()));
+                        /* 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,
                                                              NR::scale(i_style->stroke_width.computed), transform,
                                                              g_repr, xml_doc, doc );