Store node type separately in RsvgNode

The node name (formerly RsvgNode:type) cannot be used to infer
the sub-type of RsvgNode that we're dealing with, since for unknown
elements we put type = node-name. This lead to a (potentially exploitable)
crash e.g. when the element name started with "fe" which tricked
the old code into considering it as a RsvgFilterPrimitive.

CVE-2011-3146

https://bugzilla.gnome.org/show_bug.cgi?id=658014
parent eaaa3212
......@@ -147,7 +147,6 @@ rsvg_start_style (RsvgHandle * ctx, RsvgPropertyBag * atts)
static void
rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag * atts)
{
/*replace this stuff with a hash for fast reading! */
RsvgNode *newnode = NULL;
if (!strcmp (name, "g"))
......@@ -241,11 +240,11 @@ rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag
else if (!strcmp (name, "feFuncA"))
newnode = rsvg_new_node_component_transfer_function ('a');
else if (!strcmp (name, "feDistantLight"))
newnode = rsvg_new_filter_primitive_light_source ('d');
newnode = rsvg_new_node_light_source ('d');
else if (!strcmp (name, "feSpotLight"))
newnode = rsvg_new_filter_primitive_light_source ('s');
newnode = rsvg_new_node_light_source ('s');
else if (!strcmp (name, "fePointLight"))
newnode = rsvg_new_filter_primitive_light_source ('p');
newnode = rsvg_new_node_light_source ('p');
/* hack to make multiImage sort-of work */
else if (!strcmp (name, "multiImage"))
newnode = rsvg_new_switch ();
......@@ -259,21 +258,22 @@ rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag
newnode = rsvg_new_tspan ();
else if (!strcmp (name, "tref"))
newnode = rsvg_new_tref ();
else {
else {
/* hack for bug 401115. whenever we encounter a node we don't understand, push it into a group.
this will allow us to handle things like conditionals properly. */
newnode = rsvg_new_group ();
}
if (newnode) {
newnode->type = g_string_new (name);
g_assert (RSVG_NODE_TYPE (newnode) != RSVG_NODE_TYPE_INVALID);
newnode->name = (char *) name; /* libxml will keep this while parsing */
newnode->parent = ctx->priv->currentnode;
rsvg_node_set_atts (newnode, ctx, atts);
rsvg_defs_register_memory (ctx->priv->defs, newnode);
if (ctx->priv->currentnode) {
rsvg_node_group_pack (ctx->priv->currentnode, newnode);
ctx->priv->currentnode = newnode;
} else if (!strcmp (name, "svg")) {
} else if (RSVG_NODE_TYPE (newnode) == RSVG_NODE_TYPE_SVG) {
ctx->priv->treebase = newnode;
ctx->priv->currentnode = newnode;
}
......@@ -689,10 +689,11 @@ rsvg_end_element (void *data, const xmlChar * name)
ctx->priv->handler = NULL;
}
if (ctx->priv->currentnode
&& !strcmp ((const char *) name, ctx->priv->currentnode->type->str))
rsvg_pop_def_group (ctx);
if (ctx->priv->currentnode &&
!strcmp ((const char *) name, ctx->priv->currentnode->name))
rsvg_pop_def_group (ctx);
/* FIXMEchpe: shouldn't this check that currentnode == treebase or sth like that? */
if (ctx->priv->treebase && !strcmp ((const char *)name, "svg"))
_rsvg_node_svg_apply_atts ((RsvgNodeSvg *)ctx->priv->treebase, ctx);
}
......@@ -706,6 +707,30 @@ _rsvg_node_chars_free (RsvgNode * node)
_rsvg_node_free (node);
}
static RsvgNodeChars *
rsvg_new_node_chars (const char *text,
int len)
{
RsvgNodeChars *self;
self = g_new (RsvgNodeChars, 1);
_rsvg_node_init (&self->super, RSVG_NODE_TYPE_CHARS);
if (!g_utf8_validate (text, len, NULL)) {
char *utf8;
utf8 = rsvg_make_valid_utf8 (text, len);
self->contents = g_string_new (utf8);
g_free (utf8);
} else {
self->contents = g_string_new_len (text, len);
}
self->super.free = _rsvg_node_chars_free;
self->super.state->cond_true = FALSE;
return self;
}
static void
rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
{
......@@ -715,8 +740,9 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
return;
if (ctx->priv->currentnode) {
if (!strcmp ("tspan", ctx->priv->currentnode->type->str) ||
!strcmp ("text", ctx->priv->currentnode->type->str)) {
RsvgNodeType type = RSVG_NODE_TYPE (ctx->priv->currentnode);
if (type == RSVG_NODE_TYPE_TSPAN ||
type == RSVG_NODE_TYPE_TEXT) {
guint i;
/* find the last CHARS node in the text or tspan node, so that we
......@@ -724,7 +750,7 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
self = NULL;
for (i = 0; i < ctx->priv->currentnode->children->len; i++) {
RsvgNode *node = g_ptr_array_index (ctx->priv->currentnode->children, i);
if (!strcmp (node->type->str, "RSVG_NODE_CHARS")) {
if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
self = (RsvgNodeChars*)node;
}
}
......@@ -744,21 +770,7 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
}
}
self = g_new (RsvgNodeChars, 1);
_rsvg_node_init (&self->super);
if (!g_utf8_validate ((char *) ch, len, NULL)) {
char *utf8;
utf8 = rsvg_make_valid_utf8 ((char *) ch, len);
self->contents = g_string_new (utf8);
g_free (utf8);
} else {
self->contents = g_string_new_len ((char *) ch, len);
}
self->super.type = g_string_new ("RSVG_NODE_CHARS");
self->super.free = _rsvg_node_chars_free;
self->super.state->cond_true = FALSE;
self = rsvg_new_node_chars ((char *) ch, len);
rsvg_defs_register_memory (ctx->priv->defs, (RsvgNode *) self);
if (ctx->priv->currentnode)
......
......@@ -147,7 +147,7 @@ _pattern_add_rsvg_color_stops (cairo_pattern_t * pattern,
for (i = 0; i < stops->len; i++) {
node = (RsvgNode *) g_ptr_array_index (stops, i);
if (strcmp (node->type->str, "stop"))
if (RSVG_NODE_TYPE (node) != RSVG_NODE_TYPE_STOP)
continue;
stop = (RsvgGradientStop *) node;
rgba = stop->rgba;
......
......@@ -495,7 +495,7 @@ rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
for (i = 0; i < self->super.children->len; i++) {
current = g_ptr_array_index (self->super.children, i);
if (!strncmp (current->super.type->str, "fe", 2))
if (RSVG_NODE_IS_FILTER_PRIMITIVE (&current->super))
rsvg_filter_primitive_render (current, ctx);
}
......@@ -703,7 +703,7 @@ rsvg_filter_parse (const RsvgDefs * defs, const char *str)
val = rsvg_defs_lookup (defs, name);
g_free (name);
if (val && (!strcmp (val->type->str, "filter")))
if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_FILTER)
return (RsvgFilter *) val;
}
return NULL;
......@@ -754,7 +754,7 @@ rsvg_new_filter (void)
RsvgFilter *filter;
filter = g_new (RsvgFilter, 1);
_rsvg_node_init (&filter->super);
_rsvg_node_init (&filter->super, RSVG_NODE_TYPE_FILTER);
filter->filterunits = objectBoundingBox;
filter->primitiveunits = userSpaceOnUse;
filter->x = _rsvg_css_parse_length ("-10%");
......@@ -978,7 +978,7 @@ rsvg_new_filter_primitive_blend (void)
{
RsvgFilterPrimitiveBlend *filter;
filter = g_new (RsvgFilterPrimitiveBlend, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_BLEND);
filter->mode = normal;
filter->super.in = g_string_new ("none");
filter->in2 = g_string_new ("none");
......@@ -1230,7 +1230,7 @@ rsvg_new_filter_primitive_convolve_matrix (void)
{
RsvgFilterPrimitiveConvolveMatrix *filter;
filter = g_new (RsvgFilterPrimitiveConvolveMatrix, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_CONVOLVE_MATRIX);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -1471,7 +1471,7 @@ rsvg_new_filter_primitive_gaussian_blur (void)
{
RsvgFilterPrimitiveGaussianBlur *filter;
filter = g_new (RsvgFilterPrimitiveGaussianBlur, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_GAUSSIAN_BLUR);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -1607,7 +1607,7 @@ rsvg_new_filter_primitive_offset (void)
{
RsvgFilterPrimitiveOffset *filter;
filter = g_new (RsvgFilterPrimitiveOffset, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_OFFSET);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -1648,7 +1648,7 @@ rsvg_filter_primitive_merge_render (RsvgFilterPrimitive * self, RsvgFilterContex
for (i = 0; i < upself->super.super.children->len; i++) {
RsvgFilterPrimitive *mn;
mn = g_ptr_array_index (upself->super.super.children, i);
if (strcmp (mn->super.type->str, "feMergeNode"))
if (RSVG_NODE_TYPE (&mn->super) != RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE)
continue;
in = rsvg_filter_get_in (mn->in, ctx);
rsvg_alpha_blt (in, boundarys.x0, boundarys.y0, boundarys.x1 - boundarys.x0,
......@@ -1701,7 +1701,7 @@ rsvg_new_filter_primitive_merge (void)
{
RsvgFilterPrimitiveMerge *filter;
filter = g_new (RsvgFilterPrimitiveMerge, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE);
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
filter->super.height.factor = 'n';
......@@ -1744,7 +1744,7 @@ rsvg_new_filter_primitive_merge_node (void)
{
RsvgFilterPrimitive *filter;
filter = g_new (RsvgFilterPrimitive, 1);
_rsvg_node_init (&filter->super);
_rsvg_node_init (&filter->super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE);
filter->in = g_string_new ("none");
filter->super.free = rsvg_filter_primitive_merge_node_free;
filter->render = &rsvg_filter_primitive_merge_node_render;
......@@ -1978,7 +1978,7 @@ rsvg_new_filter_primitive_colour_matrix (void)
{
RsvgFilterPrimitiveColourMatrix *filter;
filter = g_new (RsvgFilterPrimitiveColourMatrix, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_COLOUR_MATRIX);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -2010,8 +2010,9 @@ struct _RsvgNodeComponentTransferFunc {
gint slope;
gint intercept;
gint amplitude;
gdouble exponent;
gint offset;
gdouble exponent;
char channel;
};
struct _RsvgFilterPrimitiveComponentTransfer {
......@@ -2107,15 +2108,18 @@ rsvg_filter_primitive_component_transfer_render (RsvgFilterPrimitive *
for (c = 0; c < 4; c++) {
char channel = "RGBA"[c];
for (i = 0; i < self->super.children->len; i++) {
RsvgNodeComponentTransferFunc *temp;
temp = (RsvgNodeComponentTransferFunc *)
g_ptr_array_index (self->super.children, i);
if (!strncmp (temp->super.type->str, "feFunc", 6))
if (temp->super.type->str[6] == channel) {
RsvgNode *child_node;
child_node = (RsvgNode *) g_ptr_array_index (self->super.children, i);
if (RSVG_NODE_TYPE (child_node) == RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER) {
RsvgNodeComponentTransferFunc *temp = (RsvgNodeComponentTransferFunc *) child_node;
if (temp->channel == channel) {
functions[ctx->channelmap[c]] = temp->function;
channels[ctx->channelmap[c]] = temp;
break;
}
}
}
if (i == self->super.children->len)
functions[ctx->channelmap[c]] = identity_component_transfer_func;
......@@ -2198,7 +2202,7 @@ rsvg_new_filter_primitive_component_transfer (void)
RsvgFilterPrimitiveComponentTransfer *filter;
filter = g_new (RsvgFilterPrimitiveComponentTransfer, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER);
filter->super.result = g_string_new ("none");
filter->super.in = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -2272,7 +2276,7 @@ rsvg_new_node_component_transfer_function (char channel)
RsvgNodeComponentTransferFunc *filter;
filter = g_new (RsvgNodeComponentTransferFunc, 1);
_rsvg_node_init (&filter->super);
_rsvg_node_init (&filter->super, RSVG_NODE_TYPE_COMPONENT_TRANFER_FUNCTION);
filter->super.free = rsvg_component_transfer_function_free;
filter->super.set_atts = rsvg_node_component_transfer_function_set_atts;
filter->function = identity_component_transfer_func;
......@@ -2414,7 +2418,7 @@ rsvg_new_filter_primitive_erode (void)
{
RsvgFilterPrimitiveErode *filter;
filter = g_new (RsvgFilterPrimitiveErode, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_ERODE);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -2639,7 +2643,7 @@ rsvg_new_filter_primitive_composite (void)
{
RsvgFilterPrimitiveComposite *filter;
filter = g_new (RsvgFilterPrimitiveComposite, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPOSITE);
filter->mode = COMPOSITE_MODE_OVER;
filter->super.in = g_string_new ("none");
filter->in2 = g_string_new ("none");
......@@ -2744,7 +2748,7 @@ rsvg_new_filter_primitive_flood (void)
{
RsvgFilterPrimitive *filter;
filter = g_new (RsvgFilterPrimitive, 1);
_rsvg_node_init (&filter->super);
_rsvg_node_init (&filter->super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_FLOOD);
filter->in = g_string_new ("none");
filter->result = g_string_new ("none");
filter->x.factor = filter->y.factor = filter->width.factor = filter->height.factor = 'n';
......@@ -2920,7 +2924,7 @@ rsvg_new_filter_primitive_displacement_map (void)
{
RsvgFilterPrimitiveDisplacementMap *filter;
filter = g_new (RsvgFilterPrimitiveDisplacementMap, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_DISPLACEMENT_MAP);
filter->super.in = g_string_new ("none");
filter->in2 = g_string_new ("none");
filter->super.result = g_string_new ("none");
......@@ -3291,7 +3295,7 @@ rsvg_new_filter_primitive_turbulence (void)
{
RsvgFilterPrimitiveTurbulence *filter;
filter = g_new (RsvgFilterPrimitiveTurbulence, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_TURBULENCE);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -3510,7 +3514,7 @@ rsvg_new_filter_primitive_image (void)
{
RsvgFilterPrimitiveImage *filter;
filter = g_new (RsvgFilterPrimitiveImage, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_IMAGE);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -3871,8 +3875,8 @@ get_light_colour (RsvgNodeLightSource * source, vector3 colour,
static void
rsvg_filter_primitive_light_source_set_atts (RsvgNode * self,
RsvgHandle * ctx, RsvgPropertyBag * atts)
rsvg_node_light_source_set_atts (RsvgNode * self,
RsvgHandle * ctx, RsvgPropertyBag * atts)
{
RsvgNodeLightSource *data;
const char *value;
......@@ -3904,13 +3908,13 @@ rsvg_filter_primitive_light_source_set_atts (RsvgNode * self,
}
RsvgNode *
rsvg_new_filter_primitive_light_source (char type)
rsvg_new_node_light_source (char type)
{
RsvgNodeLightSource *data;
data = g_new (RsvgNodeLightSource, 1);
_rsvg_node_init (&data->super);
_rsvg_node_init (&data->super, RSVG_NODE_TYPE_LIGHT_SOURCE);
data->super.free = _rsvg_node_free;
data->super.set_atts = rsvg_filter_primitive_light_source_set_atts;
data->super.set_atts = rsvg_node_light_source_set_atts;
data->specularExponent = 1;
if (type == 's')
data->type = SPOTLIGHT;
......@@ -3960,10 +3964,11 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
for (i = 0; i < self->super.children->len; i++) {
RsvgNode *temp;
temp = g_ptr_array_index (self->super.children, i);
if (!strcmp (temp->type->str, "feDistantLight") ||
!strcmp (temp->type->str, "fePointLight") || !strcmp (temp->type->str, "feSpotLight"))
if (RSVG_NODE_TYPE (temp) == RSVG_NODE_TYPE_LIGHT_SOURCE) {
source = (RsvgNodeLightSource *) temp;
}
}
if (source == NULL)
return;
......@@ -4080,7 +4085,7 @@ rsvg_new_filter_primitive_diffuse_lighting (void)
{
RsvgFilterPrimitiveDiffuseLighting *filter;
filter = g_new (RsvgFilterPrimitiveDiffuseLighting, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_DIFFUSE_LIGHTING);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -4135,9 +4140,9 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
for (i = 0; i < self->super.children->len; i++) {
RsvgNode *temp;
temp = g_ptr_array_index (self->super.children, i);
if (!strcmp (temp->type->str, "feDistantLight") ||
!strcmp (temp->type->str, "fePointLight") || !strcmp (temp->type->str, "feSpotLight"))
if (RSVG_NODE_TYPE (temp) == RSVG_NODE_TYPE_LIGHT_SOURCE) {
source = (RsvgNodeLightSource *) temp;
}
}
if (source == NULL)
return;
......@@ -4259,7 +4264,7 @@ rsvg_new_filter_primitive_specular_lighting (void)
{
RsvgFilterPrimitiveSpecularLighting *filter;
filter = g_new (RsvgFilterPrimitiveSpecularLighting, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_SPECULAR_LIGHTING);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......@@ -4381,7 +4386,7 @@ rsvg_new_filter_primitive_tile (void)
{
RsvgFilterPrimitiveTile *filter;
filter = g_new (RsvgFilterPrimitiveTile, 1);
_rsvg_node_init (&filter->super.super);
_rsvg_node_init (&filter->super.super, RSVG_NODE_TYPE_FILTER_PRIMITIVE_TILE);
filter->super.in = g_string_new ("none");
filter->super.result = g_string_new ("none");
filter->super.x.factor = filter->super.y.factor = filter->super.width.factor =
......
......@@ -64,7 +64,7 @@ RsvgNode *rsvg_new_filter_primitive_displacement_map (void);
RsvgNode *rsvg_new_filter_primitive_turbulence (void);
RsvgNode *rsvg_new_filter_primitive_image (void);
RsvgNode *rsvg_new_filter_primitive_diffuse_lighting (void);
RsvgNode *rsvg_new_filter_primitive_light_source (char type);
RsvgNode *rsvg_new_node_light_source (char type);
RsvgNode *rsvg_new_filter_primitive_specular_lighting (void);
RsvgNode *rsvg_new_filter_primitive_tile (void);
......
......@@ -356,7 +356,7 @@ rsvg_new_image (void)
{
RsvgNodeImage *image;
image = g_new (RsvgNodeImage, 1);
_rsvg_node_init (&image->super);
_rsvg_node_init (&image->super, RSVG_NODE_TYPE_IMAGE);
g_assert (image->super.state);
image->img = NULL;
image->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
......
......@@ -84,7 +84,7 @@ rsvg_new_marker (void)
{
RsvgMarker *marker;
marker = g_new (RsvgMarker, 1);
_rsvg_node_init (&marker->super);
_rsvg_node_init (&marker->super, RSVG_NODE_TYPE_MARKER);
marker->orient = 0;
marker->orientAuto = FALSE;
marker->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
......@@ -198,7 +198,7 @@ rsvg_marker_parse (const RsvgDefs * defs, const char *str)
val = rsvg_defs_lookup (defs, name);
g_free (name);
if (val && (!strcmp (val->type->str, "marker")))
if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_MARKER)
return val;
}
return NULL;
......
......@@ -74,7 +74,7 @@ rsvg_new_mask (void)
RsvgMask *mask;
mask = g_new (RsvgMask, 1);
_rsvg_node_init (&mask->super);
_rsvg_node_init (&mask->super, RSVG_NODE_TYPE_MASK);
mask->maskunits = objectBoundingBox;
mask->contentunits = userSpaceOnUse;
mask->x = _rsvg_css_parse_length ("0");
......@@ -113,7 +113,7 @@ rsvg_mask_parse (const RsvgDefs * defs, const char *str)
val = rsvg_defs_lookup (defs, name);
g_free (name);
if (val && (!strcmp (val->type->str, "mask")))
if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_MASK)
return val;
}
return NULL;
......@@ -130,7 +130,7 @@ rsvg_clip_path_parse (const RsvgDefs * defs, const char *str)
val = rsvg_defs_lookup (defs, name);
g_free (name);
if (val && (!strcmp (val->type->str, "clipPath")))
if (val && RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_CLIP_PATH)
return val;
}
return NULL;
......@@ -168,7 +168,7 @@ rsvg_new_clip_path (void)
RsvgClipPath *clip_path;
clip_path = g_new (RsvgClipPath, 1);
_rsvg_node_init (&clip_path->super);
_rsvg_node_init (&clip_path->super, RSVG_NODE_TYPE_CLIP_PATH);
clip_path->units = userSpaceOnUse;
clip_path->super.set_atts = rsvg_clip_path_set_atts;
clip_path->super.free = _rsvg_node_free;
......
......@@ -129,11 +129,11 @@ rsvg_paint_server_parse (gboolean * inherit, const RsvgDefs * defs, const char *
if (val == NULL)
return NULL;
if (!strcmp (val->type->str, "linearGradient"))
if (RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_LINEAR_GRADIENT)
return rsvg_paint_server_lin_grad ((RsvgLinearGradient *) val);
else if (!strcmp (val->type->str, "radialGradient"))
else if (RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_RADIAL_GRADIENT)
return rsvg_paint_server_rad_grad ((RsvgRadialGradient *) val);
else if (!strcmp (val->type->str, "pattern"))
else if (RSVG_NODE_TYPE (val) == RSVG_NODE_TYPE_PATTERN)
return rsvg_paint_server_pattern ((RsvgPattern *) val);
else
return NULL;
......@@ -224,7 +224,7 @@ RsvgNode *
rsvg_new_stop (void)
{
RsvgGradientStop *stop = g_new (RsvgGradientStop, 1);
_rsvg_node_init (&stop->super);
_rsvg_node_init (&stop->super, RSVG_NODE_TYPE_STOP);
stop->super.set_atts = rsvg_stop_set_atts;
stop->offset = 0;
stop->rgba = 0;
......@@ -293,7 +293,7 @@ rsvg_new_linear_gradient (void)
{
RsvgLinearGradient *grad = NULL;
grad = g_new (RsvgLinearGradient, 1);
_rsvg_node_init (&grad->super);
_rsvg_node_init (&grad->super, RSVG_NODE_TYPE_LINEAR_GRADIENT);
_rsvg_affine_identity (grad->affine);
grad->has_current_color = FALSE;
grad->x1 = grad->y1 = grad->y2 = _rsvg_css_parse_length ("0");
......@@ -376,7 +376,7 @@ rsvg_new_radial_gradient (void)
{
RsvgRadialGradient *grad = g_new (RsvgRadialGradient, 1);
_rsvg_node_init (&grad->super);
_rsvg_node_init (&grad->super, RSVG_NODE_TYPE_RADIAL_GRADIENT);
_rsvg_affine_identity (grad->affine);
grad->has_current_color = FALSE;
grad->obj_bbox = TRUE;
......@@ -458,7 +458,7 @@ RsvgNode *
rsvg_new_pattern (void)
{
RsvgPattern *pattern = g_new (RsvgPattern, 1);
_rsvg_node_init (&pattern->super);
_rsvg_node_init (&pattern->super, RSVG_NODE_TYPE_PATTERN);
pattern->obj_bbox = TRUE;
pattern->obj_cbbox = FALSE;
pattern->x = pattern->y = pattern->width = pattern->height = _rsvg_css_parse_length ("0");
......@@ -477,7 +477,8 @@ hasstop (GPtrArray * lookin)
{
unsigned int i;
for (i = 0; i < lookin->len; i++) {
if (!strcmp (((RsvgNode *) g_ptr_array_index (lookin, i))->type->str, "stop"))
RsvgNode *node = g_ptr_array_index (lookin, i);
if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_STOP)
return 1;
}
return 0;
......@@ -490,7 +491,7 @@ rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
int i;
ufallback = grad->fallback;
while (ufallback != NULL) {
if (!strcmp (ufallback->type->str, "linearGradient")) {
if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_LINEAR_GRADIENT) {
RsvgLinearGradient *fallback = (RsvgLinearGradient *) ufallback;
if (!grad->hasx1 && fallback->hasx1) {
grad->hasx1 = TRUE;
......@@ -525,7 +526,7 @@ rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
grad->super.children = fallback->super.children;
}
ufallback = fallback->fallback;
} else if (!strcmp (ufallback->type->str, "radialGradient")) {
} else if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_RADIAL_GRADIENT) {
RsvgRadialGradient *fallback = (RsvgRadialGradient *) ufallback;
if (!grad->hastransform && fallback->hastransform) {
grad->hastransform = TRUE;
......@@ -555,7 +556,7 @@ rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
int i;
ufallback = grad->fallback;
while (ufallback != NULL) {
if (!strcmp (ufallback->type->str, "radialGradient")) {
if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_RADIAL_GRADIENT) {
RsvgRadialGradient *fallback = (RsvgRadialGradient *) ufallback;
if (!grad->hascx && fallback->hascx) {
grad->hascx = TRUE;
......@@ -594,7 +595,7 @@ rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
grad->super.children = fallback->super.children;
}
ufallback = fallback->fallback;
} else if (!strcmp (ufallback->type->str, "linearGradient")) {
} else if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_LINEAR_GRADIENT) {
RsvgLinearGradient *fallback = (RsvgLinearGradient *) ufallback;
if (!grad->hastransform && fallback->hastransform) {
grad->hastransform = TRUE;
......
......@@ -255,16 +255,74 @@ struct RsvgSizeCallbackData {
void _rsvg_size_callback (int *width, int *height, gpointer data);
typedef enum {
RSVG_NODE_TYPE_INVALID = 0,
RSVG_NODE_TYPE_CHARS,
RSVG_NODE_TYPE_CIRCLE,
RSVG_NODE_TYPE_CLIP_PATH,
RSVG_NODE_TYPE_COMPONENT_TRANFER_FUNCTION,
RSVG_NODE_TYPE_DEFS,
RSVG_NODE_TYPE_ELLIPSE,
RSVG_NODE_TYPE_FILTER,
RSVG_NODE_TYPE_GROUP,
RSVG_NODE_TYPE_IMAGE,
RSVG_NODE_TYPE_LIGHT_SOURCE,
RSVG_NODE_TYPE_LINE,
RSVG_NODE_TYPE_LINEAR_GRADIENT,
RSVG_NODE_TYPE_MARKER,
RSVG_NODE_TYPE_MASK,
RSVG_NODE_TYPE_PATH,
RSVG_NODE_TYPE_PATTERN,
RSVG_NODE_TYPE_POLYGON,
RSVG_NODE_TYPE_POLYLINE,
RSVG_NODE_TYPE_RADIAL_GRADIENT,
RSVG_NODE_TYPE_RECT,
RSVG_NODE_TYPE_STOP,
RSVG_NODE_TYPE_SVG,
RSVG_NODE_TYPE_SWITCH,
RSVG_NODE_TYPE_SYMBOL,
RSVG_NODE_TYPE_TEXT,
RSVG_NODE_TYPE_TREF,
RSVG_NODE_TYPE_TSPAN,
RSVG_NODE_TYPE_USE,
/* Filter primitives */
RSVG_NODE_TYPE_FILTER_PRIMITIVE = 64,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_BLEND,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_COLOUR_MATRIX,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPOSITE,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_CONVOLVE_MATRIX,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_DIFFUSE_LIGHTING,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_DISPLACEMENT_MAP,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_ERODE,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_FLOOD,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_GAUSSIAN_BLUR,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_IMAGE,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_OFFSET,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_SPECULAR_LIGHTING,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_TILE,
RSVG_NODE_TYPE_FILTER_PRIMITIVE_TURBULENCE,
} RsvgNodeType;
struct _RsvgNode {
RsvgState *state;
RsvgNode *parent;
GString *type;
GPtrArray *children;
RsvgNodeType type;
const char *name; /* owned by the xmlContext, invalid after parsing! */
void (*free) (RsvgNode * self);
void (*draw) (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate);
void (*set_atts) (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag *);
};
#define RSVG_NODE_TYPE(node) ((node)->type)
#define RSVG_NODE_IS_FILTER_PRIMITIVE(node) (RSVG_NODE_TYPE((node)) & RSVG_NODE_TYPE_FILTER_PRIMITIVE)
struct _RsvgNodeChars {
RsvgNode super;
GString *contents;
......
......@@ -89,7 +89,7 @@ rsvg_new_path (void)
{
RsvgNodePath *path;
path = g_new (RsvgNodePath, 1);
_rsvg_node_init (&path->super);
_rsvg_node_init (&path->super, RSVG_NODE_TYPE_PATH);
path->d = NULL;
path->super.free = rsvg_node_path_free;
path->super.draw = rsvg_node_path_draw;
......@@ -101,7 +101,6 @@ rsvg_new_path (void)
struct _RsvgNodePoly {
RsvgNode super;
gdouble *pointlist;
gboolean is_polyline;
guint pointlist_len;
};
......@@ -126,7 +125,8 @@ _rsvg_node_poly_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * a
rsvg_defs_register_name (ctx->priv->defs, value, self);
}
rsvg_parse_style_attrs (ctx, self->state, (poly->is_polyline ? "polyline" : "polygon"),
rsvg_parse_style_attrs (ctx, self->state,
RSVG_NODE_TYPE (self) == RSVG_NODE_TYPE_POLYLINE ? "polyline" : "polygon",
klazz, id, atts);
}
......@@ -160,7 +160,7 @@ _rsvg_node_poly_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
g_string_append (d, g_ascii_dtostr (buf, sizeof (buf), poly->pointlist[i + 1]));
}
if (!poly->is_polyline)
if (RSVG_NODE_TYPE (self) == RSVG_NODE_TYPE_POLYGON)
g_string_append (d, " Z");
rsvg_state_reinherit_top (ctx, self->state, dominate);
......@@ -181,16 +181,15 @@ _rsvg_node_poly_free (RsvgNode * self)
static RsvgNode *
rsvg_new_any_poly (gboolean is_polyline)
rsvg_new_any_poly (RsvgNodeType type)
{
RsvgNodePoly *poly;
poly = g_new (RsvgNodePoly, 1);
_rsvg_node_init (&poly->super);
_rsvg_node_init (&poly->super, type);
poly->super.free = _rsvg_node_poly_free;
poly->super.draw = _rsvg_node_poly_draw;
poly->super.set_atts = _rsvg_node_poly_set_atts;
poly->pointlist = NULL;
poly->is_polyline = is_polyline;
poly->pointlist_len = 0;
return &poly->super;
}
......@@ -198,13 +197,13 @@ rsvg_new_any_poly (gboolean is_polyline)