librsvg: update to 2.32.1
[openembedded.git] / recipes / librsvg / librsvg / librsvg-CVE-2011-3146.patch
1 librsvg: CVE-2011-3146
2
3 Store node type separately in RsvgNode
4
5 commit 34c95743ca692ea0e44778e41a7c0a129363de84 upstream
6
7 The node name (formerly RsvgNode:type) cannot be used to infer
8 the sub-type of RsvgNode that we're dealing with, since for unknown
9 elements we put type = node-name. This lead to a (potentially exploitable)
10 crash e.g. when the element name started with "fe" which tricked
11 the old code into considering it as a RsvgFilterPrimitive.
12 http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-3146
13
14 https://bugzilla.gnome.org/show_bug.cgi?id=658014
15 ---
16  rsvg-base.c         |   68 ++++++++++++++++++++++++++------------------
17  rsvg-cairo-draw.c   |    2 +-
18  rsvg-filter.c       |   79 +++++++++++++++++++++++++++------------------------
19  rsvg-filter.h       |    2 +-
20  rsvg-image.c        |    2 +-
21  rsvg-marker.c       |    4 +-
22  rsvg-mask.c         |    8 ++--
23  rsvg-paint-server.c |   25 ++++++++--------
24  rsvg-private.h      |   60 ++++++++++++++++++++++++++++++++++++++-
25  rsvg-shapes.c       |   25 ++++++++--------
26  rsvg-shapes.h       |    2 +-
27  rsvg-structure.c    |   25 ++++++++--------
28  rsvg-structure.h    |    5 ++-
29  rsvg-text.c         |   22 ++++++++------
30  14 files changed, 204 insertions(+), 125 deletions(-)
31
32 diff --git a/rsvg-base.c b/rsvg-base.c
33 index 1f5c48c..b1a2d8b 100644
34 --- a/rsvg-base.c
35 +++ b/rsvg-base.c
36 @@ -147,7 +147,6 @@ rsvg_start_style (RsvgHandle * ctx, RsvgPropertyBag * atts)
37  static void
38  rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag * atts)
39  {
40 -
41      /*replace this stuff with a hash for fast reading! */
42      RsvgNode *newnode = NULL;
43      if (!strcmp (name, "g"))
44 @@ -241,11 +240,11 @@ rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag
45      else if (!strcmp (name, "feFuncA"))
46          newnode = rsvg_new_node_component_transfer_function ('a');
47      else if (!strcmp (name, "feDistantLight"))
48 -        newnode = rsvg_new_filter_primitive_light_source ('d');
49 +        newnode = rsvg_new_node_light_source ('d');
50      else if (!strcmp (name, "feSpotLight"))
51 -        newnode = rsvg_new_filter_primitive_light_source ('s');
52 +        newnode = rsvg_new_node_light_source ('s');
53      else if (!strcmp (name, "fePointLight"))
54 -        newnode = rsvg_new_filter_primitive_light_source ('p');
55 +        newnode = rsvg_new_node_light_source ('p');
56      /* hack to make multiImage sort-of work */
57      else if (!strcmp (name, "multiImage"))
58          newnode = rsvg_new_switch ();
59 @@ -259,21 +258,22 @@ rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag
60          newnode = rsvg_new_tspan ();
61      else if (!strcmp (name, "tref"))
62          newnode = rsvg_new_tref ();
63 -       else {
64 +    else {
65                 /* hack for bug 401115. whenever we encounter a node we don't understand, push it into a group. 
66                    this will allow us to handle things like conditionals properly. */
67                 newnode = rsvg_new_group ();
68         }
69  
70      if (newnode) {
71 -        newnode->type = g_string_new (name);
72 +        g_assert (RSVG_NODE_TYPE (newnode) != RSVG_NODE_TYPE_INVALID);
73 +        newnode->name = (char *) name; /* libxml will keep this while parsing */
74          newnode->parent = ctx->priv->currentnode;
75          rsvg_node_set_atts (newnode, ctx, atts);
76          rsvg_defs_register_memory (ctx->priv->defs, newnode);
77          if (ctx->priv->currentnode) {
78              rsvg_node_group_pack (ctx->priv->currentnode, newnode);
79              ctx->priv->currentnode = newnode;
80 -        } else if (!strcmp (name, "svg")) {
81 +        } else if (RSVG_NODE_TYPE (newnode) == RSVG_NODE_TYPE_SVG) {
82              ctx->priv->treebase = newnode;
83              ctx->priv->currentnode = newnode;
84          }
85 @@ -689,10 +689,11 @@ rsvg_end_element (void *data, const xmlChar * name)
86              ctx->priv->handler = NULL;
87          }
88  
89 -        if (ctx->priv->currentnode
90 -            && !strcmp ((const char *) name, ctx->priv->currentnode->type->str))
91 -            rsvg_pop_def_group (ctx);
92 +        if (ctx->priv->currentnode &&
93 +            !strcmp ((const char *) name, ctx->priv->currentnode->name))
94 +                rsvg_pop_def_group (ctx);
95  
96 +        /* FIXMEchpe: shouldn't this check that currentnode == treebase or sth like that? */
97          if (ctx->priv->treebase && !strcmp ((const char *)name, "svg"))
98              _rsvg_node_svg_apply_atts ((RsvgNodeSvg *)ctx->priv->treebase, ctx);
99      }
100 @@ -706,6 +707,30 @@ _rsvg_node_chars_free (RsvgNode * node)
101      _rsvg_node_free (node);
102  }
103  
104 +static RsvgNodeChars *
105 +rsvg_new_node_chars (const char *text,
106 +                     int len)
107 +{
108 +    RsvgNodeChars *self;
109 +
110 +    self = g_new (RsvgNodeChars, 1);
111 +    _rsvg_node_init (&self->super, RSVG_NODE_TYPE_CHARS);
112 +
113 +    if (!g_utf8_validate (text, len, NULL)) {
114 +        char *utf8;
115 +        utf8 = rsvg_make_valid_utf8 (text, len);
116 +        self->contents = g_string_new (utf8);
117 +        g_free (utf8);
118 +    } else {
119 +        self->contents = g_string_new_len (text, len);
120 +    }
121 +
122 +    self->super.free = _rsvg_node_chars_free;
123 +    self->super.state->cond_true = FALSE;
124 +
125 +    return self;
126 +}
127 +
128  static void
129  rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
130  {
131 @@ -715,8 +740,9 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
132          return;
133  
134      if (ctx->priv->currentnode) {
135 -        if (!strcmp ("tspan", ctx->priv->currentnode->type->str) ||
136 -            !strcmp ("text", ctx->priv->currentnode->type->str)) {
137 +        RsvgNodeType type = RSVG_NODE_TYPE (ctx->priv->currentnode);
138 +        if (type == RSVG_NODE_TYPE_TSPAN ||
139 +            type == RSVG_NODE_TYPE_TEXT) {
140              guint i;
141  
142              /* find the last CHARS node in the text or tspan node, so that we
143 @@ -724,7 +750,7 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
144              self = NULL;
145              for (i = 0; i < ctx->priv->currentnode->children->len; i++) {
146                  RsvgNode *node = g_ptr_array_index (ctx->priv->currentnode->children, i);
147 -                if (!strcmp (node->type->str, "RSVG_NODE_CHARS")) {
148 +                if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
149                      self = (RsvgNodeChars*)node;
150                  }
151              }
152 @@ -744,21 +770,7 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
153          }
154      }
155  
156 -    self = g_new (RsvgNodeChars, 1);
157 -    _rsvg_node_init (&self->super);
158 -
159 -    if (!g_utf8_validate ((char *) ch, len, NULL)) {
160 -        char *utf8;
161 -        utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
162 -        self->contents = g_string_new (utf8);
163 -        g_free (utf8);
164 -    } else {
165 -        self->contents = g_string_new_len ((char *) ch, len);
166 -    }
167 -
168 -    self->super.type = g_string_new ("RSVG_NODE_CHARS");
169 -    self->super.free = _rsvg_node_chars_free;
170 -    self->super.state->cond_true = FALSE;
171 +    self = rsvg_new_node_chars ((char *) ch, len);
172  
173      rsvg_defs_register_memory (ctx->priv->defs, (RsvgNode *) self);
174      if (ctx->priv->currentnode)
175 diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
176 index 0b74e22..c01cd17 100644
177 --- a/rsvg-cairo-draw.c
178 +++ b/rsvg-cairo-draw.c
179 @@ -147,7 +147,7 @@ _pattern_add_rsvg_color_stops (cairo_pattern_t * pattern,
180  
181      for (i = 0; i < stops->len; i++) {
182          node = (RsvgNode *) g_ptr_array_index (stops, i);
183 -        if (strcmp (node->type->str, "stop"))
184 +        if (RSVG_NODE_TYPE (node) != RSVG_NODE_TYPE_STOP)
185              continue;
186          stop = (RsvgGradientStop *) node;
187          rgba = stop->rgba;
188 diff --git a/rsvg-filter.c b/rsvg-filter.c
189 index e65be41..ce96c4f 100644
190 --- a/rsvg-filter.c
191 +++ b/rsvg-filter.c
192 @@ -495,7 +495,7 @@ rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
193  
194      for (i = 0; i < self->super.children->len; i++) {
195          current = g_ptr_array_index (self->super.children, i);
196 -        if (!strncmp (current->super.type->str, "fe", 2))
197 +        if (RSVG_NODE_IS_FILTER_PRIMITIVE (&current->super))
198              rsvg_filter_primitive_render (current, ctx);
199      }
200  
201 @@ -703,7 +703,7 @@ rsvg_filter_parse (const RsvgDefs * defs, const char *str)
202          val = rsvg_defs_lookup (defs, name);
203          g_free (name);
204  
205 -        if (val && (!strcmp (val->type->str, "filter")))
206 +        if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_FILTER)
207              return (RsvgFilter *) val;
208      }
209      return NULL;
210 @@ -754,7 +754,7 @@ rsvg_new_filter (void)
211      RsvgFilter *filter;
212  
213      filter = g_new (RsvgFilter, 1);
214 -    _rsvg_node_init (&filter->super);
215 +    _rsvg_node_init (&filter->super, RSVG_NODE_TYPE_FILTER);
216      filter->filterunits = objectBoundingBox;
217      filter->primitiveunits = userSpaceOnUse;
218      filter->x = _rsvg_css_parse_length ("-10%");
219 @@ -978,7 +978,7 @@ rsvg_new_filter_primitive_blend (void)
220  {
221      RsvgFilterPrimitiveBlend *filter;
222      filter = g_new (RsvgFilterPrimitiveBlend, 1);
223 -    _rsvg_node_init (&filter->super.super);
224 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_BLEND);
225      filter->mode = normal;
226      filter->super.in = g_string_new ("none");
227      filter->in2 = g_string_new ("none");
228 @@ -1230,7 +1230,7 @@ rsvg_new_filter_primitive_convolve_matrix (void)
229  {
230      RsvgFilterPrimitiveConvolveMatrix *filter;
231      filter = g_new (RsvgFilterPrimitiveConvolveMatrix, 1);
232 -    _rsvg_node_init (&filter->super.super);
233 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_CONVOLVE_MATRIX);
234      filter->super.in = g_string_new ("none");
235      filter->super.result = g_string_new ("none");
236      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
237 @@ -1471,7 +1471,7 @@ rsvg_new_filter_primitive_gaussian_blur (void)
238  {
239      RsvgFilterPrimitiveGaussianBlur *filter;
240      filter = g_new (RsvgFilterPrimitiveGaussianBlur, 1);
241 -    _rsvg_node_init (&filter->super.super);
242 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_GAUSSIAN_BLUR);
243      filter->super.in = g_string_new ("none");
244      filter->super.result = g_string_new ("none");
245      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
246 @@ -1607,7 +1607,7 @@ rsvg_new_filter_primitive_offset (void)
247  {
248      RsvgFilterPrimitiveOffset *filter;
249      filter = g_new (RsvgFilterPrimitiveOffset, 1);
250 -    _rsvg_node_init (&filter->super.super);
251 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_OFFSET);
252      filter->super.in = g_string_new ("none");
253      filter->super.result = g_string_new ("none");
254      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
255 @@ -1648,7 +1648,7 @@ rsvg_filter_primitive_merge_render (RsvgFilterPrimitive * self, RsvgFilterContex
256      for (i = 0; i < upself->super.super.children->len; i++) {
257          RsvgFilterPrimitive *mn;
258          mn = g_ptr_array_index (upself->super.super.children, i);
259 -        if (strcmp (mn->super.type->str, "feMergeNode"))
260 +        if (RSVG_NODE_TYPE (&mn->super) != RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE)
261              continue;
262          in = rsvg_filter_get_in (mn->in, ctx);
263          rsvg_alpha_blt (in, boundarys.x0, boundarys.y0, boundarys.x1 - boundarys.x0,
264 @@ -1701,7 +1701,7 @@ rsvg_new_filter_primitive_merge (void)
265  {
266      RsvgFilterPrimitiveMerge *filter;
267      filter = g_new (RsvgFilterPrimitiveMerge, 1);
268 -    _rsvg_node_init (&filter->super.super);
269 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE);
270      filter->super.result = g_string_new ("none");
271      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
272          filter->super.height.factor = 'n';
273 @@ -1744,7 +1744,7 @@ rsvg_new_filter_primitive_merge_node (void)
274  {
275      RsvgFilterPrimitive *filter;
276      filter = g_new (RsvgFilterPrimitive, 1);
277 -    _rsvg_node_init (&filter->super);
278 +    _rsvg_node_init (&filter->super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE);
279      filter->in = g_string_new ("none");
280      filter->super.free = rsvg_filter_primitive_merge_node_free;
281      filter->render = &rsvg_filter_primitive_merge_node_render;
282 @@ -1978,7 +1978,7 @@ rsvg_new_filter_primitive_colour_matrix (void)
283  {
284      RsvgFilterPrimitiveColourMatrix *filter;
285      filter = g_new (RsvgFilterPrimitiveColourMatrix, 1);
286 -    _rsvg_node_init (&filter->super.super);
287 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_COLOUR_MATRIX);
288      filter->super.in = g_string_new ("none");
289      filter->super.result = g_string_new ("none");
290      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
291 @@ -2010,8 +2010,9 @@ struct _RsvgNodeComponentTransferFunc {
292      gint slope;
293      gint intercept;
294      gint amplitude;
295 -    gdouble exponent;
296      gint offset;
297 +    gdouble exponent;
298 +    char channel;
299  };
300  
301  struct _RsvgFilterPrimitiveComponentTransfer {
302 @@ -2107,15 +2108,18 @@ rsvg_filter_primitive_component_transfer_render (RsvgFilterPrimitive *
303      for (c = 0; c < 4; c++) {
304          char channel = "RGBA"[c];
305          for (i = 0; i < self->super.children->len; i++) {
306 -            RsvgNodeComponentTransferFunc *temp;
307 -            temp = (RsvgNodeComponentTransferFunc *)
308 -                g_ptr_array_index (self->super.children, i);
309 -            if (!strncmp (temp->super.type->str, "feFunc", 6))
310 -                if (temp->super.type->str[6] == channel) {
311 +            RsvgNode *child_node;
312 +
313 +            child_node = (RsvgNode *) g_ptr_array_index (self->super.children, i);
314 +            if (RSVG_NODE_TYPE (child_node) == RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER) {
315 +                RsvgNodeComponentTransferFunc *temp = (RsvgNodeComponentTransferFunc *) child_node;
316 +
317 +                if (temp->channel == channel) {
318                      functions[ctx->channelmap[c]] = temp->function;
319                      channels[ctx->channelmap[c]] = temp;
320                      break;
321                  }
322 +            }
323          }
324          if (i == self->super.children->len)
325              functions[ctx->channelmap[c]] = identity_component_transfer_func;
326 @@ -2198,7 +2202,7 @@ rsvg_new_filter_primitive_component_transfer (void)
327      RsvgFilterPrimitiveComponentTransfer *filter;
328  
329      filter = g_new (RsvgFilterPrimitiveComponentTransfer, 1);
330 -    _rsvg_node_init (&filter->super.super);
331 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER);
332      filter->super.result = g_string_new ("none");
333      filter->super.in = g_string_new ("none");
334      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
335 @@ -2272,7 +2276,7 @@ rsvg_new_node_component_transfer_function (char channel)
336      RsvgNodeComponentTransferFunc *filter;
337  
338      filter = g_new (RsvgNodeComponentTransferFunc, 1);
339 -    _rsvg_node_init (&filter->super);
340 +    _rsvg_node_init (&filter->super, RSVG_NODE_TYPE_COMPONENT_TRANFER_FUNCTION);
341      filter->super.free = rsvg_component_transfer_function_free;
342      filter->super.set_atts = rsvg_node_component_transfer_function_set_atts;
343      filter->function = identity_component_transfer_func;
344 @@ -2414,7 +2418,7 @@ rsvg_new_filter_primitive_erode (void)
345  {
346      RsvgFilterPrimitiveErode *filter;
347      filter = g_new (RsvgFilterPrimitiveErode, 1);
348 -    _rsvg_node_init (&filter->super.super);
349 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_ERODE);
350      filter->super.in = g_string_new ("none");
351      filter->super.result = g_string_new ("none");
352      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
353 @@ -2639,7 +2643,7 @@ rsvg_new_filter_primitive_composite (void)
354  {
355      RsvgFilterPrimitiveComposite *filter;
356      filter = g_new (RsvgFilterPrimitiveComposite, 1);
357 -    _rsvg_node_init (&filter->super.super);
358 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPOSITE);
359      filter->mode = COMPOSITE_MODE_OVER;
360      filter->super.in = g_string_new ("none");
361      filter->in2 = g_string_new ("none");
362 @@ -2744,7 +2748,7 @@ rsvg_new_filter_primitive_flood (void)
363  {
364      RsvgFilterPrimitive *filter;
365      filter = g_new (RsvgFilterPrimitive, 1);
366 -    _rsvg_node_init (&filter->super);
367 +    _rsvg_node_init (&filter->super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_FLOOD);
368      filter->in = g_string_new ("none");
369      filter->result = g_string_new ("none");
370      filter->x.factor = filter->y.factor = filter->width.factor = filter->height.factor = 'n';
371 @@ -2920,7 +2924,7 @@ rsvg_new_filter_primitive_displacement_map (void)
372  {
373      RsvgFilterPrimitiveDisplacementMap *filter;
374      filter = g_new (RsvgFilterPrimitiveDisplacementMap, 1);
375 -    _rsvg_node_init (&filter->super.super);
376 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_DISPLACEMENT_MAP);
377      filter->super.in = g_string_new ("none");
378      filter->in2 = g_string_new ("none");
379      filter->super.result = g_string_new ("none");
380 @@ -3291,7 +3295,7 @@ rsvg_new_filter_primitive_turbulence (void)
381  {
382      RsvgFilterPrimitiveTurbulence *filter;
383      filter = g_new (RsvgFilterPrimitiveTurbulence, 1);
384 -    _rsvg_node_init (&filter->super.super);
385 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_TURBULENCE);
386      filter->super.in = g_string_new ("none");
387      filter->super.result = g_string_new ("none");
388      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
389 @@ -3510,7 +3514,7 @@ rsvg_new_filter_primitive_image (void)
390  {
391      RsvgFilterPrimitiveImage *filter;
392      filter = g_new (RsvgFilterPrimitiveImage, 1);
393 -    _rsvg_node_init (&filter->super.super);
394 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_IMAGE);
395      filter->super.in = g_string_new ("none");
396      filter->super.result = g_string_new ("none");
397      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
398 @@ -3871,8 +3875,8 @@ get_light_colour (RsvgNodeLightSource * source, vector3 colour,
399  
400  
401  static void
402 -rsvg_filter_primitive_light_source_set_atts (RsvgNode * self,
403 -                                             RsvgHandle * ctx, RsvgPropertyBag * atts)
404 +rsvg_node_light_source_set_atts (RsvgNode * self,
405 +                                 RsvgHandle * ctx, RsvgPropertyBag * atts)
406  {
407      RsvgNodeLightSource *data;
408      const char *value;
409 @@ -3904,13 +3908,13 @@ rsvg_filter_primitive_light_source_set_atts (RsvgNode * self,
410  }
411  
412  RsvgNode *
413 -rsvg_new_filter_primitive_light_source (char type)
414 +rsvg_new_node_light_source (char type)
415  {
416      RsvgNodeLightSource *data;
417      data = g_new (RsvgNodeLightSource, 1);
418 -    _rsvg_node_init (&data->super);
419 +    _rsvg_node_init (&data->super, RSVG_NODE_TYPE_LIGHT_SOURCE);
420      data->super.free = _rsvg_node_free;
421 -    data->super.set_atts = rsvg_filter_primitive_light_source_set_atts;
422 +    data->super.set_atts = rsvg_node_light_source_set_atts;
423      data->specularExponent = 1;
424      if (type == 's')
425          data->type = SPOTLIGHT;
426 @@ -3960,10 +3964,11 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
427  
428      for (i = 0; i < self->super.children->len; i++) {
429          RsvgNode *temp;
430 +
431          temp = g_ptr_array_index (self->super.children, i);
432 -        if (!strcmp (temp->type->str, "feDistantLight") ||
433 -            !strcmp (temp->type->str, "fePointLight") || !strcmp (temp->type->str, "feSpotLight"))
434 +        if (RSVG_NODE_TYPE (temp) == RSVG_NODE_TYPE_LIGHT_SOURCE) {
435              source = (RsvgNodeLightSource *) temp;
436 +        }
437      }
438      if (source == NULL)
439          return;
440 @@ -4080,7 +4085,7 @@ rsvg_new_filter_primitive_diffuse_lighting (void)
441  {
442      RsvgFilterPrimitiveDiffuseLighting *filter;
443      filter = g_new (RsvgFilterPrimitiveDiffuseLighting, 1);
444 -    _rsvg_node_init (&filter->super.super);
445 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_DIFFUSE_LIGHTING);
446      filter->super.in = g_string_new ("none");
447      filter->super.result = g_string_new ("none");
448      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
449 @@ -4135,9 +4140,9 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
450      for (i = 0; i < self->super.children->len; i++) {
451          RsvgNode *temp;
452          temp = g_ptr_array_index (self->super.children, i);
453 -        if (!strcmp (temp->type->str, "feDistantLight") ||
454 -            !strcmp (temp->type->str, "fePointLight") || !strcmp (temp->type->str, "feSpotLight"))
455 +        if (RSVG_NODE_TYPE (temp) == RSVG_NODE_TYPE_LIGHT_SOURCE) {
456              source = (RsvgNodeLightSource *) temp;
457 +        }
458      }
459      if (source == NULL)
460          return;
461 @@ -4259,7 +4264,7 @@ rsvg_new_filter_primitive_specular_lighting (void)
462  {
463      RsvgFilterPrimitiveSpecularLighting *filter;
464      filter = g_new (RsvgFilterPrimitiveSpecularLighting, 1);
465 -    _rsvg_node_init (&filter->super.super);
466 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_SPECULAR_LIGHTING);
467      filter->super.in = g_string_new ("none");
468      filter->super.result = g_string_new ("none");
469      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
470 @@ -4381,7 +4386,7 @@ rsvg_new_filter_primitive_tile (void)
471  {
472      RsvgFilterPrimitiveTile *filter;
473      filter = g_new (RsvgFilterPrimitiveTile, 1);
474 -    _rsvg_node_init (&filter->super.super);
475 +    _rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_TILE);
476      filter->super.in = g_string_new ("none");
477      filter->super.result = g_string_new ("none");
478      filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
479 diff --git a/rsvg-filter.h b/rsvg-filter.h
480 index 25dac75..0aeda22 100644
481 --- a/rsvg-filter.h
482 +++ b/rsvg-filter.h
483 @@ -64,7 +64,7 @@ RsvgNode    *rsvg_new_filter_primitive_displacement_map     (void);
484  RsvgNode    *rsvg_new_filter_primitive_turbulence           (void);
485  RsvgNode    *rsvg_new_filter_primitive_image                (void);
486  RsvgNode    *rsvg_new_filter_primitive_diffuse_lighting            (void);
487 -RsvgNode    *rsvg_new_filter_primitive_light_source            (char type);
488 +RsvgNode    *rsvg_new_node_light_source                            (char type);
489  RsvgNode    *rsvg_new_filter_primitive_specular_lighting    (void);
490  RsvgNode    *rsvg_new_filter_primitive_tile                 (void);
491  
492 diff --git a/rsvg-image.c b/rsvg-image.c
493 index a81dcf5..02882bd 100644
494 --- a/rsvg-image.c
495 +++ b/rsvg-image.c
496 @@ -356,7 +356,7 @@ rsvg_new_image (void)
497  {
498      RsvgNodeImage *image;
499      image = g_new (RsvgNodeImage, 1);
500 -    _rsvg_node_init (&image->super);
501 +    _rsvg_node_init (&image->super, RSVG_NODE_TYPE_IMAGE);
502      g_assert (image->super.state);
503      image->img = NULL;
504      image->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
505 diff --git a/rsvg-marker.c b/rsvg-marker.c
506 index 591e1e0..c7e76f1 100644
507 --- a/rsvg-marker.c
508 +++ b/rsvg-marker.c
509 @@ -84,7 +84,7 @@ rsvg_new_marker (void)
510  {
511      RsvgMarker *marker;
512      marker = g_new (RsvgMarker, 1);
513 -    _rsvg_node_init (&marker->super);
514 +    _rsvg_node_init (&marker->super, RSVG_NODE_TYPE_MARKER);
515      marker->orient = 0;
516      marker->orientAuto = FALSE;
517      marker->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
518 @@ -198,7 +198,7 @@ rsvg_marker_parse (const RsvgDefs * defs, const char *str)
519          val = rsvg_defs_lookup (defs, name);
520          g_free (name);
521  
522 -        if (val && (!strcmp (val->type->str, "marker")))
523 +        if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_MARKER)
524              return val;
525      }
526      return NULL;
527 diff --git a/rsvg-mask.c b/rsvg-mask.c
528 index dd36a38..8e3cba3 100644
529 --- a/rsvg-mask.c
530 +++ b/rsvg-mask.c
531 @@ -74,7 +74,7 @@ rsvg_new_mask (void)
532      RsvgMask *mask;
533  
534      mask = g_new (RsvgMask, 1);
535 -    _rsvg_node_init (&mask->super);
536 +    _rsvg_node_init (&mask->super, RSVG_NODE_TYPE_MASK);
537      mask->maskunits = objectBoundingBox;
538      mask->contentunits = userSpaceOnUse;
539      mask->x = _rsvg_css_parse_length ("0");
540 @@ -113,7 +113,7 @@ rsvg_mask_parse (const RsvgDefs * defs, const char *str)
541          val = rsvg_defs_lookup (defs, name);
542          g_free (name);
543  
544 -        if (val && (!strcmp (val->type->str, "mask")))
545 +        if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_MASK)
546              return val;
547      }
548      return NULL;
549 @@ -130,7 +130,7 @@ rsvg_clip_path_parse (const RsvgDefs * defs, const char *str)
550          val = rsvg_defs_lookup (defs, name);
551          g_free (name);
552  
553 -        if (val && (!strcmp (val->type->str, "clipPath")))
554 +        if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_CLIP_PATH)
555              return val;
556      }
557      return NULL;
558 @@ -168,7 +168,7 @@ rsvg_new_clip_path (void)
559      RsvgClipPath *clip_path;
560  
561      clip_path = g_new (RsvgClipPath, 1);
562 -    _rsvg_node_init (&clip_path->super);
563 +    _rsvg_node_init (&clip_path->super, RSVG_NODE_TYPE_CLIP_PATH);
564      clip_path->units = userSpaceOnUse;
565      clip_path->super.set_atts = rsvg_clip_path_set_atts;
566      clip_path->super.free = _rsvg_node_free;
567 diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c
568 index 4967e03..7903684 100644
569 --- a/rsvg-paint-server.c
570 +++ b/rsvg-paint-server.c
571 @@ -129,11 +129,11 @@ rsvg_paint_server_parse (gboolean * inherit, const RsvgDefs * defs, const char *
572  
573          if (val == NULL)
574              return NULL;
575 -        if (!strcmp (val->type->str, "linearGradient"))
576 +        if (RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_LINEAR_GRADIENT)
577              return rsvg_paint_server_lin_grad ((RsvgLinearGradient *) val);
578 -        else if (!strcmp (val->type->str, "radialGradient"))
579 +        else if (RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_RADIAL_GRADIENT)
580              return rsvg_paint_server_rad_grad ((RsvgRadialGradient *) val);
581 -        else if (!strcmp (val->type->str, "pattern"))
582 +        else if (RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_PATTERN)
583              return rsvg_paint_server_pattern ((RsvgPattern *) val);
584          else
585              return NULL;
586 @@ -224,7 +224,7 @@ RsvgNode *
587  rsvg_new_stop (void)
588  {
589      RsvgGradientStop *stop = g_new (RsvgGradientStop, 1);
590 -    _rsvg_node_init (&stop->super);
591 +    _rsvg_node_init (&stop->super, RSVG_NODE_TYPE_STOP);
592      stop->super.set_atts = rsvg_stop_set_atts;
593      stop->offset = 0;
594      stop->rgba = 0;
595 @@ -293,7 +293,7 @@ rsvg_new_linear_gradient (void)
596  {
597      RsvgLinearGradient *grad = NULL;
598      grad = g_new (RsvgLinearGradient, 1);
599 -    _rsvg_node_init (&grad->super);
600 +    _rsvg_node_init (&grad->super, RSVG_NODE_TYPE_LINEAR_GRADIENT);
601      _rsvg_affine_identity (grad->affine);
602      grad->has_current_color = FALSE;
603      grad->x1 = grad->y1 = grad->y2 = _rsvg_css_parse_length ("0");
604 @@ -376,7 +376,7 @@ rsvg_new_radial_gradient (void)
605  {
606  
607      RsvgRadialGradient *grad = g_new (RsvgRadialGradient, 1);
608 -    _rsvg_node_init (&grad->super);
609 +    _rsvg_node_init (&grad->super, RSVG_NODE_TYPE_RADIAL_GRADIENT);
610      _rsvg_affine_identity (grad->affine);
611      grad->has_current_color = FALSE;
612      grad->obj_bbox = TRUE;
613 @@ -458,7 +458,7 @@ RsvgNode *
614  rsvg_new_pattern (void)
615  {
616      RsvgPattern *pattern = g_new (RsvgPattern, 1);
617 -    _rsvg_node_init (&pattern->super);
618 +    _rsvg_node_init (&pattern->super, RSVG_NODE_TYPE_PATTERN);
619      pattern->obj_bbox = TRUE;
620      pattern->obj_cbbox = FALSE;
621      pattern->x = pattern->y = pattern->width = pattern->height = _rsvg_css_parse_length ("0");
622 @@ -477,7 +477,8 @@ hasstop (GPtrArray * lookin)
623  {
624      unsigned int i;
625      for (i = 0; i < lookin->len; i++) {
626 -        if (!strcmp (((RsvgNode *) g_ptr_array_index (lookin, i))->type->str, "stop"))
627 +        RsvgNode *node = g_ptr_array_index (lookin, i);
628 +        if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_STOP)
629              return 1;
630      }
631      return 0;
632 @@ -490,7 +491,7 @@ rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
633      int i;
634      ufallback = grad->fallback;
635      while (ufallback != NULL) {
636 -        if (!strcmp (ufallback->type->str, "linearGradient")) {
637 +        if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_LINEAR_GRADIENT) {
638              RsvgLinearGradient *fallback = (RsvgLinearGradient *) ufallback;
639              if (!grad->hasx1 && fallback->hasx1) {
640                  grad->hasx1 = TRUE;
641 @@ -525,7 +526,7 @@ rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
642                  grad->super.children = fallback->super.children;
643              }
644              ufallback = fallback->fallback;
645 -        } else if (!strcmp (ufallback->type->str, "radialGradient")) {
646 +        } else if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_RADIAL_GRADIENT) {
647              RsvgRadialGradient *fallback = (RsvgRadialGradient *) ufallback;
648              if (!grad->hastransform && fallback->hastransform) {
649                  grad->hastransform = TRUE;
650 @@ -555,7 +556,7 @@ rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
651      int i;
652      ufallback = grad->fallback;
653      while (ufallback != NULL) {
654 -        if (!strcmp (ufallback->type->str, "radialGradient")) {
655 +        if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_RADIAL_GRADIENT) {
656              RsvgRadialGradient *fallback = (RsvgRadialGradient *) ufallback;
657              if (!grad->hascx && fallback->hascx) {
658                  grad->hascx = TRUE;
659 @@ -594,7 +595,7 @@ rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
660                  grad->super.children = fallback->super.children;
661              }
662              ufallback = fallback->fallback;
663 -        } else if (!strcmp (ufallback->type->str, "linearGradient")) {
664 +        } else if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_LINEAR_GRADIENT) {
665              RsvgLinearGradient *fallback = (RsvgLinearGradient *) ufallback;
666              if (!grad->hastransform && fallback->hastransform) {
667                  grad->hastransform = TRUE;
668 diff --git a/rsvg-private.h b/rsvg-private.h
669 index 288c2de..162917a 100644
670 --- a/rsvg-private.h
671 +++ b/rsvg-private.h
672 @@ -255,16 +255,74 @@ struct RsvgSizeCallbackData {
673  
674  void _rsvg_size_callback (int *width, int *height, gpointer data);
675  
676 +typedef enum {
677 +    RSVG_NODE_TYPE_INVALID = 0,
678 +
679 +    RSVG_NODE_TYPE_CHARS,
680 +    RSVG_NODE_TYPE_CIRCLE,
681 +    RSVG_NODE_TYPE_CLIP_PATH,
682 +    RSVG_NODE_TYPE_COMPONENT_TRANFER_FUNCTION,
683 +    RSVG_NODE_TYPE_DEFS,
684 +    RSVG_NODE_TYPE_ELLIPSE,
685 +    RSVG_NODE_TYPE_FILTER,
686 +    RSVG_NODE_TYPE_GROUP,
687 +    RSVG_NODE_TYPE_IMAGE,
688 +    RSVG_NODE_TYPE_LIGHT_SOURCE,
689 +    RSVG_NODE_TYPE_LINE,
690 +    RSVG_NODE_TYPE_LINEAR_GRADIENT,
691 +    RSVG_NODE_TYPE_MARKER,
692 +    RSVG_NODE_TYPE_MASK,
693 +    RSVG_NODE_TYPE_PATH,
694 +    RSVG_NODE_TYPE_PATTERN,
695 +    RSVG_NODE_TYPE_POLYGON,
696 +    RSVG_NODE_TYPE_POLYLINE,
697 +    RSVG_NODE_TYPE_RADIAL_GRADIENT,
698 +    RSVG_NODE_TYPE_RECT,
699 +    RSVG_NODE_TYPE_STOP,
700 +    RSVG_NODE_TYPE_SVG,
701 +    RSVG_NODE_TYPE_SWITCH,
702 +    RSVG_NODE_TYPE_SYMBOL,
703 +    RSVG_NODE_TYPE_TEXT,
704 +    RSVG_NODE_TYPE_TREF,
705 +    RSVG_NODE_TYPE_TSPAN,
706 +    RSVG_NODE_TYPE_USE,
707 +
708 +    /* Filter primitives */
709 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE = 64,
710 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_BLEND,
711 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_COLOUR_MATRIX,
712 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER,
713 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPOSITE,
714 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_CONVOLVE_MATRIX,
715 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_DIFFUSE_LIGHTING,
716 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_DISPLACEMENT_MAP,
717 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_ERODE,
718 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_FLOOD,
719 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_GAUSSIAN_BLUR,
720 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_IMAGE,
721 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE,
722 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE,
723 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_OFFSET,
724 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_SPECULAR_LIGHTING,
725 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_TILE,
726 +    RSVG_NODE_TYPE_FILTER_PRIMITIVE_TURBULENCE,
727 +
728 +} RsvgNodeType;
729 +
730  struct _RsvgNode {
731      RsvgState *state;
732      RsvgNode *parent;
733 -    GString *type;
734      GPtrArray *children;
735 +    RsvgNodeType type;
736 +    const char *name; /* owned by the xmlContext, invalid after parsing! */
737      void (*free) (RsvgNode * self);
738      void (*draw) (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate);
739      void (*set_atts) (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag *);
740  };
741  
742 +#define RSVG_NODE_TYPE(node)                ((node)->type)
743 +#define RSVG_NODE_IS_FILTER_PRIMITIVE(node) (RSVG_NODE_TYPE((node)) & RSVG_NODE_TYPE_FILTER_PRIMITIVE)
744 +
745  struct _RsvgNodeChars {
746      RsvgNode super;
747      GString *contents;
748 diff --git a/rsvg-shapes.c b/rsvg-shapes.c
749 index d481abf..07baf24 100644
750 --- a/rsvg-shapes.c
751 +++ b/rsvg-shapes.c
752 @@ -89,7 +89,7 @@ rsvg_new_path (void)
753  {
754      RsvgNodePath *path;
755      path = g_new (RsvgNodePath, 1);
756 -    _rsvg_node_init (&path->super);
757 +    _rsvg_node_init (&path->super, RSVG_NODE_TYPE_PATH);
758      path->d = NULL;
759      path->super.free = rsvg_node_path_free;
760      path->super.draw = rsvg_node_path_draw;
761 @@ -101,7 +101,6 @@ rsvg_new_path (void)
762  struct _RsvgNodePoly {
763      RsvgNode super;
764      gdouble *pointlist;
765 -    gboolean is_polyline;
766      guint pointlist_len;
767  };
768  
769 @@ -126,7 +125,8 @@ _rsvg_node_poly_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * a
770              rsvg_defs_register_name (ctx->priv->defs, value, self);
771          }
772  
773 -        rsvg_parse_style_attrs (ctx, self->state, (poly->is_polyline ? "polyline" : "polygon"),
774 +        rsvg_parse_style_attrs (ctx, self->state,
775 +                                RSVG_NODE_TYPE (self) == RSVG_NODE_TYPE_POLYLINE ? "polyline" : "polygon",
776                                  klazz, id, atts);
777      }
778  
779 @@ -160,7 +160,7 @@ _rsvg_node_poly_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
780          g_string_append (d, g_ascii_dtostr (buf, sizeof (buf), poly->pointlist[i + 1]));
781      }
782  
783 -    if (!poly->is_polyline)
784 +    if (RSVG_NODE_TYPE (self) == RSVG_NODE_TYPE_POLYGON)
785          g_string_append (d, " Z");
786  
787      rsvg_state_reinherit_top (ctx, self->state, dominate);
788 @@ -181,16 +181,15 @@ _rsvg_node_poly_free (RsvgNode * self)
789  
790  
791  static RsvgNode *
792 -rsvg_new_any_poly (gboolean is_polyline)
793 +rsvg_new_any_poly (RsvgNodeType type)
794  {
795      RsvgNodePoly *poly;
796      poly = g_new (RsvgNodePoly, 1);
797 -    _rsvg_node_init (&poly->super);
798 +    _rsvg_node_init (&poly->super, type);
799      poly->super.free = _rsvg_node_poly_free;
800      poly->super.draw = _rsvg_node_poly_draw;
801      poly->super.set_atts = _rsvg_node_poly_set_atts;
802      poly->pointlist = NULL;
803 -    poly->is_polyline = is_polyline;
804      poly->pointlist_len = 0;
805      return &poly->super;
806  }
807 @@ -198,13 +197,13 @@ rsvg_new_any_poly (gboolean is_polyline)
808  RsvgNode *
809  rsvg_new_polygon (void)
810  {
811 -    return rsvg_new_any_poly (FALSE);
812 +    return rsvg_new_any_poly (RSVG_NODE_TYPE_POLYGON);
813  }
814  
815  RsvgNode *
816  rsvg_new_polyline (void)
817  {
818 -    return rsvg_new_any_poly (TRUE);
819 +    return rsvg_new_any_poly (RSVG_NODE_TYPE_POLYLINE);
820  }
821  
822  
823 @@ -275,7 +274,7 @@ rsvg_new_line (void)
824  {
825      RsvgNodeLine *line;
826      line = g_new (RsvgNodeLine, 1);
827 -    _rsvg_node_init (&line->super);
828 +    _rsvg_node_init (&line->super, RSVG_NODE_TYPE_LINE);
829      line->super.draw = _rsvg_node_line_draw;
830      line->super.set_atts = _rsvg_node_line_set_atts;
831      line->x1 = line->x2 = line->y1 = line->y2 = _rsvg_css_parse_length ("0");
832 @@ -451,7 +450,7 @@ rsvg_new_rect (void)
833  {
834      RsvgNodeRect *rect;
835      rect = g_new (RsvgNodeRect, 1);
836 -    _rsvg_node_init (&rect->super);
837 +    _rsvg_node_init (&rect->super, RSVG_NODE_TYPE_RECT);
838      rect->super.draw = _rsvg_node_rect_draw;
839      rect->super.set_atts = _rsvg_node_rect_set_atts;
840      rect->x = rect->y = rect->w = rect->h = rect->rx = rect->ry = _rsvg_css_parse_length ("0");
841 @@ -577,7 +576,7 @@ rsvg_new_circle (void)
842  {
843      RsvgNodeCircle *circle;
844      circle = g_new (RsvgNodeCircle, 1);
845 -    _rsvg_node_init (&circle->super);
846 +    _rsvg_node_init (&circle->super, RSVG_NODE_TYPE_CIRCLE);
847      circle->super.draw = _rsvg_node_circle_draw;
848      circle->super.set_atts = _rsvg_node_circle_set_atts;
849      circle->cx = circle->cy = circle->r = _rsvg_css_parse_length ("0");
850 @@ -703,7 +702,7 @@ rsvg_new_ellipse (void)
851  {
852      RsvgNodeEllipse *ellipse;
853      ellipse = g_new (RsvgNodeEllipse, 1);
854 -    _rsvg_node_init (&ellipse->super);
855 +    _rsvg_node_init (&ellipse->super, RSVG_NODE_TYPE_ELLIPSE);
856      ellipse->super.draw = _rsvg_node_ellipse_draw;
857      ellipse->super.set_atts = _rsvg_node_ellipse_set_atts;
858      ellipse->cx = ellipse->cy = ellipse->rx = ellipse->ry = _rsvg_css_parse_length ("0");
859 diff --git a/rsvg-shapes.h b/rsvg-shapes.h
860 index 7cf6621..baad98f 100644
861 --- a/rsvg-shapes.h
862 +++ b/rsvg-shapes.h
863 @@ -34,7 +34,7 @@
864  
865  G_BEGIN_DECLS 
866  
867 -RsvgNode * rsvg_new_path (void);
868 +RsvgNode *rsvg_new_path (void);
869  RsvgNode *rsvg_new_polygon (void);
870  RsvgNode *rsvg_new_polyline (void);
871  RsvgNode *rsvg_new_line (void);
872 diff --git a/rsvg-structure.c b/rsvg-structure.c
873 index b078fea..33889be 100644
874 --- a/rsvg-structure.c
875 +++ b/rsvg-structure.c
876 @@ -103,8 +103,10 @@ _rsvg_node_dont_set_atts (RsvgNode * node, RsvgHandle * ctx, RsvgPropertyBag * a
877  }
878  
879  void
880 -_rsvg_node_init (RsvgNode * self)
881 +_rsvg_node_init (RsvgNode * self,
882 +                 RsvgNodeType type)
883  {
884 +    self->type = type;
885      self->parent = NULL;
886      self->children = g_ptr_array_new ();
887      self->state = g_new (RsvgState, 1);
888 @@ -112,7 +114,6 @@ _rsvg_node_init (RsvgNode * self)
889      self->free = _rsvg_node_free;
890      self->draw = _rsvg_node_draw_nothing;
891      self->set_atts = _rsvg_node_dont_set_atts;
892 -    self->type = NULL;
893  }
894  
895  void
896 @@ -124,8 +125,6 @@ _rsvg_node_finalize (RsvgNode * self)
897      }
898      if (self->children != NULL)
899          g_ptr_array_free (self->children, TRUE);
900 -    if (self->type != NULL)
901 -        g_string_free (self->type, TRUE);
902  }
903  
904  void
905 @@ -157,7 +156,7 @@ rsvg_new_group (void)
906  {
907      RsvgNodeGroup *group;
908      group = g_new (RsvgNodeGroup, 1);
909 -    _rsvg_node_init (&group->super);
910 +    _rsvg_node_init (&group->super, RSVG_NODE_TYPE_GROUP);
911      group->super.draw = _rsvg_node_draw_children;
912      group->super.set_atts = rsvg_node_group_set_atts;
913      return &group->super;
914 @@ -166,8 +165,8 @@ rsvg_new_group (void)
915  void
916  rsvg_pop_def_group (RsvgHandle * ctx)
917  {
918 -    if (ctx->priv->currentnode != NULL)
919 -        ctx->priv->currentnode = ctx->priv->currentnode->parent;
920 +    g_assert (ctx->priv->currentnode != NULL);
921 +    ctx->priv->currentnode = ctx->priv->currentnode->parent;
922  }
923  
924  void
925 @@ -218,7 +217,7 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
926          return;
927  
928      state = rsvg_current_state (ctx);
929 -    if (strcmp (child->type->str, "symbol")) {
930 +    if (RSVG_NODE_TYPE (child) != RSVG_NODE_TYPE_SYMBOL) {
931          _rsvg_affine_translate (affine, x, y);
932          _rsvg_affine_multiply (state->affine, affine, state->affine);
933  
934 @@ -397,7 +396,7 @@ rsvg_new_svg (void)
935  {
936      RsvgNodeSvg *svg;
937      svg = g_new (RsvgNodeSvg, 1);
938 -    _rsvg_node_init (&svg->super);
939 +    _rsvg_node_init (&svg->super, RSVG_NODE_TYPE_SVG);
940      svg->vbox.active = FALSE;
941      svg->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
942      svg->x = _rsvg_css_parse_length ("0");
943 @@ -444,7 +443,7 @@ rsvg_new_use (void)
944  {
945      RsvgNodeUse *use;
946      use = g_new (RsvgNodeUse, 1);
947 -    _rsvg_node_init (&use->super);
948 +    _rsvg_node_init (&use->super, RSVG_NODE_TYPE_USE);
949      use->super.draw = rsvg_node_use_draw;
950      use->super.set_atts = rsvg_node_use_set_atts;
951      use->x = _rsvg_css_parse_length ("0");
952 @@ -485,7 +484,7 @@ rsvg_new_symbol (void)
953  {
954      RsvgNodeSymbol *symbol;
955      symbol = g_new (RsvgNodeSymbol, 1);
956 -    _rsvg_node_init (&symbol->super);
957 +    _rsvg_node_init (&symbol->super, RSVG_NODE_TYPE_SYMBOL);
958      symbol->vbox.active = FALSE;
959      symbol->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
960      symbol->super.draw = _rsvg_node_draw_nothing;
961 @@ -498,7 +497,7 @@ rsvg_new_defs (void)
962  {
963      RsvgNodeGroup *group;
964      group = g_new (RsvgNodeGroup, 1);
965 -    _rsvg_node_init (&group->super);
966 +    _rsvg_node_init (&group->super, RSVG_NODE_TYPE_DEFS);
967      group->super.draw = _rsvg_node_draw_nothing;
968      group->super.set_atts = rsvg_node_group_set_atts;
969      return &group->super;
970 @@ -533,7 +532,7 @@ rsvg_new_switch (void)
971  {
972      RsvgNodeGroup *group;
973      group = g_new (RsvgNodeGroup, 1);
974 -    _rsvg_node_init (&group->super);
975 +    _rsvg_node_init (&group->super, RSVG_NODE_TYPE_SWITCH);
976      group->super.draw = _rsvg_node_switch_draw;
977      group->super.set_atts = rsvg_node_group_set_atts;
978      return &group->super;
979 diff --git a/rsvg-structure.h b/rsvg-structure.h
980 index d672977..7d17c82 100644
981 --- a/rsvg-structure.h
982 +++ b/rsvg-structure.h
983 @@ -36,7 +36,7 @@
984  
985  G_BEGIN_DECLS 
986  
987 -RsvgNode * rsvg_new_use (void);
988 +RsvgNode *rsvg_new_use (void);
989  RsvgNode *rsvg_new_symbol (void);
990  RsvgNode *rsvg_new_svg (void);
991  RsvgNode *rsvg_new_defs (void);
992 @@ -50,6 +50,7 @@ typedef struct _RsvgNodeSvg RsvgNodeSvg;
993  
994  struct _RsvgNodeGroup {
995      RsvgNode super;
996 +    char *name;
997  };
998  
999  struct _RsvgNodeSymbol {
1000 @@ -80,7 +81,7 @@ void rsvg_node_draw         (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate
1001  void _rsvg_node_draw_children   (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate);
1002  void _rsvg_node_finalize    (RsvgNode * self);
1003  void _rsvg_node_free        (RsvgNode * self);
1004 -void _rsvg_node_init        (RsvgNode * self);
1005 +void _rsvg_node_init        (RsvgNode * self, RsvgNodeType type);
1006  void _rsvg_node_svg_apply_atts  (RsvgNodeSvg * self, RsvgHandle * ctx);
1007  
1008  G_END_DECLS
1009 diff --git a/rsvg-text.c b/rsvg-text.c
1010 index 7066f24..89720de 100644
1011 --- a/rsvg-text.c
1012 +++ b/rsvg-text.c
1013 @@ -170,17 +170,19 @@ _rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
1014      rsvg_push_discrete_layer (ctx);
1015      for (i = 0; i < self->children->len; i++) {
1016          RsvgNode *node = g_ptr_array_index (self->children, i);
1017 -        if (!strcmp (node->type->str, "RSVG_NODE_CHARS")) {
1018 +        RsvgNodeType type = RSVG_NODE_TYPE (node);
1019 +
1020 +        if (type == RSVG_NODE_TYPE_CHARS) {
1021              RsvgNodeChars *chars = (RsvgNodeChars *) node;
1022              GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
1023              rsvg_text_render_text (ctx, str->str, x, y);
1024              g_string_free (str, TRUE);
1025 -        } else if (!strcmp (node->type->str, "tspan")) {
1026 +        } else if (type == RSVG_NODE_TYPE_TSPAN) {
1027              RsvgNodeText *tspan = (RsvgNodeText *) node;
1028              rsvg_state_push (ctx);
1029              _rsvg_node_text_type_tspan (tspan, ctx, x, y, lastwasspace);
1030              rsvg_state_pop (ctx);
1031 -        } else if (!strcmp (node->type->str, "tref")) {
1032 +        } else if (type == RSVG_NODE_TYPE_TREF) {
1033              RsvgNodeTref *tref = (RsvgNodeTref *) node;
1034              _rsvg_node_text_type_tref (tref, ctx, x, y, lastwasspace);
1035          }
1036 @@ -206,17 +208,19 @@ _rsvg_node_text_length_children (RsvgNode * self, RsvgDrawingCtx * ctx,
1037      int out = FALSE;
1038      for (i = 0; i < self->children->len; i++) {
1039          RsvgNode *node = g_ptr_array_index (self->children, i);
1040 +        RsvgNodeType type = RSVG_NODE_TYPE (node);
1041 +
1042          rsvg_state_push (ctx);
1043          rsvg_state_reinherit_top (ctx, node->state, 0);
1044 -        if (!strcmp (node->type->str, "RSVG_NODE_CHARS")) {
1045 +        if (type == RSVG_NODE_TYPE_CHARS) {
1046              RsvgNodeChars *chars = (RsvgNodeChars *) node;
1047              GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
1048              *x += rsvg_text_length_text_as_string (ctx, str->str);
1049              g_string_free (str, TRUE);
1050 -        } else if (!strcmp (node->type->str, "tspan")) {
1051 +        } else if (type == RSVG_NODE_TYPE_TSPAN) {
1052              RsvgNodeText *tspan = (RsvgNodeText *) node;
1053              out = _rsvg_node_text_length_tspan (tspan, ctx, x, lastwasspace);
1054 -        } else if (!strcmp (node->type->str, "tref")) {
1055 +        } else if (type == RSVG_NODE_TYPE_TREF) {
1056              RsvgNodeTref *tref = (RsvgNodeTref *) node;
1057              out = _rsvg_node_text_length_tref (tref, ctx, x, lastwasspace);
1058          }
1059 @@ -259,7 +263,7 @@ rsvg_new_text (void)
1060  {
1061      RsvgNodeText *text;
1062      text = g_new (RsvgNodeText, 1);
1063 -    _rsvg_node_init (&text->super);
1064 +    _rsvg_node_init (&text->super, RSVG_NODE_TYPE_TEXT);
1065      text->super.draw = _rsvg_node_text_draw;
1066      text->super.set_atts = _rsvg_node_text_set_atts;
1067      text->x = text->y = text->dx = text->dy = _rsvg_css_parse_length ("0");
1068 @@ -331,7 +335,7 @@ rsvg_new_tspan (void)
1069  {
1070      RsvgNodeText *text;
1071      text = g_new (RsvgNodeText, 1);
1072 -    _rsvg_node_init (&text->super);
1073 +    _rsvg_node_init (&text->super, RSVG_NODE_TYPE_TSPAN);
1074      text->super.set_atts = _rsvg_node_tspan_set_atts;
1075      text->x.factor = text->y.factor = 'n';
1076      text->dx = text->dy = _rsvg_css_parse_length ("0");
1077 @@ -374,7 +378,7 @@ rsvg_new_tref (void)
1078  {
1079      RsvgNodeTref *text;
1080      text = g_new (RsvgNodeTref, 1);
1081 -    _rsvg_node_init (&text->super);
1082 +    _rsvg_node_init (&text->super, RSVG_NODE_TYPE_TREF);
1083      text->super.set_atts = _rsvg_node_tref_set_atts;
1084      text->link = NULL;
1085      return &text->super;
1086 -- 
1087 1.7.0.5
1088