diff options
| author | Markus Engel <markus.engel@tum.de> | 2013-09-24 21:32:23 +0000 |
|---|---|---|
| committer | Markus Engel <markus.engel@tum.de> | 2013-09-24 21:32:23 +0000 |
| commit | 2f017d2ef4974eba04515b9a155656ce9f2f7822 (patch) | |
| tree | 33aac031c85048c2129e191e45c7667773f34c68 /src | |
| parent | Refactored SPGenericEllipse::set_shape (diff) | |
| download | inkscape-2f017d2ef4974eba04515b9a155656ce9f2f7822.tar.gz inkscape-2f017d2ef4974eba04515b9a155656ce9f2f7822.zip | |
Refactored SPUse.
(bzr r11608.1.128)
Diffstat (limited to '')
| -rw-r--r-- | src/object-snapper.cpp | 12 | ||||
| -rw-r--r-- | src/selection-chemistry.cpp | 46 | ||||
| -rw-r--r-- | src/sp-flowtext.cpp | 58 | ||||
| -rw-r--r-- | src/sp-item-group.cpp | 90 | ||||
| -rw-r--r-- | src/sp-use.cpp | 256 | ||||
| -rw-r--r-- | src/sp-use.h | 32 | ||||
| -rw-r--r-- | src/ui/dialog/livepatheffect-editor.cpp | 4 |
7 files changed, 304 insertions, 194 deletions
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 77ba3040f..3f3f0c1bf 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -194,7 +194,7 @@ void Inkscape::ObjectSnapper::_collectNodes(SnapSourceType const &t, //Geom::Affine i2doc(Geom::identity()); SPItem *root_item = (*i).item; if (SP_IS_USE((*i).item)) { - root_item = sp_use_root(SP_USE((*i).item)); + root_item = SP_USE((*i).item)->root(); } g_return_if_fail(root_item); @@ -382,8 +382,8 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, SPItem *root_item = NULL; /* We might have a clone at hand, so make sure we get the root item */ if (SP_IS_USE((*i).item)) { - i2doc = sp_use_get_root_transform(SP_USE((*i).item)); - root_item = sp_use_root(SP_USE((*i).item)); + i2doc = SP_USE((*i).item)->get_root_transform(); + root_item = SP_USE((*i).item)->root(); g_return_if_fail(root_item); } else { i2doc = (*i).item->i2doc_affine(); @@ -770,7 +770,7 @@ void Inkscape::ObjectSnapper::_clear_paths() const Geom::PathVector* Inkscape::ObjectSnapper::_getBorderPathv() const { - Geom::Rect const border_rect = Geom::Rect(Geom::Point(0,0), Geom::Point((_snapmanager->getDocument())->getWidth(),(_snapmanager->getDocument())->getHeight())); + Geom::Rect const border_rect = Geom::Rect(Geom::Point(0,0), Geom::Point((_snapmanager->getDocument())->getWidth().value("px"),(_snapmanager->getDocument())->getHeight().value("px"))); return _getPathvFromRect(border_rect); } @@ -787,8 +787,8 @@ Geom::PathVector* Inkscape::ObjectSnapper::_getPathvFromRect(Geom::Rect const re void Inkscape::ObjectSnapper::_getBorderNodes(std::vector<SnapCandidatePoint> *points) const { - Geom::Coord w = (_snapmanager->getDocument())->getWidth(); - Geom::Coord h = (_snapmanager->getDocument())->getHeight(); + Geom::Coord w = (_snapmanager->getDocument())->getWidth().value("px"); + Geom::Coord h = (_snapmanager->getDocument())->getHeight().value("px"); points->push_back(SnapCandidatePoint(Geom::Point(0,0), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); points->push_back(SnapCandidatePoint(Geom::Point(0,h), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); points->push_back(SnapCandidatePoint(Geom::Point(w,h), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 91b99e3f4..8a7832d2a 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -499,7 +499,7 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone) const gchar *id = old_ids[i]; SPObject *old_clone = doc->getObjectById(id); if (SP_IS_USE(old_clone)) { - SPItem *orig = sp_use_get_original(SP_USE(old_clone)); + SPItem *orig = SP_USE(old_clone)->get_original(); if (!orig) // orphaned continue; for (unsigned int j = 0; j < old_ids.size(); j++) { @@ -1104,18 +1104,21 @@ void sp_selection_cut(SPDesktop *desktop) * \pre item != NULL */ SPCSSAttr * -take_style_from_item(SPItem *item) +take_style_from_item(SPObject *object) { + // CPPIFY: + // This function should only take SPItems, but currently SPString is not an Item. + // write the complete cascaded style, context-free - SPCSSAttr *css = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); + SPCSSAttr *css = sp_css_attr_from_object(object, SP_STYLE_FLAG_ALWAYS); if (css == NULL) return NULL; - if ((SP_IS_GROUP(item) && item->children) || - (SP_IS_TEXT(item) && item->children && item->children->next == NULL)) { + if ((SP_IS_GROUP(object) && object->children) || + (SP_IS_TEXT(object) && object->children && object->children->next == NULL)) { // if this is a text with exactly one tspan child, merge the style of that tspan as well // If this is a group, merge the style of its topmost (last) child with style - for (SPObject *last_element = item->lastChild(); last_element != NULL; last_element = last_element->getPrev()) { + for (SPObject *last_element = object->lastChild(); last_element != NULL; last_element = last_element->getPrev()) { if ( last_element->style ) { SPCSSAttr *temp = sp_css_attr_from_object(last_element, SP_STYLE_FLAG_IFSET); if (temp) { @@ -1126,15 +1129,18 @@ take_style_from_item(SPItem *item) } } } - if (!(SP_IS_TEXT(item) || SP_IS_TSPAN(item) || SP_IS_TREF(item) || SP_IS_STRING(item))) { + + if (!(SP_IS_TEXT(object) || SP_IS_TSPAN(object) || SP_IS_TREF(object) || SP_IS_STRING(object))) { // do not copy text properties from non-text objects, it's confusing css = sp_css_attr_unset_text(css); } - // FIXME: also transform gradient/pattern fills, by forking? NO, this must be nondestructive - double ex = item->i2doc_affine().descrim(); - if (ex != 1.0) { - css = sp_css_attr_scale(css, ex); + if (SP_IS_ITEM(object)) { + // FIXME: also transform gradient/pattern fills, by forking? NO, this must be nondestructive + double ex = SP_ITEM(object)->i2doc_affine().descrim(); + if (ex != 1.0) { + css = sp_css_attr_scale(css, ex); + } } return css; @@ -1375,7 +1381,7 @@ selection_contains_original(SPItem *item, Inkscape::Selection *selection) SPItem *item_use_first = item; while (is_use && item_use && !contains_original) { - item_use = sp_use_get_original(SP_USE(item_use)); + item_use = SP_USE(item_use)->get_original(); contains_original |= selection->includes(item_use); if (item_use == item_use_first) break; @@ -1520,7 +1526,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons // we need to cancel out the move compensation, too // find out the clone move, same as in sp_use_move_compensate - Geom::Affine parent = sp_use_get_parent_transform(SP_USE(item)); + Geom::Affine parent = SP_USE(item)->get_parent_transform(); Geom::Affine clone_move = parent.inverse() * t * parent; if (prefs_parallel) { @@ -2616,7 +2622,7 @@ sp_selection_unlink(SPDesktop *desktop) SPItem *unlink; if (SP_IS_USE(item)) { - unlink = sp_use_unlink(SP_USE(item)); + unlink = SP_USE(item)->unlink(); // Unable to unlink use (external or invalid href?) if (!unlink) { new_select = g_slist_prepend(new_select, item); @@ -2664,7 +2670,7 @@ sp_select_clone_original(SPDesktop *desktop) SPItem *original = NULL; if (SP_IS_USE(item)) { - original = sp_use_get_original(SP_USE(item)); + original = SP_USE(item)->get_original(); } else if (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) { original = sp_offset_get_source(SP_OFFSET(item)); } else if (SP_IS_TEXT_TEXTPATH(item)) { @@ -2809,7 +2815,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = Geom::Point(0, doc->getHeight()) - *c; + Geom::Point move_p = Geom::Point(0, doc->getHeight().value("px")) - *c; move_p[Geom::Y] = -move_p[Geom::Y]; Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); @@ -3093,7 +3099,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = Geom::Point(0, doc->getHeight()) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); + Geom::Point move_p = Geom::Point(0, doc->getHeight().value("px")) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); move_p[Geom::Y] = -move_p[Geom::Y]; Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); @@ -3398,7 +3404,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) res = prefs_res; } else if (0 < prefs_min) { // If minsize is given, look up minimum bitmap size (default 250 pixels) and calculate resolution from it - res = Inkscape::Util::Quantity::convert(1, "in", "px") * prefs_min / MIN(bbox->width(), bbox->height()); + res = Inkscape::Util::Quantity::convert(prefs_min, "in", "px") / MIN(bbox->width(), bbox->height()); } else { float hint_xdpi = 0, hint_ydpi = 0; Glib::ustring hint_filename; @@ -3419,8 +3425,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) } // The width and height of the bitmap in pixels - unsigned width = (unsigned) floor(bbox->width() * res / Inkscape::Util::Quantity::convert(1, "in", "px")); - unsigned height =(unsigned) floor(bbox->height() * res / Inkscape::Util::Quantity::convert(1, "in", "px")); + unsigned width = (unsigned) floor(bbox->width() * Inkscape::Util::Quantity::convert(res, "px", "in")); + unsigned height =(unsigned) floor(bbox->height() * Inkscape::Util::Quantity::convert(res, "px", "in")); // Find out if we have to run an external filter gchar const *run = NULL; diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index c7ef579ac..88564c0ac 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -28,6 +28,7 @@ #include "text-tag-attributes.h" #include "text-chemistry.h" #include "text-editing.h" +#include "sp-text.h" #include "livarot/Shape.h" @@ -203,7 +204,7 @@ void SPFlowtext::set(unsigned int key, const gchar* value) { if ( val == NULL ) { this->par_indent = 0.0; } else { - sp_repr_get_double((Inkscape::XML::Node*)opts, "par-indent", &this->par_indent); + this->par_indent = g_ascii_strtod(val, NULL); } } @@ -280,17 +281,20 @@ void SPFlowtext::print(SPPrintContext *ctx) { this->layout.print(ctx, pbox, dbox, bbox, ctm); } +const char* SPFlowtext::displayName() { + if (SP_FLOWTEXT(this)->has_internal_frame()) { + return _("Flowed Text"); + } else { + return _("Linked Flowed Text"); + } +} + gchar* SPFlowtext::description() { Inkscape::Text::Layout const &layout = SP_FLOWTEXT(this)->layout; int const nChars = layout.iteratorToCharIndex(layout.end()); - char const *trunc = (layout.inputTruncated()) ? _(" [truncated]") : ""; - if (SP_FLOWTEXT(this)->has_internal_frame()) { - return g_strdup_printf(ngettext("<b>Flowed text</b> (%d character%s)", "<b>Flowed text</b> (%d characters%s)", nChars), nChars, trunc); - } else { - return g_strdup_printf(ngettext("<b>Linked flowed text</b> (%d character%s)", "<b>Linked flowed text</b> (%d characters%s)", nChars), nChars, trunc); - } + return g_strdup_printf(ngettext(_("(%d character%s)"), _("(%d characters%s)"), nChars), nChars, trunc); } void SPFlowtext::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) { @@ -578,7 +582,7 @@ SPItem *SPFlowtext::get_frame(SPItem *after) } if ( frame && SP_IS_USE(frame) ) { - frame = sp_use_get_original(SP_USE(frame)); + frame = SP_USE(frame)->get_original(); } } return frame; @@ -645,6 +649,44 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, return ft_item; } +Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform) +{ + if ((this->_optimizeScaledText && !xform.withoutTranslation().isNonzeroUniformScale()) + || (!this->_optimizeScaledText && !xform.isNonzeroUniformScale())) { + this->_optimizeScaledText = false; + return xform; + } + this->_optimizeScaledText = false; + + SPText *text = reinterpret_cast<SPText *>(this); + + double const ex = xform.descrim(); + if (ex == 0) { + return xform; + } + + Geom::Affine ret(xform); + ret[0] /= ex; + ret[1] /= ex; + ret[2] /= ex; + ret[3] /= ex; + + // Adjust font size + text->_adjustFontsizeRecursive (this, ex); + + // Adjust stroke width + this->adjust_stroke_width_recursive (ex); + + // Adjust pattern fill + this->adjust_pattern(xform * ret.inverse()); + + // Adjust gradient fill + this->adjust_gradient(xform * ret.inverse()); + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG); + + return ret; +} /* Local Variables: diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 010cc5449..2becf7139 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -50,6 +50,9 @@ #include "sp-switch.h" #include "sp-defs.h" #include "verbs.h" +#include "layer-model.h" +#include "sp-textpath.h" +#include "sp-flowtext.h" using Inkscape::DocumentUndo; @@ -325,12 +328,14 @@ void SPGroup::print(SPPrintContext *ctx) { } } +const char *SPGroup::displayName() { + return _("Group"); +} + gchar *SPGroup::description() { gint len = this->getItemCount(); return g_strdup_printf( - ngettext("<b>Group</b> of <b>%d</b> object", - "<b>Group</b> of <b>%d</b> objects", - len), len); + ngettext(_("of <b>%d</b> object"), _("of <b>%d</b> objects"), len), len); } void SPGroup::set(unsigned int key, gchar const* value) { @@ -467,8 +472,8 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) // Merging transform Geom::Affine ctrans; Geom::Affine const g(gitem->transform); - if (SP_IS_USE(citem) && sp_use_get_original (SP_USE(citem)) && - sp_use_get_original( SP_USE(citem) )->parent == SP_OBJECT(group)) { + if (SP_IS_USE(citem) && SP_USE(citem)->get_original() && + SP_USE(citem)->get_original()->parent == SP_OBJECT(group)) { // make sure a clone's effective transform is the same as was under group ctrans = g.inverse() * citem->transform * g; } else { @@ -642,6 +647,81 @@ void SPGroup::translateChildItems(Geom::Translate const &tr) } } +// Recursively scale child items around a point +void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p) +{ + if ( hasChildren() ) { + for (SPObject *o = firstChild() ; o ; o = o->getNext() ) { + if ( SP_IS_ITEM(o) ) { + if (SP_IS_GROUP(o) && !SP_IS_BOX3D(o)) { + SP_GROUP(o)->scaleChildItemsRec(sc, p); + } else { + SPItem *item = SP_ITEM(o); + Geom::OptRect bbox = item->desktopVisualBounds(); + if (bbox) { + // Scale item + Geom::Translate const s(p); + Geom::Affine final = s.inverse() * sc * s; + + Geom::Point old_center(0,0); + if (item->isCenterSet()) { + old_center = item->getCenter(); + } + + gchar const *conn_type = NULL; + if (SP_IS_TEXT_TEXTPATH(item)) { + SP_TEXT(item)->optimizeTextpathText(); + } else if (SP_IS_FLOWTEXT(item)) { + SP_FLOWTEXT(item)->optimizeScaledText(); + } else if (SP_IS_BOX3D(item)) { + // Force recalculation from perspective + box3d_position_set(SP_BOX3D(item)); + } else if (item->getAttribute("inkscape:connector-type") != NULL + && (item->getAttribute("inkscape:connection-start") == NULL + || item->getAttribute("inkscape:connection-end") == NULL)) { + // Remove and store connector type for transform if disconnected + conn_type = item->getAttribute("inkscape:connector-type"); + item->removeAttribute("inkscape:connector-type"); + } + + if (SP_IS_PERSP3D(item)) { + persp3d_apply_affine_transformation(SP_PERSP3D(item), final); + } else if ((SP_IS_TEXT_TEXTPATH(item) || SP_IS_FLOWTEXT(item)) && !item->transform.isIdentity()) { + // Save and reset current transform + Geom::Affine tmp(item->transform); + item->transform = Geom::Affine(); + // Apply scale + item->set_i2d_affine(item->i2dt_affine() * sc); + item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + // Scale translation and restore original transform + tmp[4] *= sc[0]; + tmp[5] *= sc[1]; + item->doWriteTransform(item->getRepr(), tmp, NULL, true); + } else if (SP_IS_USE(item)) { + // calculate the matrix we need to apply to the clone + // to cancel its induced transform from its original + Geom::Affine move = final.inverse() * item->transform * final; + item->doWriteTransform(item->getRepr(), move, &move, true); + } else { + item->set_i2d_affine(item->i2dt_affine() * final); + item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + } + + if (conn_type != NULL) { + item->setAttribute("inkscape:connector-type", conn_type); + } + + if (item->isCenterSet() && !(final.isTranslation() || final.isIdentity())) { + item->setCenter(old_center * final); + item->updateRepr(); + } + } + } + } + } + } +} + gint SPGroup::getItemCount() { gint len = 0; for (SPObject *o = this->firstChild() ; o ; o = o->getNext() ) { diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 44935e61d..a558c6bf4 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -37,12 +37,6 @@ #include "sp-use.h" #include "sp-use-reference.h" -/* fixme: */ -static void sp_use_href_changed(SPObject *old_ref, SPObject *ref, SPUse *use); -static void sp_use_delete_self(SPObject *deleted, SPUse *self); - -#include "sp-factory.h" - namespace { SPObject* createUse() { return new SPUse(); @@ -51,23 +45,20 @@ namespace { bool useRegistered = SPFactory::instance().registerObject("svg:use", createUse); } -SPUse::SPUse() : SPItem() { - this->child = NULL; - +SPUse::SPUse() + : SPItem() + , child(NULL) + , href(NULL) + , ref(new SPUseReference(this)) +{ this->x.unset(); this->y.unset(); this->width.unset(SVGLength::PERCENT, 1.0, 1.0); this->height.unset(SVGLength::PERCENT, 1.0, 1.0); - this->href = NULL; - - //new (&this->_delete_connection) sigc::connection(); - //new (&this->_changed_connection) sigc::connection(); - - //new (&this->_transformed_connection) sigc::connection(); - this->ref = new SPUseReference(this); - - this->_changed_connection = this->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_use_href_changed), this)); + this->_changed_connection = this->ref->changedSignal().connect( + sigc::hide(sigc::hide(sigc::mem_fun(this, &SPUse::href_changed))) + ); } SPUse::~SPUse() { @@ -79,11 +70,6 @@ SPUse::~SPUse() { this->ref->detach(); delete this->ref; this->ref = 0; - - //this->_delete_connection.~connection(); - //this->_changed_connection.~connection(); - - //this->_transformed_connection.~connection(); } void SPUse::build(SPDocument *document, Inkscape::XML::Node *repr) { @@ -195,12 +181,8 @@ Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XM Geom::OptRect SPUse::bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) { Geom::OptRect bbox; - if (this->child && SP_IS_ITEM(this->child)) { - SPItem *child = SP_ITEM(this->child); - Geom::Affine const ct( child->transform - * Geom::Translate(this->x.computed, - this->y.computed) - * transform ); + if (this->child) { + Geom::Affine const ct(child->transform * Geom::Translate(this->x.computed, this->y.computed) * transform ); bbox = child->bounds(bboxtype, ct); } @@ -217,8 +199,8 @@ void SPUse::print(SPPrintContext* ctx) { translated = true; } - if (this->child && SP_IS_ITEM(this->child)) { - SP_ITEM(this->child)->invoke_print(ctx); + if (this->child) { + this->child->invoke_print(ctx); } if (translated) { @@ -226,12 +208,18 @@ void SPUse::print(SPPrintContext* ctx) { } } +const char* SPUse::displayName() { + if (this->child && SP_IS_SYMBOL( this->child )) { + return _("Symbol"); + } + + return _("Clone"); +} + gchar* SPUse::description() { if (this->child) { if( SP_IS_SYMBOL( this->child ) ) { - char *symbol_desc = SP_ITEM(this->child)->title(); - return g_strdup_printf(_("<b>'%s' Symbol</b>"), symbol_desc ); - g_free(symbol_desc); + return g_strdup_printf(_("called %s"), this->child->title()); } static unsigned recursion_depth = 0; @@ -245,15 +233,15 @@ gchar* SPUse::description() { } ++recursion_depth; - char *child_desc = SP_ITEM(this->child)->getDetailedDescription(); + char *child_desc = this->child->detailedDescription(); --recursion_depth; - char *ret = g_strdup_printf(_("<b>Clone</b> of: %s"), child_desc); + char *ret = g_strdup_printf(_("of: %s"), child_desc); g_free(child_desc); return ret; } else { - return g_strdup(_("<b>Orphaned clone</b>")); + return g_strdup(_("[orphaned]")); } } @@ -263,7 +251,8 @@ Inkscape::DrawingItem* SPUse::show(Inkscape::Drawing &drawing, unsigned int key, ai->setStyle(this->style); if (this->child) { - Inkscape::DrawingItem *ac = SP_ITEM(this->child)->invoke_show(drawing, key, flags); + Inkscape::DrawingItem *ac = this->child->invoke_show(drawing, key, flags); + if (ac) { ai->prependChild(ac); } @@ -277,7 +266,7 @@ Inkscape::DrawingItem* SPUse::show(Inkscape::Drawing &drawing, unsigned int key, void SPUse::hide(unsigned int key) { if (this->child) { - SP_ITEM(this->child)->invoke_hide(key); + this->child->invoke_hide(key); } // SPItem::onHide(key); @@ -292,38 +281,42 @@ void SPUse::hide(unsigned int key) { * 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". */ -SPItem * -sp_use_root(SPUse *use) -{ - SPObject *orig = use->child; +SPItem *SPUse::root() { + SPItem *orig = this->child; + while (orig && SP_IS_USE(orig)) { orig = SP_USE(orig)->child; } - if (!orig || !SP_IS_ITEM(orig)) + + if (!orig) { return NULL; - return SP_ITEM(orig); + } + + return orig; } /** * Returns the effective transform that goes from the ultimate original to given SPUse, both ends * included. */ -Geom::Affine -sp_use_get_root_transform(SPUse *use) -{ +Geom::Affine SPUse::get_root_transform() { //track the ultimate source of a chain of uses - SPObject *orig = use->child; + SPObject *orig = this->child; + GSList *chain = NULL; - chain = g_slist_prepend(chain, use); + chain = g_slist_prepend(chain, this); + while (SP_IS_USE(orig)) { chain = g_slist_prepend(chain, orig); orig = SP_USE(orig)->child; } + chain = g_slist_prepend(chain, orig); - //calculate the accummulated transform, starting from the original + // calculate the accummulated transform, starting from the original Geom::Affine t(Geom::identity()); + for (GSList *i = chain; i != NULL; i = i->next) { SPItem *i_tem = SP_ITEM(i->data); @@ -332,6 +325,7 @@ sp_use_get_root_transform(SPUse *use) // represent the values of the x and y attributes on the 'use' element." - http://www.w3.org/TR/SVG11/struct.html#UseElement 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 * Geom::Translate(i_use->x._set ? i_use->x.computed : 0, i_use->y._set ? i_use->y.computed : 0); } @@ -348,16 +342,14 @@ 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. */ -Geom::Affine -sp_use_get_parent_transform(SPUse *use) -{ +Geom::Affine SPUse::get_parent_transform() { Geom::Affine t(Geom::identity()); - if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { - t *= Geom::Translate(use->x._set ? use->x.computed : 0, - use->y._set ? use->y.computed : 0); + + if ((this->x._set && this->x.computed != 0) || (this->y._set && this->y.computed != 0)) { + t *= Geom::Translate(this->x._set ? this->x.computed : 0, this->y._set ? this->y.computed : 0); } - t *= SP_ITEM(use)->transform; + t *= this->transform; return t; } @@ -366,17 +358,15 @@ sp_use_get_parent_transform(SPUse *use) * that the clone stays unmoved or moves in parallel (depending on user setting) regardless of the * clone's transform. */ -static void -sp_use_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPUse *self) -{ +void SPUse::move_compensate(Geom::Affine const *mp) { // 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 - if (self->cloned) { + if (this->cloned) { return; } // never compensate uses which are used in flowtext - if (self->parent && SP_IS_FLOWREGION(self->parent)) { + if (this->parent && SP_IS_FLOWREGION(this->parent)) { return; } @@ -393,9 +383,9 @@ sp_use_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPUse *self return; // restore item->transform field from the repr, in case it was changed by seltrans - self->readAttr ("transform"); + this->readAttr ("transform"); - Geom::Affine t = sp_use_get_parent_transform(self); + Geom::Affine t = this->get_parent_transform(); Geom::Affine clone_move = t.inverse() * m * t; // calculate the compensation matrix and the advertized movement matrix @@ -411,77 +401,63 @@ sp_use_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPUse *self } // commit the compensation - self->transform *= clone_move; - self->doWriteTransform(self->getRepr(), self->transform, &advertized_move); - self->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + this->transform *= clone_move; + this->doWriteTransform(this->getRepr(), this->transform, &advertized_move); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -static void -sp_use_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPUse *use) -{ - SPItem *item = SP_ITEM(use); - - use->_delete_connection.disconnect(); - use->_transformed_connection.disconnect(); +void SPUse::href_changed() { + this->_delete_connection.disconnect(); + this->_transformed_connection.disconnect(); - if (use->child) { - use->detach(use->child); - use->child = NULL; + if (this->child) { + this->detach(this->child); + this->child = NULL; } - if (use->href) { - SPItem *refobj = use->ref->getObject(); + if (this->href) { + SPItem *refobj = this->ref->getObject(); + if (refobj) { Inkscape::XML::Node *childrepr = refobj->getRepr(); -// GType type = sp_repr_type_lookup(childrepr); -// g_return_if_fail(type > G_TYPE_NONE); -// if (g_type_is_a(type, SP_TYPE_ITEM)) { -// use->child = (SPObject*) g_object_new(type, 0); -// use->attach(use->child, use->lastChild()); -// sp_object_unref(use->child, use); -// (use->child)->invoke_build(use->document, childrepr, TRUE); -// -// for (SPItemView *v = item->display; v != NULL; v = v->next) { -// Inkscape::DrawingItem *ai; -// ai = SP_ITEM(use->child)->invoke_show(v->arenaitem->drawing(), v->key, v->flags); -// if (ai) { -// v->arenaitem->prependChild(ai); -// } -// } -// } - SPObject* obj = SPFactory::instance().createObject(NodeTraits::get_type_string(*childrepr)); + if (SP_IS_ITEM(obj)) { - use->child = obj; + this->child = SP_ITEM(obj); + + this->attach(this->child, this->lastChild()); + sp_object_unref(this->child, this); - use->attach(use->child, use->lastChild()); - sp_object_unref(use->child, use); - (use->child)->invoke_build(use->document, childrepr, TRUE); + this->child->invoke_build(this->document, childrepr, TRUE); + + for (SPItemView *v = this->display; v != NULL; v = v->next) { + Inkscape::DrawingItem *ai = this->child->invoke_show(v->arenaitem->drawing(), v->key, v->flags); - for (SPItemView *v = item->display; v != NULL; v = v->next) { - Inkscape::DrawingItem *ai; - ai = SP_ITEM(use->child)->invoke_show(v->arenaitem->drawing(), v->key, v->flags); if (ai) { v->arenaitem->prependChild(ai); } } } else { delete obj; + g_warning("Tried to create svg:use from invalid object"); } - use->_delete_connection = refobj->connectDelete(sigc::bind(sigc::ptr_fun(&sp_use_delete_self), use)); - use->_transformed_connection = SP_ITEM(refobj)->connectTransformed(sigc::bind(sigc::ptr_fun(&sp_use_move_compensate), use)); + this->_delete_connection = refobj->connectDelete( + sigc::hide(sigc::mem_fun(this, &SPUse::delete_self)) + ); + + this->_transformed_connection = refobj->connectTransformed( + sigc::hide(sigc::mem_fun(this, &SPUse::move_compensate)) + ); } } } -static void -sp_use_delete_self(SPObject */*deleted*/, SPUse *self) -{ +void SPUse::delete_self() { // always delete uses which are used in flowtext - if (self->parent && SP_IS_FLOWREGION(self->parent)) { - self->deleteObject(); + if (this->parent && SP_IS_FLOWREGION(this->parent)) { + this->deleteObject(); return; } @@ -490,9 +466,9 @@ sp_use_delete_self(SPObject */*deleted*/, SPUse *self) SP_CLONE_ORPHANS_UNLINK); if (mode == SP_CLONE_ORPHANS_UNLINK) { - sp_use_unlink(self); + this->unlink(); } else if (mode == SP_CLONE_ORPHANS_DELETE) { - self->deleteObject(); + this->deleteObject(); } } @@ -509,7 +485,7 @@ void SPUse::update(SPCtx *ctx, unsigned flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = SP_ITEM(this)->display; v != NULL; v = v->next) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); g->setStyle(this->style); } @@ -540,14 +516,10 @@ void SPUse::update(SPCtx *ctx, unsigned flags) { sp_object_ref(this->child); if (flags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - if (SP_IS_ITEM(this->child)) { - SPItem const &chi = *SP_ITEM(this->child); - cctx.i2doc = chi.transform * ictx->i2doc; - cctx.i2vp = chi.transform * ictx->i2vp; - this->child->updateDisplay((SPCtx *)&cctx, flags); - } else { - this->child->updateDisplay(ctx, flags); - } + SPItem const &chi = *SP_ITEM(this->child); + cctx.i2doc = chi.transform * ictx->i2doc; + cctx.i2vp = chi.transform * ictx->i2vp; + this->child->updateDisplay((SPCtx *)&cctx, flags); } sp_object_unref(this->child); @@ -569,14 +541,12 @@ void SPUse::modified(unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = SP_ITEM(this)->display; v != NULL; v = v->next) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); g->setStyle(this->style); } } - SPObject *child = this->child; - if (child) { sp_object_ref(child); @@ -588,30 +558,26 @@ void SPUse::modified(unsigned int flags) { } } -SPItem *sp_use_unlink(SPUse *use) -{ - if (!use) { - return NULL; - } +SPItem *SPUse::unlink() { + Inkscape::XML::Node *repr = this->getRepr(); - Inkscape::XML::Node *repr = use->getRepr(); if (!repr) { return NULL; } Inkscape::XML::Node *parent = repr->parent(); - SPDocument *document = use->document; + SPDocument *document = this->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); // Track the ultimate source of a chain of uses. - SPItem *orig = sp_use_root(use); + SPItem *orig = this->root(); if (!orig) { return NULL; } // Calculate the accumulated transform, starting from the original. - Geom::Affine t = sp_use_get_root_transform(use); + Geom::Affine t = this->get_root_transform(); Inkscape::XML::Node *copy = NULL; @@ -634,19 +600,19 @@ SPItem *sp_use_unlink(SPUse *use) // Merge style from the use. SPStyle *unli_sty = unlinked->style; - SPStyle const *use_sty = use->style; + SPStyle const *use_sty = this->style; sp_style_merge_from_dying_parent(unli_sty, use_sty); sp_style_merge_from_parent(unli_sty, unlinked->parent->style); unlinked->updateRepr(); // Hold onto our SPObject and repr for now. - sp_object_ref(use, NULL); + sp_object_ref(this, NULL); Inkscape::GC::anchor(repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. - use->deleteObject(false); + this->deleteObject(false); // Give the copy our old id and let go of our old repr. copy->setAttribute("id", repr->attribute("id")); @@ -660,10 +626,11 @@ SPItem *sp_use_unlink(SPUse *use) copy->setAttribute("inkscape:tile-cy", NULL); // Establish the succession and let go of our object. - use->setSuccessor(unlinked); - sp_object_unref(use, NULL); + this->setSuccessor(unlinked); + sp_object_unref(this, NULL); SPItem *item = SP_ITEM(unlinked); + // Set the accummulated transform. { Geom::Affine nomove(Geom::identity()); @@ -674,21 +641,18 @@ SPItem *sp_use_unlink(SPUse *use) return item; } -SPItem *sp_use_get_original(SPUse *use) -{ +SPItem *SPUse::get_original() { SPItem *ref = NULL; - if (use) { - if (use->ref){ - ref = use->ref->getObject(); + if (this->ref){ + ref = this->ref->getObject(); } - } return ref; } void SPUse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) { - SPItem *root = sp_use_root(this); + SPItem *root = this->root(); if (!root) { return; diff --git a/src/sp-use.h b/src/sp-use.h index 37ff2cf66..6a83c384f 100644 --- a/src/sp-use.h +++ b/src/sp-use.h @@ -30,7 +30,7 @@ public: // item built from the original's repr (the visible clone) // relative to the SPUse itself, it is treated as a child, similar to a grouped item relative to its group - SPObject *child; + SPItem *child; // SVG attrs SVGLength x; @@ -57,17 +57,35 @@ public: virtual void modified(unsigned int flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype); + virtual const char* displayName(); virtual gchar* description(); virtual void print(SPPrintContext *ctx); virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide(unsigned int key); virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); -}; -SPItem *sp_use_unlink (SPUse *use); -SPItem *sp_use_get_original (SPUse *use); -Geom::Affine sp_use_get_parent_transform (SPUse *use); -Geom::Affine sp_use_get_root_transform(SPUse *use); + SPItem *root(); + + SPItem *unlink(); + SPItem *get_original(); + Geom::Affine get_parent_transform(); + Geom::Affine get_root_transform(); + +private: + void href_changed(); + void move_compensate(Geom::Affine const *mp); + void delete_self(); +}; -SPItem *sp_use_root(SPUse *use); #endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index 6dc9c1ee3..0102977e4 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -296,7 +296,7 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel) } } else if ( SP_IS_USE(item) ) { // test whether linked object is supported by the CLONE_ORIGINAL LPE - SPItem *orig = sp_use_get_original( SP_USE(item) ); + SPItem *orig = SP_USE(item)->get_original(); if ( SP_IS_SHAPE(orig) || SP_IS_TEXT(orig) ) { @@ -433,7 +433,7 @@ LivePathEffectEditor::onAdd() // convert to path, apply CLONE_ORIGINAL LPE, link it to the cloned path // test whether linked object is supported by the CLONE_ORIGINAL LPE - SPItem *orig = sp_use_get_original( SP_USE(item) ); + SPItem *orig = SP_USE(item)->get_original(); if ( SP_IS_SHAPE(orig) || SP_IS_TEXT(orig) ) { |
