X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-use.cpp;h=36372e67b4f3f8a5a0c7fadb0d98a6e994cb93b9;hb=ea479a317d3fb2890308a1cc99ee730dd7b76de8;hp=5b2ed9e239c81d23eb41de9247120753bcffb97a;hpb=3caca4f8381f7ae35678d16074c2414c02a0c0ff;p=inkscape.git diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 5b2ed9e23..36372e67b 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -16,9 +16,13 @@ #ifdef HAVE_CONFIG_H # include #endif + +#include +#include + #include #include -#include "libnr/nr-matrix-translate-ops.h" +#include <2geom/transforms.h> #include #include "display/nr-arena-group.h" #include "attributes.h" @@ -28,7 +32,7 @@ #include "uri.h" #include "print.h" #include "xml/repr.h" -#include "prefs-utils.h" +#include "preferences.h" #include "style.h" #include "sp-symbol.h" #include "sp-use.h" @@ -43,11 +47,12 @@ static void sp_use_finalize(GObject *obj); static void sp_use_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); static void sp_use_release(SPObject *object); static void sp_use_set(SPObject *object, unsigned key, gchar const *value); -static Inkscape::XML::Node *sp_use_write(SPObject *object, Inkscape::XML::Node *repr, guint flags); +static Inkscape::XML::Node *sp_use_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static void sp_use_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_use_modified(SPObject *object, guint flags); -static void sp_use_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags); +static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_use_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); static void sp_use_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_use_description(SPItem *item); static NRArenaItem *sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags); @@ -59,7 +64,7 @@ static void sp_use_delete_self(SPObject *deleted, SPUse *self); static SPItemClass *parent_class; -//void m_print(gchar *say, NR::Matrix m) +//void m_print(gchar *say, Geom::Matrix m) //{ g_print("%s %g %g %g %g %g %g\n", say, m[0], m[1], m[2], m[3], m[4], m[5]); } GType @@ -107,6 +112,7 @@ sp_use_class_init(SPUseClass *classname) item_class->print = sp_use_print; item_class->show = sp_use_show; item_class->hide = sp_use_hide; + item_class->snappoints = sp_use_snappoints; } static void @@ -133,6 +139,12 @@ sp_use_finalize(GObject *obj) { SPUse *use = (SPUse *) obj; + if (use->child) { + sp_object_detach(SP_OBJECT(obj), use->child); + use->child = NULL; + } + + use->ref->detach(); delete use->ref; use->_delete_connection.~connection(); @@ -164,7 +176,10 @@ sp_use_release(SPObject *object) { SPUse *use = SP_USE(object); - use->child = NULL; + if (use->child) { + sp_object_detach(object, use->child); + use->child = NULL; + } use->_delete_connection.disconnect(); use->_changed_connection.disconnect(); @@ -236,17 +251,16 @@ sp_use_set(SPObject *object, unsigned key, gchar const *value) } static Inkscape::XML::Node * -sp_use_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) +sp_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { SPUse *use = SP_USE(object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object)); repr = xml_doc->createElement("svg:use"); } if (((SPObjectClass *) (parent_class))->write) { - ((SPObjectClass *) (parent_class))->write(object, repr, flags); + ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags); } sp_repr_set_svg_double(repr, "x", use->x.computed); @@ -264,15 +278,15 @@ sp_use_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) } static void -sp_use_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags) +sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) { SPUse const *use = SP_USE(item); if (use->child && SP_IS_ITEM(use->child)) { SPItem *child = SP_ITEM(use->child); - NR::Matrix const ct( child->transform - * NR::translate(use->x.computed, - use->y.computed) + Geom::Matrix const ct( child->transform + * Geom::Translate(use->x.computed, + use->y.computed) * transform ); sp_item_invoke_bbox_full(child, bbox, ct, flags, FALSE); } @@ -282,12 +296,11 @@ static void sp_use_print(SPItem *item, SPPrintContext *ctx) { bool translated = false; - NRMatrix tp; SPUse *use = SP_USE(item); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { - nr_matrix_set_translate(&tp, use->x.computed, use->y.computed); - sp_print_bind(ctx, &tp, 1.0); + Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed)); + sp_print_bind(ctx, tp, 1.0); translated = true; } @@ -340,11 +353,10 @@ sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags) NRArenaItem *ac = sp_item_invoke_show(SP_ITEM(use->child), arena, key, flags); if (ac) { nr_arena_item_add_child(ai, ac, NULL); - nr_arena_item_unref(ac); } - NR::translate t(use->x.computed, + Geom::Translate t(use->x.computed, use->y.computed); - nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), NR::Matrix(t)); + nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), Geom::Matrix(t)); } return ai; @@ -366,7 +378,8 @@ sp_use_hide(SPItem *item, unsigned key) /** * Returns the ultimate original of a SPUse (i.e. the first object in the chain of its originals - * which is not an SPUse). + * which is not an SPUse). If no original is found, NULL is returned (it is the responsibility + * of the caller to make sure that this is handled correctly). * * Note that the returned is the clone object, i.e. the child of an SPUse (of the argument one for * the trivial case) and not the "true original". @@ -378,7 +391,7 @@ sp_use_root(SPUse *use) while (SP_IS_USE(orig)) { orig = SP_USE(orig)->child; } - g_assert(SP_IS_ITEM(orig)); + g_return_val_if_fail(SP_IS_ITEM(orig), NULL); return SP_ITEM(orig); } @@ -386,7 +399,7 @@ sp_use_root(SPUse *use) * Returns the effective transform that goes from the ultimate original to given SPUse, both ends * included. */ -NR::Matrix +Geom::Matrix sp_use_get_root_transform(SPUse *use) { //track the ultimate source of a chain of uses @@ -401,7 +414,7 @@ sp_use_get_root_transform(SPUse *use) //calculate the accummulated transform, starting from the original - NR::Matrix t(NR::identity()); + Geom::Matrix t(Geom::identity()); for (GSList *i = chain; i != NULL; i = i->next) { SPItem *i_tem = SP_ITEM(i->data); @@ -411,7 +424,7 @@ sp_use_get_root_transform(SPUse *use) if (SP_IS_USE(i_tem)) { SPUse *i_use = SP_USE(i_tem); if ((i_use->x._set && i_use->x.computed != 0) || (i_use->y._set && i_use->y.computed != 0)) { - t = t * NR::translate(i_use->x._set ? i_use->x.computed : 0, i_use->y._set ? i_use->y.computed : 0); + t = t * Geom::Translate(i_use->x._set ? i_use->x.computed : 0, i_use->y._set ? i_use->y.computed : 0); } } @@ -426,12 +439,12 @@ sp_use_get_root_transform(SPUse *use) * Returns the transform that leads to the use from its immediate original. * Does not inlcude the original's transform if any. */ -NR::Matrix +Geom::Matrix sp_use_get_parent_transform(SPUse *use) { - NR::Matrix t(NR::identity()); + Geom::Matrix t(Geom::identity()); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { - t *= NR::translate(use->x._set ? use->x.computed : 0, + t *= Geom::Translate(use->x._set ? use->x.computed : 0, use->y._set ? use->y.computed : 0); } @@ -445,7 +458,7 @@ sp_use_get_parent_transform(SPUse *use) * clone's transform. */ static void -sp_use_move_compensate(NR::Matrix const *mp, SPItem *original, SPUse *self) +sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self) { // the clone is orphaned; or this is not a real use, but a clone of another use; // we skip it, otherwise duplicate compensation will occur @@ -458,31 +471,32 @@ sp_use_move_compensate(NR::Matrix const *mp, SPItem *original, SPUse *self) return; } - guint mode = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_PARALLEL); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL); // user wants no compensation if (mode == SP_CLONE_COMPENSATION_NONE) return; - NR::Matrix m(*mp); + Geom::Matrix m(*mp); // this is not a simple move, do not try to compensate - if (!(m.is_translation())) + if (!(m.isTranslation())) return; // restore item->transform field from the repr, in case it was changed by seltrans sp_object_read_attr (SP_OBJECT (self), "transform"); - NR::Matrix t = sp_use_get_parent_transform(self); - NR::Matrix clone_move = t.inverse() * m * t; + Geom::Matrix t = sp_use_get_parent_transform(self); + Geom::Matrix clone_move = t.inverse() * m * t; // calculate the compensation matrix and the advertized movement matrix - NR::Matrix advertized_move; + Geom::Matrix advertized_move; if (mode == SP_CLONE_COMPENSATION_PARALLEL) { clone_move = clone_move.inverse() * m; advertized_move = m; } else if (mode == SP_CLONE_COMPENSATION_UNMOVED) { clone_move = clone_move.inverse(); - advertized_move.set_identity(); + advertized_move.setIdentity(); } else { g_assert_not_reached(); } @@ -495,7 +509,7 @@ sp_use_move_compensate(NR::Matrix const *mp, SPItem *original, SPUse *self) } static void -sp_use_href_changed(SPObject *old_ref, SPObject *ref, SPUse *use) +sp_use_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPUse *use) { SPItem *item = SP_ITEM(use); @@ -524,7 +538,6 @@ sp_use_href_changed(SPObject *old_ref, SPObject *ref, SPUse *use) ai = sp_item_invoke_show(SP_ITEM(use->child), NR_ARENA_ITEM_ARENA(v->arenaitem), v->key, v->flags); if (ai) { nr_arena_item_add_child(v->arenaitem, ai, NULL); - nr_arena_item_unref(ai); } } @@ -536,7 +549,7 @@ sp_use_href_changed(SPObject *old_ref, SPObject *ref, SPUse *use) } static void -sp_use_delete_self(SPObject *deleted, SPUse *self) +sp_use_delete_self(SPObject */*deleted*/, SPUse *self) { // always delete uses which are used in flowtext if (SP_OBJECT_PARENT(self) && SP_IS_FLOWREGION(SP_OBJECT_PARENT(self))) { @@ -544,7 +557,8 @@ sp_use_delete_self(SPObject *deleted, SPUse *self) return; } - guint const mode = prefs_get_int_attribute("options.cloneorphans", "value", + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + guint const mode = prefs->getInt("/options/cloneorphans/value", SP_CLONE_ORPHANS_UNLINK); if (mode == SP_CLONE_ORPHANS_UNLINK) { @@ -570,7 +584,7 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags) if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = SP_ITEM(object)->display; v != NULL; v = v->next) { - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); } } @@ -591,7 +605,7 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags) cctx.vp.y0 = 0.0; cctx.vp.x1 = use->width.computed; cctx.vp.y1 = use->height.computed; - cctx.i2vp = NR::identity(); + cctx.i2vp = Geom::identity(); flags&=~SP_OBJECT_USER_MODIFIED_FLAG_B; if (use->child) { @@ -611,9 +625,8 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags) /* As last step set additional transform of arena group */ for (SPItemView *v = item->display; v != NULL; v = v->next) { - NRMatrix t; - nr_matrix_set_translate(&t, use->x.computed, use->y.computed); - nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t); + Geom::Matrix t(Geom::Translate(use->x.computed, use->y.computed)); + nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), t); } } @@ -629,7 +642,7 @@ sp_use_modified(SPObject *object, guint flags) if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = SP_ITEM(object)->display; v != NULL; v = v->next) { - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); } } @@ -657,19 +670,20 @@ sp_use_unlink(SPUse *use) // Track the ultimate source of a chain of uses. SPItem *orig = sp_use_root(use); + g_return_val_if_fail(orig, NULL); // Calculate the accumulated transform, starting from the original. - NR::Matrix t = sp_use_get_root_transform(use); + Geom::Matrix t = sp_use_get_root_transform(use); Inkscape::XML::Node *copy = NULL; if (SP_IS_SYMBOL(orig)) { // make a group, copy children copy = xml_doc->createElement("svg:g"); for (Inkscape::XML::Node *child = SP_OBJECT_REPR(orig)->firstChild() ; child != NULL; child = child->next()) { - Inkscape::XML::Node *newchild = child->duplicate(); + Inkscape::XML::Node *newchild = child->duplicate(xml_doc); copy->appendChild(newchild); } } else { // just copy - copy = SP_OBJECT_REPR(orig)->duplicate(); + copy = SP_OBJECT_REPR(orig)->duplicate(xml_doc); } // Add the duplicate repr just after the existing one. @@ -712,10 +726,9 @@ sp_use_unlink(SPUse *use) SPItem *item = SP_ITEM(unlinked); // Set the accummulated transform. { - NR::Matrix nomove(NR::identity()); - NRMatrix ctrans = t.operator const NRMatrix&(); + Geom::Matrix nomove(Geom::identity()); // Advertise ourselves as not moving. - sp_item_write_transform(item, SP_OBJECT_REPR(item), &ctrans, &nomove); + sp_item_write_transform(item, SP_OBJECT_REPR(item), t, &nomove); } return item; } @@ -727,6 +740,23 @@ sp_use_get_original(SPUse *use) return ref; } +static void +sp_use_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +{ + g_assert (item != NULL); + g_assert (SP_IS_ITEM(item)); + g_assert (SP_IS_USE(item)); + + SPUse *use = SP_USE(item); + SPItem *root = sp_use_root(use); + g_return_if_fail(root); + + SPItemClass const &item_class = *(SPItemClass const *) G_OBJECT_GET_CLASS(root); + if (item_class.snappoints) { + item_class.snappoints(root, p, snapprefs); + } +} + /* Local Variables: