Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
repr-css.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
/*
5 * Authors: see git history
6 *
7 * Copyright (C) 2018 Authors
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10/*
11 * bulia byak <buliabyak@users.sf.net>
12 * Tavmjong Bah <tavmjong@free.fr> (Documentation)
13 *
14 * Functions to manipulate SPCSSAttr which is a class derived from Inkscape::XML::Node See
15 * sp-css-attr.h and node.h
16 *
17 * SPCSSAttr is a special node type where the "attributes" are the properties in an element's style
18 * attribute. For example, style="fill:blue;stroke:none" is stored in a List (Inkscape::Util:List)
19 * where the key is the property (e.g. "fill" or "stroke") and the value is the property's value
20 * (e.g. "blue" or "none"). An element's properties are manipulated by adding, removing, or
21 * changing an item in the List. Utility functions are provided to go back and forth between the
22 * two ways of representing properties (by a string or by a list).
23 *
24 * Use sp_repr_css_write_string to go from a property list to a style string.
25 *
26 */
27
28#define SP_REPR_CSS_C
29
30#include <cstring>
31#include <string>
32#include <sstream>
33
34#include <glibmm/ustring.h>
35
37
39
40#include "xml/repr.h"
41#include "xml/simple-document.h"
42#include "xml/sp-css-attr.h"
43
48
49struct SPCSSAttrImpl : public SimpleNode, public SPCSSAttr {
50public:
51 SPCSSAttrImpl(Document *doc)
52 : SimpleNode(g_quark_from_static_string("css"), doc) {}
53 SPCSSAttrImpl(SPCSSAttrImpl const &other, Document *doc)
54 : SimpleNode(other, doc) {}
55
56 NodeType type() const override { return Inkscape::XML::NodeType::ELEMENT_NODE; }
57
58protected:
59 SimpleNode *duplicate(Document *doc) const override { return new SPCSSAttrImpl(*this, doc); }
60};
61
62static void sp_repr_css_add_components(SPCSSAttr *css, Node const *repr, gchar const *attr);
63
68{
69 static auto const attr_doc = new Inkscape::XML::SimpleDocument();
70 return new SPCSSAttrImpl(attr_doc);
71}
72
77{
78 g_assert(css != nullptr);
80}
81
88SPCSSAttr *sp_repr_css_attr(Node const *repr, gchar const *attr)
89{
90 g_assert(repr != nullptr);
91 g_assert(attr != nullptr);
92
95 return css;
96}
97
98
102static void sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node const *repr, gchar const *attr)
103{
104 const Node *parent = repr->parent();
105
106 // read the ancestors from root down, using head recursion, so that children override parents
107 if (parent) {
109 }
110 sp_repr_css_add_components(css, repr, attr);
111}
112
116SPCSSAttr *sp_repr_css_attr_inherited(Node const *repr, gchar const *attr)
117{
118 g_assert(repr != nullptr);
119 g_assert(attr != nullptr);
120
122
124
125 return css;
126}
127
133static void sp_repr_css_add_components(SPCSSAttr *css, Node const *repr, gchar const *attr)
134{
135 g_assert(css != nullptr);
136 g_assert(repr != nullptr);
137 g_assert(attr != nullptr);
138
139 char const *data = repr->attribute(attr);
141}
142
147char const *sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
148{
149 g_assert(css != nullptr);
150 g_assert(name != nullptr);
151
152 char const *attr = ((Node *)css)->attribute(name);
153 return ( attr == nullptr
154 ? defval
155 : attr );
156}
157
162Glib::ustring sp_repr_css_property(SPCSSAttr *css, Glib::ustring const &name, Glib::ustring const &defval)
163{
164 g_assert(css != nullptr);
165
166 Glib::ustring retval = defval;
167 char const *attr = ((Node *)css)->attribute(name.c_str());
168 if (attr) {
169 retval = attr;
170 }
171
172 return retval;
173}
174
179{
180 g_assert(css != nullptr);
181 g_assert(name != nullptr);
182
183 char const *attr = ((Node *)css)->attribute(name);
184 return (attr && !strcmp(attr, "inkscape:unset"));
185}
186
187
191void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
192{
193 g_assert(css != nullptr);
194 g_assert(name != nullptr);
195
196 ((Node *) css)->setAttribute(name, value);
197}
198
203{
204 g_assert(css != nullptr);
205 g_assert(name != nullptr);
206
207 ((Node *) css)->setAttribute(name, "inkscape:unset");
208}
209
213double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval)
214{
215 g_assert(css != nullptr);
216 g_assert(name != nullptr);
217
218 return css->getAttributeDouble(name, defval);
219}
220
224void sp_repr_css_set_property_double(SPCSSAttr *css, gchar const *name, double value)
225{
226 g_assert(css != nullptr);
227 g_assert(name != nullptr);
228
229 ((Node *) css)->setAttributeCssDouble(name, value);
230}
231
235void sp_repr_css_set_property_string(SPCSSAttr *css, char const *name, std::string const &value)
236{
237 sp_repr_css_set_property(css, name, value.c_str());
238}
239
243void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
244{
245 str.clear();
246 for (const auto & iter : css->attributeList())
247 {
248 if (iter.value && !strcmp(iter.value, "inkscape:unset")) {
249 continue;
250 }
251
252 if (!str.empty()) {
253 str.push_back(';');
254 }
255
256 str.append(g_quark_to_string(iter.key));
257 str.push_back(':');
258 str.append(iter.value); // Any necessary quoting to be done by calling routine.
259 }
260}
261
265void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
266{
267 g_assert(repr != nullptr);
268 g_assert(css != nullptr);
269 g_assert(attr != nullptr);
270
271 Glib::ustring value;
273
274 /*
275 * If the new value is different from the old value, this will sometimes send a signal via
276 * CompositeNodeObserver::notiftyAttributeChanged() which results in calling
277 * SPObject::repr_attr_changed and thus updates the object's SPStyle. This update
278 * results in another call to repr->setAttribute().
279 */
280 repr->setAttributeOrRemoveIfEmpty(attr, value);
281}
282
287{
288 for ( const auto & attr: css->attributeList() )
289 {
290 gchar const * key = g_quark_to_string(attr.key);
291 gchar const * val = attr.value;
292 g_print("%s:\t%s\n",key,val);
293 }
294}
295
300{
301 g_assert(dst != nullptr);
302 g_assert(src != nullptr);
303
304 dst->mergeFrom(src, "");
305}
306
315{
316 guchar *const str_value_unsigned = cr_term_to_string(decl->value);
317 css->setAttribute(decl->property->stryng->str, reinterpret_cast<char const *>(str_value_unsigned));
318 g_free(str_value_unsigned);
319}
320
326static void sp_repr_css_merge_from_decl_list(SPCSSAttr *css, CRDeclaration const *const decl_list)
327{
328 // read the decls from start to end, using tail recursion, so that latter declarations override
329 // (Ref: http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order point 4.)
330 // because sp_repr_css_merge_from_decl sets properties unconditionally
332 if (decl_list->next) {
334 }
335}
336
342{
343 if (p != nullptr) {
344 CRDeclaration *const decl_list
345 = cr_declaration_parse_list_from_buf(reinterpret_cast<guchar const *>(p), CR_UTF_8);
346 if (decl_list) {
348 cr_declaration_destroy(decl_list);
349 }
350 }
351}
352
358void sp_repr_css_change(Node *repr, SPCSSAttr *css, gchar const *attr)
359{
360 g_assert(repr != nullptr);
361 g_assert(css != nullptr);
362 g_assert(attr != nullptr);
363
364 SPCSSAttr *current = sp_repr_css_attr(repr, attr);
366 sp_repr_css_set(repr, current, attr);
367
369}
370
371void sp_repr_css_change_recursive(Node *repr, SPCSSAttr *css, gchar const *attr)
372{
373 g_assert(repr != nullptr);
374 g_assert(css != nullptr);
375 g_assert(attr != nullptr);
376
377 sp_repr_css_change(repr, css, attr);
378
379 for (Node *child = repr->firstChild(); child != nullptr; child = child->next()) {
381 }
382}
383
388{
389 SPCSSAttr* css_unset = sp_repr_css_attr_new();
390 for ( const auto & iter : css->attributeList() ) {
391 sp_repr_css_set_property (css_unset, g_quark_to_string(iter.key), "inkscape:unset");
392 }
393 return css_unset;
394}
395
396/*
397 Local Variables:
398 mode:c++
399 c-file-style:"stroustrup"
400 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
401 indent-tabs-mode:nil
402 fill-column:99
403 End:
404*/
405// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
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
virtual Node * firstChild()=0
Get the first child of this node.
virtual void mergeFrom(Node const *src, char const *key, bool extension=false, bool clean=false)=0
Merge all children of another node with the current.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Default implementation of the XML node stored in memory.
Definition simple-node.h:37
The declaration of the CRDeclaration class.
CRDeclaration * cr_declaration_parse_list_from_buf(const guchar *a_str, enum CREncoding a_enc)
void cr_declaration_destroy(CRDeclaration *a_this)
guchar * cr_term_to_string(CRTerm const *a_this)
@ CR_UTF_8
Definition cr-utils.h:89
TODO: insert short description here.
std::shared_ptr< Css const > css
static char const *const current
Definition dir-util.cpp:71
static char const *const parent
Definition dir-util.cpp:70
void duplicate(InkscapeApplication *app)
static R & release(R &r)
Decrements the reference count of a anchored object.
GType type()
Returns the type used for storing an object of type T inside a value.
Definition value-utils.h:29
NodeType
Enumeration containing all supported node types.
Definition node.h:40
@ ELEMENT_NODE
Regular element node, e.g. <group />.
static cairo_user_data_key_t key
Ocnode * child[8]
Definition quantize.cpp:33
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
Definition repr-css.cpp:67
void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
Write a style attribute string from a list of properties stored in an SPCSAttr object.
Definition repr-css.cpp:243
void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src)
Merges two SPCSSAttr's.
Definition repr-css.cpp:299
SPCSSAttr * sp_repr_css_attr_inherited(Node const *repr, gchar const *attr)
Creates a new SPCSSAttr with one attribute whose value is determined by cascading.
Definition repr-css.cpp:116
static void sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node const *repr, gchar const *attr)
Adds an attribute to an existing SPCSAttr with the cascaded value including all parents.
Definition repr-css.cpp:102
void sp_repr_css_change(Node *repr, SPCSSAttr *css, gchar const *attr)
Creates a new SPCSAttr with the values filled from a repr, merges in properties from the given SPCSAt...
Definition repr-css.cpp:358
void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
Sets an attribute (e.g.
Definition repr-css.cpp:265
void sp_repr_css_set_property_double(SPCSSAttr *css, gchar const *name, double value)
Set a style property to a new float value (e.g.
Definition repr-css.cpp:224
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
Definition repr-css.cpp:76
double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval)
Return the value of a style property if property define, or a default value if not.
Definition repr-css.cpp:213
SPCSSAttr * sp_repr_css_attr(Node const *repr, gchar const *attr)
Creates a new SPCSSAttr with one attribute (i.e.
Definition repr-css.cpp:88
void sp_repr_css_set_property_string(SPCSSAttr *css, char const *name, std::string const &value)
Set a style property to a standard string.
Definition repr-css.cpp:235
void sp_repr_css_print(SPCSSAttr *css)
Loops through a List of style properties, printing key/value pairs.
Definition repr-css.cpp:286
void sp_repr_css_change_recursive(Node *repr, SPCSSAttr *css, gchar const *attr)
Definition repr-css.cpp:371
char const * sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
Returns a character string of the value of a given style property or a default value if the attribute...
Definition repr-css.cpp:147
SPCSSAttr * sp_repr_css_attr_unset_all(SPCSSAttr *css)
Return a new SPCSSAttr with all the properties found in the input SPCSSAttr unset.
Definition repr-css.cpp:387
static void sp_repr_css_add_components(SPCSSAttr *css, Node const *repr, gchar const *attr)
Adds components (style properties) to an existing SPCSAttr from the specified attribute's data (nomin...
Definition repr-css.cpp:133
void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
Set a style property to "inkscape:unset".
Definition repr-css.cpp:202
bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name)
Returns true if a style property is present and its value is unset.
Definition repr-css.cpp:178
static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *const decl)
Merges style properties as parsed by libcroco into an existing SPCSSAttr.
Definition repr-css.cpp:314
static void sp_repr_css_merge_from_decl_list(SPCSSAttr *css, CRDeclaration const *const decl_list)
Merges style properties as parsed by libcroco into an existing SPCSSAttr.
Definition repr-css.cpp:326
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
Definition repr-css.cpp:191
void sp_repr_css_attr_add_from_string(SPCSSAttr *css, gchar const *p)
Use libcroco to parse a string for CSS properties and then merge them into an existing SPCSSAttr.
Definition repr-css.cpp:341
C facade to Inkscape::XML::Node.
Inkscape::XML::SimpleDocument - generic XML document implementation.
SPCSSAttr - interface for CSS Attributes.
NodeType
static const Point data[]
Interface for XML documents.
Definition document.h:43
CRString *CRTerm * value
The property.
CRDeclaration * next
Glib::ustring name
Definition toolbars.cpp:55