Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sp-use.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * SVG <use> implementation
4 *
5 * Authors:
6 * Lauris Kaplinski <lauris@kaplinski.com>
7 * bulia byak <buliabyak@users.sf.net>
8 * Jon A. Cruz <jon@joncruz.org>
9 * Abhishek Sharma
10 *
11 * Copyright (C) 1999-2005 authors
12 * Copyright (C) 2000-2001 Ximian, Inc.
13 *
14 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
15 */
16
17#include <cstring>
18
19#include <2geom/transforms.h>
20#include <glibmm/i18n.h>
21#include <glibmm/markup.h>
22
23#include "attributes.h"
24#include "bad-uri-exception.h"
25#include "document.h"
26#include "enums.h" // for SP_CLONE_COMPENS...
27#include "preferences.h"
28#include "print.h"
29#include "sp-clippath.h"
30#include "sp-factory.h"
31#include "sp-flowregion.h"
32#include "sp-flowtext.h"
33#include "sp-mask.h"
34#include "sp-root.h"
35#include "sp-shape.h"
36#include "sp-symbol.h"
37#include "sp-text.h"
38#include "snap-candidate.h"
39#include "sp-use-reference.h"
40#include "sp-use.h"
41#include "style.h"
42#include "uri.h"
43
45#include "xml/document.h" // for Document
46#include "xml/href-attribute-helper.h" // for getHrefAttribute
47
48namespace Inkscape {
49class Drawing;
50class SnapCandidatePoint;
51class SnapPreferences;
52} // namespace Inkscape
53
55 : SPItem(),
57 child(nullptr),
58 href(nullptr),
59 ref(new SPUseReference(this)),
60 _delete_connection(),
61 _changed_connection(),
62 _transformed_connection()
63{
64 this->x.unset();
65 this->y.unset();
66 this->width.unset(SVGLength::PERCENT, 1.0, 1.0);
67 this->height.unset(SVGLength::PERCENT, 1.0, 1.0);
68
69 this->_changed_connection = this->ref->changedSignal().connect(
70 sigc::hide(sigc::hide(sigc::mem_fun(*this, &SPUse::href_changed)))
71 );
72}
73
75 if (this->child) {
76 this->detach(this->child);
77 this->child = nullptr;
78 }
79
80 this->ref->detach();
81 delete this->ref;
82 this->ref = nullptr;
83}
84
87
88 this->readAttr(SPAttr::X);
89 this->readAttr(SPAttr::Y);
93
94 // We don't need to create child here:
95 // reading xlink:href will attach ref, and that will cause the changed signal to be emitted,
96 // which will call SPUse::href_changed, and that will take care of the child
97}
98
100 if (this->child) {
101 this->detach(this->child);
102 this->child = nullptr;
103 }
104
105 this->_delete_connection.disconnect();
106 this->_changed_connection.disconnect();
107 this->_transformed_connection.disconnect();
108
109 g_free(this->href);
110 this->href = nullptr;
111
112 this->ref->detach();
113
115}
116
117void SPUse::set(SPAttr key, const gchar* value) {
118 switch (key) {
119 case SPAttr::X:
120 this->x.readOrUnset(value);
122 break;
123
124 case SPAttr::Y:
125 this->y.readOrUnset(value);
127 break;
128
129 case SPAttr::WIDTH:
130 this->width.readOrUnset(value, SVGLength::PERCENT, 1.0, 1.0);
132 break;
133
134 case SPAttr::HEIGHT:
135 this->height.readOrUnset(value, SVGLength::PERCENT, 1.0, 1.0);
137 break;
138
139 case SPAttr::XLINK_HREF: {
140 if ( value && this->href && ( strcmp(value, this->href) == 0 ) ) {
141 /* No change, do nothing. */
142 } else {
143 g_free(this->href);
144 this->href = nullptr;
145
146 if (value) {
147 // First, set the href field, because SPUse::href_changed will need it.
148 this->href = g_strdup(value);
149
150 // Now do the attaching, which emits the changed signal.
151 try {
152 this->ref->attach(Inkscape::URI(value));
153 } catch (Inkscape::BadURIException &e) {
154 g_warning("%s", e.what());
155 this->ref->detach();
156 }
157 } else {
158 this->ref->detach();
159 }
160 }
161 break;
162 }
163
164 default:
165 SPItem::set(key, value);
166 break;
167 }
168}
169
171 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
172 repr = xml_doc->createElement("svg:use");
173 }
174
175 SPItem::write(xml_doc, repr, flags);
176
177 this->writeDimensions(repr);
178
179 if (this->ref->getURI()) {
180 auto uri_string = this->ref->getURI()->str();
181 auto href_key = Inkscape::getHrefAttribute(*repr).first;
183 }
184
185 auto shape = cast<SPShape>(child);
186 if (shape) {
187 shape->set_shape(); // evaluate SPCurve of child
188 } else {
189 auto text = cast<SPText>(child);
190 if (text) {
191 text->rebuildLayout(); // refresh Layout, LP Bug 1339305
192 } else if (auto flowtext = cast<SPFlowtext>(child)) {
193 if (auto flowregion = cast<SPFlowregion>(flowtext->firstChild())) {
194 flowregion->updateComputed();
195 }
196 flowtext->rebuildLayout();
197 }
198 }
199
200 return repr;
201}
202
203Geom::OptRect SPUse::bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const {
205
206 if (this->child) {
208
210 }
211
212 return bbox;
213}
214
215std::optional<Geom::PathVector> SPUse::documentExactBounds() const
216{
217 std::optional<Geom::PathVector> result;
218 auto *original = trueOriginal();
219 if (!original) {
220 return result;
221 }
222 result = original->documentExactBounds();
223
225 if (is<SPSymbol>(original)) {
227 } else if (auto const *parent = cast<SPItem>(original->parent)) {
228 private_transform = get_root_transform() * parent->transform.inverse() * parent->i2doc_affine();
229 }
230 result = result ? (*result // TODO: is there a simpler way to get the transform below?
231 * original->i2doc_affine().inverse()
233 : result;
234 return result;
235}
236
238 if (has_xy_offset()) {
239 ctx->bind(Geom::Translate(this->x.computed, this->y.computed), 1.0);
240 }
241
242 if (this->child) {
243 this->child->invoke_print(ctx);
244 }
245
246 if (has_xy_offset()) {
247 ctx->release();
248 }
249}
250
251const char* SPUse::typeName() const {
252 if (is<SPSymbol>(child)) {
253 return "symbol";
254 } else {
255 return "clone";
256 }
257}
258
259const char* SPUse::displayName() const {
260 if (is<SPSymbol>(child)) {
261 return _("Symbol");
262 } else {
263 return _("Clone");
264 }
265}
266
267gchar* SPUse::description() const {
268 if (child) {
269 if (is<SPSymbol>(child)) {
270 if (child->title()) {
271 return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(nullptr, "Symbol", child->title()))).c_str());
272 } else if (child->getAttribute("id")) {
273 return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(nullptr, "Symbol", child->getAttribute("id")))).c_str());
274 } else {
275 return g_strdup_printf(_("called %s"), _("Unnamed Symbol"));
276 }
277 }
278
279 static unsigned recursion_depth = 0;
280
281 if (recursion_depth >= 4) {
282 /* TRANSLATORS: Used for statusbar description for long <use> chains:
283 * "Clone of: Clone of: ... in Layer 1". */
284 return g_strdup(_("..."));
285 /* We could do better, e.g. chasing the href chain until we reach something other than
286 * a <use>, and giving its description. */
287 }
288
290 char *child_desc = this->child->detailedDescription();
292
293 char *ret = g_strdup_printf(_("of: %s"), child_desc);
295
296 return ret;
297 } else {
298 return g_strdup(_("[orphaned]"));
299 }
300}
301
302Inkscape::DrawingItem* SPUse::show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) {
303
304 // std::cout << "SPUse::show: " << (getId()?getId():"null") << std::endl;
306 ai->setPickChildren(false);
307 this->context_style = this->style;
308 ai->setStyle(this->style, this->context_style);
309
310 if (this->child) {
311 Inkscape::DrawingItem *ac = this->child->invoke_show(drawing, key, flags);
312
313 if (ac) {
314 ai->prependChild(ac);
315 }
316
318 ai->setChildTransform(t);
319 }
320
321 return ai;
322}
323
324void SPUse::hide(unsigned int key) {
325 if (this->child) {
326 this->child->invoke_hide(key);
327 }
328
329// SPItem::onHide(key);
330}
331
332
342 SPItem *orig = this->child;
343
344 auto use = cast<SPUse>(orig);
345 while (orig && use) {
346 orig = use->child;
348 }
349
350 return orig;
351}
352
353SPItem const *SPUse::root() const {
354 return const_cast<SPUse*>(this)->root();
355}
356
363{
364 int const depth = cloneDepth();
365 if (depth < 0) {
366 return nullptr;
367 }
368
369 SPItem *original_item = (SPItem *)this;
370 for (int i = 0; i < depth; ++i) {
371 if (auto const *intermediate_clone = cast<SPUse>(original_item)) {
372 original_item = intermediate_clone->get_original();
373 } else {
374 return nullptr;
375 }
376 }
377 return original_item;
378}
379
388bool SPUse::anyInChain(bool (*predicate)(SPItem const *)) const
389{
390 int const depth = cloneDepth();
391 if (depth < 0) {
392 return predicate(this);
393 }
394
395 SPItem const *item = this;
396 if (predicate(item)) {
397 return true;
398 }
399
400 for (int i = 0; i < depth; ++i) {
401 if (auto const *intermediate_clone = cast<SPUse>(item)) {
402 item = intermediate_clone->get_original();
403 if (predicate(item)) {
404 return true;
405 }
406 } else {
407 break;
408 }
409 }
410 return false;
411}
412
417int SPUse::cloneDepth() const {
418 unsigned depth = 1;
419 SPItem *orig = this->child;
420
421 while (orig && cast<SPUse>(orig)) {
422 ++depth;
423 orig = cast<SPUse>(orig)->child;
424 }
425
426 if (!orig) {
427 return -1;
428 } else {
429 return depth;
430 }
431}
432
438{
439 //track the ultimate source of a chain of uses
440 SPObject *orig = this->child;
441
442 std::vector<SPItem const *> chain;
443 chain.push_back(this);
444
445 while (cast<SPUse>(orig)) {
446 chain.push_back(cast<SPItem>(orig));
447 orig = cast<SPUse>(orig)->child;
448 }
449
450 chain.push_back(cast<SPItem>(orig));
451
452 // calculate the accumulated transform, starting from the original
454
455 for (auto i=chain.rbegin(); i!=chain.rend(); ++i) {
456 auto *i_tem = *i;
457
458 // "An additional transformation translate(x,y) is appended to the end (i.e.,
459 // right-side) of the transform attribute on the generated 'g', where x and y
460 // represent the values of the x and y attributes on the 'use' element." - http://www.w3.org/TR/SVG11/struct.html#UseElement
461 auto *i_use = cast<SPUse>(i_tem);
462 if (i_use && i_use->has_xy_offset()) {
463 t = t * i_use->get_xy_offset();
464 }
465
466 t *= i_tem->transform;
467 }
468 return t;
469}
470
476{
478
479 if (has_xy_offset()) {
480 t *= get_xy_offset();
481 }
482
483 t *= this->transform;
484 return t;
485}
486
488 return (this->x._set && this->x.computed != 0) || (this->y._set && this->y.computed != 0);
489}
490
492 return Geom::Translate(this->x._set ? this->x.computed : 0, this->y._set ? this->y.computed : 0);
493}
494
501 // the clone is orphaned; or this is not a real use, but a clone of another use;
502 // we skip it, otherwise duplicate compensation will occur
503 if (this->cloned) {
504 return;
505 }
506
507 // never compensate uses which are used in flowtext
509 return;
510 }
511
513 guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
514 // user wants no compensation
516 return;
517
518 Geom::Affine m(*mp);
520 Geom::Affine clone_move = t.inverse() * m * t;
521
522 // this is not a simple move, do not try to compensate
523 if (!(m.isTranslation())){
524 //BUT move clippaths accordingly.
525 //if clone has a clippath, move it accordingly
526 if (getClipObject()) {
527 for (auto &clip : getClipObject()->children) {
528 SPItem *item = (SPItem*) &clip;
529 if(item){
530 item->transform *= m;
531 Geom::Affine identity;
532 item->doWriteTransform(item->transform, &identity);
533 }
534 }
535 }
536 if (getMaskObject()) {
537 for (auto &mask : getMaskObject()->children) {
538 SPItem *item = (SPItem*) &mask;
539 if(item){
540 item->transform *= m;
541 Geom::Affine identity;
542 item->doWriteTransform(item->transform, &identity);
543 }
544 }
545 }
546 return;
547 }
548
549 // restore item->transform field from the repr, in case it was changed by seltrans
551
552
553 // calculate the compensation matrix and the advertized movement matrix
556 clone_move = clone_move.inverse() * m;
557 advertized_move = m;
558 } else if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
559 clone_move = clone_move.inverse();
560 advertized_move.setIdentity();
561 } else {
563 }
564
565 //if clone has a clippath, move it accordingly
566 if (getClipObject()) {
567 for (auto &clip : getClipObject()->children) {
568 SPItem *item = (SPItem*) &clip;
569 if(item){
570 item->transform *= clone_move.inverse();
571 Geom::Affine identity;
572 item->doWriteTransform(item->transform, &identity);
573 }
574 }
575 }
576 if (getMaskObject()) {
577 for (auto &mask : getMaskObject()->children) {
578 SPItem *item = (SPItem*) &mask;
579 if(item){
580 item->transform *= clone_move.inverse();
581 Geom::Affine identity;
582 item->doWriteTransform(item->transform, &identity);
583 }
584 }
585 }
586
587
588 // commit the compensation
589 this->transform *= clone_move;
590 this->doWriteTransform(this->transform, &advertized_move);
592}
593
595 this->_delete_connection.disconnect();
596 this->_transformed_connection.disconnect();
597
598 if (this->child) {
599 this->detach(this->child);
600 this->child = nullptr;
601 }
602
603 if (this->href) {
604 SPItem *refobj = this->ref->getObject();
605
606 if (refobj) {
608
610
611 auto item = cast<SPItem>(obj);
612 if (item) {
613 child = item;
614
615 this->attach(this->child, this->lastChild());
616 sp_object_unref(this->child, this);
617
618 this->child->invoke_build(refobj->document, childrepr, TRUE);
619
620 for (auto &v : views) {
621 auto ai = this->child->invoke_show(v.drawingitem->drawing(), v.key, v.flags);
622 if (ai) {
623 v.drawingitem->prependChild(ai);
624 }
625 }
626
627 this->_delete_connection = refobj->connectDelete(
628 sigc::hide(sigc::mem_fun(*this, &SPUse::delete_self))
629 );
630
632 sigc::hide(sigc::mem_fun(*this, &SPUse::move_compensate))
633 );
634 } else {
635 delete obj;
636 }
637 }
638 }
639}
640
642 // always delete uses which are used in flowtext
644 deleteObject();
645 return;
646 }
647
649 guint const mode = prefs->getInt("/options/cloneorphans/value",
651
653 this->unlink();
654 } else if (mode == SP_CLONE_ORPHANS_DELETE) {
655 this->deleteObject();
656 }
657}
658
659void SPUse::update(SPCtx *ctx, unsigned flags) {
660 // std::cout << "SPUse::update: " << (getId()?getId():"null") << std::endl;
663
664 unsigned childflags = flags;
665 if (flags & SP_OBJECT_MODIFIED_FLAG) {
667 }
668
670
671 /* Set up child viewport */
672 this->calcDimsFromParentViewport(ictx);
673
675
676 if (this->child) {
677 sp_object_ref(this->child);
678
679 if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
681 cctx.i2doc = child->transform * ictx->i2doc;
682 cctx.i2vp = child->transform * ictx->i2vp;
684 }
685
686 sp_object_unref(this->child);
687 }
688
689 SPItem::update(ctx, flags);
690
691 if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
692 for (auto &v : views) {
693 auto g = cast<Inkscape::DrawingGroup>(v.drawingitem.get());
695 g->setStyle(style, context_style);
696 }
697 }
698
699 /* As last step set additional transform of arena group */
700 for (auto &v : views) {
701 auto g = cast<Inkscape::DrawingGroup>(v.drawingitem.get());
703 g->setChildTransform(t);
704 }
705}
706
707void SPUse::modified(unsigned flags)
708{
709 // std::cout << "SPUse::modified: " << (getId()?getId():"null") << std::endl;
710 flags = cascade_flags(flags);
711
712 if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
713 for (auto &v : views) {
714 auto g = cast<Inkscape::DrawingGroup>(v.drawingitem.get());
716 g->setStyle(style, context_style);
717 }
718 }
719
720 if (child) {
722
724 child->emitModified(flags);
725 }
726
728 }
729}
730
733
734 if (!repr) {
735 return nullptr;
736 }
737
741
742 // Track the ultimate source of a chain of uses.
743 SPItem *orig = this->root();
744 SPItem *origtrue = this->trueOriginal();
745 if (!orig) {
746 return nullptr;
747 }
748
749 // Calculate the accumulated transform, starting from the original.
751
752 Inkscape::XML::Node *copy = nullptr;
753
754 if (auto symbol = cast<SPSymbol>(orig)) {
755 // make a group, copy children
756 copy = xml_doc->createElement("svg:g");
757 copy->setAttribute("display","none");
758
759 for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != nullptr; child = child->next()) {
761 copy->appendChild(newchild);
762 }
763
764 // viewBox transformation
765 t = symbol->c2p * t;
766 } else { // just copy
767 copy = orig->getRepr()->duplicate(xml_doc);
768 copy->setAttribute("display","none");
769 }
770 // Add the duplicate repr just after the existing one.
771 parent->addChild(copy, repr);
772
773 // Retrieve the SPItem of the resulting repr.
775 if (origtrue) {
776 if (unlinked) {
777 origtrue->setTmpSuccessor(unlinked);
778 }
780 if (newLPEObj) {
781 // force always fork
782 newLPEObj->forkPathEffectsIfNecessary(1, true, true);
783 }
784 origtrue->fixTmpSuccessors();
785 origtrue->unsetTmpSuccessor();
786 }
787
788 // Merge style from the use.
789 unlinked->style->merge( this->style );
790 unlinked->style->cascade( unlinked->parent->style );
791 unlinked->updateRepr();
792 unlinked->removeAttribute("display");
793
794 // Hold onto our SPObject and repr for now.
795 sp_object_ref(this);
797
798 // Remove ourselves, not propagating delete events to avoid a
799 // chain-reaction with other elements that might reference us.
800 this->deleteObject(false);
801
802 // Give the copy our old id and let go of our old repr.
803 copy->setAttribute("id", repr->attribute("id"));
805
806 // Remove tiled clone attrs.
807 copy->removeAttribute("inkscape:tiled-clone-of");
808 copy->removeAttribute("inkscape:tile-w");
809 copy->removeAttribute("inkscape:tile-h");
810 copy->removeAttribute("inkscape:tile-cx");
811 copy->removeAttribute("inkscape:tile-cy");
812
813 // Establish the succession and let go of our object.
814 this->setSuccessor(unlinked);
815 sp_object_unref(this);
816
817 auto item = cast<SPItem>(unlinked);
818 g_assert(item != nullptr);
819
820 // Set the accummulated transform.
821 {
823 // Advertise ourselves as not moving.
825 }
826
827 return item;
828}
829
831{
832 SPItem *ref = nullptr;
833
834 if (this->ref){
835 ref = this->ref->getObject();
836 }
837
838 return ref;
839}
840
841void SPUse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const {
842 SPItem const *child = this->child;
843
844 if (!child) {
845 return;
846 }
847
848 // Collect the candidate snap points from the original item (i.e. from the child)
849 std::vector<Inkscape::SnapCandidatePoint> vec_pts;
850 child->snappoints(vec_pts, snapprefs);
851
852 // Offset these snap candidate points if the X/Y attributes have been set for this item
853 // (see https://gitlab.com/inkscape/inkscape/-/issues/2765)
854 if (has_xy_offset()) {
855 // All snappoints are in desktop coordinates, but the item's transformation is in document coordinates
857 for (auto& it: vec_pts) {
858 it.movePoint(offset_dt);
859 }
860 }
861
862 // Return the offsetted snap candidate points in vector p
863 std::move(vec_pts.begin(), vec_pts.end(), std::back_inserter(p));
864}
865
866void SPUse::getLinked(std::vector<SPObject *> &objects, LinkedObjectNature direction) const
867{
868 if (direction == LinkedObjectNature::ANY || direction == LinkedObjectNature::DEPENDENCY) {
869 if (auto linked = (ref ? ref->getObject() : nullptr)) {
870 objects.emplace_back(linked);
871 }
872 }
873 SPObject::getLinked(objects, direction);
874}
875
876/*
877 Local Variables:
878 mode:c++
879 c-file-style:"stroustrup"
880 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
881 indent-tabs-mode:nil
882 fill-column:99
883 End:
884*/
885// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
Lookup dictionary for attributes/properties.
SPAttr
Definition attributes.h:27
@ XLINK_HREF
TODO: insert short description here.
3x3 matrix representing an affine transformation.
Definition affine.h:70
bool isTranslation(Coord eps=EPSILON) const
Check whether this matrix represents a pure translation.
Definition affine.cpp:123
Affine inverse() const
Compute the inverse matrix.
Definition affine.cpp:388
Affine withoutTranslation() const
Definition affine.h:169
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Two-dimensional point that doubles as a vector.
Definition point.h:66
Translation by a vector.
Definition transforms.h:115
Point vector() const
Definition transforms.h:131
void setChildTransform(Geom::Affine const &)
Set additional transform for the group.
SVG drawing item for display.
virtual void setStyle(SPStyle const *style, SPStyle const *context_style=nullptr)
Process information related to the new style.
Preference storage class.
Definition preferences.h:66
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
Storing of snapping preferences.
URI const * getURI() const
Returns a pointer to a URI containing the currently attached URI, or NULL if no URI is currently atta...
void detach()
Detaches from the currently attached URI target, if any; the current referrent is signaled as NULL.
sigc::signal< void(SPObject *, SPObject *)> changedSignal()
Accessor for the referrent change notification signal; this signal is emitted whenever the URIReferen...
void attach(URI const &uri)
Attaches to a URI, relative to the specified document.
Represents an URI as per RFC 2396.
Definition uri.h:36
std::string str(char const *baseuri=nullptr) const
Return the string representation of this URI.
Definition uri.cpp:281
Interface for refcounted XML nodes.
Definition node.h:80
virtual Node * parent()=0
Get the parent of this node.
void setAttributeOrRemoveIfEmpty(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:167
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
void calcDimsFromParentViewport(const SPItemCtx *ictx, bool assign_to_set=false, SPDimensions const *use=nullptr)
Update computed x/y/width/height for "percent" units and/or from its referencing clone parent.
SVGLength y
SVGLength height
SVGLength width
void writeDimensions(Inkscape::XML::Node *) const
Write the geometric properties (x/y/width/height) to XML attributes, if they are set.
SVGLength x
Typed SVG document implementation.
Definition document.h:103
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:213
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
Base class for visual SVG elements.
Definition sp-item.h:109
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
Definition sp-item.cpp:1821
void update(SPCtx *ctx, unsigned int flags) override
Definition sp-item.cpp:780
Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform=Geom::identity()) const
Definition sp-item.cpp:995
virtual void snappoints(std::vector< Inkscape::SnapCandidatePoint > &p, Inkscape::SnapPreferences const *snapprefs) const
Definition sp-item.cpp:1096
Inkscape::XML::Node * write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override
Definition sp-item.cpp:851
Inkscape::DrawingItem * invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
Definition sp-item.cpp:1269
void set(SPAttr key, char const *value) override
Definition sp-item.cpp:559
SPMask * getMaskObject() const
Definition sp-item.cpp:177
sigc::connection connectTransformed(sigc::slot< void(Geom::Affine const *, SPItem *)> slot)
Definition sp-item.h:234
void invoke_print(SPPrintContext *ctx)
Definition sp-item.cpp:1158
void release() override
Definition sp-item.cpp:535
Geom::Affine transform
Definition sp-item.h:138
void invoke_hide(unsigned int key)
Definition sp-item.cpp:1320
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
Definition sp-item.cpp:1816
char * detailedDescription() const
Returns a string suitable for status bar, formatted in pango markup language.
Definition sp-item.cpp:1193
void build(SPDocument *document, Inkscape::XML::Node *repr) override
Definition sp-item.cpp:512
void doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv=nullptr, bool compensate=true)
Set a new transform on an object.
Definition sp-item.cpp:1658
std::vector< SPItemView > views
Definition sp-item.h:163
SPClipPath * getClipObject() const
Definition sp-item.cpp:102
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
Inkscape::XML::Node * repr
Definition sp-object.h:193
unsigned int uflags
Definition sp-object.h:182
void detach(SPObject *object)
Remove object from parent's children, release and unref it.
sigc::connection connectDelete(sigc::slot< void(SPObject *)> slot)
Connects a slot to be called when an object is deleted.
Definition sp-object.h:545
SPObject * lastChild()
Definition sp-object.h:318
unsigned int mflags
Definition sp-object.h:183
void invoke_build(SPDocument *document, Inkscape::XML::Node *repr, unsigned int cloned)
void attach(SPObject *object, SPObject *prev)
Put object into object tree, under parent, and behind prev; also update object's XML space.
SPDocument * document
Definition sp-object.h:188
void updateDisplay(SPCtx *ctx, unsigned int flags)
Updates the object's display immediately.
void emitModified(unsigned int flags)
Emits the MODIFIED signal with the object's flags.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
void setSuccessor(SPObject *successor)
Indicates that another object supercedes this one.
Definition sp-object.h:564
SPObject * parent
Definition sp-object.h:189
SPStyle * context_style
Represents the style that should be used to resolve 'context-fill' and 'context-stroke'.
Definition sp-object.h:253
void readAttr(char const *key)
Read value of key attribute from XML node into object.
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
char const * getAttribute(char const *name) const
char * title() const
Returns the title of this object, or NULL if there is none.
virtual void getLinked(std::vector< SPObject * > &objects, LinkedObjectNature direction=LinkedObjectNature::ANY) const
Get objects which are linked to this object as either a source or a target.
unsigned int cloned
Definition sp-object.h:180
LinkedObjectNature
Definition sp-object.h:168
void addChild(Inkscape::XML::Node *child, Inkscape::XML::Node *prev=nullptr)
ChildrenList children
Definition sp-object.h:907
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
void cascade(SPStyle const *parent)
Sets computed values in style, which may involve inheriting from (or in some other way calculating fr...
Definition style.cpp:817
SPItem * getObject() const
Definition sp-use.h:25
~SPUse() override
Definition sp-use.cpp:74
Geom::Affine get_root_transform() const
Returns the effective transform that goes from the ultimate original to given SPUse,...
Definition sp-use.cpp:437
const char * typeName() const override
The item's type name, not node tag name.
Definition sp-use.cpp:251
SPItem * unlink()
Definition sp-use.cpp:731
SPItem * get_original() const
Definition sp-use.cpp:830
SPUseReference * ref
Definition sp-use.h:39
SPItem * trueOriginal() const
Returns the ultimate original of a SPUse, i.e., the first object in the chain of uses which is not it...
Definition sp-use.cpp:362
void update(SPCtx *ctx, unsigned int flags) override
Definition sp-use.cpp:659
void getLinked(std::vector< SPObject * > &objects, LinkedObjectNature direction=LinkedObjectNature::ANY) const override
Get objects which are linked to this object as either a source or a target.
Definition sp-use.cpp:866
void move_compensate(Geom::Affine const *mp)
Sensing a movement of the original, this function attempts to compensate for it in such a way that th...
Definition sp-use.cpp:500
void build(SPDocument *doc, Inkscape::XML::Node *repr) override
Definition sp-use.cpp:85
SPItem * child
Definition sp-use.h:33
sigc::connection _delete_connection
Definition sp-use.h:42
bool has_xy_offset() const
Definition sp-use.cpp:487
SPUse()
Definition sp-use.cpp:54
Geom::Affine get_parent_transform() const
Returns the transform that leads to the use from its immediate original.
Definition sp-use.cpp:475
void snappoints(std::vector< Inkscape::SnapCandidatePoint > &p, Inkscape::SnapPreferences const *snapprefs) const override
Definition sp-use.cpp:841
void hide(unsigned int key) override
Definition sp-use.cpp:324
Inkscape::DrawingItem * show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) override
Definition sp-use.cpp:302
std::optional< Geom::PathVector > documentExactBounds() const override
Get an exact geometric shape representing the visual bounds of the item in the document coordinates.
Definition sp-use.cpp:215
int cloneDepth() const
Get the number of dereferences or calls to get_original() needed to get an object which is not an svg...
Definition sp-use.cpp:417
void href_changed()
Definition sp-use.cpp:594
void print(SPPrintContext *ctx) override
Definition sp-use.cpp:237
const char * displayName() const override
The item's type name as a translated human string.
Definition sp-use.cpp:259
SPItem * root()
Returns the ultimate original of a SPUse (i.e.
Definition sp-use.cpp:341
void release() override
Definition sp-use.cpp:99
Geom::Translate get_xy_offset() const
Definition sp-use.cpp:491
sigc::connection _changed_connection
Definition sp-use.h:43
void modified(unsigned int flags) override
Definition sp-use.cpp:707
Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const override
Definition sp-use.cpp:203
char * href
Definition sp-use.h:36
void delete_self()
Definition sp-use.cpp:641
sigc::connection _transformed_connection
Definition sp-use.h:46
bool anyInChain(bool(*predicate)(SPItem const *)) const
Test the passed predicate on all items in a chain of uses.
Definition sp-use.cpp:388
char * description() const override
Definition sp-use.cpp:267
void set(SPAttr key, char const *value) override
Definition sp-use.cpp:117
Inkscape::XML::Node * write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override
Definition sp-use.cpp:170
void readOrUnset(char const *str, Unit u=NONE, float v=0, float c=0)
bool _set
Definition svg-length.h:41
void unset(Unit u=NONE, float v=0, float c=0)
float computed
Definition svg-length.h:50
ObserverPredicate predicate
Css & result
Geom::Point orig
Group belonging to an SVG drawing element.
@ SP_CLONE_ORPHANS_UNLINK
Definition enums.h:95
@ SP_CLONE_ORPHANS_DELETE
Definition enums.h:96
@ SP_CLONE_COMPENSATION_UNMOVED
Definition enums.h:90
@ SP_CLONE_COMPENSATION_PARALLEL
Definition enums.h:89
@ SP_CLONE_COMPENSATION_NONE
Definition enums.h:91
SPItem * item
std::string original
Affine identity()
Create an identity matrix.
Definition affine.h:210
static R & anchor(R &r)
Increments the reference count of a anchored object.
Definition gc-anchored.h:92
static R & release(R &r)
Decrements the reference count of a anchored object.
Helper class to stream background task notifications as a series of messages.
std::pair< char const *, char const * > getHrefAttribute(XML::Node const &node)
Get the 'href' or 'xlink:href' (fallback) attribute from an XML node.
static T clip(T const &v, T const &a, T const &b)
static cairo_user_data_key_t key
int mode
Singleton class to access the preferences file in a convenient way.
Ocnode * child[8]
Definition quantize.cpp:33
Ocnode ** ref
Definition quantize.cpp:32
Some utility classes to store various kinds of snap candidates.
TODO: insert short description here.
TODO: insert short description here.
SPObject * sp_object_unref(SPObject *object, SPObject *owner)
Decrease reference count of object, with possible debugging and finalization.
SPObject * sp_object_ref(SPObject *object, SPObject *owner)
Increase reference count of object, with possible debugging.
unsigned cascade_flags(unsigned flags)
Definition sp-object.h:60
SPRoot: SVG <svg> implementation.
Interface for XML documents.
Definition document.h:43
static std::string get_type_string(Inkscape::XML::Node const &node)
Unused.
Definition sp-object.h:94
static SPObject * createObject(std::string const &id)
Contains transformations to document/viewport and the viewport size.
Definition sp-item.h:92
SPStyle - a style object for SPItem objects.
Affine transformation classes.
Interface for XML documents.