Code

Modified filter rendering area handling to better accommodate upcoming feOffset
[inkscape.git] / src / sp-shape.cpp
index 53f161470a196c9d83ef2ecc24f4d7180b5deb77..6dba2afb67b2f36a63b0d6f3ecd0ead17c03c4e6 100644 (file)
@@ -32,7 +32,7 @@
 #include "print.h"
 #include "document.h"
 #include "style.h"
-#include "sp-marker.h"
+#include "marker.h"
 #include "sp-path.h"
 #include "prefs-utils.h"
 
@@ -88,19 +88,19 @@ sp_shape_get_type (void)
 static void
 sp_shape_class_init (SPShapeClass *klass)
 {
-        GObjectClass *gobject_class;
+    GObjectClass *gobject_class;
        SPObjectClass *sp_object_class;
        SPItemClass * item_class;
        SPPathClass * path_class;
 
-        gobject_class = (GObjectClass *) klass;
+    gobject_class = (GObjectClass *) klass;
        sp_object_class = (SPObjectClass *) klass;
        item_class = (SPItemClass *) klass;
        path_class = (SPPathClass *) klass;
 
        parent_class = (SPItemClass *)g_type_class_peek_parent (klass);
 
-        gobject_class->finalize = sp_shape_finalize;
+    gobject_class->finalize = sp_shape_finalize;
 
        sp_object_class->build = sp_shape_build;
        sp_object_class->release = sp_shape_release;
@@ -111,7 +111,7 @@ sp_shape_class_init (SPShapeClass *klass)
        item_class->print = sp_shape_print;
        item_class->show = sp_shape_show;
        item_class->hide = sp_shape_hide;
-        item_class->snappoints = sp_shape_snappoints;
+    item_class->snappoints = sp_shape_snappoints;
 }
 
 /**
@@ -238,13 +238,15 @@ sp_shape_update (SPObject *object, SPCtx *ctx, unsigned int flags)
        if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
                /* This is suboptimal, because changing parent style schedules recalculation */
                /* But on the other hand - how can we know that parent does not tie style and transform */
-                NR::Rect const paintbox = SP_ITEM(object)->invokeBbox(NR::identity());
+                NR::Maybe<NR::Rect> paintbox = SP_ITEM(object)->getBounds(NR::identity());
                for (SPItemView *v = SP_ITEM (shape)->display; v != NULL; v = v->next) {
                     NRArenaShape * const s = NR_ARENA_SHAPE(v->arenaitem);
                     if (flags & SP_OBJECT_MODIFIED_FLAG) {
                         nr_arena_shape_set_path(s, shape->curve, (flags & SP_OBJECT_USER_MODIFIED_FLAG_B));
                     }
-                    s->setPaintBox(paintbox);
+                    if (paintbox) {
+                        s->setPaintBox(*paintbox);
+                    }
                }
        }
 
@@ -616,43 +618,46 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &tr
 
         nr_path_matrix_bbox_union(&bp, transform, &cbbox);
 
-        SPStyle* style=SP_OBJECT_STYLE (item);
-        if (style->stroke.type != SP_PAINT_TYPE_NONE) {
-            double const scale = expansion(transform);
-            if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
-                double const width = MAX(0.125, style->stroke_width.computed * scale);
-                if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) {
-                    cbbox.x0-=0.5*width;
-                    cbbox.x1+=0.5*width;
-                    cbbox.y0-=0.5*width;
-                    cbbox.y1+=0.5*width;
+        if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) {
+            
+            SPStyle* style=SP_OBJECT_STYLE (item);
+            if (style->stroke.type != SP_PAINT_TYPE_NONE) {
+                double const scale = expansion(transform);
+                if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
+                    double const width = MAX(0.125, style->stroke_width.computed * scale);
+                    if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) {
+                        cbbox.x0-=0.5*width;
+                        cbbox.x1+=0.5*width;
+                        cbbox.y0-=0.5*width;
+                        cbbox.y1+=0.5*width;
+                    }
                 }
             }
-        }
 
-        // Union with bboxes of the markers, if any
-        if (sp_shape_has_markers (shape)) {
-            for (NArtBpath* bp = SP_CURVE_BPATH(shape->curve); bp->code != NR_END; bp++) {
-                for (int m = SP_MARKER_LOC_START; m < SP_MARKER_LOC_QTY; m++) {
-                    if (sp_shape_marker_required (shape, m, bp)) {
+            // Union with bboxes of the markers, if any
+            if (sp_shape_has_markers (shape)) {
+                for (NArtBpath* bp = SP_CURVE_BPATH(shape->curve); bp->code != NR_END; bp++) {
+                    for (int m = SP_MARKER_LOC_START; m < SP_MARKER_LOC_QTY; m++) {
+                        if (sp_shape_marker_required (shape, m, bp)) {
 
-                        SPMarker* marker = SP_MARKER (shape->marker[m]);
-                        SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[m]));
+                            SPMarker* marker = SP_MARKER (shape->marker[m]);
+                            SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[m]));
 
-                        NR::Matrix tr(sp_shape_marker_get_transform(shape, bp));
+                            NR::Matrix tr(sp_shape_marker_get_transform(shape, bp));
 
-                        if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
-                            tr = NR::scale(style->stroke_width.computed) * tr;
-                        }
+                            if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+                                tr = NR::scale(style->stroke_width.computed) * tr;
+                            }
 
-                        // total marker transform
-                        tr = marker_item->transform * marker->c2p * tr * transform;
+                            // total marker transform
+                            tr = marker_item->transform * marker->c2p * tr * transform;
 
-                        // get bbox of the marker with that transform
-                        NRRect marker_bbox;
-                        sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
-                        // union it with the shape bbox
-                        nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+                            // get bbox of the marker with that transform
+                            NRRect marker_bbox;
+                            sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
+                            // union it with the shape bbox
+                            nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+                        }
                     }
                 }
             }
@@ -753,8 +758,10 @@ sp_shape_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flag
         NRArenaShape * const s = NR_ARENA_SHAPE(arenaitem);
        nr_arena_shape_set_style(s, object->style);
        nr_arena_shape_set_path(s, shape->curve, false);
-        NR::Rect const paintbox = item->invokeBbox(NR::identity());
-        s->setPaintBox(paintbox);
+        NR::Maybe<NR::Rect> paintbox = item->getBounds(NR::identity());
+        if (paintbox) {
+            s->setPaintBox(*paintbox);
+        }
 
         if (sp_shape_has_markers (shape)) {
 
@@ -1014,6 +1021,11 @@ static void sp_shape_snappoints(SPItem const *item, SnapPointsIter p)
 
     /* Use the end points of each segment of the path */
     NArtBpath const *bp = SP_CURVE_BPATH(shape->curve);
+
+    if (bp->code == NR_MOVETO) { // Indicates the start of a closed subpath, see nr-path-code.h
+        bp++; //The first point of a closed path is coincident with the end point. Skip the first point as we need only one
+    }
+
     while (bp->code != NR_END) {
         *p = bp->c(3) * i2d;
         bp++;