X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsp-item-group.cpp;h=7ac7880a79d0e17a9653a6212d09aba2e84fa479;hb=d91c7044b45dde766203822b19e4affead5ce10f;hp=d0338f369ecc8bba93bd5d6632f308ddd062b97f;hpb=e9b6af083e34e2397a8ddbe9781920733d09d151;p=inkscape.git diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index d0338f369..7ac7880a7 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -34,6 +34,7 @@ #include "sp-item-transform.h" #include "sp-root.h" #include "sp-use.h" +#include "sp-offset.h" #include "sp-clippath.h" #include "sp-mask.h" #include "sp-path.h" @@ -42,6 +43,7 @@ #include "inkscape.h" #include "desktop-handles.h" #include "selection.h" +#include "live_effects/effect.h" #include "live_effects/lpeobject.h" #include "live_effects/lpeobject-reference.h" #include "sp-title.h" @@ -68,10 +70,10 @@ static gchar * sp_group_description (SPItem * item); static Geom::Matrix sp_group_set_transform(SPItem *item, Geom::Matrix const &xform); static NRArenaItem *sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static void sp_group_hide (SPItem * item, unsigned int key); -static void sp_group_snappoints (SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_group_snappoints (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_group_update_patheffect(SPLPEItem *lpeitem, bool write); -static void sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup); +static void sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write); static SPLPEItemClass * parent_class; @@ -338,14 +340,14 @@ sp_group_hide (SPItem *item, unsigned int key) SP_GROUP(item)->group->hide(key); } -static void sp_group_snappoints (SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_group_snappoints (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { for (SPObject const *o = sp_object_first_child(SP_OBJECT(item)); o != NULL; o = SP_OBJECT_NEXT(o)) { if (SP_IS_ITEM(o)) { - sp_item_snappoints(SP_ITEM(o), p, snapprefs); + sp_item_snappoints(SP_ITEM(o), target, p, snapprefs); } } } @@ -366,18 +368,18 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) g_return_if_fail (!strcmp (grepr->name(), "svg:g") || !strcmp (grepr->name(), "svg:a") || !strcmp (grepr->name(), "svg:switch")); - // this converts the gradient/pattern fill/stroke on the group, if any, to userSpaceOnUse - sp_item_adjust_paint_recursive (gitem, NR::identity(), NR::identity(), false); + // this converts the gradient/pattern fill/stroke on the group, if any, to userSpaceOnUse + sp_item_adjust_paint_recursive (gitem, Geom::identity(), Geom::identity(), false); SPItem *pitem = SP_ITEM (SP_OBJECT_PARENT (gitem)); Inkscape::XML::Node *prepr = SP_OBJECT_REPR (pitem); - if (SP_IS_BOX3D(gitem)) { - group = box3d_convert_to_group(SP_BOX3D(gitem)); - gitem = SP_ITEM(group); - } + if (SP_IS_BOX3D(gitem)) { + group = box3d_convert_to_group(SP_BOX3D(gitem)); + gitem = SP_ITEM(group); + } - sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(group), false); + sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(group), false); /* Step 1 - generate lists of children objects */ GSList *items = NULL; @@ -391,7 +393,7 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) /* Merging of style */ // this converts the gradient/pattern fill/stroke, if any, to userSpaceOnUse; we need to do // it here _before_ the new transform is set, so as to use the pre-transform bbox - sp_item_adjust_paint_recursive (citem, NR::identity(), NR::identity(), false); + sp_item_adjust_paint_recursive (citem, Geom::identity(), Geom::identity(), false); sp_style_merge_from_dying_parent(SP_OBJECT_STYLE(child), SP_OBJECT_STYLE(gitem)); /* @@ -428,7 +430,24 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) // make sure a clone's effective transform is the same as was under group ctrans = g.inverse() * citem->transform * g; } else { - ctrans = citem->transform * g; + // We should not apply the group's transformation to both a linked offset AND to its source + if (SP_IS_OFFSET(citem)) { // Do we have an offset at hand (whether it's dynamic or linked)? + SPItem *source = sp_offset_get_source(SP_OFFSET(citem)); + // When dealing with a chain of linked offsets, the transformation of an offset will be + // tied to the transformation of the top-most source, not to any of the intermediate + // offsets. So let's find the top-most source + while (source != NULL && SP_IS_OFFSET(source)) { + source = sp_offset_get_source(SP_OFFSET(source)); + } + if (source != NULL && // If true then we must be dealing with a linked offset ... + SP_OBJECT(group)->isAncestorOf(SP_OBJECT(source)) == false) { // ... of which the source is not in the same group + ctrans = citem->transform * g; // then we should apply the transformation of the group to the offset + } else { + ctrans = citem->transform; + } + } else { + ctrans = citem->transform * g; + } } // FIXME: constructing a transform that would fully preserve the appearance of a @@ -443,7 +462,7 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) // (i.e. optimized into the object if the corresponding preference is set) gchar *affinestr=sp_svg_transform_write(ctrans); nrepr->setAttribute("transform", affinestr); - g_free(affinestr); + g_free(affinestr); items = g_slist_prepend (items, nrepr); @@ -464,11 +483,11 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) if (objects) { Inkscape::XML::Node *last_def = SP_OBJECT_REPR(defs)->lastChild(); while (objects) { - Inkscape::XML::Node *repr = (Inkscape::XML::Node *) objects->data; - if (!sp_repr_is_meta_element(repr)) - SP_OBJECT_REPR(defs)->addChild(repr, last_def); - Inkscape::GC::release(repr); - objects = g_slist_remove (objects, objects->data); + Inkscape::XML::Node *repr = (Inkscape::XML::Node *) objects->data; + if (!sp_repr_is_meta_element(repr)) + SP_OBJECT_REPR(defs)->addChild(repr, last_def); + Inkscape::GC::release(repr); + objects = g_slist_remove (objects, objects->data); } } @@ -476,7 +495,7 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) while (items) { Inkscape::XML::Node *repr = (Inkscape::XML::Node *) items->data; // add item - prepr->appendChild(repr); + prepr->appendChild(repr); // restore position; since the items list was prepended (i.e. reverse), we now add // all children at the same pos, which inverts the order once again repr->setPosition(pos > 0 ? pos : 0); @@ -504,15 +523,12 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) GSList * sp_item_group_item_list (SPGroup * group) { - GSList *s; - SPObject *o; - g_return_val_if_fail (group != NULL, NULL); g_return_val_if_fail (SP_IS_GROUP (group), NULL); - s = NULL; + GSList *s = NULL; - for ( o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { + for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { if (SP_IS_ITEM (o)) { s = g_slist_prepend (s, o); } @@ -701,7 +717,7 @@ void CGroup::onModified(guint flags) { void CGroup::calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) { - boost::optional dummy_bbox; + Geom::OptRect dummy_bbox; GSList *l = _group->childList(false, SPObject::ActionBBox); while (l) { @@ -836,35 +852,44 @@ sp_group_update_patheffect (SPLPEItem *lpeitem, bool write) for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++) { LivePathEffectObject *lpeobj = (*it)->lpeobject; - if (lpeobj->get_lpe()) { + if (lpeobj && lpeobj->get_lpe()) { lpeobj->get_lpe()->doBeforeEffect(lpeitem); } } - sp_group_perform_patheffect(SP_GROUP(lpeitem), SP_GROUP(lpeitem)); + sp_group_perform_patheffect(SP_GROUP(lpeitem), SP_GROUP(lpeitem), write); } } static void -sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup) +sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) { GSList const *item_list = sp_item_group_item_list(SP_GROUP(group)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast(iter->data); if (SP_IS_GROUP(subitem)) { - sp_group_perform_patheffect(SP_GROUP(subitem), topgroup); + sp_group_perform_patheffect(SP_GROUP(subitem), topgroup, write); } else if (SP_IS_SHAPE(subitem)) { - SPCurve * c = sp_shape_get_curve(SP_SHAPE(subitem)); + SPCurve * c = NULL; + if (SP_IS_PATH(subitem)) { + c = sp_path_get_original_curve(SP_PATH(subitem)); + } else { + c = sp_shape_get_curve(SP_SHAPE(subitem)); + } // only run LPEs when the shape has a curve defined if (c) { sp_lpe_item_perform_path_effect(SP_LPE_ITEM(topgroup), c); sp_shape_set_curve(SP_SHAPE(subitem), c, TRUE); - Inkscape::XML::Node *repr = SP_OBJECT_REPR(subitem); - - gchar *str = sp_svg_write_path(c->get_pathvector()); - repr->setAttribute("d", str); - g_free(str); + if (write) { + Inkscape::XML::Node *repr = SP_OBJECT_REPR(subitem); + gchar *str = sp_svg_write_path(c->get_pathvector()); + repr->setAttribute("d", str); +#ifdef GROUP_VERBOSE +g_message("sp_group_perform_patheffect writes 'd' attribute"); +#endif + g_free(str); + } c->unref(); }