Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sp-symbol.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * SVG <symbol> implementation
4 *
5 * Authors:
6 * Lauris Kaplinski <lauris@kaplinski.com>
7 * Abhishek Sharma
8 * Jon A. Cruz <jon@joncruz.org>
9 *
10 * Copyright (C) 1999-2003 Lauris Kaplinski
11 *
12 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13 */
14
15#include "sp-symbol.h"
16
17#include <glibmm/i18n.h>
18
19#include <2geom/transforms.h>
20#include <2geom/pathvector.h>
21
22#include "attributes.h"
23#include "desktop.h"
24#include "document.h"
25#include "inkscape.h"
26#include "layer-manager.h"
27#include "print.h"
28#include "sp-use.h"
29
31#include "svg/svg.h"
32#include "xml/document.h" // for Document
33
34namespace Inkscape {
35class Drawing;
36} // namespace Inkscape
37
40
41SPSymbol::~SPSymbol() = default;
42
46 this->readAttr(SPAttr::X);
47 this->readAttr(SPAttr::Y);
52
53 SPGroup::build(document, repr);
54
55 document->addResource("symbol", this);
56}
57
59 if (document) {
60 document->removeResource("symbol", this);
61 }
62
64}
65
66void SPSymbol::set(SPAttr key, const gchar* value) {
67 switch (key) {
68 case SPAttr::REFX:
70 this->refX.readOrUnset(value);
72 break;
73
74 case SPAttr::REFY:
76 this->refY.readOrUnset(value);
78 break;
79
80 case SPAttr::X:
81 this->x.readOrUnset(value);
83 break;
84
85 case SPAttr::Y:
86 this->y.readOrUnset(value);
88 break;
89
90 case SPAttr::WIDTH:
91 this->width.readOrUnset(value, SVGLength::PERCENT, 1.0, 1.0);
93 break;
94
95 case SPAttr::HEIGHT:
96 this->height.readOrUnset(value, SVGLength::PERCENT, 1.0, 1.0);
98 break;
99
100 case SPAttr::VIEWBOX:
101 set_viewBox( value );
102 // std::cout << "Symbol: ViewBox: " << viewBox << std::endl;
104 break;
105
108 // std::cout << "Symbol: Preserve aspect ratio: " << aspect_align << ", " << aspect_clip << std::endl;
110 break;
111
112 default:
113 SPGroup::set(key, value);
114 break;
115 }
116}
117
121
123{
124 SPDocument *doc = this->document;
126 // Check if something is selected.
127
128 doc->ensureUpToDate();
129
130 // Create new <g> and insert in current layer
131 Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
132 //TODO: Better handle if no desktop, currently go to defs without it
134 if(desktop && desktop->doc() == doc) {
136 } else {
137 parent->getRepr()->appendChild(group);
138 }
139
140 // Move all children of symbol to group
141 std::vector<SPObject*> children = childList(false);
142
143 // Converting a group to a symbol inserts a group for non-translational transform.
144 // In converting a symbol back to a group we strip out the inserted group (or any other
145 // group that only adds a transform to the symbol content).
146 if( children.size() == 1 ) {
147 SPObject *object = children[0];
148 if (is<SPGroup>( object ) ) {
149 if( object->getAttribute("style") == nullptr ||
150 object->getAttribute("class") == nullptr ) {
151
152 group->setAttribute("transform", object->getAttribute("transform"));
153 children = object->childList(false);
154 }
155 }
156 }
157 for (std::vector<SPObject*>::const_reverse_iterator i=children.rbegin();i!=children.rend();++i){
158 Inkscape::XML::Node *repr = (*i)->getRepr();
160 group->addChild(repr,nullptr);
161 }
162
163 // Copy relevant attributes
164 group->setAttribute("style", getAttribute("style"));
165 group->setAttribute("class", getAttribute("class"));
166 group->setAttribute("title", getAttribute("title"));
167 group->setAttribute("inkscape:transform-center-x",
168 getAttribute("inkscape:transform-center-x"));
169 group->setAttribute("inkscape:transform-center-y",
170 getAttribute("inkscape:transform-center-y"));
171
172
173 // Need to delete <symbol>; all <use> elements that referenced <symbol> should
174 // auto-magically reference <g> (if <symbol> deleted after setting <g> 'id').
175 Glib::ustring id = getAttribute("id");
176 group->setAttribute("id", id);
177
178 deleteObject(true);
179
180 // Clean up
182}
183
184std::optional<Geom::PathVector> SPSymbol::documentExactBounds() const
185{
186 Geom::PathVector shape;
187 bool is_empty = true;
188 for (auto &child : children) {
189 if (auto const item = cast<SPItem>(&child)) {
190 if (auto bounds = item->documentExactBounds()) {
191 shape.insert(shape.end(), bounds->begin(), bounds->end());
192 is_empty = false;
193 }
194 }
195 }
196 std::optional<Geom::PathVector> result;
197 if (!is_empty) {
198 result = shape * i2doc_affine();
199 }
200 return result;
201}
202
203void SPSymbol::update(SPCtx *ctx, guint flags) {
204 if (this->cloned) {
205
207
208 // Calculate x, y, width, height from parent/initial viewport
209 this->calcDimsFromParentViewport(ictx, false, cast<SPUse>(parent));
210
213 rctx = get_rctx(&rctx);
214
215 // Shift according to refX, refY
216 if (refX._set && refY._set) {
217 refX.update(1, 1, viewBox.width());
218 refY.update(1, 1, viewBox.height());
221 }
222
223 // And invoke parent method
224 SPGroup::update((SPCtx *) &rctx, flags);
225
226 // As last step set additional transform of drawing group
227 for (auto &v : views) {
228 auto g = cast<Inkscape::DrawingGroup>(v.drawingitem.get());
229 g->setChildTransform(this->c2p);
230 }
231 } else {
232 // No-op
233 SPGroup::update(ctx, flags);
234 }
235}
236
237void SPSymbol::modified(unsigned int flags) {
238 SPGroup::modified(flags);
239}
240
241
243 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
244 repr = xml_doc->createElement("svg:symbol");
245 }
246
247 if (refX._set) {
249 }
250 if (refY._set) {
252 }
253
254 this->writeDimensions(repr);
255 this->write_viewBox(repr);
256 this->write_preserveAspectRatio(repr);
257
258 SPGroup::write(xml_doc, repr, flags);
259
260 return repr;
261}
262
263Inkscape::DrawingItem* SPSymbol::show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags)
264{
265 Inkscape::DrawingItem *ai = nullptr;
266
267 if (cloned) {
268 // Cloned <symbol> is actually renderable
269 ai = SPGroup::show(drawing, key, flags);
270
271 if (auto g = cast<Inkscape::DrawingGroup>(ai)) {
272 g->setChildTransform(this->c2p);
273 }
274 }
275
276 return ai;
277}
278
279void SPSymbol::hide(unsigned int key) {
280 if (this->cloned) {
281 /* Cloned <symbol> is actually renderable */
282 SPGroup::hide(key);
283 }
284}
285
286
288{
290 return SPGroup::bbox(a, type);
291}
292
294 if (this->cloned) {
295 // Cloned <symbol> is actually renderable
296
297 ctx->bind(this->c2p, 1.0);
298
299 SPGroup::print(ctx);
300
301 ctx->release ();
302 }
303}
304
305/*
306 Local Variables:
307 mode:c++
308 c-file-style:"stroustrup"
309 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
310 indent-tabs-mode:nil
311 fill-column:99
312 End:
313*/
314// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Lookup dictionary for attributes/properties.
SPAttr
Definition attributes.h:27
@ PRESERVEASPECTRATIO
Geom::IntRect bounds
Definition canvas.cpp:182
3x3 matrix representing an affine transformation.
Definition affine.h:70
static CRect from_xywh(Coord x, Coord y, Coord w, Coord h)
Create rectangle from origin and dimensions.
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Sequence of subpaths.
Definition pathvector.h:122
iterator insert(iterator pos, Path const &p)
Definition pathvector.h:179
iterator end()
Definition pathvector.h:152
Two-dimensional point that doubles as a vector.
Definition point.h:66
Translation by a vector.
Definition transforms.h:115
SVG drawing item for display.
SPGroup * currentLayer() const
Returns current top layer.
Interface for refcounted XML nodes.
Definition node.h:80
virtual Node * parent()=0
Get the parent of this node.
virtual void addChild(Node *child, Node *after)=0
Insert another node as a child of this node.
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
virtual void removeChild(Node *child)=0
Remove a child of this node.
To do: update description of desktop.
Definition desktop.h:149
SPDocument * doc() const
Definition desktop.h:159
Inkscape::LayerManager & layerManager()
Definition desktop.h:287
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:101
bool removeResource(char const *key, SPObject *object)
bool addResource(char const *key, SPObject *object)
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:211
int ensureUpToDate(unsigned int object_modified_tag=0)
Repeatedly works on getting the document updated, since sometimes it takes more than one pass to get ...
void release() override
Inkscape::DrawingItem * show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) override
void print(SPPrintContext *ctx) override
Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const override
Inkscape::XML::Node * write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override
void set(SPAttr key, char const *value) override
void build(SPDocument *document, Inkscape::XML::Node *repr) override
void child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) override
void modified(unsigned int flags) override
void hide(unsigned int key) override
void update(SPCtx *ctx, unsigned int flags) override
virtual std::optional< Geom::PathVector > documentExactBounds() const
Get an exact geometric shape representing the visual bounds of the item in the document coordinates.
Definition sp-item.cpp:1043
Geom::Affine transform
Definition sp-item.h:138
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
Definition sp-item.cpp:1824
std::vector< SPItemView > views
Definition sp-item.h:163
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
std::vector< SPObject * > childList(bool add_ref, Action action=ActionGeneral)
Retrieves the children as a std vector object, optionally ref'ing the children in the process,...
SPDocument * document
Definition sp-object.h:188
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
unsigned int cloned
Definition sp-object.h:180
ChildrenList children
Definition sp-object.h:907
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
void modified(unsigned int flags) override
Inkscape::XML::Node * write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override
SVGLength refY
Definition sp-symbol.h:51
void print(SPPrintContext *ctx) override
~SPSymbol() override
Inkscape::DrawingItem * show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) override
void set(SPAttr key, char const *value) override
Definition sp-symbol.cpp:66
void build(SPDocument *document, Inkscape::XML::Node *repr) override
Definition sp-symbol.cpp:43
Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const override
void unSymbol()
SVGLength refX
Definition sp-symbol.h:50
void child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) override
void update(SPCtx *ctx, unsigned int flags) override
void release() override
Definition sp-symbol.cpp:58
std::optional< Geom::PathVector > documentExactBounds() const override
Get an exact geometric shape representing the visual bounds of the item in the document coordinates.
void hide(unsigned int key) override
void set_viewBox(const gchar *value)
Definition viewbox.cpp:50
Geom::Rect viewBox
Definition viewbox.h:35
Geom::Affine c2p
Definition viewbox.h:43
void set_preserveAspectRatio(const gchar *value)
Definition viewbox.cpp:98
void write_preserveAspectRatio(Inkscape::XML::Node *repr) const
Write preserveAspectRatio attribute to XML, if set.
Definition viewbox.cpp:305
SPItemCtx get_rctx(const SPItemCtx *ictx, double scale_none=1.0)
Definition viewbox.cpp:260
void write_viewBox(Inkscape::XML::Node *repr) const
Write viewBox attribute to XML, if set.
Definition viewbox.cpp:289
void readOrUnset(char const *str, Unit u=NONE, float v=0, float c=0)
bool _set
Definition svg-length.h:41
float computed
Definition svg-length.h:50
void update(double em, double ex, double scale)
Css & result
Editable view implementation.
static char const *const parent
Definition dir-util.cpp:70
Group belonging to an SVG drawing element.
SPItem * item
Affine identity()
Create an identity matrix.
Definition affine.h:210
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.
char const * refY_named_to_percent(char const *str)
char const * refX_named_to_percent(char const *str)
static cairo_user_data_key_t key
PathVector - a sequence of subpaths.
Ocnode * child[8]
Definition quantize.cpp:33
Ocnode ** ref
Definition quantize.cpp:32
Interface for XML documents.
Definition document.h:43
Unused.
Definition sp-object.h:94
Contains transformations to document/viewport and the viewport size.
Definition sp-item.h:92
unsigned int bind(Geom::Affine const &transform, float opacity)
Definition print.cpp:39
std::string sp_svg_length_write_with_units(SVGLength const &length)
N.B. This routine will sometimes return strings with ā€˜e’ notation, so is unsuitable for CSS lengths (...
SPDesktop * desktop
Affine transformation classes.
Interface for XML documents.