[librsvg] Consolidate (tree, defs, css_styles) into an Svg type, invisible to C



commit 04e93aef8725c208031bc29cf5be92d06d5ebee9
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Nov 30 18:53:56 2018 -0600

    Consolidate (tree, defs, css_styles) into an Svg type, invisible to C
    
    The tree/defs/css_styles always go together, so we encapsulate them
    into an Svg type.
    
    In addition, we put this in the Rust Handle, not in the C
    RsvgHandlePrivate, so the C code does not ever see the Svg type.
    
    This requires moving a bunch of C-visible functions like
    rsvg_defs_foo() to rsvg_handle_rust_defs_foo().  These will go away in
    the end, as more of the code is ported to Rust.

 Makefile.am                                      |   1 +
 librsvg/rsvg-handle.c                            | 109 +++++-----------
 librsvg/rsvg-load.c                              |  31 ++---
 librsvg/rsvg-load.h                              |   7 +-
 librsvg/rsvg-private.h                           |  73 +----------
 rsvg_internals/src/clip_path.rs                  |   2 +-
 rsvg_internals/src/css.rs                        |  14 --
 rsvg_internals/src/defs.rs                       |  81 ++----------
 rsvg_internals/src/drawing_ctx.rs                |  37 +++---
 rsvg_internals/src/filters/blend.rs              |   2 +-
 rsvg_internals/src/filters/bounds.rs             |   6 +-
 rsvg_internals/src/filters/color_matrix.rs       |   2 +-
 rsvg_internals/src/filters/component_transfer.rs |   2 +-
 rsvg_internals/src/filters/composite.rs          |   2 +-
 rsvg_internals/src/filters/context.rs            |  18 +--
 rsvg_internals/src/filters/convolve_matrix.rs    |   2 +-
 rsvg_internals/src/filters/displacement_map.rs   |   2 +-
 rsvg_internals/src/filters/flood.rs              |   2 +-
 rsvg_internals/src/filters/gaussian_blur.rs      |   2 +-
 rsvg_internals/src/filters/image.rs              |   6 +-
 rsvg_internals/src/filters/light/lighting.rs     |   2 +-
 rsvg_internals/src/filters/merge.rs              |   4 +-
 rsvg_internals/src/filters/mod.rs                |   6 +-
 rsvg_internals/src/filters/morphology.rs         |   2 +-
 rsvg_internals/src/filters/offset.rs             |   2 +-
 rsvg_internals/src/filters/tile.rs               |   2 +-
 rsvg_internals/src/filters/turbulence.rs         |   2 +-
 rsvg_internals/src/gradient.rs                   |   6 +-
 rsvg_internals/src/handle.rs                     | 159 ++++++++++++++++++++---
 rsvg_internals/src/image.rs                      |   2 +-
 rsvg_internals/src/lib.rs                        |  17 +--
 rsvg_internals/src/link.rs                       |   2 +-
 rsvg_internals/src/marker.rs                     |   6 +-
 rsvg_internals/src/mask.rs                       |   2 +-
 rsvg_internals/src/node.rs                       |   6 +-
 rsvg_internals/src/paint_server.rs               |  15 +--
 rsvg_internals/src/pattern.rs                    |   4 +-
 rsvg_internals/src/shapes.rs                     |  16 +--
 rsvg_internals/src/structure.rs                  |   8 +-
 rsvg_internals/src/svg.rs                        |  30 +++++
 rsvg_internals/src/text.rs                       |  28 ++--
 rsvg_internals/src/tree.rs                       |  59 +--------
 rsvg_internals/src/viewport.rs                   |   4 +-
 rsvg_internals/src/xml.rs                        |  72 +++++-----
 44 files changed, 373 insertions(+), 484 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ec8a4dd5..cb67d101 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -111,6 +111,7 @@ RUST_SRC =                                                  \
        rsvg_internals/src/stop.rs                              \
        rsvg_internals/src/structure.rs                         \
        rsvg_internals/src/style.rs                             \
+       rsvg_internals/src/svg.rs                               \
        rsvg_internals/src/text.rs                              \
        rsvg_internals/src/transform.rs                         \
        rsvg_internals/src/tree.rs                              \
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 17ab2934..f9bf7e66 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -127,6 +127,16 @@
 #include "rsvg-load.h"
 #include "rsvg-private.h"
 
+/* Implemented in rsvg_internals/src/handle.rs */
+extern RsvgHandleRust *rsvg_handle_rust_new (void);
+extern void rsvg_handle_rust_free (RsvgHandleRust *raw_handle);
+extern void rsvg_handle_rust_cascade (RsvgHandleRust *raw_handle);
+extern void rsvg_handle_rust_set_base_url (RsvgHandleRust *raw_handle, const char *uri);
+extern RsvgNode *rsvg_handle_rust_get_root (RsvgHandleRust *raw_handle);
+extern GFile *rsvg_handle_rust_get_base_gfile (RsvgHandleRust *raw_handle);
+extern RsvgNode *rsvg_handle_defs_lookup (RsvgHandle *handle, const char *name);
+extern gboolean rsvg_handle_rust_node_is_root(RsvgHandleRust *raw_handle, RsvgNode *node);
+
 enum {
     PROP_0,
     PROP_FLAGS,
@@ -158,10 +168,6 @@ rsvg_handle_init (RsvgHandle * self)
     self->priv->dpi_x = rsvg_internal_dpi_x;
     self->priv->dpi_y = rsvg_internal_dpi_y;
 
-    self->priv->tree = NULL;
-    self->priv->defs = NULL;
-    self->priv->css_styles = NULL;
-
     self->priv->cancellable = NULL;
 
     self->priv->in_loop = FALSE;
@@ -187,9 +193,7 @@ rsvg_handle_dispose (GObject *instance)
     }
 
     g_clear_pointer (&self->priv->load, rsvg_load_free);
-    g_clear_pointer (&self->priv->defs, rsvg_defs_free);
-    g_clear_pointer (&self->priv->css_styles, rsvg_css_styles_free);
-    g_clear_pointer (&self->priv->tree, rsvg_tree_free);
+
     g_clear_pointer (&self->priv->base_uri, g_free);
 
 #ifdef HAVE_PANGOFT2
@@ -659,55 +663,24 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
     return rsvg_load_write (priv->load, buf, count, error);
 }
 
-static gboolean
-tree_is_valid (RsvgTree *tree, GError **error)
-{
-    if (!tree) {
-        g_set_error (error, RSVG_ERROR, RSVG_ERROR_FAILED, _("SVG has no elements"));
-        return FALSE;
-    }
-
-    if (!rsvg_tree_root_is_svg (tree)) {
-        g_set_error (error, RSVG_ERROR, RSVG_ERROR_FAILED, _("root element is not <svg>"));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
 static gboolean
 finish_load (RsvgHandle *handle, gboolean was_successful, GError **error)
 {
-    RsvgTree *tree = NULL;
-    RsvgDefs *defs = NULL;
-    RsvgCssStyles *css_styles = NULL;
-
     g_assert (handle->priv->load != NULL);
-    g_assert (handle->priv->tree == NULL);
 
     if (was_successful) {
         g_assert (error == NULL || *error == NULL);
 
-        rsvg_load_steal_result (handle->priv->load, &tree, &defs, &css_styles);
-        was_successful = tree_is_valid (tree, error);
-        if (!was_successful) {
-            g_clear_pointer (&tree, rsvg_tree_free);
-            g_clear_pointer (&defs, rsvg_defs_free);
-            g_clear_pointer (&css_styles, rsvg_css_styles_free);
-        }
+        was_successful = rsvg_load_finish_load(handle->priv->load, error);
     }
 
     if (was_successful) {
-        g_assert (tree != NULL);
         handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_OK;
     } else {
         handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_ERROR;
     }
 
     g_clear_pointer (&handle->priv->load, rsvg_load_free);
-    handle->priv->tree = tree;
-    handle->priv->defs = defs;
-    handle->priv->css_styles = css_styles;
 
     return was_successful;
 }
@@ -885,7 +858,7 @@ rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri)
     gchar *uri;
     GFile *file;
 
-    g_return_if_fail (handle != NULL);
+    g_return_if_fail (RSVG_IS_HANDLE (handle));
 
     if (base_uri == NULL)
         return;
@@ -1017,30 +990,12 @@ rsvg_handle_get_flags (RsvgHandle *handle)
     return (guint) handle->priv->flags;
 }
 
-RsvgDefs *
-rsvg_handle_get_defs (RsvgHandle *handle)
-{
-    return handle->priv->defs;
-}
-
-RsvgTree *
-rsvg_handle_get_tree (RsvgHandle *handle)
-{
-    return handle->priv->tree;
-}
-
 RsvgHandleRust *
 rsvg_handle_get_rust (RsvgHandle *handle)
 {
     return handle->priv->rust_handle;
 }
 
-RsvgCssStyles *
-rsvg_handle_get_css_styles (RsvgHandle *handle)
-{
-    return handle->priv->css_styles;
-}
-
 gboolean
 rsvg_handle_keep_image_data (RsvgHandle *handle)
 {
@@ -1085,7 +1040,7 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
     cairo_status_t status;
     gboolean res;
 
-    g_return_val_if_fail (handle != NULL, FALSE);
+    g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
 
     if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
         return FALSE;
@@ -1100,7 +1055,7 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
     }
 
     if (id && *id)
-        drawsub = rsvg_defs_lookup (handle->priv->defs, handle, id);
+        drawsub = rsvg_handle_defs_lookup (handle, id);
 
     if (drawsub == NULL && id != NULL) {
         g_warning ("element id=\"%s\" does not exist", id);
@@ -1120,8 +1075,8 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
         rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, drawsub);
     }
 
-    rsvg_tree_cascade (handle->priv->tree);
-    res = rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->tree);
+    rsvg_handle_rust_cascade (handle->priv->rust_handle);
+    res = rsvg_drawing_ctx_draw_node_from_stack (draw);
 
     rsvg_drawing_ctx_free (draw);
 
@@ -1199,9 +1154,9 @@ get_node_geometry(RsvgHandle *handle, RsvgNode *node, RsvgRectangle *ink_rect, R
     draw = rsvg_handle_create_drawing_ctx (handle, cr, &dimensions);
     rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, node);
 
-    rsvg_tree_cascade (handle->priv->tree);
+    rsvg_handle_rust_cascade (handle->priv->rust_handle);
     /* FIXME: expose this as a RenderingError in the public API */
-    res = rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->tree);
+    res = rsvg_drawing_ctx_draw_node_from_stack (draw);
     if (res) {
         rsvg_drawing_ctx_get_geometry (draw, ink_rect, logical_rect);
     }
@@ -1272,7 +1227,7 @@ gboolean
 rsvg_handle_get_geometry_sub (RsvgHandle * handle, RsvgRectangle * ink_rect, RsvgRectangle * logical_rect, 
const char *id)
 {
     RsvgNode *root = NULL;
-    RsvgNode *node;
+    RsvgNode *node = NULL;
     gboolean has_size;
     int root_width, root_height;
     gboolean res = FALSE;
@@ -1283,18 +1238,15 @@ rsvg_handle_get_geometry_sub (RsvgHandle * handle, RsvgRectangle * ink_rect, Rsv
     memset (&ink_r, 0, sizeof (RsvgRectangle));
     memset (&logical_r, 0, sizeof (RsvgRectangle));
 
-    if (handle->priv->tree == NULL)
-        return FALSE;
+    g_return_val_if_fail (handle->priv->hstate == RSVG_HANDLE_STATE_CLOSED_OK, FALSE);
 
-    root = rsvg_tree_get_root (handle->priv->tree);
+    root = rsvg_handle_rust_get_root (handle->priv->rust_handle);
 
     if (id && *id) {
-        node = rsvg_defs_lookup (handle->priv->defs, handle, id);
+        node = rsvg_handle_defs_lookup (handle, id);
 
-        if (node && rsvg_tree_is_root (handle->priv->tree, node))
+        if (node && rsvg_handle_rust_node_is_root (handle->priv->rust_handle, node))
             id = NULL;
-    } else {
-        node = root;
     }
 
     if (!node && id) {
@@ -1306,7 +1258,7 @@ rsvg_handle_get_geometry_sub (RsvgHandle * handle, RsvgRectangle * ink_rect, Rsv
                                        &root_width, &root_height);
 
     if (id || !has_size) {
-        res = get_node_geometry (handle, node, &ink_r, &logical_r);
+        res = get_node_geometry (handle, node ? node : root, &ink_r, &logical_r);
         if (!res) {
             goto out;
         }
@@ -1334,6 +1286,7 @@ out:
         *logical_rect = logical_r;
     }
 
+    g_clear_pointer (&node, rsvg_node_unref);
     g_clear_pointer (&root, rsvg_node_unref);
 
     return res;
@@ -1398,12 +1351,12 @@ gboolean
 rsvg_handle_has_sub (RsvgHandle * handle,
                      const char *id)
 {
-    g_return_val_if_fail (handle, FALSE);
+    g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
 
     if (G_UNLIKELY (!id || !id[0]))
       return FALSE;
 
-    return rsvg_defs_lookup (handle->priv->defs, handle, id) != NULL;
+    return rsvg_handle_defs_lookup (handle, id) != NULL;
 }
 
 /**
@@ -1436,7 +1389,7 @@ rsvg_handle_get_pixbuf_sub (RsvgHandle * handle, const char *id)
     cairo_surface_t *surface;
     cairo_t *cr;
 
-    g_return_val_if_fail (handle != NULL, NULL);
+    g_return_val_if_fail (RSVG_IS_HANDLE (handle), NULL);
 
     if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
         return NULL;
@@ -1518,7 +1471,7 @@ rsvg_handle_set_dpi (RsvgHandle * handle, double dpi)
 void
 rsvg_handle_set_dpi_x_y (RsvgHandle * handle, double dpi_x, double dpi_y)
 {
-    g_return_if_fail (handle != NULL);
+    g_return_if_fail (RSVG_IS_HANDLE (handle));
 
     if (dpi_x <= 0.)
         handle->priv->dpi_x = rsvg_internal_dpi_x;
@@ -1576,7 +1529,7 @@ rsvg_handle_set_size_callback (RsvgHandle * handle,
                                RsvgSizeFunc size_func,
                                gpointer user_data, GDestroyNotify user_data_destroy)
 {
-    g_return_if_fail (handle != NULL);
+    g_return_if_fail (RSVG_IS_HANDLE (handle));
 
     if (handle->priv->user_data_destroy)
         (*handle->priv->user_data_destroy) (handle->priv->user_data);
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index a4944a16..7caaecb9 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -38,24 +38,13 @@ typedef enum {
     LOAD_STATE_CLOSED
 } LoadState;
 
-/* Implemented in rsvg_internals/src/load.rs */
-G_GNUC_INTERNAL
-void rsvg_load_set_svg_node_atts (RsvgHandle *handle, RsvgNode *node);
-
-/* Implemented in rsvg_internals/src/node.rs */
-G_GNUC_INTERNAL
-void rsvg_node_register_in_defs(RsvgNode *node, RsvgDefs *defs);
-
 /* Implemented in rsvg_internals/src/xml.rs */
 typedef struct RsvgXmlState RsvgXmlState;
 
 /* Implemented in rsvg_internals/src/xml.rs */
 extern RsvgXmlState *rsvg_xml_state_new ();
 extern void rsvg_xml_state_free (RsvgXmlState *xml);
-extern void rsvg_xml_state_steal_result(RsvgXmlState *xml,
-                                        RsvgTree **out_tree,
-                                        RsvgDefs **out_defs,
-                                        RsvgCssStyles **out_css_styles);
+extern gboolean rsvg_xml_state_tree_is_valid(RsvgXmlState *xml, GError **error);
 extern void rsvg_xml_state_start_element(RsvgXmlState *xml, RsvgHandle *handle, const char *name, 
RsvgPropertyBag atts);
 extern void rsvg_xml_state_end_element(RsvgXmlState *xml, RsvgHandle *handle, const char *name);
 extern void rsvg_xml_state_characters(RsvgXmlState *xml, const char *unterminated_text, gsize len);
@@ -72,6 +61,9 @@ extern void rsvg_xml_state_load_css_from_href(RsvgXmlState *xml,
                                               RsvgHandle *handle,
                                               const char *href);
 
+/* Implemented in rsvg_internals/src/handle.rs */
+extern void rsvg_handle_rust_steal_result (RsvgHandleRust *raw_handle, RsvgXmlState *xml);
+
 
 /* Holds the XML parsing state */
 typedef struct {
@@ -149,13 +141,16 @@ rsvg_load_free (RsvgLoad *load)
     g_free (load);
 }
 
-void
-rsvg_load_steal_result (RsvgLoad *load,
-                        RsvgTree **out_tree,
-                        RsvgDefs **out_defs,
-                        RsvgCssStyles **out_css_styles)
+gboolean
+rsvg_load_finish_load (RsvgLoad *load, GError **error)
 {
-    rsvg_xml_state_steal_result (load->xml.rust_state, out_tree, out_defs, out_css_styles);
+    gboolean was_successful = rsvg_xml_state_tree_is_valid(load->xml.rust_state, error);
+
+    if (was_successful) {
+        rsvg_handle_rust_steal_result (load->handle->priv->rust_handle, load->xml.rust_state);
+    }
+
+    return was_successful;
 }
 
 static void
diff --git a/librsvg/rsvg-load.h b/librsvg/rsvg-load.h
index 4b803cfb..99e9fed7 100644
--- a/librsvg/rsvg-load.h
+++ b/librsvg/rsvg-load.h
@@ -32,13 +32,10 @@ G_GNUC_INTERNAL
 void rsvg_load_free (RsvgLoad *load);
 
 G_GNUC_INTERNAL
-gboolean rsvg_load_handle_xml_xinclude (RsvgHandle *handle, const char *url);
+gboolean rsvg_load_finish_load(RsvgLoad *load, GError **error);
 
 G_GNUC_INTERNAL
-void rsvg_load_steal_result (RsvgLoad *load,
-                             RsvgTree **out_tree,
-                             RsvgDefs **out_defs,
-                             RsvgCssStyles **out_css_styles);
+gboolean rsvg_load_handle_xml_xinclude (RsvgHandle *handle, const char *url);
 
 G_GNUC_INTERNAL
 gboolean rsvg_load_write (RsvgLoad *load, const guchar *buf, gsize count, GError **error) 
G_GNUC_WARN_UNUSED_RESULT;
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index f934b06b..49343060 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -58,7 +58,6 @@ typedef struct RsvgDrawingCtx RsvgDrawingCtx;
 typedef struct RsvgState RsvgState;
 
 typedef void   *RsvgPropertyBag;
-typedef struct _RsvgDefs RsvgDefs;
 typedef struct _RsvgNode RsvgNode;
 typedef struct _RsvgFilter RsvgFilter;
 
@@ -81,10 +80,6 @@ typedef enum {
 
 typedef struct RsvgLoad RsvgLoad;
 
-typedef struct RsvgTree RsvgTree;
-
-typedef struct RsvgCssStyles RsvgCssStyles;
-
 /* Defined in rsvg_internals/src/handle.rs */
 typedef struct RsvgHandleRust RsvgHandleRust;
 
@@ -99,10 +94,6 @@ struct RsvgHandlePrivate {
     gpointer user_data;
     GDestroyNotify user_data_destroy;
 
-    RsvgTree *tree;
-    RsvgDefs *defs; /* lookup table for nodes that have an id="foo" attribute */
-    RsvgCssStyles *css_styles;
-
     GCancellable *cancellable;
 
     double dpi_x;
@@ -133,34 +124,6 @@ void rsvg_node_set_overridden_properties (RsvgNode *node);
 
 typedef struct RsvgNodeChildrenIter *RsvgNodeChildrenIter;
 
-/* Implemented in rsvg_internals/src/tree.rs */
-G_GNUC_INTERNAL
-void rsvg_tree_free (RsvgTree *tree);
-
-/* Implemented in rsvg_internals/src/tree.rs */
-G_GNUC_INTERNAL
-RsvgNode *rsvg_tree_get_root (RsvgTree *tree);
-
-/* Implemented in rsvg_internals/src/tree.rs */
-G_GNUC_INTERNAL
-gboolean rsvg_tree_is_root (RsvgTree *tree, RsvgNode *node);
-
-/* Implemented in rsvg_internals/src/tree.rs */
-G_GNUC_INTERNAL
-gboolean rsvg_tree_root_is_svg (RsvgTree *tree);
-
-/* Implemented in rsvg_internals/src/tree.rs */
-G_GNUC_INTERNAL
-void rsvg_tree_cascade (RsvgTree *tree);
-
-/* Implemented in rsvg_internals/src/css.rs */
-G_GNUC_INTERNAL
-RsvgCssStyles *rsvg_css_styles_new (void);
-
-/* Implemented in rsvg_internals/src/css.rs */
-G_GNUC_INTERNAL
-void rsvg_css_styles_free (RsvgCssStyles *styles);
-
 /* Implemented in rsvg_internals/src/structure.rs */
 G_GNUC_INTERNAL
 gboolean rsvg_node_svg_get_size (RsvgNode *node, double dpi_x, double dpi_y, int *out_width, int 
*out_height);
@@ -218,7 +181,7 @@ void rsvg_drawing_ctx_add_node_and_ancestors_to_stack (RsvgDrawingCtx *draw_ctx,
 
 /* Defined in rsvg_internals/src/drawing_ctx.rs */
 G_GNUC_INTERNAL
-gboolean rsvg_drawing_ctx_draw_node_from_stack (RsvgDrawingCtx *ctx, RsvgTree *tree) 
G_GNUC_WARN_UNUSED_RESULT;;
+gboolean rsvg_drawing_ctx_draw_node_from_stack (RsvgDrawingCtx *ctx) G_GNUC_WARN_UNUSED_RESULT;;
 
 /* Defined in rsvg_internals/src/drawing_ctx.rs */
 G_GNUC_INTERNAL
@@ -235,46 +198,12 @@ void rsvg_return_if_fail_warning (const char *pretty_function,
 G_GNUC_INTERNAL
 RsvgNode *rsvg_load_destroy (RsvgLoad *load) G_GNUC_WARN_UNUSED_RESULT;
 
-/* Defined in rsvg_internals/src/defs.rs */
-G_GNUC_INTERNAL
-void rsvg_defs_free (RsvgDefs *defs);
-
-/* Defined in rsvg_internals/src/defs.rs */
-G_GNUC_INTERNAL
-RsvgNode *rsvg_defs_lookup (const RsvgDefs * defs, RsvgHandle *handle, const char *name);
-
 G_GNUC_INTERNAL
 guint rsvg_handle_get_flags (RsvgHandle *handle);
 
-G_GNUC_INTERNAL
-RsvgDefs *rsvg_handle_get_defs (RsvgHandle *handle);
-
-G_GNUC_INTERNAL
-RsvgTree *rsvg_handle_get_tree (RsvgHandle *handle);
-
 G_GNUC_INTERNAL
 RsvgHandleRust *rsvg_handle_get_rust (RsvgHandle *handle);
 
-G_GNUC_INTERNAL
-RsvgCssStyles *rsvg_handle_get_css_styles (RsvgHandle *handle);
-
-/* Implemented in rsvg_internals/src/handle.rs */
-G_GNUC_INTERNAL
-RsvgHandleRust *rsvg_handle_rust_new (void);
-
-/* Implemented in rsvg_internals/src/handle.rs */
-G_GNUC_INTERNAL
-void rsvg_handle_rust_free (RsvgHandleRust *raw_handle);
-
-/* Implemented in rsvg_internals/src/handle.rs */
-G_GNUC_INTERNAL
-void rsvg_handle_rust_set_base_url (RsvgHandleRust *raw_handle,
-                                    const char *uri);
-
-/* Implemented in rsvg_internals/src/handle.rs */
-G_GNUC_INTERNAL
-GFile *rsvg_handle_rust_get_base_gfile (RsvgHandleRust *raw_handle);
-
 G_GNUC_INTERNAL
 gboolean rsvg_handle_keep_image_data (RsvgHandle *handle);
 
diff --git a/rsvg_internals/src/clip_path.rs b/rsvg_internals/src/clip_path.rs
index 3a8f2347..d674e10f 100644
--- a/rsvg_internals/src/clip_path.rs
+++ b/rsvg_internals/src/clip_path.rs
@@ -32,7 +32,7 @@ impl NodeClipPath {
         &self,
         node: &RsvgNode,
         affine_before_clip: &cairo::Matrix,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<(), RenderingError> {
         let cascaded = node.get_cascaded_values();
 
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index efedb35e..9c6d0163 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -14,8 +14,6 @@ use handle::{self, RsvgHandle};
 use state::State;
 use util::utf8_cstr;
 
-pub enum RsvgCssStyles {}
-
 struct Declaration {
     prop_value: String,
     important: bool,
@@ -224,15 +222,3 @@ unsafe extern "C" fn css_error(_a_this: *mut CRDocHandler) {
 unsafe extern "C" fn css_unrecoverable_error(_a_this: *mut CRDocHandler) {
     println!("CSS unrecoverable error");
 }
-
-#[no_mangle]
-pub extern "C" fn rsvg_css_styles_new() -> *mut RsvgCssStyles {
-    Box::into_raw(Box::new(CssStyles::new())) as *mut RsvgCssStyles
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_css_styles_free(raw_styles: *mut RsvgCssStyles) {
-    assert!(!raw_styles.is_null());
-
-    Box::from_raw(raw_styles as *mut CssStyles);
-}
diff --git a/rsvg_internals/src/defs.rs b/rsvg_internals/src/defs.rs
index 6f50cd63..373e8e22 100644
--- a/rsvg_internals/src/defs.rs
+++ b/rsvg_internals/src/defs.rs
@@ -1,19 +1,13 @@
-use libc;
 use std::collections::hash_map::Entry;
 use std::collections::HashMap;
 use std::fmt;
-use std::ptr;
 use std::rc::Rc;
 
 use allowed_url::AllowedUrl;
 use error::ValueErrorKind;
 use handle::{self, RsvgHandle};
-use node::{Node, RsvgNode};
+use node::Node;
 use parsers::ParseError;
-use util::rsvg_g_warning;
-use util::utf8_cstr;
-
-pub enum RsvgDefs {}
 
 pub struct Defs {
     nodes: HashMap<String, Rc<Node>>,
@@ -32,6 +26,10 @@ impl Defs {
         self.nodes.entry(id.to_string()).or_insert(node.clone());
     }
 
+    pub fn lookup_fragment_id(&self, id: &str) -> Option<Rc<Node>> {
+        self.nodes.get(id).map(|n| (*n).clone())
+    }
+
     /// Returns a node referenced by a fragment ID
     ///
     /// If the `Fragment`'s URL is `None`, then the fragment ID refers
@@ -39,16 +37,14 @@ impl Defs {
     /// an externally-loaded SVG file that is referenced by the
     /// current one.  If the element's id is not found, returns
     /// `None`.
-    pub fn lookup(&mut self, handle: *const RsvgHandle, fragment: &Fragment) -> Option<&Rc<Node>> {
+    pub fn lookup(&mut self, handle: *const RsvgHandle, fragment: &Fragment) -> Option<Rc<Node>> {
         if let Some(ref href) = fragment.uri() {
             match self.get_extern_handle(handle, href) {
-                Ok(extern_handle) => handle::get_defs(extern_handle)
-                    .nodes
-                    .get(fragment.fragment()),
+                Ok(extern_handle) => handle::lookup_fragment_id(extern_handle, fragment),
                 Err(()) => None,
             }
         } else {
-            self.nodes.get(fragment.fragment())
+            self.lookup_fragment_id(fragment.fragment())
         }
     }
 
@@ -204,67 +200,6 @@ impl Href {
     }
 }
 
-#[no_mangle]
-pub extern "C" fn rsvg_defs_free(defs: *mut RsvgDefs) {
-    assert!(!defs.is_null());
-
-    unsafe {
-        let defs = { &mut *(defs as *mut Defs) };
-        Box::from_raw(defs);
-    }
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_defs_lookup(
-    defs: *mut RsvgDefs,
-    handle: *const RsvgHandle,
-    name: *const libc::c_char,
-) -> *const RsvgNode {
-    assert!(!defs.is_null());
-    assert!(!name.is_null());
-
-    let defs = unsafe { &mut *(defs as *mut Defs) };
-    let name = unsafe { utf8_cstr(name) };
-
-    let r = Href::with_fragment(name);
-    if r.is_err() {
-        return ptr::null();
-    }
-
-    match r.unwrap() {
-        Href::WithFragment(fragment) => {
-            if let Some(uri) = fragment.uri() {
-                // The public APIs to get geometries of individual elements, or to render
-                // them, should only allow referencing elements within the main handle's
-                // SVG file; that is, only plain "#foo" fragment IDs are allowed here.
-                // Otherwise, a calling program could request "another-file#foo" and cause
-                // another-file to be loaded, even if it is not part of the set of
-                // resources that the main SVG actually references.  In the future we may
-                // relax this requirement to allow lookups within that set, but not to
-                // other random files.
-
-                let msg = format!(
-                    "the public API is not allowed to look up external references: {}#{}",
-                    uri,
-                    fragment.fragment()
-                );
-
-                rsvg_log!("{}", msg);
-
-                rsvg_g_warning(&msg);
-                return ptr::null();
-            }
-
-            match defs.lookup(handle, &fragment) {
-                Some(n) => n as *const RsvgNode,
-                None => ptr::null(),
-            }
-        }
-
-        _ => unreachable!(),
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index f7594249..56af9951 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -13,7 +13,7 @@ use std::rc::{Rc, Weak};
 use bbox::BoundingBox;
 use clip_path::{ClipPathUnits, NodeClipPath};
 use coord_units::CoordUnits;
-use defs::{Defs, Fragment};
+use defs::Fragment;
 use error::RenderingError;
 use filters;
 use float_eq_cairo::ApproxEqCairo;
@@ -35,7 +35,6 @@ use state::{
     StrokeLinejoin,
     TextRendering,
 };
-use tree::{RsvgTree, Tree};
 use unitinterval::UnitInterval;
 use viewbox::ViewBox;
 
@@ -98,7 +97,7 @@ impl Drop for ViewParams {
 
 pub enum RsvgDrawingCtx {}
 
-pub struct DrawingCtx<'a> {
+pub struct DrawingCtx {
     handle: *const RsvgHandle,
 
     rect: cairo::Rectangle,
@@ -130,13 +129,12 @@ pub struct DrawingCtx<'a> {
 
     drawsub_stack: Vec<RsvgNode>,
 
-    defs: RefCell<&'a mut Defs>,
     acquired_nodes: Rc<RefCell<Vec<RsvgNode>>>,
 
     is_testing: bool,
 }
 
-impl<'a> DrawingCtx<'a> {
+impl DrawingCtx {
     pub fn new(
         handle: *const RsvgHandle,
         cr: cairo::Context,
@@ -147,7 +145,7 @@ impl<'a> DrawingCtx<'a> {
         dpi_x: f64,
         dpi_y: f64,
         is_testing: bool,
-    ) -> DrawingCtx<'a> {
+    ) -> DrawingCtx {
         let mut affine = cr.get_matrix();
         let rect = cairo::Rectangle {
             x: 0.0,
@@ -186,7 +184,6 @@ impl<'a> DrawingCtx<'a> {
             bbox: BoundingBox::new(&affine),
             bbox_stack: Vec::new(),
             drawsub_stack: Vec::new(),
-            defs: RefCell::new(handle::get_defs(handle)),
             acquired_nodes: Rc::new(RefCell::new(Vec::new())),
             is_testing,
         }
@@ -291,8 +288,8 @@ impl<'a> DrawingCtx<'a> {
     // acquire it again.  If you acquire a node "#foo" and don't release it before
     // trying to acquire "foo" again, you will obtain a %NULL the second time.
     pub fn get_acquired_node(&mut self, fragment: &Fragment) -> Option<AcquiredNode> {
-        if let Some(node) = self.defs.borrow_mut().lookup(self.handle, fragment) {
-            if !self.acquired_nodes_contains(node) {
+        if let Some(node) = handle::lookup_node(self.handle, fragment) {
+            if !self.acquired_nodes_contains(&node) {
                 self.acquired_nodes.borrow_mut().push(node.clone());
                 let acq = AcquiredNode(self.acquired_nodes.clone(), node.clone());
                 return Some(acq);
@@ -345,7 +342,7 @@ impl<'a> DrawingCtx<'a> {
         node: &RsvgNode,
         values: &ComputedValues,
         clipping: bool,
-        draw_fn: &mut FnMut(&mut DrawingCtx<'_>) -> Result<(), RenderingError>,
+        draw_fn: &mut FnMut(&mut DrawingCtx) -> Result<(), RenderingError>,
     ) -> Result<(), RenderingError> {
         if clipping {
             draw_fn(self)
@@ -1058,19 +1055,21 @@ impl From<TextRendering> for cairo::Antialias {
 #[no_mangle]
 pub extern "C" fn rsvg_drawing_ctx_draw_node_from_stack(
     raw_draw_ctx: *mut RsvgDrawingCtx,
-    raw_tree: *const RsvgTree,
 ) -> glib_sys::gboolean {
     assert!(!raw_draw_ctx.is_null());
-    let draw_ctx = unsafe { &mut *(raw_draw_ctx as *mut DrawingCtx<'_>) };
-
-    assert!(!raw_tree.is_null());
-    let tree = unsafe { &*(raw_tree as *const Tree) };
+    let draw_ctx = unsafe { &mut *(raw_draw_ctx as *mut DrawingCtx) };
 
     // FIXME: The public API doesn't let us return a GError from the rendering
     // functions, just a boolean.  Add a proper API to return proper errors from
     // the rendering path.
+
+    let svg_ref = handle::get_svg(draw_ctx.handle);
+    let svg = svg_ref.as_ref().unwrap();
+
+    let root = svg.tree.root();
+
     if draw_ctx
-        .draw_node_from_stack(&tree.root.get_cascaded_values(), &tree.root, false)
+        .draw_node_from_stack(&root.get_cascaded_values(), &root, false)
         .is_ok()
     {
         true.to_glib()
@@ -1085,7 +1084,7 @@ pub extern "C" fn rsvg_drawing_ctx_add_node_and_ancestors_to_stack(
     raw_node: *const RsvgNode,
 ) {
     assert!(!raw_draw_ctx.is_null());
-    let draw_ctx = unsafe { &mut *(raw_draw_ctx as *mut DrawingCtx<'_>) };
+    let draw_ctx = unsafe { &mut *(raw_draw_ctx as *mut DrawingCtx) };
 
     assert!(!raw_node.is_null());
     let node = unsafe { &*raw_node };
@@ -1109,7 +1108,7 @@ pub unsafe extern "C" fn rsvg_drawing_ctx_get_geometry(
     logical_rect: *mut RsvgRectangle,
 ) {
     assert!(!raw_draw_ctx.is_null());
-    let draw_ctx = &mut *(raw_draw_ctx as *mut DrawingCtx<'_>);
+    let draw_ctx = &mut *(raw_draw_ctx as *mut DrawingCtx);
 
     assert!(!ink_rect.is_null());
     assert!(!logical_rect.is_null());
@@ -1213,7 +1212,7 @@ pub extern "C" fn rsvg_drawing_ctx_new(
 #[no_mangle]
 pub extern "C" fn rsvg_drawing_ctx_free(raw_draw_ctx: *mut RsvgDrawingCtx) {
     assert!(!raw_draw_ctx.is_null());
-    let draw_ctx = unsafe { &mut *(raw_draw_ctx as *mut DrawingCtx<'_>) };
+    let draw_ctx = unsafe { &mut *(raw_draw_ctx as *mut DrawingCtx) };
 
     unsafe {
         Box::from_raw(draw_ctx);
diff --git a/rsvg_internals/src/filters/blend.rs b/rsvg_internals/src/filters/blend.rs
index cd237df2..27accc41 100644
--- a/rsvg_internals/src/filters/blend.rs
+++ b/rsvg_internals/src/filters/blend.rs
@@ -72,7 +72,7 @@ impl Filter for Blend {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let input_2 = ctx.get_input(draw_ctx, self.in2.borrow().as_ref())?;
diff --git a/rsvg_internals/src/filters/bounds.rs b/rsvg_internals/src/filters/bounds.rs
index cb8e90a4..d858cab3 100644
--- a/rsvg_internals/src/filters/bounds.rs
+++ b/rsvg_internals/src/filters/bounds.rs
@@ -83,7 +83,7 @@ impl<'a> BoundsBuilder<'a> {
 
     /// Returns the final pixel bounds.
     #[inline]
-    pub fn into_irect(self, draw_ctx: &mut DrawingCtx<'_>) -> IRect {
+    pub fn into_irect(self, draw_ctx: &mut DrawingCtx) -> IRect {
         let mut bbox = self.apply_properties(draw_ctx);
 
         let effects_region = self.ctx.effects_region();
@@ -96,12 +96,12 @@ impl<'a> BoundsBuilder<'a> {
     ///
     /// Used by feImage.
     #[inline]
-    pub fn into_irect_without_clipping(self, draw_ctx: &mut DrawingCtx<'_>) -> IRect {
+    pub fn into_irect_without_clipping(self, draw_ctx: &mut DrawingCtx) -> IRect {
         self.apply_properties(draw_ctx).rect.unwrap().into()
     }
 
     /// Applies the filter primitive properties.
-    fn apply_properties(mut self, draw_ctx: &mut DrawingCtx<'_>) -> BoundingBox {
+    fn apply_properties(mut self, draw_ctx: &mut DrawingCtx) -> BoundingBox {
         if self.bbox.rect.is_none() || self.standard_input_was_referenced {
             // The default value is the filter effects region.
             let effects_region = self.ctx.effects_region();
diff --git a/rsvg_internals/src/filters/color_matrix.rs b/rsvg_internals/src/filters/color_matrix.rs
index ec06e230..c0488f83 100644
--- a/rsvg_internals/src/filters/color_matrix.rs
+++ b/rsvg_internals/src/filters/color_matrix.rs
@@ -170,7 +170,7 @@ impl Filter for ColorMatrix {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let bounds = self
diff --git a/rsvg_internals/src/filters/component_transfer.rs 
b/rsvg_internals/src/filters/component_transfer.rs
index 863a5f34..de3075f9 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -276,7 +276,7 @@ impl Filter for ComponentTransfer {
         &self,
         node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let bounds = self
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index 378d4732..b86a62aa 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -149,7 +149,7 @@ impl Filter for Composite {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let input_2 = ctx.get_input(draw_ctx, self.in2.borrow().as_ref())?;
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index 62d07930..1c230643 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -104,7 +104,7 @@ pub struct FilterContext {
 fn compute_effects_region(
     filter_node: &RsvgNode,
     computed_from_target_node: &ComputedValues,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     affine: cairo::Matrix,
     width: f64,
     height: f64,
@@ -195,7 +195,7 @@ impl FilterContext {
         filter_node: &RsvgNode,
         computed_from_node_being_filtered: &ComputedValues,
         source_surface: SharedImageSurface,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Self {
         let cr_affine = draw_ctx.get_cairo_context().get_matrix();
         let bbox = draw_ctx.get_bbox().clone();
@@ -294,7 +294,7 @@ impl FilterContext {
     /// Computes and returns the background image snapshot.
     fn compute_background_image(
         &self,
-        draw_ctx: &DrawingCtx<'_>,
+        draw_ctx: &DrawingCtx,
     ) -> Result<cairo::ImageSurface, cairo::Status> {
         let surface = cairo::ImageSurface::create(
             cairo::Format::ARgb32,
@@ -325,7 +325,7 @@ impl FilterContext {
     /// Returns the surface corresponding to the background image snapshot.
     pub fn background_image(
         &self,
-        draw_ctx: &DrawingCtx<'_>,
+        draw_ctx: &DrawingCtx,
     ) -> Result<&SharedImageSurface, FilterError> {
         {
             // At this point either no, or only immutable references to background_surface exist, so
@@ -360,7 +360,7 @@ impl FilterContext {
     #[inline]
     pub fn background_alpha(
         &self,
-        draw_ctx: &DrawingCtx<'_>,
+        draw_ctx: &DrawingCtx,
         bounds: IRect,
     ) -> Result<SharedImageSurface, FilterError> {
         self.background_image(draw_ctx)?
@@ -422,7 +422,7 @@ impl FilterContext {
     }
 
     /// Calls the given function with correct behavior for the value of `primitiveUnits`.
-    pub fn with_primitive_units<F, T>(&self, draw_ctx: &mut DrawingCtx<'_>, f: F) -> T
+    pub fn with_primitive_units<F, T>(&self, draw_ctx: &mut DrawingCtx, f: F) -> T
     // TODO: Get rid of this Box? Can't just impl Trait because Rust cannot do higher-ranked types.
     where
         for<'b> F: FnOnce(Box<Fn(&Length) -> f64 + 'b>) -> T,
@@ -449,7 +449,7 @@ impl FilterContext {
     /// Computes and returns a surface corresponding to the given paint server.
     fn get_paint_server_surface(
         &self,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         paint_server: &PaintServer,
         opacity: UnitInterval,
     ) -> Result<cairo::ImageSurface, cairo::Status> {
@@ -489,7 +489,7 @@ impl FilterContext {
     /// Does not take `processing_linear_rgb` into account.
     fn get_input_raw(
         &self,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         in_: Option<&Input>,
     ) -> Result<FilterInput, FilterError> {
         if in_.is_none() {
@@ -546,7 +546,7 @@ impl FilterContext {
     /// Retrieves the filter input surface according to the SVG rules.
     pub fn get_input(
         &self,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         in_: Option<&Input>,
     ) -> Result<FilterInput, FilterError> {
         let raw = self.get_input_raw(draw_ctx, in_)?;
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index d04acac1..892b10c6 100644
--- a/rsvg_internals/src/filters/convolve_matrix.rs
+++ b/rsvg_internals/src/filters/convolve_matrix.rs
@@ -233,7 +233,7 @@ impl Filter for ConvolveMatrix {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let mut bounds = self
diff --git a/rsvg_internals/src/filters/displacement_map.rs b/rsvg_internals/src/filters/displacement_map.rs
index 41ac3944..006879db 100644
--- a/rsvg_internals/src/filters/displacement_map.rs
+++ b/rsvg_internals/src/filters/displacement_map.rs
@@ -82,7 +82,7 @@ impl Filter for DisplacementMap {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let displacement_input = ctx.get_input(draw_ctx, self.in2.borrow().as_ref())?;
diff --git a/rsvg_internals/src/filters/flood.rs b/rsvg_internals/src/filters/flood.rs
index ee87fcbb..bd65ae3b 100644
--- a/rsvg_internals/src/filters/flood.rs
+++ b/rsvg_internals/src/filters/flood.rs
@@ -42,7 +42,7 @@ impl Filter for Flood {
         &self,
         node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let bounds = self.base.get_bounds(ctx).into_irect(draw_ctx);
 
diff --git a/rsvg_internals/src/filters/gaussian_blur.rs b/rsvg_internals/src/filters/gaussian_blur.rs
index c66e7948..f508f921 100644
--- a/rsvg_internals/src/filters/gaussian_blur.rs
+++ b/rsvg_internals/src/filters/gaussian_blur.rs
@@ -206,7 +206,7 @@ impl Filter for GaussianBlur {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let bounds = self
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index f5290ea1..56dad677 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -56,7 +56,7 @@ impl Image {
     fn render_node(
         &self,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         bounds: IRect,
         fragment: &Fragment,
     ) -> Result<ImageSurface, FilterError> {
@@ -120,7 +120,7 @@ impl Image {
     fn render_external_image(
         &self,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         bounds_builder: BoundsBuilder<'_>,
         href: &Href,
     ) -> Result<ImageSurface, FilterError> {
@@ -218,7 +218,7 @@ impl Filter for Image {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let bounds_builder = self.base.get_bounds(ctx);
         let bounds = bounds_builder.into_irect(draw_ctx);
diff --git a/rsvg_internals/src/filters/light/lighting.rs b/rsvg_internals/src/filters/light/lighting.rs
index 1e77f882..55661037 100644
--- a/rsvg_internals/src/filters/light/lighting.rs
+++ b/rsvg_internals/src/filters/light/lighting.rs
@@ -202,7 +202,7 @@ impl Filter for Lighting {
         &self,
         node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let mut bounds = self
diff --git a/rsvg_internals/src/filters/merge.rs b/rsvg_internals/src/filters/merge.rs
index 08668c7c..fa5bb8c4 100644
--- a/rsvg_internals/src/filters/merge.rs
+++ b/rsvg_internals/src/filters/merge.rs
@@ -80,7 +80,7 @@ impl MergeNode {
     fn render(
         &self,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         bounds: IRect,
         output_surface: Option<SharedImageSurface>,
     ) -> Result<SharedImageSurface, FilterError> {
@@ -134,7 +134,7 @@ impl Filter for Merge {
         &self,
         node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         // Compute the filter bounds, taking each child node's input into account.
         let mut bounds = self.base.get_bounds(ctx);
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index cf88be9d..769091b3 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -58,7 +58,7 @@ trait Filter: NodeTrait {
         &self,
         node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError>;
 
     /// Returns `true` if this filter primitive is affected by the `color-interpolation-filters`
@@ -195,7 +195,7 @@ impl PrimitiveWithInput {
     fn get_input(
         &self,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterInput, FilterError> {
         ctx.get_input(draw_ctx, self.in_.borrow().as_ref())
     }
@@ -235,7 +235,7 @@ pub fn render(
     filter_node: &RsvgNode,
     computed_from_node_being_filtered: &ComputedValues,
     source: &cairo::ImageSurface,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
 ) -> Result<cairo::ImageSurface, RenderingError> {
     let filter_node = &*filter_node;
     assert_eq!(filter_node.get_type(), NodeType::Filter);
diff --git a/rsvg_internals/src/filters/morphology.rs b/rsvg_internals/src/filters/morphology.rs
index 60fbcef0..3e43a614 100644
--- a/rsvg_internals/src/filters/morphology.rs
+++ b/rsvg_internals/src/filters/morphology.rs
@@ -83,7 +83,7 @@ impl Filter for Morphology {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let bounds = self
diff --git a/rsvg_internals/src/filters/offset.rs b/rsvg_internals/src/filters/offset.rs
index f9f8a524..2b85c2d8 100644
--- a/rsvg_internals/src/filters/offset.rs
+++ b/rsvg_internals/src/filters/offset.rs
@@ -64,7 +64,7 @@ impl Filter for Offset {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
         let bounds = self
diff --git a/rsvg_internals/src/filters/tile.rs b/rsvg_internals/src/filters/tile.rs
index f18c73a8..1c407ff4 100644
--- a/rsvg_internals/src/filters/tile.rs
+++ b/rsvg_internals/src/filters/tile.rs
@@ -40,7 +40,7 @@ impl Filter for Tile {
         &self,
         _node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let input = self.base.get_input(ctx, draw_ctx)?;
 
diff --git a/rsvg_internals/src/filters/turbulence.rs b/rsvg_internals/src/filters/turbulence.rs
index 30643d59..a5eebdf9 100644
--- a/rsvg_internals/src/filters/turbulence.rs
+++ b/rsvg_internals/src/filters/turbulence.rs
@@ -345,7 +345,7 @@ impl Filter for Turbulence {
         &self,
         node: &RsvgNode,
         ctx: &FilterContext,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         let bounds = self.base.get_bounds(ctx).into_irect(draw_ctx);
 
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index eb6846e3..2e8867b1 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -430,7 +430,7 @@ impl Gradient {
     }
 }
 
-fn acquire_gradient<'a>(draw_ctx: &'a mut DrawingCtx<'_>, name: &Fragment) -> Option<AcquiredNode> {
+fn acquire_gradient<'a>(draw_ctx: &'a mut DrawingCtx, name: &Fragment) -> Option<AcquiredNode> {
     if let Some(acquired) = draw_ctx.get_acquired_node(name) {
         let node_type = acquired.get().get_type();
 
@@ -519,7 +519,7 @@ impl PaintSource<Gradient> for NodeGradient {
     fn resolve(
         &self,
         node: &RsvgNode,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         bbox: &BoundingBox,
     ) -> Option<Gradient> {
         let gradient =
@@ -559,7 +559,7 @@ impl PaintSource<Gradient> for NodeGradient {
         &self,
         gradient: &Gradient,
         values: &ComputedValues,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         opacity: &UnitInterval,
         bbox: &BoundingBox,
     ) -> Result<bool, RenderingError> {
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 9d8ce5f7..a7683db5 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1,6 +1,7 @@
 use std::cell::{Ref, RefCell};
 use std::error::Error;
 use std::ptr;
+use std::rc::Rc;
 
 use cairo::{ImageSurface, Status};
 use cairo_sys;
@@ -14,11 +15,14 @@ use url::Url;
 
 use allowed_url::AllowedUrl;
 use css::{self, CssStyles};
-use defs::{Defs, RsvgDefs};
+use defs::{Fragment, Href};
 use error::{set_gerror, LoadingError};
 use io;
+use node::{box_node, Node, RsvgNode};
 use surface_utils::shared_surface::SharedImageSurface;
-use tree::{RsvgTree, Tree};
+use svg::Svg;
+use util::rsvg_g_warning;
+use xml::{RsvgXmlState, XmlState};
 
 pub enum RsvgHandle {}
 
@@ -26,12 +30,14 @@ pub enum RsvgHandleRust {}
 
 struct Handle {
     base_url: RefCell<Option<Url>>,
+    svg: RefCell<Option<Svg>>,
 }
 
 impl Handle {
     fn new() -> Handle {
         Handle {
             base_url: RefCell::new(None),
+            svg: RefCell::new(None),
         }
     }
 }
@@ -39,8 +45,6 @@ impl Handle {
 #[allow(improper_ctypes)]
 extern "C" {
     fn rsvg_handle_get_flags(handle: *const RsvgHandle) -> u32;
-    fn rsvg_handle_get_defs(handle: *const RsvgHandle) -> *const RsvgDefs;
-    fn rsvg_handle_get_tree(handle: *const RsvgHandle) -> *const RsvgTree;
 
     fn rsvg_handle_new_from_gfile_sync(
         file: *const gio_sys::GFile,
@@ -61,18 +65,27 @@ extern "C" {
     fn rsvg_handle_get_cancellable(handle: *const RsvgHandle) -> *mut gio_sys::GCancellable;
 }
 
-pub fn get_defs<'a>(handle: *const RsvgHandle) -> &'a mut Defs {
-    unsafe {
-        let d = rsvg_handle_get_defs(handle);
-        &mut *(d as *mut Defs)
-    }
+pub fn lookup_node(handle: *const RsvgHandle, fragment: &Fragment) -> Option<Rc<Node>> {
+    let rhandle = get_rust_handle(handle);
+
+    let svg_ref = rhandle.svg.borrow();
+    let svg = svg_ref.as_ref().unwrap();
+    let mut defs_ref = svg.defs.borrow_mut();
+
+    defs_ref.lookup(handle, fragment)
 }
 
-pub fn get_tree<'a>(handle: *const RsvgHandle) -> &'a Tree {
-    unsafe {
-        let t = rsvg_handle_get_tree(handle);
-        &*(t as *mut Tree)
-    }
+// Looks up a node by its id.
+//
+// Note that this ignores the Fragment's url; it only uses the fragment identifier.
+pub fn lookup_fragment_id(handle: *const RsvgHandle, fragment: &Fragment) -> Option<Rc<Node>> {
+    let rhandle = get_rust_handle(handle);
+
+    let svg_ref = rhandle.svg.borrow();
+    let svg = svg_ref.as_ref().unwrap();
+    let defs_ref = svg.defs.borrow();
+
+    defs_ref.lookup_fragment_id(fragment.fragment())
 }
 
 pub fn load_extern(handle: *const RsvgHandle, aurl: &AllowedUrl) -> Result<*const RsvgHandle, ()> {
@@ -89,8 +102,12 @@ pub fn load_extern(handle: *const RsvgHandle, aurl: &AllowedUrl) -> Result<*cons
         if res.is_null() {
             Err(())
         } else {
-            let tree = get_tree(res);
-            tree.cascade();
+            let rhandle = get_rust_handle(handle);
+
+            let svg_ref = rhandle.svg.borrow();
+            let svg = svg_ref.as_ref().unwrap();
+
+            svg.tree.cascade();
 
             Ok(res)
         }
@@ -237,6 +254,12 @@ pub fn load_css(css_styles: &mut CssStyles, handle: *mut RsvgHandle, href_str: &
     }
 }
 
+pub fn get_svg<'a>(handle: *const RsvgHandle) -> Ref<'a, Option<Svg>> {
+    let rhandle = get_rust_handle(handle);
+
+    rhandle.svg.borrow()
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_handle_rust_new() -> *mut RsvgHandleRust {
     Box::into_raw(Box::new(Handle::new())) as *mut RsvgHandleRust
@@ -293,6 +316,61 @@ pub unsafe extern "C" fn rsvg_handle_rust_get_base_gfile(
     }
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_defs_lookup(
+    handle: *const RsvgHandle,
+    name: *const libc::c_char,
+) -> *const RsvgNode {
+    assert!(!name.is_null());
+
+    let rhandle = get_rust_handle(handle);
+
+    let svg_ref = rhandle.svg.borrow();
+    let svg = svg_ref.as_ref().unwrap();
+
+    let mut defs = svg.defs.borrow_mut();
+
+    let name: String = from_glib_none(name);
+
+    let r = Href::with_fragment(&name);
+    if r.is_err() {
+        return ptr::null();
+    }
+
+    match r.unwrap() {
+        Href::WithFragment(fragment) => {
+            if let Some(uri) = fragment.uri() {
+                // The public APIs to get geometries of individual elements, or to render
+                // them, should only allow referencing elements within the main handle's
+                // SVG file; that is, only plain "#foo" fragment IDs are allowed here.
+                // Otherwise, a calling program could request "another-file#foo" and cause
+                // another-file to be loaded, even if it is not part of the set of
+                // resources that the main SVG actually references.  In the future we may
+                // relax this requirement to allow lookups within that set, but not to
+                // other random files.
+
+                let msg = format!(
+                    "the public API is not allowed to look up external references: {}#{}",
+                    uri,
+                    fragment.fragment()
+                );
+
+                rsvg_log!("{}", msg);
+
+                rsvg_g_warning(&msg);
+                return ptr::null();
+            }
+
+            match defs.lookup(handle, &fragment) {
+                Some(n) => box_node(n),
+                None => ptr::null(),
+            }
+        }
+
+        _ => unreachable!(),
+    }
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_handle_acquire_data(
     handle: *mut RsvgHandle,
@@ -368,3 +446,52 @@ pub unsafe extern "C" fn rsvg_handle_acquire_stream(
         }
     }
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_steal_result(
+    raw_handle: *const RsvgHandleRust,
+    raw_xml_state: *mut RsvgXmlState,
+) {
+    let handle = &*(raw_handle as *const Handle);
+    let xml = &mut *(raw_xml_state as *mut XmlState);
+
+    *handle.svg.borrow_mut() = Some(xml.steal_result());
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_cascade(raw_handle: *const RsvgHandleRust) {
+    let rhandle = &*(raw_handle as *const Handle);
+
+    let svg_ref = rhandle.svg.borrow();
+    let svg = svg_ref.as_ref().unwrap();
+
+    svg.tree.cascade();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_get_root(
+    raw_handle: *const RsvgHandleRust,
+) -> *const RsvgNode {
+    let rhandle = &*(raw_handle as *const Handle);
+
+    let svg_ref = rhandle.svg.borrow();
+    let svg = svg_ref.as_ref().unwrap();
+
+    box_node(svg.tree.root())
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_node_is_root(
+    raw_handle: *const RsvgHandleRust,
+    node: *mut RsvgNode,
+) -> glib_sys::gboolean {
+    let rhandle = &*(raw_handle as *const Handle);
+
+    assert!(!node.is_null());
+    let node: &RsvgNode = &*node;
+
+    let svg_ref = rhandle.svg.borrow();
+    let svg = svg_ref.as_ref().unwrap();
+
+    Rc::ptr_eq(&svg.tree.root(), node).to_glib()
+}
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index cfe2079c..2b3cda1c 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -103,7 +103,7 @@ impl NodeTrait for NodeImage {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 8b88d6fa..23d3e763 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -34,10 +34,6 @@ extern crate lazy_static;
 
 pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
 
-pub use css::{rsvg_css_styles_free, rsvg_css_styles_new};
-
-pub use defs::{rsvg_defs_free, rsvg_defs_lookup};
-
 pub use drawing_ctx::{
     rsvg_drawing_ctx_add_node_and_ancestors_to_stack,
     rsvg_drawing_ctx_draw_node_from_stack,
@@ -49,24 +45,19 @@ pub use drawing_ctx::{
 pub use handle::{
     rsvg_handle_acquire_data,
     rsvg_handle_acquire_stream,
+    rsvg_handle_defs_lookup,
     rsvg_handle_rust_free,
     rsvg_handle_rust_get_base_gfile,
     rsvg_handle_rust_new,
+    rsvg_handle_rust_node_is_root,
     rsvg_handle_rust_set_base_url,
+    rsvg_handle_rust_steal_result,
 };
 
 pub use io::rsvg_get_input_stream_for_loading;
 
 pub use node::rsvg_node_unref;
 
-pub use tree::{
-    rsvg_tree_cascade,
-    rsvg_tree_free,
-    rsvg_tree_get_root,
-    rsvg_tree_is_root,
-    rsvg_tree_root_is_svg,
-};
-
 pub use property_bag::{
     rsvg_property_bag_free,
     rsvg_property_bag_iter_begin,
@@ -87,7 +78,6 @@ pub use xml::{
     rsvg_xml_state_load_css_from_href,
     rsvg_xml_state_new,
     rsvg_xml_state_start_element,
-    rsvg_xml_state_steal_result,
 };
 
 #[macro_use]
@@ -142,6 +132,7 @@ mod stop;
 mod structure;
 mod style;
 pub mod surface_utils;
+mod svg;
 mod text;
 mod transform;
 mod tree;
diff --git a/rsvg_internals/src/link.rs b/rsvg_internals/src/link.rs
index 216232a8..32b92818 100644
--- a/rsvg_internals/src/link.rs
+++ b/rsvg_internals/src/link.rs
@@ -43,7 +43,7 @@ impl NodeTrait for NodeLink {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let link = self.link.borrow();
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index b58c1b1a..a6f1b341 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -122,7 +122,7 @@ impl NodeMarker {
     fn render(
         &self,
         node: &RsvgNode,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         xpos: f64,
         ypos: f64,
         computed_angle: f64,
@@ -634,7 +634,7 @@ enum MarkerType {
 }
 
 fn emit_marker_by_name(
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     name: &Fragment,
     xpos: f64,
     ypos: f64,
@@ -692,7 +692,7 @@ where
 
 pub fn render_markers_for_path_builder(
     builder: &PathBuilder,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     values: &ComputedValues,
     clipping: bool,
 ) -> Result<(), RenderingError> {
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index 906157b5..11ff7c7a 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -59,7 +59,7 @@ impl NodeMask {
         &self,
         node: &RsvgNode,
         affine_before_mask: &cairo::Matrix,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
     ) -> Result<(), RenderingError> {
         let cascaded = node.get_cascaded_values();
         let values = cascaded.get();
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 5ce01b16..edff726a 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -116,7 +116,7 @@ pub trait NodeTrait: Downcast {
         &self,
         _node: &RsvgNode,
         _cascaded: &CascadedValues<'_>,
-        _draw_ctx: &mut DrawingCtx<'_>,
+        _draw_ctx: &mut DrawingCtx,
         _clipping: bool,
     ) -> Result<(), RenderingError> {
         // by default nodes don't draw themselves
@@ -535,7 +535,7 @@ impl Node {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         if !self.is_in_error() {
@@ -592,7 +592,7 @@ impl Node {
     pub fn draw_children(
         &self,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         for child in self.children() {
diff --git a/rsvg_internals/src/paint_server.rs b/rsvg_internals/src/paint_server.rs
index d01e5b0c..0e812fab 100644
--- a/rsvg_internals/src/paint_server.rs
+++ b/rsvg_internals/src/paint_server.rs
@@ -52,7 +52,7 @@ impl Parse for PaintServer {
 }
 
 fn set_color(
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     color: &cssparser::Color,
     opacity: &UnitInterval,
     current_color: &cssparser::RGBA,
@@ -72,18 +72,13 @@ fn set_color(
 }
 
 pub trait PaintSource<T> {
-    fn resolve(
-        &self,
-        node: &RsvgNode,
-        draw_ctx: &mut DrawingCtx<'_>,
-        bbox: &BoundingBox,
-    ) -> Option<T>;
+    fn resolve(&self, node: &RsvgNode, draw_ctx: &mut DrawingCtx, bbox: &BoundingBox) -> Option<T>;
 
     fn set_pattern_on_draw_context(
         &self,
         pattern: &T,
         values: &ComputedValues,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         opacity: &UnitInterval,
         bbox: &BoundingBox,
     ) -> Result<bool, RenderingError>;
@@ -91,7 +86,7 @@ pub trait PaintSource<T> {
     fn resolve_fallbacks_and_set_pattern(
         &self,
         node: &RsvgNode,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         opacity: &UnitInterval,
         bbox: &BoundingBox,
     ) -> Result<bool, RenderingError> {
@@ -106,7 +101,7 @@ pub trait PaintSource<T> {
 }
 
 pub fn set_source_paint_server(
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     ps: &PaintServer,
     opacity: &UnitInterval,
     bbox: &BoundingBox,
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index f599b0e0..df144b59 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -243,7 +243,7 @@ impl PaintSource<Pattern> for NodePattern {
     fn resolve(
         &self,
         node: &RsvgNode,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         _bbox: &BoundingBox,
     ) -> Option<Pattern> {
         let node_pattern = node.get_impl::<NodePattern>().unwrap();
@@ -282,7 +282,7 @@ impl PaintSource<Pattern> for NodePattern {
         &self,
         pattern: &Pattern,
         values: &ComputedValues,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         _opacity: &UnitInterval,
         bbox: &BoundingBox,
     ) -> Result<bool, RenderingError> {
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index 94763542..1c581721 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -17,7 +17,7 @@ use state::ComputedValues;
 
 fn render_path_builder(
     builder: &PathBuilder,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     node: &RsvgNode,
     values: &ComputedValues,
     render_markers: bool,
@@ -51,7 +51,7 @@ fn render_ellipse(
     cy: f64,
     rx: f64,
     ry: f64,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     node: &RsvgNode,
     values: &ComputedValues,
     clipping: bool,
@@ -155,7 +155,7 @@ impl NodeTrait for NodePath {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -222,7 +222,7 @@ impl NodeTrait for NodePoly {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -286,7 +286,7 @@ impl NodeTrait for NodeLine {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -377,7 +377,7 @@ impl NodeTrait for NodeRect {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -561,7 +561,7 @@ impl NodeTrait for NodeCircle {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -625,7 +625,7 @@ impl NodeTrait for NodeEllipse {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index 060db1f2..7aaf123f 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -38,7 +38,7 @@ impl NodeTrait for NodeGroup {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -80,7 +80,7 @@ impl NodeTrait for NodeSwitch {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -191,7 +191,7 @@ impl NodeTrait for NodeSvg {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -289,7 +289,7 @@ impl NodeTrait for NodeUse {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
diff --git a/rsvg_internals/src/svg.rs b/rsvg_internals/src/svg.rs
new file mode 100644
index 00000000..2c823594
--- /dev/null
+++ b/rsvg_internals/src/svg.rs
@@ -0,0 +1,30 @@
+use std::cell::RefCell;
+
+use css::CssStyles;
+use defs::Defs;
+use tree::Tree;
+
+/// A loaded SVG file and its derived data
+///
+/// This contains the tree of nodes (SVG elements), the mapping
+/// of id to node, and the CSS styles defined for this SVG.
+pub struct Svg {
+    pub tree: Tree,
+
+    // This requires interior mutability because we load the extern
+    // defs all over the place.  Eventually we'll be able to do this
+    // once, at loading time, and keep this immutable.
+    pub defs: RefCell<Defs>,
+
+    pub css_styles: CssStyles,
+}
+
+impl Svg {
+    pub fn new(tree: Tree, defs: Defs, css_styles: CssStyles) -> Svg {
+        Svg {
+            tree,
+            defs: RefCell::new(defs),
+            css_styles,
+        }
+    }
+}
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index e3fa4335..5e6a4d41 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -90,7 +90,7 @@ impl NodeChars {
         &self,
         node: &RsvgNode,
         values: &ComputedValues,
-        draw_ctx: &DrawingCtx<'_>,
+        draw_ctx: &DrawingCtx,
     ) -> pango::Layout {
         self.ensure_normalized_string(node, values);
         let norm = self.space_normalized.borrow();
@@ -102,7 +102,7 @@ impl NodeChars {
         &self,
         node: &RsvgNode,
         values: &ComputedValues,
-        draw_ctx: &DrawingCtx<'_>,
+        draw_ctx: &DrawingCtx,
         length: &mut f64,
     ) {
         let layout = self.create_layout(node, values, draw_ctx);
@@ -115,7 +115,7 @@ impl NodeChars {
         &self,
         node: &RsvgNode,
         values: &ComputedValues,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         x: &mut f64,
         y: &mut f64,
         clipping: bool,
@@ -189,7 +189,7 @@ impl NodeTrait for NodeText {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         clipping: bool,
     ) -> Result<(), RenderingError> {
         let values = cascaded.get();
@@ -243,7 +243,7 @@ impl NodeTRef {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         length: &mut f64,
     ) -> bool {
         let link = self.link.borrow();
@@ -273,7 +273,7 @@ impl NodeTRef {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         x: &mut f64,
         y: &mut f64,
         clipping: bool,
@@ -338,7 +338,7 @@ impl NodeTSpan {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         length: &mut f64,
         usetextonly: bool,
     ) -> bool {
@@ -363,7 +363,7 @@ impl NodeTSpan {
         &self,
         node: &RsvgNode,
         cascaded: &CascadedValues<'_>,
-        draw_ctx: &mut DrawingCtx<'_>,
+        draw_ctx: &mut DrawingCtx,
         x: &mut f64,
         y: &mut f64,
         usetextonly: bool,
@@ -537,7 +537,7 @@ impl From<WritingMode> for pango::Gravity {
 }
 
 fn create_pango_layout(
-    draw_ctx: &DrawingCtx<'_>,
+    draw_ctx: &DrawingCtx,
     values: &ComputedValues,
     text: &str,
 ) -> pango::Layout {
@@ -617,7 +617,7 @@ fn create_pango_layout(
 fn anchor_offset(
     node: &RsvgNode,
     cascaded: &CascadedValues<'_>,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     anchor: TextAnchor,
     textonly: bool,
 ) -> f64 {
@@ -640,7 +640,7 @@ fn anchor_offset(
 fn measure_children(
     node: &RsvgNode,
     cascaded: &CascadedValues<'_>,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     length: &mut f64,
     textonly: bool,
 ) -> bool {
@@ -665,7 +665,7 @@ fn measure_children(
 fn measure_child(
     node: &RsvgNode,
     cascaded: &CascadedValues<'_>,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     length: &mut f64,
     textonly: bool,
 ) -> bool {
@@ -722,7 +722,7 @@ fn measure_child(
 fn render_children(
     node: &RsvgNode,
     cascaded: &CascadedValues<'_>,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     x: &mut f64,
     y: &mut f64,
     textonly: bool,
@@ -742,7 +742,7 @@ fn render_children(
 fn render_child(
     node: &RsvgNode,
     cascaded: &CascadedValues<'_>,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     x: &mut f64,
     y: &mut f64,
     textonly: bool,
diff --git a/rsvg_internals/src/tree.rs b/rsvg_internals/src/tree.rs
index ad35d089..ceadf0a3 100644
--- a/rsvg_internals/src/tree.rs
+++ b/rsvg_internals/src/tree.rs
@@ -1,16 +1,11 @@
-use glib::translate::*;
-use glib_sys;
-
 use std::cell::Cell;
 use std::rc::Rc;
 
-use node::{box_node, Node, NodeType, RsvgNode};
+use node::{Node, NodeType};
 use state::ComputedValues;
 
-pub enum RsvgTree {}
-
 pub struct Tree {
-    pub root: Rc<Node>,
+    root: Rc<Node>,
     already_cascaded: Cell<bool>,
 }
 
@@ -30,53 +25,11 @@ impl Tree {
         }
     }
 
-    fn root_is_svg(&self) -> bool {
-        self.root.get_type() == NodeType::Svg
+    pub fn root(&self) -> Rc<Node> {
+        self.root.clone()
     }
-}
 
-#[no_mangle]
-pub extern "C" fn rsvg_tree_free(tree: *mut RsvgTree) {
-    if !tree.is_null() {
-        let tree = unsafe { &mut *(tree as *mut Tree) };
-        let _ = unsafe { Box::from_raw(tree) };
+    pub fn root_is_svg(&self) -> bool {
+        self.root.get_type() == NodeType::Svg
     }
 }
-
-#[no_mangle]
-pub extern "C" fn rsvg_tree_cascade(tree: *const RsvgTree) {
-    assert!(!tree.is_null());
-    let tree = unsafe { &*(tree as *const Tree) };
-
-    tree.cascade();
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_tree_get_root(tree: *const RsvgTree) -> *mut RsvgNode {
-    assert!(!tree.is_null());
-    let tree = unsafe { &*(tree as *const Tree) };
-
-    box_node(tree.root.clone())
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_tree_is_root(
-    tree: *const RsvgTree,
-    node: *mut RsvgNode,
-) -> glib_sys::gboolean {
-    assert!(!tree.is_null());
-    let tree = unsafe { &*(tree as *const Tree) };
-
-    assert!(!node.is_null());
-    let node: &RsvgNode = unsafe { &*node };
-
-    Rc::ptr_eq(&tree.root, node).to_glib()
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_tree_root_is_svg(tree: *const RsvgTree) -> glib_sys::gboolean {
-    assert!(!tree.is_null());
-    let tree = unsafe { &*(tree as *const Tree) };
-
-    tree.root_is_svg().to_glib()
-}
diff --git a/rsvg_internals/src/viewport.rs b/rsvg_internals/src/viewport.rs
index d19beae1..9d617eba 100644
--- a/rsvg_internals/src/viewport.rs
+++ b/rsvg_internals/src/viewport.rs
@@ -27,9 +27,9 @@ pub fn draw_in_viewport(
     node: &RsvgNode,
     values: &ComputedValues,
     mut affine: cairo::Matrix,
-    draw_ctx: &mut DrawingCtx<'_>,
+    draw_ctx: &mut DrawingCtx,
     clipping: bool,
-    draw_fn: &mut FnMut(&mut DrawingCtx<'_>) -> Result<(), RenderingError>,
+    draw_fn: &mut FnMut(&mut DrawingCtx) -> Result<(), RenderingError>,
 ) -> Result<(), RenderingError> {
     // width or height set to 0 disables rendering of the element
     // https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index 41fc8e01..aafecb21 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -12,15 +12,17 @@ use std::str;
 use allowed_url::AllowedUrl;
 use attributes::Attribute;
 use create_node::create_node_and_register_id;
-use css::{self, CssStyles, RsvgCssStyles};
-use defs::{Defs, RsvgDefs};
+use css::{self, CssStyles};
+use defs::Defs;
+use error::set_gerror;
 use handle::{self, RsvgHandle};
 use node::{node_new, Node, NodeType};
 use property_bag::PropertyBag;
 use structure::NodeSvg;
 use style::NodeStyle;
+use svg::Svg;
 use text::NodeChars;
-use tree::{RsvgTree, Tree};
+use tree::Tree;
 use util::utf8_cstr;
 
 #[derive(Clone)]
@@ -94,8 +96,8 @@ extern "C" {
 /// that context, all XML events will be forwarded to it, and processed in one of the `XmlHandler`
 /// trait objects. Normally the context refers to a `NodeCreationContext` implementation which is
 /// what creates normal graphical elements.
-struct XmlState {
-    tree: Option<Box<Tree>>,
+pub struct XmlState {
+    tree: Option<Tree>,
     defs: Option<Defs>,
     css_styles: Option<CssStyles>,
     context: Context,
@@ -130,19 +132,19 @@ impl XmlState {
         }
     }
 
-    pub fn set_root(&mut self, root: &Rc<Node>) {
+    fn set_root(&mut self, root: &Rc<Node>) {
         if self.tree.is_some() {
             panic!("The tree root has already been set");
         }
 
-        self.tree = Some(Box::new(Tree::new(root)));
+        self.tree = Some(Tree::new(root));
     }
 
-    pub fn steal_result(&mut self) -> (Option<Box<Tree>>, Box<Defs>, Box<CssStyles>) {
-        (
-            self.tree.take(),
-            Box::new(self.defs.take().unwrap()),
-            Box::new(self.css_styles.take().unwrap()),
+    pub fn steal_result(&mut self) -> Svg {
+        Svg::new(
+            self.tree.take().unwrap(),
+            self.defs.take().unwrap(),
+            self.css_styles.take().unwrap(),
         )
     }
 
@@ -524,31 +526,6 @@ pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
     }
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_xml_state_steal_result(
-    xml: *mut RsvgXmlState,
-    out_tree: *mut *mut RsvgTree,
-    out_defs: *mut *mut RsvgDefs,
-    out_css_styles: *mut *mut RsvgCssStyles,
-) {
-    assert!(!xml.is_null());
-    assert!(!out_tree.is_null());
-    assert!(!out_defs.is_null());
-    assert!(!out_css_styles.is_null());
-
-    let xml = &mut *(xml as *mut XmlState);
-
-    let (tree, defs, css_styles) = xml.steal_result();
-
-    *out_tree = tree
-        .map(|tree| Box::into_raw(tree) as *mut RsvgTree)
-        .unwrap_or(ptr::null_mut());
-
-    *out_defs = Box::into_raw(defs) as *mut RsvgDefs;
-
-    *out_css_styles = Box::into_raw(css_styles) as *mut RsvgCssStyles;
-}
-
 #[no_mangle]
 pub extern "C" fn rsvg_xml_state_start_element(
     xml: *mut RsvgXmlState,
@@ -662,3 +639,24 @@ pub unsafe extern "C" fn rsvg_xml_state_load_css_from_href(
 
     handle::load_css(xml.css_styles.as_mut().unwrap(), handle, &href);
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_xml_state_tree_is_valid(
+    xml: *mut RsvgXmlState,
+    error: *mut *mut glib_sys::GError,
+) -> glib_sys::gboolean {
+    assert!(!xml.is_null());
+    let xml = &mut *(xml as *mut XmlState);
+
+    if let Some(ref tree) = xml.tree {
+        if tree.root_is_svg() {
+            true.to_glib()
+        } else {
+            set_gerror(error, 0, "root element is not <svg>");
+            false.to_glib()
+        }
+    } else {
+        set_gerror(error, 0, "SVG has no elements");
+        false.to_glib()
+    }
+}


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