2
* bulia byak <buliabyak@users.sf.net>
8
#include <glibmm/ustring.h>
11
#include "xml/simple-document.h"
12
#include "xml/simple-node.h"
14
#include "libcroco/cr-sel-eng.h"
16
using Inkscape::Util::List;
17
using Inkscape::XML::AttributeRecord;
18
using Inkscape::XML::SimpleNode;
19
using Inkscape::XML::Node;
20
using Inkscape::XML::NodeType;
21
using Inkscape::XML::Document;
23
struct SPCSSAttrImpl : public SimpleNode, public SPCSSAttr {
25
SPCSSAttrImpl(Document *doc)
26
: SimpleNode(g_quark_from_static_string("css"), doc) {}
27
SPCSSAttrImpl(SPCSSAttrImpl const &other, Document *doc)
28
: SimpleNode(other, doc) {}
30
NodeType type() const { return Inkscape::XML::ELEMENT_NODE; }
33
SimpleNode *_duplicate(Document* doc) const { return new SPCSSAttrImpl(*this, doc); }
36
static void sp_repr_css_add_components(SPCSSAttr *css, Node *repr, gchar const *attr);
40
sp_repr_css_attr_new()
42
static Inkscape::XML::Document *attr_doc=NULL;
44
attr_doc = new Inkscape::XML::SimpleDocument();
46
return new SPCSSAttrImpl(attr_doc);
50
sp_repr_css_attr_unref(SPCSSAttr *css)
52
g_assert(css != NULL);
53
Inkscape::GC::release((Node *) css);
56
SPCSSAttr *sp_repr_css_attr(Node *repr, gchar const *attr)
58
g_assert(repr != NULL);
59
g_assert(attr != NULL);
61
SPCSSAttr *css = sp_repr_css_attr_new();
62
sp_repr_css_add_components(css, repr, attr);
67
sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node *repr, gchar const *attr)
69
Node *parent = sp_repr_parent(repr);
71
// read the ancestors from root down, using head recursion, so that children override parents
73
sp_repr_css_attr_inherited_recursive(css, parent, attr);
76
sp_repr_css_add_components(css, repr, attr);
80
SPCSSAttr *sp_repr_css_attr_inherited(Node *repr, gchar const *attr)
82
g_assert(repr != NULL);
83
g_assert(attr != NULL);
85
SPCSSAttr *css = sp_repr_css_attr_new();
87
sp_repr_css_attr_inherited_recursive(css, repr, attr);
93
sp_repr_css_add_components(SPCSSAttr *css, Node *repr, gchar const *attr)
95
g_assert(css != NULL);
96
g_assert(repr != NULL);
97
g_assert(attr != NULL);
99
char const *data = repr->attribute(attr);
100
sp_repr_css_attr_add_from_string(css, data);
104
sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
106
g_assert(css != NULL);
107
g_assert(name != NULL);
109
char const *attr = ((Node *)css)->attribute(name);
110
return ( attr == NULL
116
sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name)
118
g_assert(css != NULL);
119
g_assert(name != NULL);
121
char const *attr = ((Node *)css)->attribute(name);
122
return (attr && !strcmp(attr, "inkscape:unset"));
127
sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
129
g_assert(css != NULL);
130
g_assert(name != NULL);
132
((Node *) css)->setAttribute(name, value, false);
136
sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
138
g_assert(css != NULL);
139
g_assert(name != NULL);
141
((Node *) css)->setAttribute(name, "inkscape:unset", false);
145
sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval)
147
g_assert(css != NULL);
148
g_assert(name != NULL);
150
return sp_repr_get_double_attribute((Node *) css, name, defval);
154
sp_repr_css_write_string(SPCSSAttr *css)
156
Glib::ustring buffer;
158
for ( List<AttributeRecord const> iter = css->attributeList() ;
161
if (iter->value && !strcmp(iter->value, "inkscape:unset")) {
165
buffer.append(g_quark_to_string(iter->key));
166
buffer.push_back(':');
167
if (!strcmp(g_quark_to_string(iter->key), "font-family")
168
|| !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) {
169
// we only quote font-family/font-specification, as SPStyle does
170
gchar *t = g_strdup (iter->value);
172
gchar *val_quoted = css2_escape_quote (iter->value);
174
buffer.append(val_quoted);
178
buffer.append(iter->value); // unquoted
182
buffer.push_back(';');
186
return (buffer.empty() ? NULL : g_strdup (buffer.c_str()));
190
sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
192
g_assert(repr != NULL);
193
g_assert(css != NULL);
194
g_assert(attr != NULL);
196
gchar *value = sp_repr_css_write_string(css);
198
repr->setAttribute(attr, value);
200
if (value) g_free (value);
204
sp_repr_css_print(SPCSSAttr *css)
206
for ( List<AttributeRecord const> iter = css->attributeList() ;
209
gchar const * key = g_quark_to_string(iter->key);
210
gchar const * val = iter->value;
211
g_print("%s:\t%s\n",key,val);
216
sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src)
218
g_assert(dst != NULL);
219
g_assert(src != NULL);
221
dst->mergeFrom(src, "");
226
sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *const decl)
228
guchar *const str_value_unsigned = cr_term_to_string(decl->value);
229
gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned);
230
gchar *value_unquoted = attribute_unquote (str_value); // libcroco returns strings quoted in ""
231
((Node *) css)->setAttribute(decl->property->stryng->str, value_unquoted, false);
232
g_free(value_unquoted);
237
* \pre decl_list != NULL
240
sp_repr_css_merge_from_decl_list(SPCSSAttr *css, CRDeclaration const *const decl_list)
242
// read the decls from start to end, using tail recursion, so that latter declarations override
243
// (Ref: http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order point 4.)
244
// because sp_repr_css_merge_from_decl sets properties unconditionally
245
sp_repr_css_merge_from_decl(css, decl_list);
246
if (decl_list->next) {
247
sp_repr_css_merge_from_decl_list(css, decl_list->next);
252
sp_repr_css_attr_add_from_string(SPCSSAttr *css, gchar const *p)
255
CRDeclaration *const decl_list
256
= cr_declaration_parse_list_from_buf(reinterpret_cast<guchar const *>(p), CR_UTF_8);
258
sp_repr_css_merge_from_decl_list(css, decl_list);
259
cr_declaration_destroy(decl_list);
265
sp_repr_css_change(Node *repr, SPCSSAttr *css, gchar const *attr)
267
g_assert(repr != NULL);
268
g_assert(css != NULL);
269
g_assert(attr != NULL);
271
SPCSSAttr *current = sp_repr_css_attr(repr, attr);
272
sp_repr_css_merge(current, css);
273
sp_repr_css_set(repr, current, attr);
275
sp_repr_css_attr_unref(current);
279
sp_repr_css_change_recursive(Node *repr, SPCSSAttr *css, gchar const *attr)
281
g_assert(repr != NULL);
282
g_assert(css != NULL);
283
g_assert(attr != NULL);
285
sp_repr_css_change(repr, css, attr);
287
for (Node *child = repr->firstChild(); child != NULL; child = child->next()) {
288
sp_repr_css_change_recursive(child, css, attr);
296
c-file-style:"stroustrup"
297
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
302
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :