Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sp-use-reference.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * The reference corresponding to href of <use> element.
4 *
5 * Copyright (C) 2004 Bulia Byak
6 * Copyright (C) 2004 Monash University
7 *
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10
11#include "sp-use-reference.h"
12
13#include <cstring>
14#include <string>
15
16#include "bad-uri-exception.h"
17#include "enums.h"
18
19#include "display/curve.h"
20#include "livarot/Path.h"
21#include "preferences.h"
22#include "sp-shape.h"
23#include "sp-text.h"
24#include "uri.h"
25
27{
28 if (!is<SPItem>(obj))
29 return false;
30 return URIReference::_acceptObject(obj);
31}
32
33
36static void sp_usepath_delete_self(SPObject *deleted, SPUsePath *offset);
37static void sp_usepath_source_modified(SPObject *iSource, guint flags, SPUsePath *offset);
38
40 , owner(i_owner)
41{
42 _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_usepath_href_changed), this)); // listening to myself, this should be virtual instead
43 user_unlink = nullptr;
44}
45
47{
48 _changed_connection.disconnect(); // to do before unlinking
49
51 unlink();
52}
53
54void
56{
57 if ( to == nullptr ) {
59 unlink();
60 } else {
61 if ( !sourceHref || ( strcmp(to, sourceHref) != 0 ) ) {
62 g_free(sourceHref);
63 sourceHref = g_strdup(to);
64 try {
66 } catch (Inkscape::BadURIException &e) {
67 /* TODO: Proper error handling as per
68 * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing.
69 */
70 g_warning("%s", e.what());
71 detach();
72 }
73 }
74 }
75}
76
77void
79{
80 g_free(sourceHref);
81 sourceHref = nullptr;
82 detach();
83}
84
86{
87 if ( to == nullptr ) {
88 return;
89 }
90 sourceObject = to;
91 sourceRepr = to->getRepr();
92 _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&sp_usepath_delete_self), this));
93 _transformed_connection = to->connectTransformed(sigc::bind(sigc::ptr_fun(&sp_usepath_move_compensate), this));
94 _modified_connection = to->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_usepath_source_modified), this));
95}
96
97void
99{
100 if ( sourceObject == nullptr ) {
101 return;
102 }
103 _modified_connection.disconnect();
104 _delete_connection.disconnect();
105 _transformed_connection.disconnect();
106 sourceRepr = nullptr;
107 sourceObject = nullptr;
108}
109
110static void
112{
113 offset->quit_listening();
114 SPItem *refobj = offset->getObject();
115 if ( refobj ) {
116 offset->start_listening(refobj);
117 }
118 offset->sourceDirty=true;
119 offset->owner->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
120}
121
122static void
124{
126 guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
128 return;
129 }
130 auto item = cast<SPItem>(self->owner);
131
132// TODO kill naughty naughty #if 0
133#if 0
134 Geom::Affine m(*mp);
135 if (!(m.is_translation())) {
136 return;
137 }
138 Geom::Affine const t(item->transform);
139 Geom::Affine clone_move = t.inverse() * m * t;
140
141 // Calculate the compensation matrix and the advertized movement matrix.
142 Geom::Affine advertized_move;
144 //clone_move = clone_move.inverse();
145 advertized_move.set_identity();
146 } else if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
147 clone_move = clone_move.inverse() * m;
148 advertized_move = m;
149 } else {
150 g_assert_not_reached();
151 }
152
153 // Commit the compensation.
154 item->transform *= clone_move;
155 sp_item_write_transform(item, item->getRepr(), item->transform, &advertized_move);
156#else
157 (void)mp;
158 (void)original;
159#endif
160
161 self->sourceDirty = true;
162 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
163}
164
165static void
167{
169 guint const mode = prefs->getInt("/options/cloneorphans/value", SP_CLONE_ORPHANS_UNLINK);
170
172 // leave it be. just forget about the source
173 offset->quit_listening();
174 offset->unlink();
175 if (offset->user_unlink)
176 offset->user_unlink(offset->owner);
177 } else if (mode == SP_CLONE_ORPHANS_DELETE) {
178 offset->owner->deleteObject();
179 }
180}
181
182static void
183sp_usepath_source_modified(SPObject */*iSource*/, guint /*flags*/, SPUsePath *offset)
184{
185 offset->sourceDirty = true;
186 offset->owner->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
187}
188
190{
191 sourceDirty = false;
192
193 originalPath.reset();
194
195 SPObject *refobj = sourceObject;
196 if ( refobj == nullptr ) return;
197
198 if (auto shape = cast<SPShape>(refobj)) {
199 if (shape->curve()) {
200 originalPath = *shape->curve();
201 } else {
202 sourceDirty = true;
203 }
204 } else if (auto text = cast<SPText>(refobj)) {
205 originalPath = text->getNormalizedBpath();
206 }
207}
208
209
210/*
211 Local Variables:
212 mode:c++
213 c-file-style:"stroustrup"
214 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
215 indent-tabs-mode:nil
216 fill-column:99
217 End:
218*/
219// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
TODO: insert short description here.
TODO: insert short description here.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Affine inverse() const
Compute the inverse matrix.
Definition affine.cpp:388
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.
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
Base class for visual SVG elements.
Definition sp-item.h:109
sigc::connection connectTransformed(sigc::slot< void(Geom::Affine const *, SPItem *)> slot)
Definition sp-item.h:234
Geom::Affine transform
Definition sp-item.h:138
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
sigc::connection connectDelete(sigc::slot< void(SPObject *)> slot)
Connects a slot to be called when an object is deleted.
Definition sp-object.h:545
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
sigc::connection connectModified(sigc::slot< void(SPObject *, unsigned int)> slot)
Connects to the modification notification signal.
Definition sp-object.h:705
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
~SPUsePath() override
char * sourceHref
SPUsePath(SPObject *i_owner)
void(* user_unlink)(SPObject *user)
Inkscape::XML::Node * sourceRepr
sigc::connection _changed_connection
sigc::connection _transformed_connection
void link(char *to)
sigc::connection _modified_connection
void start_listening(SPItem *to)
SPObject * owner
SPObject * sourceObject
sigc::connection _delete_connection
void quit_listening()
std::optional< SPCurve > originalPath
bool _acceptObject(SPObject *const obj) const override
@ 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
double offset
int mode
Singleton class to access the preferences file in a convenient way.
Ocnode ** ref
Definition quantize.cpp:32
static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPTagUsePath *offset)
static void sp_usepath_delete_self(SPObject *deleted, SPTagUsePath *offset)
static void sp_usepath_source_modified(SPObject *iSource, guint flags, SPUsePath *offset)
static void sp_usepath_delete_self(SPObject *deleted, SPUsePath *offset)
static void sp_usepath_move_compensate(Geom::Affine const *mp, SPItem *original, SPUsePath *self)
static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPUsePath *offset)