~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/xml/repr-css.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   bulia byak <buliabyak@users.sf.net>
 
3
*/
 
4
 
 
5
#define SP_REPR_CSS_C
 
6
 
 
7
#include <cstring>
 
8
#include <glibmm/ustring.h>
 
9
 
 
10
#include "xml/repr.h"
 
11
#include "xml/simple-document.h"
 
12
#include "xml/simple-node.h"
 
13
#include "style.h"
 
14
#include "libcroco/cr-sel-eng.h"
 
15
 
 
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;
 
22
 
 
23
struct SPCSSAttrImpl : public SimpleNode, public SPCSSAttr {
 
24
public:
 
25
    SPCSSAttrImpl(Document *doc)
 
26
    : SimpleNode(g_quark_from_static_string("css"), doc) {}
 
27
    SPCSSAttrImpl(SPCSSAttrImpl const &other, Document *doc)
 
28
    : SimpleNode(other, doc) {}
 
29
 
 
30
    NodeType type() const { return Inkscape::XML::ELEMENT_NODE; }
 
31
 
 
32
protected:
 
33
    SimpleNode *_duplicate(Document* doc) const { return new SPCSSAttrImpl(*this, doc); }
 
34
};
 
35
 
 
36
static void sp_repr_css_add_components(SPCSSAttr *css, Node *repr, gchar const *attr);
 
37
 
 
38
 
 
39
SPCSSAttr *
 
40
sp_repr_css_attr_new()
 
41
{
 
42
    static Inkscape::XML::Document *attr_doc=NULL;
 
43
    if (!attr_doc) {
 
44
        attr_doc = new Inkscape::XML::SimpleDocument();
 
45
    }
 
46
    return new SPCSSAttrImpl(attr_doc);
 
47
}
 
48
 
 
49
void
 
50
sp_repr_css_attr_unref(SPCSSAttr *css)
 
51
{
 
52
    g_assert(css != NULL);
 
53
    Inkscape::GC::release((Node *) css);
 
54
}
 
55
 
 
56
SPCSSAttr *sp_repr_css_attr(Node *repr, gchar const *attr)
 
57
{
 
58
    g_assert(repr != NULL);
 
59
    g_assert(attr != NULL);
 
60
 
 
61
    SPCSSAttr *css = sp_repr_css_attr_new();
 
62
    sp_repr_css_add_components(css, repr, attr);
 
63
    return css;
 
64
}
 
65
 
 
66
static void
 
67
sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node *repr, gchar const *attr)
 
68
{
 
69
    Node *parent = sp_repr_parent(repr);
 
70
 
 
71
    // read the ancestors from root down, using head recursion, so that children override parents
 
72
    if (parent) {
 
73
        sp_repr_css_attr_inherited_recursive(css, parent, attr);
 
74
    }
 
75
 
 
76
    sp_repr_css_add_components(css, repr, attr);
 
77
}
 
78
 
 
79
 
 
80
SPCSSAttr *sp_repr_css_attr_inherited(Node *repr, gchar const *attr)
 
81
{
 
82
    g_assert(repr != NULL);
 
83
    g_assert(attr != NULL);
 
84
 
 
85
    SPCSSAttr *css = sp_repr_css_attr_new();
 
86
 
 
87
    sp_repr_css_attr_inherited_recursive(css, repr, attr);
 
88
 
 
89
    return css;
 
90
}
 
91
 
 
92
static void
 
93
sp_repr_css_add_components(SPCSSAttr *css, Node *repr, gchar const *attr)
 
94
{
 
95
    g_assert(css != NULL);
 
96
    g_assert(repr != NULL);
 
97
    g_assert(attr != NULL);
 
98
 
 
99
    char const *data = repr->attribute(attr);
 
100
    sp_repr_css_attr_add_from_string(css, data);
 
101
}
 
102
 
 
103
char const *
 
104
sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
 
105
{
 
106
    g_assert(css != NULL);
 
107
    g_assert(name != NULL);
 
108
 
 
109
    char const *attr = ((Node *)css)->attribute(name);
 
110
    return ( attr == NULL
 
111
             ? defval
 
112
             : attr );
 
113
}
 
114
 
 
115
bool
 
116
sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name)
 
117
{
 
118
    g_assert(css != NULL);
 
119
    g_assert(name != NULL);
 
120
 
 
121
    char const *attr = ((Node *)css)->attribute(name);
 
122
    return (attr && !strcmp(attr, "inkscape:unset"));
 
123
}
 
124
 
 
125
 
 
126
void
 
127
sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
 
128
{
 
129
    g_assert(css != NULL);
 
130
    g_assert(name != NULL);
 
131
 
 
132
    ((Node *) css)->setAttribute(name, value, false);
 
133
}
 
134
 
 
135
void
 
136
sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
 
137
{
 
138
    g_assert(css != NULL);
 
139
    g_assert(name != NULL);
 
140
 
 
141
    ((Node *) css)->setAttribute(name, "inkscape:unset", false);
 
142
}
 
143
 
 
144
double
 
145
sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval)
 
146
{
 
147
    g_assert(css != NULL);
 
148
    g_assert(name != NULL);
 
149
 
 
150
    return sp_repr_get_double_attribute((Node *) css, name, defval);
 
151
}
 
152
 
 
153
gchar *
 
154
sp_repr_css_write_string(SPCSSAttr *css)
 
155
{
 
156
    Glib::ustring buffer;
 
157
 
 
158
    for ( List<AttributeRecord const> iter = css->attributeList() ;
 
159
          iter ; ++iter )
 
160
    {
 
161
        if (iter->value && !strcmp(iter->value, "inkscape:unset")) {
 
162
            continue;
 
163
        }
 
164
 
 
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);
 
171
            g_free (t);
 
172
            gchar *val_quoted = css2_escape_quote (iter->value);
 
173
            if (val_quoted) {
 
174
                buffer.append(val_quoted);
 
175
                g_free (val_quoted);
 
176
            }
 
177
        } else {
 
178
            buffer.append(iter->value); // unquoted
 
179
        }
 
180
 
 
181
        if (rest(iter)) {
 
182
            buffer.push_back(';');
 
183
        }
 
184
    }
 
185
 
 
186
    return (buffer.empty() ? NULL : g_strdup (buffer.c_str()));
 
187
}
 
188
 
 
189
void
 
190
sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
 
191
{
 
192
    g_assert(repr != NULL);
 
193
    g_assert(css != NULL);
 
194
    g_assert(attr != NULL);
 
195
 
 
196
    gchar *value = sp_repr_css_write_string(css);
 
197
 
 
198
    repr->setAttribute(attr, value);
 
199
 
 
200
    if (value) g_free (value);
 
201
}
 
202
 
 
203
void
 
204
sp_repr_css_print(SPCSSAttr *css)
 
205
{
 
206
    for ( List<AttributeRecord const> iter = css->attributeList() ;
 
207
          iter ; ++iter )
 
208
    {
 
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);
 
212
    }
 
213
}
 
214
 
 
215
void
 
216
sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src)
 
217
{
 
218
    g_assert(dst != NULL);
 
219
    g_assert(src != NULL);
 
220
 
 
221
    dst->mergeFrom(src, "");
 
222
}
 
223
 
 
224
 
 
225
static void
 
226
sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *const decl)
 
227
{
 
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);
 
233
    g_free(str_value);
 
234
}
 
235
 
 
236
/**
 
237
 * \pre decl_list != NULL
 
238
 */
 
239
static void
 
240
sp_repr_css_merge_from_decl_list(SPCSSAttr *css, CRDeclaration const *const decl_list)
 
241
{
 
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);
 
248
    }
 
249
}
 
250
 
 
251
void
 
252
sp_repr_css_attr_add_from_string(SPCSSAttr *css, gchar const *p)
 
253
{
 
254
    if (p != NULL) {
 
255
        CRDeclaration *const decl_list
 
256
            = cr_declaration_parse_list_from_buf(reinterpret_cast<guchar const *>(p), CR_UTF_8);
 
257
        if (decl_list) {
 
258
            sp_repr_css_merge_from_decl_list(css, decl_list);
 
259
            cr_declaration_destroy(decl_list);
 
260
        }
 
261
    }
 
262
}
 
263
 
 
264
void
 
265
sp_repr_css_change(Node *repr, SPCSSAttr *css, gchar const *attr)
 
266
{
 
267
    g_assert(repr != NULL);
 
268
    g_assert(css != NULL);
 
269
    g_assert(attr != NULL);
 
270
 
 
271
    SPCSSAttr *current = sp_repr_css_attr(repr, attr);
 
272
    sp_repr_css_merge(current, css);
 
273
    sp_repr_css_set(repr, current, attr);
 
274
 
 
275
    sp_repr_css_attr_unref(current);
 
276
}
 
277
 
 
278
void
 
279
sp_repr_css_change_recursive(Node *repr, SPCSSAttr *css, gchar const *attr)
 
280
{
 
281
    g_assert(repr != NULL);
 
282
    g_assert(css != NULL);
 
283
    g_assert(attr != NULL);
 
284
 
 
285
    sp_repr_css_change(repr, css, attr);
 
286
 
 
287
    for (Node *child = repr->firstChild(); child != NULL; child = child->next()) {
 
288
        sp_repr_css_change_recursive(child, css, attr);
 
289
    }
 
290
}
 
291
 
 
292
 
 
293
/*
 
294
  Local Variables:
 
295
  mode:c++
 
296
  c-file-style:"stroustrup"
 
297
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
298
  indent-tabs-mode:nil
 
299
  fill-column:99
 
300
  End:
 
301
*/
 
302
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :