diff options
Diffstat (limited to 'src/sp-item-group.cpp')
| -rw-r--r-- | src/sp-item-group.cpp | 233 |
1 files changed, 179 insertions, 54 deletions
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 83d67cf5a..88b2bb1f9 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -15,7 +15,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include <config.h> #endif #include <glibmm/i18n.h> @@ -32,16 +32,13 @@ #include "attributes.h" #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" #include "box3d.h" #include "persp3d.h" -#include "inkscape.h" -#include "selection.h" #include "live_effects/effect.h" #include "live_effects/lpeobject.h" #include "live_effects/lpeobject-reference.h" @@ -50,9 +47,11 @@ #include "sp-switch.h" #include "sp-defs.h" #include "verbs.h" -#include "layer-model.h" #include "sp-textpath.h" #include "sp-flowtext.h" +#include "selection-chemistry.h" +#include "xml/sp-css-attr.h" +#include "svg/css-ostringstream.h" using Inkscape::DocumentUndo; @@ -133,7 +132,7 @@ void SPGroup::remove_child(Inkscape::XML::Node *child) { void SPGroup::order_changed (Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref) { - SPLPEItem::order_changed(child, old_ref, new_ref); + SPLPEItem::order_changed(child, old_ref, new_ref); SPItem *item = dynamic_cast<SPItem *>(get_child_by_repr(child)); if ( item ) { @@ -200,11 +199,18 @@ void SPGroup::modified(guint flags) { // std::cout << "SPGroup::modified(): " << (getId()?getId():"null") << std::endl; SPLPEItem::modified(flags); if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { + Inkscape::DrawingGroup *group = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); + group->setStyle(this->style); + } + } + std::vector<SPObject*> l=this->childList(true); for(std::vector<SPObject*>::const_iterator i=l.begin();i!=l.end();++i){ SPObject *child = *i; @@ -231,9 +237,9 @@ Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape:: l = NULL; - for (SPObject *child = firstChild(); child; child = child->getNext() ) { - if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) { - Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags); + for (auto& child: children) { + if ( !dynamic_cast<SPTitle *>(&child) && !dynamic_cast<SPDesc *>(&child) ) { + Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { l = g_slist_prepend (l, crepr); @@ -247,9 +253,9 @@ Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape:: l = g_slist_remove (l, l->data); } } else { - for (SPObject *child = firstChild() ; child ; child = child->getNext() ) { - if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) { - child->updateRepr(flags); + for (auto& child: children) { + if ( !dynamic_cast<SPTitle *>(&child) && !dynamic_cast<SPDesc *>(&child) ) { + child.updateRepr(flags); } } } @@ -293,9 +299,8 @@ Geom::OptRect SPGroup::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox } void SPGroup::print(SPPrintContext *ctx) { - std::vector<SPObject*> l=this->childList(false); - for(std::vector<SPObject*>::const_iterator i=l.begin();i!=l.end();++i){ - SPObject *o = *i; + for(auto& child: children){ + SPObject *o = &child; SPItem *item = dynamic_cast<SPItem *>(o); if (item) { item->invoke_print(ctx); @@ -347,7 +352,7 @@ Inkscape::DrawingItem *SPGroup::show (Inkscape::Drawing &drawing, unsigned int k } void SPGroup::hide (unsigned int key) { - std::vector<SPObject*> l=this->childList(false, SPObject::ActionShow); + std::vector<SPObject*> l=this->childList(false, SPObject::ActionShow); for(std::vector<SPObject*>::const_iterator i=l.begin();i!=l.end();++i){ SPObject *o = *i; @@ -362,9 +367,9 @@ void SPGroup::hide (unsigned int key) { void SPGroup::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const { - for ( SPObject const *o = this->firstChild(); o; o = o->getNext() ) + for (auto& o: children) { - SPItem const *item = dynamic_cast<SPItem const *>(o); + SPItem const *item = dynamic_cast<SPItem const *>(&o); if (item) { item->getSnappoints(p, snapprefs); } @@ -389,6 +394,89 @@ void sp_item_group_ungroup_handle_clones(SPItem *parent, Geom::Affine const g) } void +sp_recursive_scale_text_size(Inkscape::XML::Node *repr, double scale){ + for (Inkscape::XML::Node *child = repr->firstChild() ; child; child = child->next() ){ + if ( child) { + sp_recursive_scale_text_size(child, scale); + } + } + SPCSSAttr * css = sp_repr_css_attr(repr,"style"); + Glib::ustring element = g_quark_to_string(repr->code()); + if ((css && element == "svg:text") || element == "svg:tspan") { + gchar const *w = sp_repr_css_property(css, "font-size", NULL); + if (w) { + gchar *units = NULL; + double wd = g_ascii_strtod(w, &units); + wd *= scale; + if (w != units) { + Inkscape::CSSOStringStream os; + os << wd << units; // reattach units + sp_repr_css_set_property(css, "font-size", os.str().c_str()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + } + } + w = NULL; + w = sp_repr_css_property(css, "letter-spacing", NULL); + if (w) { + gchar *units = NULL; + double wd = g_ascii_strtod(w, &units); + wd *= scale; + if (w != units) { + Inkscape::CSSOStringStream os; + os << wd << units; // reattach units + sp_repr_css_set_property(css, "letter-spacing", os.str().c_str()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + } + } + w = NULL; + w = sp_repr_css_property(css, "word-spacing", NULL); + if (w) { + gchar *units = NULL; + double wd = g_ascii_strtod(w, &units); + wd *= scale; + if (w != units) { + Inkscape::CSSOStringStream os; + os << wd << units; // reattach units + sp_repr_css_set_property(css, "word-spacing", os.str().c_str()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + } + } + gchar const *dx = repr->attribute("dx"); + if (dx) { + gchar ** dxarray = g_strsplit(dx, " ", 0); + Inkscape::SVGOStringStream dx_data; + while (*dxarray != NULL) { + double pos; + sp_svg_number_read_d(*dxarray, &pos); + pos *= scale; + dx_data << pos << " "; + dxarray++; + } + repr->setAttribute("dx", dx_data.str().c_str()); + } + gchar const *dy = repr->attribute("dy"); + if (dy) { + gchar ** dyarray = g_strsplit(dy, " ", 0); + Inkscape::SVGOStringStream dy_data; + while (*dyarray != NULL) { + double pos; + sp_svg_number_read_d(*dyarray, &pos); + pos *= scale; + dy_data << pos << " "; + dyarray++; + } + repr->setAttribute("dy", dy_data.str().c_str()); + } + } +} + +void sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_done) { g_return_if_fail (group != NULL); @@ -425,20 +513,21 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d GSList *objects = NULL; Geom::Affine const g(group->transform); - for (SPObject *child = group->firstChild() ; child; child = child->getNext() ) - if (SPItem *citem = dynamic_cast<SPItem *>(child)) - sp_item_group_ungroup_handle_clones(citem,g); - + for (auto& child: group->children) { + if (SPItem *citem = dynamic_cast<SPItem *>(&child)) { + sp_item_group_ungroup_handle_clones(citem, g); + } + } - for (SPObject *child = group->firstChild() ; child; child = child->getNext() ) { - SPItem *citem = dynamic_cast<SPItem *>(child); + for (auto& child: group->children) { + SPItem *citem = dynamic_cast<SPItem *>(&child); if (citem) { /* 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 citem->adjust_paint_recursive (Geom::identity(), Geom::identity(), false); - child->style->merge( group->style ); + child.style->merge( group->style ); /* * fixme: We currently make no allowance for the case where child is cloned * and the group has any style settings. @@ -460,9 +549,9 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d * extra complication & maintenance burden and this case is rare. */ - child->updateRepr(); + child.updateRepr(); - Inkscape::XML::Node *nrepr = child->getRepr()->duplicate(prepr->document()); + Inkscape::XML::Node *nrepr = child.getRepr()->duplicate(prepr->document()); // Merging transform Geom::Affine ctrans = citem->transform * g; @@ -492,13 +581,30 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d // reattached outside of the group, the transform will be written more properly // (i.e. optimized into the object if the corresponding preference is set) gchar *affinestr=sp_svg_transform_write(ctrans); - nrepr->setAttribute("transform", affinestr); + SPText * text = dynamic_cast<SPText *>(citem); + if (text) { + //this causes a change in text-on-path appearance when there is a non-conformal transform, see bug #1594565 + SPTextPath * text_path = dynamic_cast<SPTextPath *>(text->firstChild()); + if (!text_path) { + nrepr->setAttribute("transform", affinestr); + } else { + // The following breaks roundtripping group -> ungroup + // double scale = (ctrans.expansionX() + ctrans.expansionY()) / 2.0; + // sp_recursive_scale_text_size(nrepr, scale); + Geom::Affine ttrans = ctrans.inverse() * SP_ITEM(text)->transform * ctrans; + gchar *affinestr = sp_svg_transform_write(ttrans); + nrepr->setAttribute("transform", affinestr); + g_free(affinestr); + } + } else { + nrepr->setAttribute("transform", affinestr); + } g_free(affinestr); items = g_slist_prepend (items, nrepr); } else { - Inkscape::XML::Node *nrepr = child->getRepr()->duplicate(prepr->document()); + Inkscape::XML::Node *nrepr = child.getRepr()->duplicate(prepr->document()); objects = g_slist_prepend (objects, nrepr); } } @@ -560,9 +666,9 @@ std::vector<SPItem*> sp_item_group_item_list(SPGroup * group) std::vector<SPItem*> s; g_return_val_if_fail(group != NULL, s); - for (SPObject *o = group->firstChild() ; o ; o = o->getNext() ) { - if ( dynamic_cast<SPItem *>(o) ) { - s.push_back((SPItem*)o); + for (auto& o: group->children) { + if ( dynamic_cast<SPItem *>(&o) ) { + s.push_back((SPItem*)&o); } } return s; @@ -633,8 +739,8 @@ void SPGroup::_updateLayerMode(unsigned int display_key) { void SPGroup::translateChildItems(Geom::Translate const &tr) { if ( hasChildren() ) { - for (SPObject *o = firstChild() ; o ; o = o->getNext() ) { - SPItem *item = dynamic_cast<SPItem *>(o); + for (auto& o: children) { + SPItem *item = dynamic_cast<SPItem *>(&o); if ( item ) { sp_item_move_rel(item, tr); } @@ -646,14 +752,14 @@ void SPGroup::translateChildItems(Geom::Translate const &tr) void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bool noRecurse) { if ( hasChildren() ) { - for (SPObject *o = firstChild() ; o ; o = o->getNext() ) { - if ( SPDefs *defs = dynamic_cast<SPDefs *>(o) ) { // select symbols from defs, ignore clips, masks, patterns - for (SPObject *defschild = defs->firstChild() ; defschild ; defschild = defschild->getNext() ) { - SPGroup *defsgroup = dynamic_cast<SPGroup *>(defschild); + for (auto& o: children) { + if ( SPDefs *defs = dynamic_cast<SPDefs *>(&o) ) { // select symbols from defs, ignore clips, masks, patterns + for (auto& defschild: defs->children) { + SPGroup *defsgroup = dynamic_cast<SPGroup *>(&defschild); if (defsgroup) defsgroup->scaleChildItemsRec(sc, p, false); } - } else if ( SPItem *item = dynamic_cast<SPItem *>(o) ) { + } else if ( SPItem *item = dynamic_cast<SPItem *>(&o) ) { SPGroup *group = dynamic_cast<SPGroup *>(item); if (group && !dynamic_cast<SPBox3D *>(item)) { /* Using recursion breaks clipping because transforms are applied @@ -769,8 +875,8 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bo gint SPGroup::getItemCount() const { gint len = 0; - for (SPObject const *o = this->firstChild() ; o ; o = o->getNext() ) { - if (dynamic_cast<SPItem const *>(o)) { + for (auto& child: children) { + if (dynamic_cast<SPItem const *>(&child)) { len++; } } @@ -820,6 +926,15 @@ void SPGroup::update_patheffect(bool write) { } sp_group_perform_patheffect(this, this, write); + + for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it) + { + LivePathEffectObject *lpeobj = (*it)->lpeobject; + + if (lpeobj && lpeobj->get_lpe()) { + lpeobj->get_lpe()->doAfterEffect(this); + } + } } } @@ -845,25 +960,35 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) } else { c = subShape->getCurve(); } - + bool success = false; // only run LPEs when the shape has a curve defined if (c) { c->transform(i2anc_affine(subitem, topgroup)); - topgroup->performPathEffect(c); + success = topgroup->performPathEffect(c, subShape); c->transform(i2anc_affine(subitem, topgroup).inverse()); - subShape->setCurve(c, TRUE); - - if (write) { - Inkscape::XML::Node *repr = subitem->getRepr(); - gchar *str = sp_svg_write_path(c->get_pathvector()); - repr->setAttribute("d", str); + Inkscape::XML::Node *repr = subitem->getRepr(); + if (c && success) { + subShape->setCurve(c, TRUE); + if (write) { + 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"); + g_message("sp_group_perform_patheffect writes 'd' attribute"); #endif - g_free(str); + g_free(str); + } + c->unref(); + } else { + // LPE was unsuccesfull or doeffect stack return null. Read the old 'd'-attribute. + if (gchar const * value = repr->attribute("d")) { + Geom::PathVector pv = sp_svg_read_pathv(value); + SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); + if (oldcurve) { + subShape->setCurve(oldcurve, TRUE); + oldcurve->unref(); + } + } } - - c->unref(); } } } |
