diff options
| author | Martin Owens <doctormo@gmail.com> | 2014-03-27 01:33:44 +0000 |
|---|---|---|
| committer | Martin Owens <doctormo@gmail.com> | 2014-03-27 01:33:44 +0000 |
| commit | 5a4fb2325f60d292b47330f540b26a3279341c90 (patch) | |
| tree | d2aa7967be25450b83e625025366c618101ae49f /src/sp-shape.cpp | |
| parent | The Polar Arrange Tab of the Arrange Dialog now hides the parametric (diff) | |
| parent | Remove Snap menu item and improve grid menu item text (diff) | |
| download | inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.tar.gz inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.zip | |
Commit a merge to trunk, with probabal errors
(bzr r11073.1.36)
Diffstat (limited to 'src/sp-shape.cpp')
| -rw-r--r-- | src/sp-shape.cpp | 556 |
1 files changed, 236 insertions, 320 deletions
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index f27b3c9db..b3a331cba 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -53,111 +53,34 @@ #define noSHAPE_VERBOSE -void sp_shape_print (SPItem * item, SPPrintContext * ctx); +static void sp_shape_update_marker_view (SPShape *shape, Inkscape::DrawingItem *ai); -SPLPEItemClass * SPShapeClass::parent_class = 0; - -/** - * Registers the SPShape class with Gdk and returns its type number. - */ -GType SPShape::getType(void) -{ - static GType type = 0; - if (!type) { - GTypeInfo info = { - sizeof (SPShapeClass), - NULL, NULL, - (GClassInitFunc) SPShapeClass::sp_shape_class_init, - NULL, NULL, - sizeof (SPShape), - 16, - (GInstanceInitFunc) sp_shape_init, - NULL, /* value_table */ - }; - type = g_type_register_static (SP_TYPE_LPE_ITEM, "SPShape", &info, (GTypeFlags)0); +SPShape::SPShape() : SPLPEItem() { + for ( int i = 0 ; i < SP_MARKER_LOC_QTY ; i++ ) { + new (&this->_release_connect[i]) sigc::connection(); + new (&this->_modified_connect[i]) sigc::connection(); + this->_marker[i] = NULL; } - return type; -} -/** - * Initializes a SPShapeClass object. Establishes the function pointers to the class' - * member routines in the class vtable, and sets pointers to parent classes. - */ -void SPShapeClass::sp_shape_class_init(SPShapeClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - SPObjectClass *sp_object_class = SP_OBJECT_CLASS(klass); - SPItemClass * item_class = SP_ITEM_CLASS(klass); - SPLPEItemClass * lpe_item_class = SP_LPE_ITEM_CLASS(klass); - - parent_class = (SPLPEItemClass *)g_type_class_peek_parent (klass); - - gobject_class->finalize = SPShape::sp_shape_finalize; - - sp_object_class->build = SPShape::sp_shape_build; - sp_object_class->release = SPShape::sp_shape_release; - sp_object_class->set = SPShape::sp_shape_set; - sp_object_class->update = SPShape::sp_shape_update; - sp_object_class->modified = SPShape::sp_shape_modified; - sp_object_class->write = SPShape::sp_shape_write; - - item_class->bbox = SPShape::sp_shape_bbox; - item_class->print = sp_shape_print; - item_class->show = SPShape::sp_shape_show; - item_class->hide = SPShape::sp_shape_hide; - item_class->snappoints = SPShape::sp_shape_snappoints; - lpe_item_class->update_patheffect = NULL; - - klass->set_shape = NULL; + this->_curve = NULL; + this->_curve_before_lpe = NULL; } -/** - * Initializes an SPShape object. - */ -void SPShape::sp_shape_init(SPShape *shape) -{ +SPShape::~SPShape() { 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; + this->_release_connect[i].disconnect(); + this->_modified_connect[i].disconnect(); } - shape->_curve = NULL; - shape->_curve_before_lpe = NULL; } -void SPShape::sp_shape_finalize(GObject *object) -{ - SPShape *shape=(SPShape *)object; - - for ( int i = 0 ; i < SP_MARKER_LOC_QTY ; i++ ) { - shape->_release_connect[i].disconnect(); - shape->_release_connect[i].~connection(); - shape->_modified_connect[i].disconnect(); - shape->_modified_connect[i].~connection(); - } +void SPShape::build(SPDocument *document, Inkscape::XML::Node *repr) { + SPLPEItem::build(document, repr); - if (((GObjectClass *) (SPShapeClass::parent_class))->finalize) { - (* ((GObjectClass *) (SPShapeClass::parent_class))->finalize)(object); + for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) { + sp_shape_set_marker (this, i, this->style->marker[i].value); } } -/** - * Virtual build callback for SPMarker. - * - * This is to be invoked immediately after creation of an SPShape. - * - * \see sp_object_build() - */ -void SPShape::sp_shape_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) -{ - if (((SPObjectClass *) (SPShapeClass::parent_class))->build) { - (*((SPObjectClass *) (SPShapeClass::parent_class))->build) (object, document, repr); - } - - for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) { - sp_shape_set_marker (object, i, object->style->marker[i].value); - } -} /** * Removes, releases and unrefs all children of object @@ -167,69 +90,45 @@ void SPShape::sp_shape_build(SPObject *object, SPDocument *document, Inkscape::X * by other objects. This routine also disconnects/unrefs markers and * curves attached to it. * - * \see sp_object_release() + * \see SPObject::release() */ -void SPShape::sp_shape_release(SPObject *object) -{ - SPItem *item; - SPShape *shape; - SPItemView *v; - int i; - - item = (SPItem *) object; - shape = (SPShape *) object; +void SPShape::release() { + for (int i = 0; i < SP_MARKER_LOC_QTY; i++) { + if (this->_marker[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], v->arenaitem->key() + i); + for (SPItemView *v = this->display; v != NULL; v = v->next) { + sp_marker_hide ((SPMarker *) this->_marker[i], v->arenaitem->key() + i); } - shape->_release_connect[i].disconnect(); - shape->_modified_connect[i].disconnect(); - shape->_marker[i] = sp_object_hunref (shape->_marker[i], object); + + this->_release_connect[i].disconnect(); + this->_modified_connect[i].disconnect(); + this->_marker[i] = sp_object_hunref (this->_marker[i], this); } } - if (shape->_curve) { - shape->_curve = shape->_curve->unref(); + + if (this->_curve) { + this->_curve = this->_curve->unref(); } - if (shape->_curve_before_lpe) { - shape->_curve_before_lpe = shape->_curve_before_lpe->unref(); + + if (this->_curve_before_lpe) { + this->_curve_before_lpe = this->_curve_before_lpe->unref(); } - if (((SPObjectClass *) SPShapeClass::parent_class)->release) { - ((SPObjectClass *) SPShapeClass::parent_class)->release (object); - } + SPLPEItem::release(); } - - -void SPShape::sp_shape_set(SPObject *object, unsigned int key, gchar const *value) -{ - if (((SPObjectClass *) SPShapeClass::parent_class)->set) { - ((SPObjectClass *) SPShapeClass::parent_class)->set(object, key, value); - } +void SPShape::set(unsigned int key, const gchar* value) { + SPLPEItem::set(key, value); } -Inkscape::XML::Node * SPShape::sp_shape_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) -{ - if (((SPObjectClass *)(SPShapeClass::parent_class))->write) { - ((SPObjectClass *)(SPShapeClass::parent_class))->write(object, doc, repr, flags); - } - return repr; +Inkscape::XML::Node* SPShape::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { + SPLPEItem::write(xml_doc, repr, flags); + return repr; } -/** - * Updates the shape when its attributes have changed. Also establishes - * marker objects to match the style settings. - */ -void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags) -{ - SPShape *shape = (SPShape *) object; - - if (((SPObjectClass *) (SPShapeClass::parent_class))->update) { - (* ((SPObjectClass *) (SPShapeClass::parent_class))->update) (object, ctx, flags); - } +void SPShape::update(SPCtx* ctx, guint flags) { + SPLPEItem::update(ctx, flags); /* This stanza checks that an object's marker style agrees with * the marker objects it has allocated. sp_shape_set_marker ensures @@ -237,18 +136,18 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags) * match the style. */ for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) { - sp_shape_set_marker (object, i, object->style->marker[i].value); - } + sp_shape_set_marker (this, i, this->style->marker[i].value); + } if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { - SPStyle *style = object->style; - if (style->stroke_width.unit == SP_CSS_UNIT_PERCENT) { + if (this->style->stroke_width.unit == SP_CSS_UNIT_PERCENT) { SPItemCtx *ictx = (SPItemCtx *) ctx; double const aw = 1.0 / ictx->i2vp.descrim(); - style->stroke_width.computed = style->stroke_width.value * aw; - for (SPItemView *v = ((SPItem *) (shape))->display; v != NULL; v = v->next) { + this->style->stroke_width.computed = this->style->stroke_width.value * aw; + + for (SPItemView *v = ((SPItem *) (this))->display; v != NULL; v = v->next) { Inkscape::DrawingShape *sh = dynamic_cast<Inkscape::DrawingShape *>(v->arenaitem); - sh->setStyle(style); + sh->setStyle(this->style); } } } @@ -256,32 +155,34 @@ void SPShape::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 */ - for (SPItemView *v = shape->display; v != NULL; v = v->next) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingShape *sh = dynamic_cast<Inkscape::DrawingShape *>(v->arenaitem); + if (flags & SP_OBJECT_MODIFIED_FLAG) { - sh->setPath(shape->_curve); + sh->setPath(this->_curve); } } } - if (shape->hasMarkers ()) { + if (this->hasMarkers ()) { /* Dimension marker views */ - for (SPItemView *v = shape->display; v != NULL; v = v->next) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { if (!v->arenaitem->key()) { v->arenaitem->setKey(SPItem::display_key_new (SP_MARKER_LOC_QTY)); } + for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) { - if (shape->_marker[i]) { - sp_marker_show_dimension ((SPMarker *) shape->_marker[i], + if (this->_marker[i]) { + sp_marker_show_dimension ((SPMarker *) this->_marker[i], v->arenaitem->key() + i, - shape->numberOfMarkers (i)); + this->numberOfMarkers (i)); } } } /* Update marker views */ - for (SPItemView *v = shape->display; v != NULL; v = v->next) { - sp_shape_update_marker_view (shape, v->arenaitem); + for (SPItemView *v = this->display; v != NULL; v = v->next) { + sp_shape_update_marker_view (this, v->arenaitem); } } } @@ -313,8 +214,7 @@ Geom::Affine sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve c double const angle1 = Geom::atan2(tang1); double const angle2 = Geom::atan2(tang2); - double ret_angle; - ret_angle = .5 * (angle1 + angle2); + double ret_angle = .5 * (angle1 + angle2); if ( fabs( angle2 - angle1 ) > M_PI ) { /* ret_angle is in the middle of the larger of the two sectors between angle1 and @@ -372,10 +272,9 @@ Geom::Affine sp_shape_marker_get_transform_at_end(Geom::Curve const & c) * * @todo figure out what to do when both 'marker' and for instance 'marker-end' are set. */ -void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai) +static void +sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem *ai) { - SPStyle *style = ((SPObject *) shape)->style; - // position arguments to sp_marker_show_instance, basically counts the amount of markers. int counter[4] = {0}; @@ -393,7 +292,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem if ( shape->_marker[i] ) { sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai, ai->key() + i, counter[i], m, - style->stroke_width.computed); + shape->style->stroke_width.computed); counter[i]++; } } @@ -411,7 +310,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem if ( shape->_marker[i] ) { sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai, ai->key() + i, counter[i], m, - style->stroke_width.computed); + shape->style->stroke_width.computed); counter[i]++; } } @@ -431,7 +330,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem if (shape->_marker[i]) { sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai, ai->key() + i, counter[i], m, - style->stroke_width.computed); + shape->style->stroke_width.computed); counter[i]++; } } @@ -448,7 +347,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem if (shape->_marker[i]) { sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai, ai->key() + i, counter[i], m, - style->stroke_width.computed); + shape->style->stroke_width.computed); counter[i]++; } } @@ -472,73 +371,69 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, Inkscape::DrawingItem if (shape->_marker[i]) { sp_marker_show_instance ((SPMarker* ) shape->_marker[i], ai, ai->key() + i, counter[i], m, - style->stroke_width.computed); + shape->style->stroke_width.computed); counter[i]++; } } } } -/** - * Sets modified flag for all sub-item views. - */ -void SPShape::sp_shape_modified(SPObject *object, unsigned int flags) -{ - SPShape *shape = SP_SHAPE (object); - - if (((SPObjectClass *) (SPShapeClass::parent_class))->modified) { - (* ((SPObjectClass *) (SPShapeClass::parent_class))->modified) (object, flags); - } +void SPShape::modified(unsigned int flags) { + SPLPEItem::modified(flags); if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = shape->display; v != NULL; v = v->next) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingShape *sh = dynamic_cast<Inkscape::DrawingShape *>(v->arenaitem); - sh->setStyle(object->style); + sh->setStyle(this->style); } } } -/** - * Calculates the bounding box for item, storing it into bbox. - * This also includes the bounding boxes of any markers included in the shape. - */ -Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType bboxtype) -{ - SPShape const *shape = SP_SHAPE (item); +Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const { Geom::OptRect bbox; - if (!shape->_curve) return bbox; - bbox = bounds_exact_transformed(shape->_curve->get_pathvector(), transform); - if (!bbox) return bbox; + if (!this->_curve) { + return bbox; + } + + bbox = bounds_exact_transformed(this->_curve->get_pathvector(), transform); + + if (!bbox) { + return bbox; + } if (bboxtype == SPItem::VISUAL_BBOX) { // convert the stroke to a path and calculate that path's geometric bbox - SPStyle* style = item->style; - if (!style->stroke.isNone()) { - Geom::PathVector *pathv = item_outline(item, true); // calculate bbox_only + + if (!this->style->stroke.isNone()) { + Geom::PathVector *pathv = item_outline(this, true); // calculate bbox_only + if (pathv) { bbox |= bounds_exact_transformed(*pathv, transform); delete pathv; } } + // Union with bboxes of the markers, if any - if ( shape->hasMarkers() && !shape->_curve->get_pathvector().empty() ) { + if ( this->hasMarkers() && !this->_curve->get_pathvector().empty() ) { /** \todo make code prettier! */ - Geom::PathVector const & pathv = shape->_curve->get_pathvector(); + Geom::PathVector const & pathv = this->_curve->get_pathvector(); // START marker for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START - if ( shape->_marker[i] ) { - SPMarker* marker = SP_MARKER (shape->_marker[i]); + if ( this->_marker[i] ) { + SPMarker* marker = SP_MARKER (this->_marker[i]); SPItem* marker_item = sp_item_first_item_child( marker ); if (marker_item) { Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); + if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + tr = Geom::Scale(this->style->stroke_width.computed) * tr; } // total marker transform @@ -549,12 +444,19 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra } } } + // MID marker for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID - if ( !shape->_marker[i] ) continue; - SPMarker* marker = SP_MARKER (shape->_marker[i]); + if ( !this->_marker[i] ) { + continue; + } + + SPMarker* marker = SP_MARKER (this->_marker[i]); SPItem* marker_item = sp_item_first_item_child( marker ); - if ( !marker_item ) continue; + + if ( !marker_item ) { + continue; + } for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { // START position @@ -562,38 +464,46 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front())); + if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + tr = Geom::Scale(this->style->stroke_width.computed) * tr; } + tr = marker_item->transform * marker->c2p * tr * transform; bbox |= marker_item->visualBounds(tr); } + // MID position if ( 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]); + SPMarker* marker = SP_MARKER (this->_marker[i]); SPItem* marker_item = sp_item_first_item_child( marker ); if (marker_item) { Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + tr = Geom::Scale(this->style->stroke_width.computed) * tr; } + tr = marker_item->transform * marker->c2p * tr * transform; bbox |= marker_item->visualBounds(tr); } @@ -602,26 +512,31 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra ++curve_it2; } } + // END position if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); + if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + tr = Geom::Scale(this->style->stroke_width.computed) * tr; } + tr = marker_item->transform * marker->c2p * tr * transform; - bbox |= marker_item->visualBounds(); + bbox |= marker_item->visualBounds(tr); } } } + // END marker for (unsigned 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]); + if ( this->_marker[i] ) { + SPMarker* marker = SP_MARKER (this->_marker[i]); SPItem* marker_item = sp_item_first_item_child( marker ); if (marker_item) { @@ -629,18 +544,22 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra * For moveto-only path, this returns the "closing line segment". */ Geom::Path const &path_last = pathv.back(); unsigned int index = path_last.size_default(); + if (index > 0) { index--; } + Geom::Curve const &lastcurve = path_last[index]; Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); + if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + tr = Geom::Scale(this->style->stroke_width.computed) * tr; } // total marker transform @@ -653,6 +572,7 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra } } } + return bbox; } @@ -674,40 +594,36 @@ sp_shape_print_invoke_marker_printing(SPObject *obj, Geom::Affine tr, SPStyle co 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, - * applies print fill/stroke, sets transforms for markers, and adds - * comment labels. - */ -void -sp_shape_print (SPItem *item, SPPrintContext *ctx) -{ - Geom::OptRect pbox, dbox, bbox; - SPShape *shape = SP_SHAPE(item); - - if (!shape->_curve) return; +void SPShape::print(SPPrintContext* ctx) { + if (!this->_curve) { + return; + } - Geom::PathVector const & pathv = shape->_curve->get_pathvector(); - if (pathv.empty()) return; + Geom::PathVector const & pathv = this->_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) { - gchar * comment = g_strdup_printf("begin '%s'", - item->defaultLabel()); - sp_print_comment(ctx, comment); - g_free(comment); - } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gint add_comments = prefs->getBool("/printing/debug/add-label-comments"); + + if (add_comments) { + gchar * comment = g_strdup_printf("begin '%s'", this->defaultLabel()); + sp_print_comment(ctx, comment); + g_free(comment); + } /* fixme: Think (Lauris) */ - pbox = item->geometricBounds(); - bbox = item->desktopVisualBounds(); - dbox = Geom::Rect::from_xywh(Geom::Point(0,0), item->document->getDimensions()); - Geom::Affine const i2dt(item->i2dt_affine()); + Geom::OptRect pbox, dbox, bbox; + pbox = this->geometricBounds(); + bbox = this->desktopVisualBounds(); + dbox = Geom::Rect::from_xywh(Geom::Point(0,0), this->document->getDimensions()); + + Geom::Affine const i2dt(this->i2dt_affine()); - SPStyle* style = item->style; + SPStyle* style = this->style; if (!style->fill.isNone()) { sp_print_fill (ctx, pathv, i2dt, style, pbox, dbox, bbox); @@ -720,26 +636,29 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) /** \todo make code prettier */ // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START - if ( shape->_marker[i] ) { + if ( this->_marker[i] ) { Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); - sp_shape_print_invoke_marker_printing(shape->_marker[i], tr, style, ctx); + sp_shape_print_invoke_marker_printing(this->_marker[i], tr, style, ctx); } } + // MID marker for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID - if (shape->_marker[i]) { + if (this->_marker[i]) { for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { // START position if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front())); - sp_shape_print_invoke_marker_printing(shape->_marker[i], tr, style, ctx); + sp_shape_print_invoke_marker_printing(this->_marker[i], tr, style, ctx); } + // MID position if ( 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. @@ -747,59 +666,56 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) * there should be a midpoint marker between last segment and closing straight line segment */ Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); - sp_shape_print_invoke_marker_printing(shape->_marker[i], tr, style, ctx); + sp_shape_print_invoke_marker_printing(this->_marker[i], tr, style, ctx); ++curve_it1; ++curve_it2; } } + if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); - sp_shape_print_invoke_marker_printing(shape->_marker[i], tr, style, ctx); + sp_shape_print_invoke_marker_printing(this->_marker[i], tr, style, ctx); } } } } + // END marker - if ( shape->_marker[SP_MARKER_LOC_END] || shape->_marker[SP_MARKER_LOC]) { + if ( this->_marker[SP_MARKER_LOC_END] || this->_marker[SP_MARKER_LOC]) { /* Get reference to last curve in the path. * For moveto-only path, this returns the "closing line segment". */ Geom::Path const &path_last = pathv.back(); unsigned int index = path_last.size_default(); + if (index > 0) { index--; } + Geom::Curve const &lastcurve = path_last[index]; Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END - if (shape->_marker[i]) { - sp_shape_print_invoke_marker_printing(shape->_marker[i], tr, style, ctx); + if (this->_marker[i]) { + sp_shape_print_invoke_marker_printing(this->_marker[i], tr, style, ctx); } } } - if (add_comments) { - gchar * comment = g_strdup_printf("end '%s'", - item->defaultLabel()); - sp_print_comment(ctx, comment); - g_free(comment); - } + if (add_comments) { + gchar * comment = g_strdup_printf("end '%s'", + this->defaultLabel()); + sp_print_comment(ctx, comment); + g_free(comment); + } } -/** - * Sets style, path, and paintbox. Updates marker views, including dimensions. - */ -Inkscape::DrawingItem * SPShape::sp_shape_show(SPItem *item, Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/) -{ - SPObject *object = item; - SPShape *shape = SP_SHAPE(item); - +Inkscape::DrawingItem* SPShape::show(Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/) { Inkscape::DrawingShape *s = new Inkscape::DrawingShape(drawing); - s->setStyle(object->style); - s->setPath(shape->_curve); + s->setStyle(this->style); + s->setPath(this->_curve); /* This stanza checks that an object's marker style agrees with * the marker objects it has allocated. sp_shape_set_marker ensures @@ -807,56 +723,45 @@ Inkscape::DrawingItem * SPShape::sp_shape_show(SPItem *item, Inkscape::Drawing & * match the style. */ for (int i = 0 ; i < SP_MARKER_LOC_QTY ; i++) { - sp_shape_set_marker (object, i, object->style->marker[i].value); - } - - if (shape->hasMarkers ()) { + sp_shape_set_marker (this, i, this->style->marker[i].value); + } + if (this->hasMarkers ()) { /* provide key and dimension the marker views */ if (!s->key()) { s->setKey(SPItem::display_key_new (SP_MARKER_LOC_QTY)); } for (int i = 0; i < SP_MARKER_LOC_QTY; i++) { - if (shape->_marker[i]) { - sp_marker_show_dimension ((SPMarker *) shape->_marker[i], + if (this->_marker[i]) { + sp_marker_show_dimension ((SPMarker *) this->_marker[i], s->key() + i, - shape->numberOfMarkers (i)); + this->numberOfMarkers (i)); } } /* Update marker views */ - sp_shape_update_marker_view (shape, s); + sp_shape_update_marker_view (this, s); } return s; } /** - * Hides/removes marker views from the shape. + * Sets style, path, and paintbox. Updates marker views, including dimensions. */ -void SPShape::sp_shape_hide(SPItem *item, unsigned int key) -{ - SPShape *shape; - SPItemView *v; - int i; - - shape = (SPShape *) item; - - for (i=0; i<SP_MARKER_LOC_QTY; i++) { - if (shape->_marker[i]) { - for (v = item->display; v != NULL; v = v->next) { - if (key == v->key) { - sp_marker_hide ((SPMarker *) shape->_marker[i], - v->arenaitem->key() + i); - } - } - } - } - - if (((SPItemClass *) SPShapeClass::parent_class)->hide) { - ((SPItemClass *) SPShapeClass::parent_class)->hide (item, key); - } +void SPShape::hide(unsigned int key) { + for (int i=0; i<SP_MARKER_LOC_QTY; i++) { + if (this->_marker[i]) { + for (SPItemView* v = this->display; v != NULL; v = v->next) { + if (key == v->key) { + sp_marker_hide ((SPMarker *) this->_marker[i], v->arenaitem->key() + i); + } + } + } + } + + //SPLPEItem::onHide(key); } /** @@ -869,6 +774,13 @@ int SPShape::hasMarkers() const all three settings. This should be fixed later such that if 'marker' is specified, then all three should appear. */ + // Ignore markers for objects which are inside markers themselves. + for (SPObject *parent = this->parent; parent != NULL; parent = parent->parent) { + if(SP_IS_MARKER(parent)) { + return 0; + } + } + return ( this->_curve && (this->_marker[SP_MARKER_LOC] || @@ -884,14 +796,14 @@ int SPShape::hasMarkers() const * \param type Marker type (e.g. SP_MARKER_LOC_START) * \return Number of markers that the shape has of this type. */ -int SPShape::numberOfMarkers(int type) -{ +int SPShape::numberOfMarkers(int type) const { Geom::PathVector const & pathv = this->_curve->get_pathvector(); + if (pathv.size() == 0) { return 0; } - switch(type) { + case SP_MARKER_LOC: { if ( this->_marker[SP_MARKER_LOC] ) { @@ -915,7 +827,9 @@ int SPShape::numberOfMarkers(int type) for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { n += path_it->size_default() + 1; } - return n - 2; // minus the start and end marker. + n = (n > 1) ? (n - 2) : 0; // Minus the start and end marker, but never negative. + // A path or polyline may have only one point. + return n; } else { return 0; } @@ -1013,19 +927,16 @@ sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value) } } - +// CPPIFY: make pure virtual +void SPShape::set_shape() { + //throw; +} /* Shape section */ /** * Calls any registered handlers for the set_shape action */ -void SPShape::setShape() -{ - if (SP_SHAPE_CLASS (G_OBJECT_GET_CLASS (this))->set_shape) { - SP_SHAPE_CLASS (G_OBJECT_GET_CLASS (this))->set_shape (this); - } -} /** * Adds a curve to the shape. If owner is specified, a reference @@ -1038,6 +949,7 @@ void SPShape::setCurve(SPCurve *new_curve, unsigned int owner) if (_curve) { _curve = _curve->unref(); } + if (new_curve) { if (owner) { _curve = new_curve->ref(); @@ -1045,6 +957,7 @@ void SPShape::setCurve(SPCurve *new_curve, unsigned int owner) _curve = new_curve->copy(); } } + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } @@ -1057,6 +970,7 @@ SPShape::setCurveBeforeLPE (SPCurve *new_curve) if (_curve_before_lpe) { _curve_before_lpe = _curve_before_lpe->unref(); } + if (new_curve) { _curve_before_lpe = new_curve->ref(); } @@ -1070,6 +984,7 @@ SPCurve * SPShape::getCurve() const if (_curve) { return _curve->copy(); } + return NULL; } @@ -1078,7 +993,7 @@ SPCurve * SPShape::getCurve() const */ SPCurve * SPShape::getCurveBeforeLPE() const { - if (sp_lpe_item_has_path_effect(this)) { + if (hasPathEffect()) { if (_curve_before_lpe) { return this->_curve_before_lpe->copy(); } @@ -1087,6 +1002,7 @@ SPCurve * SPShape::getCurveBeforeLPE() const return _curve->copy(); } } + return NULL; } @@ -1098,6 +1014,7 @@ void SPShape::setCurveInsync(SPCurve *new_curve, unsigned int owner) if (_curve) { _curve = _curve->unref(); } + if (new_curve) { if (owner) { _curve = new_curve->ref(); @@ -1107,27 +1024,22 @@ void SPShape::setCurveInsync(SPCurve *new_curve, unsigned int owner) } } -/** - * Return all nodes in a path that are to be considered for snapping - */ -void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) -{ - g_assert(item != NULL); - g_assert(SP_IS_SHAPE(item)); - - SPShape const *shape = SP_SHAPE(item); - if (shape->_curve == NULL) { +void SPShape::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const { + if (this->_curve == NULL) { return; } - Geom::PathVector const &pathv = shape->_curve->get_pathvector(); - if (pathv.empty()) + Geom::PathVector const &pathv = this->_curve->get_pathvector(); + + if (pathv.empty()) { return; + } - Geom::Affine const i2dt (item->i2dt_affine ()); + Geom::Affine const i2dt (this->i2dt_affine ()); if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_OBJECT_MIDPOINT)) { - Geom::OptRect bbox = item->desktopVisualBounds(); + Geom::OptRect bbox = this->desktopVisualBounds(); + if (bbox) { p.push_back(Inkscape::SnapCandidatePoint(bbox->midpoint(), Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); } @@ -1141,6 +1053,7 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve + while (curve_it1 != path_it->end_default()) { // For each path: consider midpoints of line segments for snapping @@ -1168,6 +1081,7 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap if (c1 || c2) { Inkscape::SnapSourceType sst; Inkscape::SnapTargetType stt; + switch (nodetype) { case Geom::NODE_CUSP: sst = Inkscape::SNAPSOURCE_NODE_CUSP; @@ -1183,6 +1097,7 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap stt = Inkscape::SNAPTARGET_UNDEFINED; break; } + p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2dt, sst, stt)); } } @@ -1193,10 +1108,12 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap // Find the internal intersections of each path and consider these for snapping // (using "Method 1" as described in Inkscape::ObjectSnapper::_collectNodes()) - if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_PATH_INTERSECTION)) { + if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_PATH_INTERSECTION) || snapprefs->isSourceSnappable(Inkscape::SNAPSOURCE_PATH_INTERSECTION)) { Geom::Crossings cs; + try { - cs = self_crossings(*path_it); + cs = self_crossings(*path_it); // This can be slow! + if (!cs.empty()) { // 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); @@ -1210,7 +1127,6 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap } } - } /* |
