[librsvg] Node: store the element's id, or None.



commit c5bfd649ac393e685fb76df2f760b2d353d22af2
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Jun 4 18:21:57 2018 -0500

    Node: store the element's id, or None.
    
    We pass it everywhere to the construction functions now.
    
    We'll use this for several things:  debugging, CSS cascading, etc.

 librsvg/filters/blend.c                 |  3 +-
 librsvg/filters/color_matrix.c          |  3 +-
 librsvg/filters/component_transfer.c    |  6 ++--
 librsvg/filters/convolve_matrix.c       |  3 +-
 librsvg/filters/diffuse_lighting.c      |  3 +-
 librsvg/filters/displacement_map.c      |  3 +-
 librsvg/filters/erode.c                 |  3 +-
 librsvg/filters/flood.c                 |  3 +-
 librsvg/filters/gaussian_blur.c         |  3 +-
 librsvg/filters/image.c                 |  3 +-
 librsvg/filters/light_source.c          |  3 +-
 librsvg/filters/merge.c                 |  6 ++--
 librsvg/filters/specular_lighting.c     |  3 +-
 librsvg/filters/tile.c                  |  3 +-
 librsvg/filters/turbulence.c            |  3 +-
 librsvg/rsvg-filter.h                   | 38 ++++++++++++------------
 librsvg/rsvg-load.c                     | 52 ++++++++++++++++++++++-----------
 librsvg/rsvg-private.h                  |  1 +
 librsvg/rsvg-structure.h                | 52 ++++++++++++++++-----------------
 rsvg_internals/src/clip_path.rs         |  3 ++
 rsvg_internals/src/cnode.rs             |  9 ++++--
 rsvg_internals/src/filters/composite.rs | 12 ++++++--
 rsvg_internals/src/filters/node.rs      |  9 +++++-
 rsvg_internals/src/filters/offset.rs    | 12 ++++++--
 rsvg_internals/src/gradient.rs          |  4 +++
 rsvg_internals/src/image.rs             |  9 +++++-
 rsvg_internals/src/link.rs              |  9 +++++-
 rsvg_internals/src/load.rs              | 37 ++++++++++++++++++++---
 rsvg_internals/src/marker.rs            |  9 +++++-
 rsvg_internals/src/mask.rs              |  9 +++++-
 rsvg_internals/src/node.rs              | 18 ++++++++++++
 rsvg_internals/src/pattern.rs           |  9 +++++-
 rsvg_internals/src/shapes.rs            | 45 ++++++++++++++++++++++++----
 rsvg_internals/src/stop.rs              |  9 +++++-
 rsvg_internals/src/structure.rs         | 49 +++++++++++++++++++++++++++----
 rsvg_internals/src/text.rs              | 32 +++++++++++++++++---
 36 files changed, 365 insertions(+), 113 deletions(-)
---
diff --git a/librsvg/filters/blend.c b/librsvg/filters/blend.c
index 6aa14333..8639fd74 100644
--- a/librsvg/filters/blend.c
+++ b/librsvg/filters/blend.c
@@ -264,7 +264,7 @@ rsvg_filter_primitive_blend_set_atts (RsvgNode *node, gpointer impl, RsvgHandle
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_blend (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_blend (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveBlend *filter;
 
@@ -277,6 +277,7 @@ rsvg_new_filter_primitive_blend (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_BLEND,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_blend_set_atts,
                                 rsvg_filter_primitive_blend_free);
diff --git a/librsvg/filters/color_matrix.c b/librsvg/filters/color_matrix.c
index 24aa9c23..fa3547e8 100644
--- a/librsvg/filters/color_matrix.c
+++ b/librsvg/filters/color_matrix.c
@@ -279,7 +279,7 @@ out:
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_color_matrix (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_color_matrix (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveColorMatrix *filter;
 
@@ -291,6 +291,7 @@ rsvg_new_filter_primitive_color_matrix (const char *element_name, RsvgNode *pare
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_COLOR_MATRIX,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_color_matrix_set_atts,
                                 rsvg_filter_primitive_color_matrix_free);
diff --git a/librsvg/filters/component_transfer.c b/librsvg/filters/component_transfer.c
index 4b7a8da1..8328fbd8 100644
--- a/librsvg/filters/component_transfer.c
+++ b/librsvg/filters/component_transfer.c
@@ -278,7 +278,7 @@ rsvg_filter_primitive_component_transfer_set_atts (RsvgNode *node, gpointer impl
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_component_transfer (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_component_transfer (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveComponentTransfer *filter;
 
@@ -289,6 +289,7 @@ rsvg_new_filter_primitive_component_transfer (const char *element_name, RsvgNode
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_COMPONENT_TRANSFER,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_component_transfer_set_atts,
                                 rsvg_filter_primitive_free);
@@ -380,7 +381,7 @@ rsvg_node_component_transfer_function_free (gpointer impl)
 }
 
 RsvgNode *
-rsvg_new_node_component_transfer_function (const char *element_name, RsvgNode *parent)
+rsvg_new_node_component_transfer_function (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgNodeComponentTransferFunc *filter;
 
@@ -406,6 +407,7 @@ rsvg_new_node_component_transfer_function (const char *element_name, RsvgNode *p
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_COMPONENT_TRANFER_FUNCTION,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_node_component_transfer_function_set_atts,
                                 rsvg_node_component_transfer_function_free);
diff --git a/librsvg/filters/convolve_matrix.c b/librsvg/filters/convolve_matrix.c
index b0865ec6..cb601f01 100644
--- a/librsvg/filters/convolve_matrix.c
+++ b/librsvg/filters/convolve_matrix.c
@@ -343,7 +343,7 @@ out:
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_convolve_matrix (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_convolve_matrix (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveConvolveMatrix *filter;
 
@@ -363,6 +363,7 @@ rsvg_new_filter_primitive_convolve_matrix (const char *element_name, RsvgNode *p
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_CONVOLVE_MATRIX,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_convolve_matrix_set_atts,
                                 rsvg_filter_primitive_convolve_matrix_free);
diff --git a/librsvg/filters/diffuse_lighting.c b/librsvg/filters/diffuse_lighting.c
index a4392f31..6ea876ba 100644
--- a/librsvg/filters/diffuse_lighting.c
+++ b/librsvg/filters/diffuse_lighting.c
@@ -196,7 +196,7 @@ rsvg_filter_primitive_diffuse_lighting_set_atts (RsvgNode *node, gpointer impl,
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_diffuse_lighting (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_diffuse_lighting (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveDiffuseLighting *filter;
 
@@ -211,6 +211,7 @@ rsvg_new_filter_primitive_diffuse_lighting (const char *element_name, RsvgNode *
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_DIFFUSE_LIGHTING,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_diffuse_lighting_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/displacement_map.c b/librsvg/filters/displacement_map.c
index d2a04732..72154385 100644
--- a/librsvg/filters/displacement_map.c
+++ b/librsvg/filters/displacement_map.c
@@ -223,7 +223,7 @@ rsvg_filter_primitive_displacement_map_set_atts (RsvgNode *node, gpointer impl,
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_displacement_map (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_displacement_map (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveDisplacementMap *filter;
 
@@ -238,6 +238,7 @@ rsvg_new_filter_primitive_displacement_map (const char *element_name, RsvgNode *
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_DISPLACEMENT_MAP,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_displacement_map_set_atts,
                                 rsvg_filter_primitive_displacement_map_free);
diff --git a/librsvg/filters/erode.c b/librsvg/filters/erode.c
index c0338dd9..399d8440 100644
--- a/librsvg/filters/erode.c
+++ b/librsvg/filters/erode.c
@@ -173,7 +173,7 @@ out:
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_erode (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_erode (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveErode *filter;
 
@@ -187,6 +187,7 @@ rsvg_new_filter_primitive_erode (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_ERODE,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_erode_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/flood.c b/librsvg/filters/flood.c
index 4d7b7b78..8ba1da6e 100644
--- a/librsvg/filters/flood.c
+++ b/librsvg/filters/flood.c
@@ -108,7 +108,7 @@ rsvg_filter_primitive_flood_set_atts (RsvgNode *node, gpointer impl, RsvgHandle
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_flood (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_flood (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitive *filter;
 
@@ -119,6 +119,7 @@ rsvg_new_filter_primitive_flood (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_FLOOD,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_flood_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/gaussian_blur.c b/librsvg/filters/gaussian_blur.c
index 523645f3..37c94327 100644
--- a/librsvg/filters/gaussian_blur.c
+++ b/librsvg/filters/gaussian_blur.c
@@ -681,7 +681,7 @@ out:
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_gaussian_blur (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_gaussian_blur (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveGaussianBlur *filter;
 
@@ -694,6 +694,7 @@ rsvg_new_filter_primitive_gaussian_blur (const char *element_name, RsvgNode *par
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_GAUSSIAN_BLUR,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_gaussian_blur_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/image.c b/librsvg/filters/image.c
index 58950935..783dc8a8 100644
--- a/librsvg/filters/image.c
+++ b/librsvg/filters/image.c
@@ -247,7 +247,7 @@ rsvg_filter_primitive_image_set_atts (RsvgNode *node, gpointer impl, RsvgHandle
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_image (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_image (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveImage *filter;
 
@@ -259,6 +259,7 @@ rsvg_new_filter_primitive_image (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_IMAGE,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_image_set_atts,
                                 rsvg_filter_primitive_image_free);
diff --git a/librsvg/filters/light_source.c b/librsvg/filters/light_source.c
index 22eb1f0c..30c607e4 100644
--- a/librsvg/filters/light_source.c
+++ b/librsvg/filters/light_source.c
@@ -446,7 +446,7 @@ find_light_source_in_children (RsvgNode *node)
 }
 
 RsvgNode *
-rsvg_new_node_light_source (const char *element_name, RsvgNode *parent)
+rsvg_new_node_light_source (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgNodeLightSource *data;
 
@@ -467,6 +467,7 @@ rsvg_new_node_light_source (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_LIGHT_SOURCE,
                                 parent,
+                                id,
                                 data,
                                 rsvg_node_light_source_set_atts,
                                 g_free);
diff --git a/librsvg/filters/merge.c b/librsvg/filters/merge.c
index 398cef0d..18de698a 100644
--- a/librsvg/filters/merge.c
+++ b/librsvg/filters/merge.c
@@ -128,7 +128,7 @@ rsvg_filter_primitive_merge_set_atts (RsvgNode *node, gpointer impl, RsvgHandle
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_merge (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_merge (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveMerge *filter;
 
@@ -138,6 +138,7 @@ rsvg_new_filter_primitive_merge (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_merge_set_atts,
                                 rsvg_filter_primitive_free);
@@ -176,7 +177,7 @@ rsvg_filter_primitive_merge_node_render (RsvgNode *node, RsvgComputedValues *val
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_merge_node (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_merge_node (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitive *filter;
 
@@ -186,6 +187,7 @@ rsvg_new_filter_primitive_merge_node (const char *element_name, RsvgNode *parent
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_merge_node_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/specular_lighting.c b/librsvg/filters/specular_lighting.c
index dc497475..e4b8bc22 100644
--- a/librsvg/filters/specular_lighting.c
+++ b/librsvg/filters/specular_lighting.c
@@ -199,7 +199,7 @@ rsvg_filter_primitive_specular_lighting_set_atts (RsvgNode *node, gpointer impl,
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_specular_lighting (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_specular_lighting (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveSpecularLighting *filter;
 
@@ -213,6 +213,7 @@ rsvg_new_filter_primitive_specular_lighting (const char *element_name, RsvgNode
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_SPECULAR_LIGHTING,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_specular_lighting_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/tile.c b/librsvg/filters/tile.c
index 4c1aef70..8b4fd7ba 100644
--- a/librsvg/filters/tile.c
+++ b/librsvg/filters/tile.c
@@ -142,7 +142,7 @@ rsvg_filter_primitive_tile_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_tile (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_tile (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveTile *filter;
 
@@ -153,6 +153,7 @@ rsvg_new_filter_primitive_tile (const char *element_name, RsvgNode *parent)
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_TILE,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_tile_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/filters/turbulence.c b/librsvg/filters/turbulence.c
index 0118ee37..64e57e02 100644
--- a/librsvg/filters/turbulence.c
+++ b/librsvg/filters/turbulence.c
@@ -407,7 +407,7 @@ out:
 }
 
 RsvgNode *
-rsvg_new_filter_primitive_turbulence (const char *element_name, RsvgNode *parent)
+rsvg_new_filter_primitive_turbulence (const char *element_name, RsvgNode *parent, const char *id)
 {
     RsvgFilterPrimitiveTurbulence *filter;
 
@@ -427,6 +427,7 @@ rsvg_new_filter_primitive_turbulence (const char *element_name, RsvgNode *parent
 
     return rsvg_rust_cnode_new (RSVG_NODE_TYPE_FILTER_PRIMITIVE_TURBULENCE,
                                 parent,
+                                id,
                                 filter,
                                 rsvg_filter_primitive_turbulence_set_atts,
                                 rsvg_filter_primitive_free);
diff --git a/librsvg/rsvg-filter.h b/librsvg/rsvg-filter.h
index 8df00524..2d494ba9 100644
--- a/librsvg/rsvg-filter.h
+++ b/librsvg/rsvg-filter.h
@@ -66,47 +66,47 @@ G_GNUC_INTERNAL
 RsvgNode    *rsvg_new_filter       (const char *element_name, RsvgNode *parent);
 
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_blend                (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_blend                (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_convolve_matrix      (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_convolve_matrix      (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_gaussian_blur        (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_gaussian_blur        (const char *element_name, RsvgNode *parent, 
const char *id);
 
 /* Implemented in rust/src/filters/offset.rs */
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_offset               (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_offset               (const char *element_name, RsvgNode *parent, 
const char *id);
 /* Implemented in rust/src/filters/composite.rs */
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_composite            (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_composite            (const char *element_name, RsvgNode *parent, 
const char *id);
 
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_merge                (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_merge                (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_merge_node           (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_merge_node           (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_color_matrix         (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_color_matrix         (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_component_transfer   (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_component_transfer   (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_node_component_transfer_function      (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_node_component_transfer_function      (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_erode                (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_erode                (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_flood                (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_flood                (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_displacement_map     (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_displacement_map     (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_turbulence           (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_turbulence           (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_image                (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_image                (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_diffuse_lighting            (const char *element_name, RsvgNode 
*parent);
+RsvgNode    *rsvg_new_filter_primitive_diffuse_lighting            (const char *element_name, RsvgNode 
*parent, const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_node_light_source                            (const char *element_name, RsvgNode 
*parent);
+RsvgNode    *rsvg_new_node_light_source                            (const char *element_name, RsvgNode 
*parent, const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_specular_lighting    (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_specular_lighting    (const char *element_name, RsvgNode *parent, 
const char *id);
 G_GNUC_INTERNAL
-RsvgNode    *rsvg_new_filter_primitive_tile                 (const char *element_name, RsvgNode *parent);
+RsvgNode    *rsvg_new_filter_primitive_tile                 (const char *element_name, RsvgNode *parent, 
const char *id);
 
 G_END_DECLS
 
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 9dd0accc..1b0f7a9e 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -292,33 +292,31 @@ free_element_name_stack (RsvgLoad *load)
 }
 
 static void
-node_set_atts (RsvgNode *node,
-               RsvgHandle *handle,
-               const char *element_name,
-               gboolean supports_class_attribute,
-               RsvgPropertyBag atts)
+get_id_and_class (RsvgPropertyBag atts,
+                  const char **out_id,
+                  const char **out_class)
 {
     RsvgPropertyBagIter *iter;
     const char *key;
     RsvgAttribute attr;
     const char *value;
+    
+    g_assert (out_id != NULL);
+    g_assert (out_class != NULL);
 
-    const char *id = NULL;
-    const char *klazz = NULL;
+    *out_id = NULL;
+    *out_class = NULL;
 
     iter = rsvg_property_bag_iter_begin (atts);
 
     while (rsvg_property_bag_iter_next (iter, &key, &attr, &value)) {
         switch (attr) {
         case RSVG_ATTRIBUTE_ID:
-            id = value;
-            rsvg_defs_register_node_by_id (handle->priv->defs, id, node);
+            *out_id = value;
             break;
 
         case RSVG_ATTRIBUTE_CLASS:
-            if (supports_class_attribute) {
-                klazz = value;
-            }
+            *out_class = value;
             break;
 
         default:
@@ -327,6 +325,18 @@ node_set_atts (RsvgNode *node,
     }
 
     rsvg_property_bag_iter_end (iter);
+}
+
+static void
+node_set_atts (RsvgNode *node,
+               RsvgHandle *handle,
+               const char *element_name,
+               const char *node_id,
+               const char *node_class,
+               RsvgPropertyBag atts)
+{
+    if (node_id != NULL)
+        rsvg_defs_register_node_by_id (handle->priv->defs, node_id, node);
 
     rsvg_node_set_atts (node, handle, atts);
 
@@ -335,7 +345,7 @@ node_set_atts (RsvgNode *node,
      * rsvg_node_svg_apply_atts()
      */
     if (rsvg_node_get_type (node) != RSVG_NODE_TYPE_SVG) {
-        rsvg_parse_style_attrs (handle, node, element_name, klazz, id, atts);
+        rsvg_parse_style_attrs (handle, node, element_name, node_class, node_id, atts);
     }
 
     rsvg_node_set_overriden_properties (node);
@@ -344,10 +354,14 @@ node_set_atts (RsvgNode *node,
 static void
 standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts)
 {
-    gboolean supports_class_attribute;
     RsvgNode *newnode;
-    
-    newnode = rsvg_load_new_node(name, load->currentnode, &supports_class_attribute);
+    const char *node_id;
+    const char *node_class;
+    gboolean supports_class_attribute;
+
+    get_id_and_class (atts, &node_id, &node_class);
+
+    newnode = rsvg_load_new_node(name, load->currentnode, node_id, &supports_class_attribute);
     g_assert (newnode != NULL);
 
     g_assert (rsvg_node_get_type (newnode) != RSVG_NODE_TYPE_INVALID);
@@ -365,7 +379,11 @@ standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts
 
     load->currentnode = rsvg_node_ref (newnode);
 
-    node_set_atts (newnode, load->handle, name, supports_class_attribute, atts);
+    if (!supports_class_attribute) {
+        node_class = NULL;
+    }
+
+    node_set_atts (newnode, load->handle, name, node_id, node_class, atts);
 
     newnode = rsvg_node_unref (newnode);
 }
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 5183070e..091289af 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -281,6 +281,7 @@ typedef void (* CNodeFree) (gpointer impl);
 G_GNUC_INTERNAL
 RsvgNode *rsvg_rust_cnode_new (RsvgNodeType  node_type,
                                RsvgNode     *parent,
+                               const char   *id,
                                gpointer      impl,
                                CNodeSetAtts  set_atts_fn,
                                CNodeFree     free_fn) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/librsvg/rsvg-structure.h b/librsvg/rsvg-structure.h
index 269f7eb7..42a603fc 100644
--- a/librsvg/rsvg-structure.h
+++ b/librsvg/rsvg-structure.h
@@ -36,39 +36,39 @@ G_BEGIN_DECLS
 
 /* Implemented in rust/src/load.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_load_new_node (const char *element_name, RsvgNode *parent, gboolean 
*supports_class_attribute);
+RsvgNode *rsvg_load_new_node (const char *element_name, RsvgNode *parent, const char *id, gboolean 
*supports_class_attribute);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_group_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_group_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/link.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_link_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_link_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_defs_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_defs_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_switch_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_switch_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_svg_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_svg_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_use_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_use_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_symbol_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_symbol_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/image.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_image_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_image_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
@@ -84,71 +84,71 @@ void rsvg_node_svg_apply_atts (RsvgNode *node, RsvgHandle *handle);
 
 /* Implemented in rust/src/text.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_text_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_text_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/text.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_tref_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_tref_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/text.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_tspan_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_tspan_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/marker.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_marker_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_marker_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/gradient.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_linear_gradient_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_linear_gradient_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/gradient.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_radial_gradient_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_radial_gradient_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/pattern.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_pattern_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_pattern_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/stop.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_stop_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_stop_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/mask.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_mask_new (const char *element_name, RsvgNode *node);
+RsvgNode *rsvg_node_mask_new (const char *element_name, RsvgNode *node, const char *id);
 
 /* Implemented in rust/src/clip_path.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_clip_path_new (const char *element_name, RsvgNode *node);
+RsvgNode *rsvg_node_clip_path_new (const char *element_name, RsvgNode *node, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_path_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_path_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_polygon_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_polygon_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_polyline_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_polyline_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_line_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_line_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_rect_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_rect_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_circle_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_circle_new (const char *element_name, RsvgNode *parent, const char *id);
 
 /* Implemented in rust/src/shapes.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_node_ellipse_new (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_ellipse_new (const char *element_name, RsvgNode *parent, const char *id);
 
 G_END_DECLS
 
diff --git a/rsvg_internals/src/clip_path.rs b/rsvg_internals/src/clip_path.rs
index 3588392a..fae147f5 100644
--- a/rsvg_internals/src/clip_path.rs
+++ b/rsvg_internals/src/clip_path.rs
@@ -10,6 +10,7 @@ use handle::RsvgHandle;
 use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgNode};
 use parsers::parse;
 use property_bag::PropertyBag;
+use util::utf8_cstr_opt;
 
 coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);
 
@@ -89,10 +90,12 @@ impl NodeTrait for NodeClipPath {
 pub extern "C" fn rsvg_node_clip_path_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
     boxed_node_new(
         NodeType::ClipPath,
         raw_parent,
+        unsafe { utf8_cstr_opt(id) },
         Box::new(NodeClipPath::new()),
     )
 }
diff --git a/rsvg_internals/src/cnode.rs b/rsvg_internals/src/cnode.rs
index 31465247..acf9e7c4 100644
--- a/rsvg_internals/src/cnode.rs
+++ b/rsvg_internals/src/cnode.rs
@@ -1,9 +1,12 @@
+use libc;
+
+use std::rc::*;
+
 use handle::*;
 use node::*;
 use property_bag::PropertyBag;
 use state::rsvg_state_new;
-
-use std::rc::*;
+use util::utf8_cstr_opt;
 
 type CNodeSetAtts = unsafe extern "C" fn(
     node: *const RsvgNode,
@@ -56,6 +59,7 @@ impl Drop for CNode {
 pub extern "C" fn rsvg_rust_cnode_new(
     node_type: NodeType,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
     c_node_impl: *const RsvgCNodeImpl,
     set_atts_fn: CNodeSetAtts,
     free_fn: CNodeFree,
@@ -71,6 +75,7 @@ pub extern "C" fn rsvg_rust_cnode_new(
     box_node(Rc::new(Node::new(
         node_type,
         node_ptr_to_weak(raw_parent),
+        unsafe { utf8_cstr_opt(id) },
         rsvg_state_new(),
         Box::new(cnode),
     )))
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index 6268a373..5c453183 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -1,7 +1,7 @@
 use std::cell::{Cell, RefCell};
 
 use cairo::{self, ImageSurface};
-use libc::c_char;
+use libc::{self, c_char};
 
 use attributes::Attribute;
 use error::{AttributeError, NodeError};
@@ -10,7 +10,7 @@ use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgN
 use parsers::{self, parse, Parse};
 use property_bag::PropertyBag;
 use srgb::{linearize_surface, unlinearize_surface};
-use util::clamp;
+use util::{clamp, utf8_cstr_opt};
 
 use super::context::{FilterContext, FilterOutput, FilterResult};
 use super::input::Input;
@@ -233,7 +233,13 @@ impl From<Operator> for cairo::Operator {
 pub unsafe extern "C" fn rsvg_new_filter_primitive_composite(
     _element_name: *const c_char,
     parent: *mut RsvgNode,
+    id: *const libc::c_char,
 ) -> *mut RsvgNode {
     let filter = Composite::new();
-    boxed_node_new(NodeType::FilterPrimitiveComposite, parent, Box::new(filter))
+    boxed_node_new(
+        NodeType::FilterPrimitiveComposite,
+        parent,
+        utf8_cstr_opt(id),
+        Box::new(filter),
+    )
 }
diff --git a/rsvg_internals/src/filters/node.rs b/rsvg_internals/src/filters/node.rs
index 93bbe79a..16e98566 100644
--- a/rsvg_internals/src/filters/node.rs
+++ b/rsvg_internals/src/filters/node.rs
@@ -10,6 +10,7 @@ use length::{LengthDir, RsvgLength};
 use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgNode};
 use parsers::{parse, Parse};
 use property_bag::PropertyBag;
+use util::utf8_cstr_opt;
 
 /// The <filter> node.
 pub struct NodeFilter {
@@ -74,6 +75,12 @@ impl NodeTrait for NodeFilter {
 pub extern "C" fn rsvg_new_filter(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Filter, raw_parent, Box::new(NodeFilter::new()))
+    boxed_node_new(
+        NodeType::Filter,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeFilter::new()),
+    )
 }
diff --git a/rsvg_internals/src/filters/offset.rs b/rsvg_internals/src/filters/offset.rs
index 04a3e9be..1e51ee97 100644
--- a/rsvg_internals/src/filters/offset.rs
+++ b/rsvg_internals/src/filters/offset.rs
@@ -1,7 +1,7 @@
 use std::cell::Cell;
 
 use cairo::{self, ImageSurface};
-use libc::c_char;
+use libc::{self, c_char};
 
 use attributes::Attribute;
 use handle::RsvgHandle;
@@ -9,7 +9,7 @@ use length::{LengthDir, RsvgLength};
 use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
 use parsers::{parse, Parse};
 use property_bag::PropertyBag;
-use util::clamp;
+use util::{clamp, utf8_cstr_opt};
 
 use super::context::{FilterContext, FilterOutput, FilterResult, IRect};
 use super::iterators::{ImageSurfaceDataShared, Pixels};
@@ -124,7 +124,13 @@ impl Filter for Offset {
 pub unsafe extern "C" fn rsvg_new_filter_primitive_offset(
     _element_name: *const c_char,
     parent: *mut RsvgNode,
+    id: *const libc::c_char,
 ) -> *mut RsvgNode {
     let filter = Offset::new();
-    boxed_node_new(NodeType::FilterPrimitiveOffset, parent, Box::new(filter))
+    boxed_node_new(
+        NodeType::FilterPrimitiveOffset,
+        parent,
+        utf8_cstr_opt(id),
+        Box::new(filter),
+    )
 }
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index 835016c5..4d24bffd 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -711,10 +711,12 @@ impl NodeTrait for NodeGradient {
 pub extern "C" fn rsvg_node_linear_gradient_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
     boxed_node_new(
         NodeType::LinearGradient,
         raw_parent,
+        unsafe { utf8_cstr_opt(id) },
         Box::new(NodeGradient::new_linear()),
     )
 }
@@ -723,10 +725,12 @@ pub extern "C" fn rsvg_node_linear_gradient_new(
 pub extern "C" fn rsvg_node_radial_gradient_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
     boxed_node_new(
         NodeType::RadialGradient,
         raw_parent,
+        unsafe { utf8_cstr_opt(id) },
         Box::new(NodeGradient::new_radial()),
     )
 }
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index e0ee8fc7..f993b6e7 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -16,6 +16,7 @@ use length::*;
 use node::*;
 use parsers::parse;
 use property_bag::PropertyBag;
+use util::utf8_cstr_opt;
 
 struct NodeImage {
     aspect: Cell<AspectRatio>,
@@ -153,6 +154,12 @@ impl NodeTrait for NodeImage {
 pub extern "C" fn rsvg_node_image_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Image, raw_parent, Box::new(NodeImage::new()))
+    boxed_node_new(
+        NodeType::Image,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeImage::new()),
+    )
 }
diff --git a/rsvg_internals/src/link.rs b/rsvg_internals/src/link.rs
index 74f3d141..fa9a04e3 100644
--- a/rsvg_internals/src/link.rs
+++ b/rsvg_internals/src/link.rs
@@ -12,6 +12,7 @@ use drawing_ctx::{self, RsvgDrawingCtx};
 use handle::RsvgHandle;
 use node::*;
 use property_bag::PropertyBag;
+use util::utf8_cstr_opt;
 
 struct NodeLink {
     link: RefCell<Option<String>>,
@@ -139,6 +140,12 @@ impl CairoTagging for cairo::Context {
 pub extern "C" fn rsvg_node_link_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Link, raw_parent, Box::new(NodeLink::new()))
+    boxed_node_new(
+        NodeType::Link,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeLink::new()),
+    )
 }
diff --git a/rsvg_internals/src/load.rs b/rsvg_internals/src/load.rs
index c4150ab1..d7eef095 100644
--- a/rsvg_internals/src/load.rs
+++ b/rsvg_internals/src/load.rs
@@ -11,80 +11,108 @@ extern "C" {
     fn rsvg_new_filter_primitive_blend(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_color_matrix(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_component_transfer(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_composite(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_convolve_matrix(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_diffuse_lighting(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_displacement_map(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
+    ) -> *const RsvgNode;
+    fn rsvg_new_node_light_source(
+        _: *const libc::c_char,
+        _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
-    fn rsvg_new_node_light_source(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_flood(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_node_component_transfer_function(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_gaussian_blur(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_image(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_merge(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_erode(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_merge_node(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_offset(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_specular_lighting(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_tile(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
     fn rsvg_new_filter_primitive_turbulence(
         _: *const libc::c_char,
         _: *const RsvgNode,
+        _: *const libc::c_char,
+    ) -> *const RsvgNode;
+    fn rsvg_new_filter(
+        _: *const libc::c_char,
+        _: *const RsvgNode,
+        _: *const libc::c_char,
     ) -> *const RsvgNode;
-    fn rsvg_new_filter(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
 }
 
-type NodeCreateFn = unsafe extern "C" fn(*const libc::c_char, *const RsvgNode) -> *const RsvgNode;
+type NodeCreateFn =
+    unsafe extern "C" fn(*const libc::c_char, *const RsvgNode, id: *const libc::c_char)
+        -> *const RsvgNode;
 
 lazy_static! {
     // Lines in comments are elements that we don't support.
@@ -183,6 +211,7 @@ lazy_static! {
 pub extern "C" fn rsvg_load_new_node(
     _name: *const libc::c_char,
     parent: *const RsvgNode,
+    id: *const libc::c_char,
     supports_class_attribute: *mut glib_sys::gboolean,
 ) -> *const RsvgNode {
     assert!(!_name.is_null());
@@ -200,6 +229,6 @@ pub extern "C" fn rsvg_load_new_node(
 
     unsafe {
         *supports_class_attribute = creator.0.to_glib();
-        creator.1(_name, parent)
+        creator.1(_name, parent, id)
     }
 }
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 175009fe..4b23c19c 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -22,6 +22,7 @@ use parsers::{parse, Parse};
 use path_builder::*;
 use property_bag::PropertyBag;
 use state::{ComputedValues, SpecifiedValue, State};
+use util::utf8_cstr_opt;
 use viewbox::*;
 
 // markerUnits attribute: https://www.w3.org/TR/SVG/painting.html#MarkerElement
@@ -258,8 +259,14 @@ impl NodeTrait for NodeMarker {
 pub extern "C" fn rsvg_node_marker_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Marker, raw_parent, Box::new(NodeMarker::new()))
+    boxed_node_new(
+        NodeType::Marker,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeMarker::new()),
+    )
 }
 
 // Machinery to figure out marker orientations
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index f4fb02d9..996007a1 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -14,6 +14,7 @@ use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgNode};
 use parsers::{parse, Parse};
 use property_bag::PropertyBag;
 use state::Opacity;
+use util::utf8_cstr_opt;
 
 coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
 coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);
@@ -220,6 +221,12 @@ impl NodeTrait for NodeMask {
 pub extern "C" fn rsvg_node_mask_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Mask, raw_parent, Box::new(NodeMask::new()))
+    boxed_node_new(
+        NodeType::Mask,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeMask::new()),
+    )
 }
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 2efaec79..acb1c887 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -161,6 +161,7 @@ pub type NodeResult = Result<(), NodeError>;
 pub struct Node {
     node_type: NodeType,
     parent: Option<Weak<Node>>, // optional; weak ref to parent
+    id: Option<String>,         // id attribute from XML element
     first_child: RefCell<Option<Rc<Node>>>,
     last_child: RefCell<Option<Weak<Node>>>,
     next_sib: RefCell<Option<Rc<Node>>>, // next sibling; strong ref
@@ -240,12 +241,14 @@ impl Node {
     pub fn new(
         node_type: NodeType,
         parent: Option<Weak<Node>>,
+        id: Option<&str>,
         state: *mut RsvgState,
         node_impl: Box<NodeTrait>,
     ) -> Node {
         Node {
             node_type,
             parent,
+            id: id.map(str::to_string),
             first_child: RefCell::new(None),
             last_child: RefCell::new(None),
             next_sib: RefCell::new(None),
@@ -481,11 +484,13 @@ pub fn node_ptr_to_weak(raw_parent: *const RsvgNode) -> Option<Weak<Node>> {
 pub fn boxed_node_new(
     node_type: NodeType,
     raw_parent: *const RsvgNode,
+    id: Option<&str>,
     node_impl: Box<NodeTrait>,
 ) -> *mut RsvgNode {
     box_node(Rc::new(Node::new(
         node_type,
         node_ptr_to_weak(raw_parent),
+        id,
         rsvg_state_new(),
         node_impl,
     )))
@@ -756,6 +761,7 @@ mod tests {
         let node = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -780,6 +786,7 @@ mod tests {
         let node = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -799,6 +806,7 @@ mod tests {
         let node1 = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -808,6 +816,7 @@ mod tests {
         let node2 = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -825,6 +834,7 @@ mod tests {
         let node = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -837,6 +847,7 @@ mod tests {
         let node = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -844,6 +855,7 @@ mod tests {
         let child = Rc::new(Node::new(
             NodeType::Path,
             Some(Rc::downgrade(&node)),
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -859,6 +871,7 @@ mod tests {
         let node = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -866,6 +879,7 @@ mod tests {
         let child = Rc::new(Node::new(
             NodeType::Path,
             Some(Rc::downgrade(&node)),
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -873,6 +887,7 @@ mod tests {
         let second_child = Rc::new(Node::new(
             NodeType::Path,
             Some(Rc::downgrade(&node)),
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -901,6 +916,7 @@ mod tests {
         let node = Rc::new(Node::new(
             NodeType::Path,
             None,
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -908,6 +924,7 @@ mod tests {
         let child = Rc::new(Node::new(
             NodeType::Path,
             Some(Rc::downgrade(&node)),
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
@@ -915,6 +932,7 @@ mod tests {
         let second_child = Rc::new(Node::new(
             NodeType::Path,
             Some(Rc::downgrade(&node)),
+            None,
             ptr::null_mut(),
             Box::new(TestNodeImpl {}),
         ));
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 7a42cece..dd708318 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -20,6 +20,7 @@ use node::*;
 use parsers::parse;
 use property_bag::PropertyBag;
 use state::ComputedValues;
+use util::utf8_cstr_opt;
 use viewbox::*;
 
 coord_units!(PatternUnits, CoordUnits::ObjectBoundingBox);
@@ -460,8 +461,14 @@ fn resolve_fallbacks_and_set_pattern(
 pub extern "C" fn rsvg_node_pattern_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Pattern, raw_parent, Box::new(NodePattern::new()))
+    boxed_node_new(
+        NodeType::Pattern,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodePattern::new()),
+    )
 }
 
 pub fn pattern_resolve_fallbacks_and_set_pattern(
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index 8c1b00d1..2c8ad09f 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -16,6 +16,7 @@ use path_builder::*;
 use path_parser;
 use property_bag::PropertyBag;
 use state::ComputedValues;
+use util::utf8_cstr_opt;
 
 fn render_path_builder(
     builder: &PathBuilder,
@@ -628,18 +629,26 @@ impl NodeTrait for NodeEllipse {
 pub extern "C" fn rsvg_node_path_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Path, raw_parent, Box::new(NodePath::new()))
+    boxed_node_new(
+        NodeType::Path,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodePath::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_polygon_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
     boxed_node_new(
         NodeType::Path,
         raw_parent,
+        unsafe { utf8_cstr_opt(id) },
         Box::new(NodePoly::new(PolyKind::Closed)),
     )
 }
@@ -648,10 +657,12 @@ pub extern "C" fn rsvg_node_polygon_new(
 pub extern "C" fn rsvg_node_polyline_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
     boxed_node_new(
         NodeType::Path,
         raw_parent,
+        unsafe { utf8_cstr_opt(id) },
         Box::new(NodePoly::new(PolyKind::Open)),
     )
 }
@@ -660,30 +671,54 @@ pub extern "C" fn rsvg_node_polyline_new(
 pub extern "C" fn rsvg_node_line_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Line, raw_parent, Box::new(NodeLine::new()))
+    boxed_node_new(
+        NodeType::Line,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeLine::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_rect_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Rect, raw_parent, Box::new(NodeRect::new()))
+    boxed_node_new(
+        NodeType::Rect,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeRect::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_circle_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Circle, raw_parent, Box::new(NodeCircle::new()))
+    boxed_node_new(
+        NodeType::Circle,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeCircle::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_ellipse_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Ellipse, raw_parent, Box::new(NodeEllipse::new()))
+    boxed_node_new(
+        NodeType::Ellipse,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeEllipse::new()),
+    )
 }
diff --git a/rsvg_internals/src/stop.rs b/rsvg_internals/src/stop.rs
index e8267173..b6aa95bb 100644
--- a/rsvg_internals/src/stop.rs
+++ b/rsvg_internals/src/stop.rs
@@ -9,6 +9,7 @@ use length::*;
 use node::*;
 use parsers::parse;
 use property_bag::PropertyBag;
+use util::utf8_cstr_opt;
 
 pub struct NodeStop {
     offset: Cell<f64>,
@@ -74,6 +75,12 @@ impl NodeTrait for NodeStop {
 pub extern "C" fn rsvg_node_stop_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Stop, raw_parent, Box::new(NodeStop::new()))
+    boxed_node_new(
+        NodeType::Stop,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeStop::new()),
+    )
 }
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index d6fd4963..75bc93eb 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -15,6 +15,7 @@ use node::*;
 use parsers::{parse, Parse};
 use property_bag::{OwnedPropertyBag, PropertyBag};
 use state::Overflow;
+use util::utf8_cstr_opt;
 use viewbox::*;
 use viewport::{draw_in_viewport, ClipMode};
 
@@ -417,48 +418,84 @@ impl NodeTrait for NodeSymbol {
 pub extern "C" fn rsvg_node_group_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Group, raw_parent, Box::new(NodeGroup::new()))
+    boxed_node_new(
+        NodeType::Group,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeGroup::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_defs_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Defs, raw_parent, Box::new(NodeDefs::new()))
+    boxed_node_new(
+        NodeType::Defs,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeDefs::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_switch_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Switch, raw_parent, Box::new(NodeSwitch::new()))
+    boxed_node_new(
+        NodeType::Switch,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeSwitch::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_svg_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Svg, raw_parent, Box::new(NodeSvg::new()))
+    boxed_node_new(
+        NodeType::Svg,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeSvg::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_use_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Use, raw_parent, Box::new(NodeUse::new()))
+    boxed_node_new(
+        NodeType::Use,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeUse::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_symbol_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Symbol, raw_parent, Box::new(NodeSymbol::new()))
+    boxed_node_new(
+        NodeType::Symbol,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeSymbol::new()),
+    )
 }
 
 #[no_mangle]
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index 538af8d0..3989a617 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -24,6 +24,7 @@ use state::{
     UnicodeBidi,
     WritingMode,
 };
+use util::utf8_cstr_opt;
 
 /// In SVG text elements, we use `NodeChars` to store character data.  For example,
 /// an element like `<text>Foo Bar</text>` will be a `NodeText` with a single child,
@@ -741,7 +742,12 @@ fn render_child(
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_chars_new(raw_parent: *const RsvgNode) -> *const RsvgNode {
-    boxed_node_new(NodeType::Chars, raw_parent, Box::new(NodeChars::new()))
+    boxed_node_new(
+        NodeType::Chars,
+        raw_parent,
+        None,
+        Box::new(NodeChars::new()),
+    )
 }
 
 #[no_mangle]
@@ -770,22 +776,40 @@ pub extern "C" fn rsvg_node_chars_append(
 pub extern "C" fn rsvg_node_text_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::Text, raw_parent, Box::new(NodeText::new()))
+    boxed_node_new(
+        NodeType::Text,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeText::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_tref_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::TRef, raw_parent, Box::new(NodeTRef::new()))
+    boxed_node_new(
+        NodeType::TRef,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeTRef::new()),
+    )
 }
 
 #[no_mangle]
 pub extern "C" fn rsvg_node_tspan_new(
     _: *const libc::c_char,
     raw_parent: *const RsvgNode,
+    id: *const libc::c_char,
 ) -> *const RsvgNode {
-    boxed_node_new(NodeType::TSpan, raw_parent, Box::new(NodeTSpan::new()))
+    boxed_node_new(
+        NodeType::TSpan,
+        raw_parent,
+        unsafe { utf8_cstr_opt(id) },
+        Box::new(NodeTSpan::new()),
+    )
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]