From 05a66d0771cb563225b8690de04e9490b35453f2 Mon Sep 17 00:00:00 2001 From: johanengelen Date: Fri, 2 Jan 2009 20:19:44 +0000 Subject: [PATCH] make 'marker' property work (shorthand for start, mid and end markers); inkscape now passes svg testsuite painting-marker-03-f.svg --- src/extension/internal/cairo-renderer.cpp | 156 +++++++--------- src/sp-marker-loc.h | 10 +- src/sp-shape.cpp | 211 +++++++++++----------- src/splivarot.cpp | 74 ++++---- 4 files changed, 221 insertions(+), 230 deletions(-) diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index a536a67ac..da88a5eae 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -155,6 +155,27 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx); static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx); static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx); +static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Matrix tr, SPStyle* style, CairoRenderContext *ctx) +{ + bool render = true; + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + if (style->stroke_width.computed > 1e-9) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } else { + render = false; // stroke width zero and marker is thus scaled down to zero, skip + } + } + + if (render) { + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + tr = (Geom::Matrix)marker_item->transform * (Geom::Matrix)marker->c2p * tr; + Geom::Matrix old_tr = marker_item->transform; + marker_item->transform = tr; + ctx->getRenderer()->renderItem (ctx, marker_item); + marker_item->transform = old_tr; + } +} + static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) { NRRect pbox; @@ -166,118 +187,75 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) sp_item_invoke_bbox(item, &pbox, Geom::identity(), TRUE); SPStyle* style = SP_OBJECT_STYLE (item); - CairoRenderer *renderer = ctx->getRenderer(); Geom::PathVector const & pathv = shape->curve->get_pathvector(); ctx->renderPathVector(pathv, style, &pbox); - /* TODO: make code prettier: lots of variables can be taken out of the loop! */ for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { - if ( shape->marker[SP_MARKER_LOC_START] ) { - SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_START]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_START])); - - Geom::Matrix tr; - if (marker->orient_auto) { - tr = sp_shape_marker_get_transform_at_start(path_it->front()); - } else { - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(path_it->front().pointAt(0)); - } - - bool render = true; - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - if (style->stroke_width.computed > 1e-9) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } else { - render = false; // stroke width zero and marker is thus scaled down to zero, skip - } - } - - if (render) { - tr = (Geom::Matrix)marker_item->transform * (Geom::Matrix)marker->c2p * tr; - Geom::Matrix old_tr = marker_item->transform; - marker_item->transform = tr; - renderer->renderItem (ctx, marker_item); - marker_item->transform = old_tr; - } - } - - 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()) - { - /* 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 */ - - SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_MID]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_MID])); - + // START position + for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START + if ( shape->marker[i] ) { + SPMarker* marker = SP_MARKER (shape->marker[i]); Geom::Matrix tr; if (marker->orient_auto) { - tr = sp_shape_marker_get_transform(*curve_it1, *curve_it2); + tr = sp_shape_marker_get_transform_at_start(path_it->front()); } else { - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(curve_it1->pointAt(1)); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(path_it->front().pointAt(0)); } + sp_shape_render_invoke_marker_rendering(marker, tr, style, ctx); + } + } - bool render = true; - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - if (style->stroke_width.computed > 1e-9) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + // MID position + for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID + if ( shape->marker[i] && (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 */ + + SPMarker* marker = SP_MARKER (shape->marker[i]); + + Geom::Matrix tr; + if (marker->orient_auto) { + tr = sp_shape_marker_get_transform(*curve_it1, *curve_it2); } else { - render = false; // stroke width zero and marker is thus scaled down to zero, skip + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(curve_it1->pointAt(1)); } - } - if (render) { - tr = (Geom::Matrix)marker_item->transform * (Geom::Matrix)marker->c2p * tr; - Geom::Matrix old_tr = marker_item->transform; - marker_item->transform = tr; - renderer->renderItem (ctx, marker_item); - marker_item->transform = old_tr; - } + sp_shape_render_invoke_marker_rendering(marker, tr, style, ctx); - ++curve_it1; - ++curve_it2; + ++curve_it1; + ++curve_it2; + } } } - if ( shape->marker[SP_MARKER_LOC_END] ) { - 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])); + // END position + for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END + if ( shape->marker[i] ) { + SPMarker* marker = SP_MARKER (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 tr; - if (marker->orient_auto) { - tr = sp_shape_marker_get_transform_at_end(lastcurve); - } else { - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(lastcurve.pointAt(1)); - } + /* 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]; - bool render = true; - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - if (style->stroke_width.computed > 1e-9) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + Geom::Matrix tr; + if (marker->orient_auto) { + tr = sp_shape_marker_get_transform_at_end(lastcurve); } else { - render = false; // stroke width zero and marker is thus scaled down to zero, skip + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(lastcurve.pointAt(1)); } - } - if (render) { - tr = (Geom::Matrix)marker_item->transform * (Geom::Matrix)marker->c2p * tr; - Geom::Matrix old_tr = marker_item->transform; - marker_item->transform = tr; - renderer->renderItem (ctx, marker_item); - marker_item->transform = old_tr; + sp_shape_render_invoke_marker_rendering(marker, tr, style, ctx); } } } diff --git a/src/sp-marker-loc.h b/src/sp-marker-loc.h index 1b763f724..98cab3746 100644 --- a/src/sp-marker-loc.h +++ b/src/sp-marker-loc.h @@ -7,11 +7,11 @@ * to do a process across all of the markers, instead of separate code stanzas for each. */ enum SPMarkerLoc { - SP_MARKER_LOC, - SP_MARKER_LOC_START, - SP_MARKER_LOC_MID, - SP_MARKER_LOC_END, - SP_MARKER_LOC_QTY + SP_MARKER_LOC = 0, + SP_MARKER_LOC_START = 1, + SP_MARKER_LOC_MID = 2, + SP_MARKER_LOC_END = 3, + SP_MARKER_LOC_QTY = 4 }; diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 155c9b454..e1fd13ffb 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -139,7 +139,9 @@ sp_shape_init (SPShape *shape) for ( int i = 0 ; i < SP_MARKER_LOC_QTY ; i++ ) { new (&shape->release_connect[i]) sigc::connection(); new (&shape->modified_connect[i]) sigc::connection(); + shape->marker[i] = NULL; } + shape->curve = NULL; } static void @@ -199,15 +201,15 @@ sp_shape_release (SPObject *object) item = (SPItem *) object; shape = (SPShape *) object; - for (i=SP_MARKER_LOC_START; imarker[i]) { - for (v = item->display; v != NULL; v = v->next) { - sp_marker_hide ((SPMarker *) shape->marker[i], NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i); + for (i = 0; i < SP_MARKER_LOC_QTY; i++) { + if (shape->marker[i]) { + for (v = item->display; v != NULL; v = v->next) { + sp_marker_hide ((SPMarker *) shape->marker[i], NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i); + } + shape->release_connect[i].disconnect(); + shape->modified_connect[i].disconnect(); + shape->marker[i] = sp_object_hunref (shape->marker[i], object); } - shape->release_connect[i].disconnect(); - shape->modified_connect[i].disconnect(); - shape->marker[i] = sp_object_hunref (shape->marker[i], object); - } } if (shape->curve) { shape->curve = shape->curve->unref(); @@ -396,9 +398,7 @@ sp_shape_marker_get_transform_at_end(Geom::Curve const & c) * Marker views have to be scaled already. The transformation * is retrieved and then shown by calling sp_marker_show_instance. * - * TODO: correctly handle the 'marker' attribute. - * "Using the marker property from a style sheet is equivalent to using all three (start, mid, end)." - * See painting-marker-03-f.svg in SVG 1.1 Full test suite. + * @todo figure out what to do when both 'marker' and for instance 'marker-end' are set. */ static void sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai) @@ -406,21 +406,23 @@ sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai) SPStyle *style = ((SPObject *) shape)->style; // position arguments to sp_marker_show_instance, basically counts the amount of markers. - int start_pos = 0; - int mid_pos = 0; - int end_pos = 0; + int counter[4] = {0}; Geom::PathVector const & pathv = shape->curve->get_pathvector(); for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { - if ( shape->marker[SP_MARKER_LOC_START] ) { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front())); - sp_marker_show_instance ((SPMarker* ) shape->marker[SP_MARKER_LOC_START], ai, - NR_ARENA_ITEM_GET_KEY(ai) + SP_MARKER_LOC_START, start_pos, m, - style->stroke_width.computed); - start_pos++; + // START position + Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front())); + for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START + if ( shape->marker[i] ) { + sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, + NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m, + style->stroke_width.computed); + counter[i]++; + } } - if ( shape->marker[SP_MARKER_LOC_MID] && (path_it->size_default() > 1) ) { + // MID position + if ( (shape->marker[SP_MARKER_LOC_MID] || shape->marker[SP_MARKER_LOC]) && (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()) @@ -430,17 +432,22 @@ sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai) * 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_marker_show_instance ((SPMarker* ) shape->marker[SP_MARKER_LOC_MID], ai, - NR_ARENA_ITEM_GET_KEY(ai) + SP_MARKER_LOC_MID, mid_pos, m, - style->stroke_width.computed); - mid_pos++; + for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID + if (shape->marker[i]) { + sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, + NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m, + style->stroke_width.computed); + counter[i]++; + } + } ++curve_it1; ++curve_it2; } } - if ( shape->marker[SP_MARKER_LOC_END] ) { + // END position + if ( shape->marker[SP_MARKER_LOC_END] || shape->marker[SP_MARKER_LOC] ) { /* 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(); @@ -448,12 +455,16 @@ sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai) 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); - end_pos++; + + for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END + if (shape->marker[i]) { + sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, + NR_ARENA_ITEM_GET_KEY(ai) + i, counter[i], m, + style->stroke_width.computed); + counter[i]++; + } + } } } } @@ -516,7 +527,7 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const & for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { if ( shape->marker[SP_MARKER_LOC_START] ) { SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_START]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_START])); + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front())); @@ -544,7 +555,7 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const & * there should be a midpoint marker between last segment and closing straight line segment */ SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_MID]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_MID])); + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); @@ -568,7 +579,7 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const & if ( shape->marker[SP_MARKER_LOC_END] ) { 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])); + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); /* Get reference to last curve in the path. * For moveto-only path, this returns the "closing line segment". */ @@ -603,6 +614,21 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const & } } +static void +sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Matrix tr, SPStyle* style, SPPrintContext *ctx) { + SPMarker *marker = SP_MARKER(obj); + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } + + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + tr = marker_item->transform * marker->c2p * tr; + + Geom::Matrix old_tr = marker_item->transform; + marker_item->transform = tr; + sp_item_invoke_print (marker_item, ctx); + marker_item->transform = old_tr; +} /** * Prepares shape for printing. Handles printing of comments for printing * debugging, sizes the item to fit into the document width/height, @@ -636,7 +662,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) sp_item_bbox_desktop (item, &bbox); Geom::Matrix const i2d(sp_item_i2d_affine(item)); - SPStyle* style = SP_OBJECT_STYLE (item); + SPStyle* style = SP_OBJECT_STYLE (item); if (!style->fill.isNone()) { sp_print_fill (ctx, shape->curve->get_pathvector(), &i2d, style, &pbox, &dbox, &bbox); @@ -649,25 +675,17 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) /* TODO: make code prettier: lots of variables can be taken out of the loop! */ Geom::PathVector const & pathv = shape->curve->get_pathvector(); for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { - if ( shape->marker[SP_MARKER_LOC_START] ) { - SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_START]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_START])); - + if ( shape->marker[SP_MARKER_LOC_START] || shape->marker[SP_MARKER_LOC]) { Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front())); - - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + if (shape->marker[SP_MARKER_LOC_START]) { + sp_shape_print_invoke_marker_printing(shape->marker[SP_MARKER_LOC_START], tr, style, ctx); + } + if (shape->marker[SP_MARKER_LOC]) { + sp_shape_print_invoke_marker_printing(shape->marker[SP_MARKER_LOC], tr, style, ctx); } - - tr = marker_item->transform * marker->c2p * tr; - - Geom::Matrix old_tr = marker_item->transform; - marker_item->transform = tr; - sp_item_invoke_print (marker_item, ctx); - marker_item->transform = old_tr; } - if ( shape->marker[SP_MARKER_LOC_MID] && (path_it->size_default() > 1) ) { + if ( (shape->marker[SP_MARKER_LOC_MID] || shape->marker[SP_MARKER_LOC]) && (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,32 +693,21 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) /* 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 */ - - SPMarker* marker = SP_MARKER (shape->marker[SP_MARKER_LOC_MID]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[SP_MARKER_LOC_MID])); - Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + if (shape->marker[SP_MARKER_LOC_MID]) { + sp_shape_print_invoke_marker_printing(shape->marker[SP_MARKER_LOC_MID], tr, style, ctx); + } + if (shape->marker[SP_MARKER_LOC]) { + sp_shape_print_invoke_marker_printing(shape->marker[SP_MARKER_LOC], tr, style, ctx); } - - tr = marker_item->transform * marker->c2p * tr; - - Geom::Matrix old_tr = marker_item->transform; - marker_item->transform = tr; - sp_item_invoke_print (marker_item, ctx); - marker_item->transform = old_tr; ++curve_it1; ++curve_it2; } } - if ( shape->marker[SP_MARKER_LOC_END] ) { - 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])); - + if ( shape->marker[SP_MARKER_LOC_END] || shape->marker[SP_MARKER_LOC]) { /* 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(); @@ -711,16 +718,12 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + if (shape->marker[SP_MARKER_LOC_END]) { + sp_shape_print_invoke_marker_printing(shape->marker[SP_MARKER_LOC_END], tr, style, ctx); + } + if (shape->marker[SP_MARKER_LOC]) { + sp_shape_print_invoke_marker_printing(shape->marker[SP_MARKER_LOC], tr, style, ctx); } - - tr = marker_item->transform * marker->c2p * tr; - - Geom::Matrix old_tr = marker_item->transform; - marker_item->transform = tr; - sp_item_invoke_print (marker_item, ctx); - marker_item->transform = old_tr; } } @@ -822,7 +825,8 @@ sp_shape_has_markers (SPShape const *shape) return ( shape->curve && - (shape->marker[SP_MARKER_LOC_START] || + (shape->marker[SP_MARKER_LOC] || + shape->marker[SP_MARKER_LOC_START] || shape->marker[SP_MARKER_LOC_MID] || shape->marker[SP_MARKER_LOC_END]) ); @@ -840,6 +844,19 @@ sp_shape_number_of_markers (SPShape *shape, int type) Geom::PathVector const & pathv = shape->curve->get_pathvector(); switch(type) { + case SP_MARKER_LOC: + { + if ( shape->marker[SP_MARKER_LOC] ) { + guint n = 2*pathv.size(); + for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { + n += path_it->size(); + n += path_it->closed() ? 1 : 0; + } + return n; + } else { + return 0; + } + } case SP_MARKER_LOC_START: return shape->marker[SP_MARKER_LOC_START] ? pathv.size() : 0; @@ -859,17 +876,7 @@ sp_shape_number_of_markers (SPShape *shape, int type) case SP_MARKER_LOC_END: { - if ( shape->marker[SP_MARKER_LOC_END] ) { - guint n = 0; - for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { - if (!path_it->empty()) { - n++; - } - } - return n; - } else { - return 0; - } + return shape->marker[SP_MARKER_LOC_END] ? pathv.size() : 0; } default: @@ -890,20 +897,20 @@ sp_shape_marker_release (SPObject *marker, SPShape *shape) item = (SPItem *) shape; - for (i = SP_MARKER_LOC_START; i < SP_MARKER_LOC_QTY; i++) { - if (marker == shape->marker[i]) { - SPItemView *v; - /* Hide marker */ - for (v = item->display; v != NULL; v = v->next) { - sp_marker_hide ((SPMarker *) (shape->marker[i]), NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i); - /* fixme: Do we need explicit remove here? (Lauris) */ - /* nr_arena_item_set_mask (v->arenaitem, NULL); */ + for (i = 0; i < SP_MARKER_LOC_QTY; i++) { + if (marker == shape->marker[i]) { + SPItemView *v; + /* Hide marker */ + for (v = item->display; v != NULL; v = v->next) { + sp_marker_hide ((SPMarker *) (shape->marker[i]), NR_ARENA_ITEM_GET_KEY (v->arenaitem) + i); + /* fixme: Do we need explicit remove here? (Lauris) */ + /* nr_arena_item_set_mask (v->arenaitem, NULL); */ + } + /* Detach marker */ + shape->release_connect[i].disconnect(); + shape->modified_connect[i].disconnect(); + shape->marker[i] = sp_object_hunref (shape->marker[i], item); } - /* Detach marker */ - shape->release_connect[i].disconnect(); - shape->modified_connect[i].disconnect(); - shape->marker[i] = sp_object_hunref (shape->marker[i], item); - } } } @@ -930,7 +937,7 @@ sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value) SPItem *item = (SPItem *) object; SPShape *shape = (SPShape *) object; - if (key < SP_MARKER_LOC_START || key > SP_MARKER_LOC_END) { + if (key < 0 || key > SP_MARKER_LOC_END) { return; } diff --git a/src/splivarot.cpp b/src/splivarot.cpp index c57c58a14..f6ae9baa0 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -858,46 +858,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 ); + } } } -- 2.30.2