[librsvg/drawing-ctx-wip] Don't keep a &DrawingCtx in FilterContext; pass it around to filter render functions



commit 1fe859986c0224ae36ac3f6db7686fad77e73842
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Jun 21 19:10:53 2018 -0500

    Don't keep a &DrawingCtx in FilterContext; pass it around to filter render functions
    
    This changes a lot of code, because all filter rendering functions now
    take a &mut DrawingCtx as an argument.  This not only makes them
    consistent with the normal node rendering functions, but it lets us
    avoid double mutable borrows if the draw_ctx needed to be kept in the
    FilterContext.

 librsvg/filters/color_matrix.c                   |   9 +-
 librsvg/filters/common.c                         |  60 --------
 librsvg/filters/common.h                         |  42 ++----
 librsvg/filters/convolve_matrix.c                |   9 +-
 librsvg/filters/diffuse_lighting.c               |  15 +-
 librsvg/filters/displacement_map.c               |  12 +-
 librsvg/filters/erode.c                          |  10 +-
 librsvg/filters/gaussian_blur.c                  |  10 +-
 librsvg/filters/specular_lighting.c              |  15 +-
 librsvg/filters/tile.c                           |  10 +-
 librsvg/filters/turbulence.c                     |  10 +-
 rsvg_internals/src/drawing_ctx.rs                |  13 +-
 rsvg_internals/src/filters/blend.rs              |  14 +-
 rsvg_internals/src/filters/bounds.rs             |  15 +-
 rsvg_internals/src/filters/component_transfer.rs |  16 +-
 rsvg_internals/src/filters/composite.rs          |  14 +-
 rsvg_internals/src/filters/context.rs            | 178 +++++++----------------
 rsvg_internals/src/filters/ffi.rs                |   7 +-
 rsvg_internals/src/filters/flood.rs              |  10 +-
 rsvg_internals/src/filters/image.rs              |  30 ++--
 rsvg_internals/src/filters/merge.rs              |  22 ++-
 rsvg_internals/src/filters/mod.rs                |  12 +-
 rsvg_internals/src/filters/offset.rs             |  16 +-
 rsvg_internals/src/lib.rs                        |   6 -
 rsvg_internals/src/structure.rs                  |   6 +-
 25 files changed, 248 insertions(+), 313 deletions(-)
---
diff --git a/librsvg/filters/color_matrix.c b/librsvg/filters/color_matrix.c
index 9fc83960..69331d2d 100644
--- a/librsvg/filters/color_matrix.c
+++ b/librsvg/filters/color_matrix.c
@@ -38,7 +38,10 @@ struct _RsvgFilterPrimitiveColorMatrix {
 };
 
 static void
-rsvg_filter_primitive_color_matrix_render (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive 
*primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_color_matrix_render (RsvgNode *node, RsvgComputedValues *values,
+                                           RsvgFilterPrimitive *primitive,
+                                           RsvgFilterContext *ctx,
+                                           RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveColorMatrix *color_matrix = (RsvgFilterPrimitiveColorMatrix *) primitive;
 
@@ -55,9 +58,9 @@ rsvg_filter_primitive_color_matrix_render (RsvgNode *node, RsvgComputedValues *v
 
     int sum;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
diff --git a/librsvg/filters/common.c b/librsvg/filters/common.c
index c4e7946d..2f080b9f 100644
--- a/librsvg/filters/common.c
+++ b/librsvg/filters/common.c
@@ -86,12 +86,6 @@ filter_primitive_set_x_y_width_height_atts (RsvgFilterPrimitive *prim, RsvgPrope
     rsvg_property_bag_iter_end (iter);
 }
 
-static void
-rsvg_filter_primitive_render (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive *primitive, 
RsvgFilterContext *ctx)
-{
-    primitive->render (node, values, primitive, ctx);
-}
-
 // RsvgIRect
 // rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
 // {
@@ -462,25 +456,6 @@ rsvg_art_affine_image (cairo_surface_t *img,
 //     g_free (ctx);
 // }
 
-static gboolean
-node_is_filter_primitive (RsvgNode *node)
-{
-    RsvgNodeType type = rsvg_node_get_type (node);
-
-    return type > RSVG_NODE_TYPE_FILTER_PRIMITIVE_FIRST && type < RSVG_NODE_TYPE_FILTER_PRIMITIVE_LAST;
-}
-
-void
-render_child_if_filter_primitive (RsvgNode *node, RsvgComputedValues *values, RsvgFilterContext *filter_ctx)
-{
-    if (node_is_filter_primitive (node)) {
-        RsvgFilterPrimitive *primitive;
-
-        primitive = rsvg_rust_cnode_get_impl (node);
-        rsvg_filter_primitive_render (node, values, primitive, filter_ctx);
-    }
-}
-
 /**
  * rsvg_filter_store_result:
  * @name: The name of the result
@@ -524,41 +499,6 @@ render_child_if_filter_primitive (RsvgNode *node, RsvgComputedValues *values, Rs
 //     rsvg_filter_store_output (name, output, ctx);
 // }
 
-static cairo_surface_t *
-surface_get_alpha (cairo_surface_t *source,
-                   RsvgFilterContext * ctx)
-{
-    guchar *data;
-    guchar *pbdata;
-    gsize i, pbsize;
-    cairo_surface_t *surface;
-
-    if (source == NULL)
-        return NULL;
-
-    cairo_surface_flush (source);
-
-    pbsize = cairo_image_surface_get_width (source) *
-             cairo_image_surface_get_height (source);
-
-    surface = _rsvg_image_surface_new (cairo_image_surface_get_width (source),
-                                       cairo_image_surface_get_height (source));
-    if (surface == NULL)
-        return NULL;
-
-    data = cairo_image_surface_get_data (surface);
-    pbdata = cairo_image_surface_get_data (source);
-
-    const int *ctx_channelmap = rsvg_filter_context_get_channelmap(ctx);
-
-    /* FIXMEchpe: rewrite this into nested width, height loops */
-    for (i = 0; i < pbsize; i++)
-        data[i * 4 + ctx_channelmap[3]] = pbdata[i * 4 + ctx_channelmap[3]];
-
-    cairo_surface_mark_dirty (surface);
-    return surface;
-}
-
 // static cairo_surface_t *
 // rsvg_compile_bg (RsvgDrawingCtx * ctx)
 // {
diff --git a/librsvg/filters/common.h b/librsvg/filters/common.h
index 4e4a600d..5e5854f1 100644
--- a/librsvg/filters/common.h
+++ b/librsvg/filters/common.h
@@ -72,7 +72,11 @@ struct _RsvgFilterPrimitive {
     GString *in;
     GString *result;
 
-    void (*render) (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive *primitive, 
RsvgFilterContext *ctx);
+    void (*render) (RsvgNode *node,
+                    RsvgComputedValues *values,
+                    RsvgFilterPrimitive *primitive,
+                    RsvgFilterContext *ctx,
+                    RsvgDrawingCtx *draw_ctx);
 };
 
 G_GNUC_INTERNAL
@@ -85,9 +89,6 @@ G_GNUC_INTERNAL
 guchar get_interp_pixel (guchar * src, gdouble ox, gdouble oy, guchar ch, RsvgIRect boundarys,
                          guint rowstride);
 
-G_GNUC_INTERNAL
-void render_child_if_filter_primitive (RsvgNode *node, RsvgComputedValues *values, RsvgFilterContext 
*filter_ctx);
-
 G_GNUC_INTERNAL
 void rsvg_alpha_blt (cairo_surface_t *src,
                      gint srcx,
@@ -124,7 +125,7 @@ gboolean rsvg_art_affine_image (cairo_surface_t *img,
 
 /* Implemented in rust/src/filters/context.rs */
 G_GNUC_INTERNAL
-cairo_surface_t *rsvg_filter_get_in (GString * name, RsvgFilterContext * ctx);
+cairo_surface_t *rsvg_filter_get_in (GString * name, RsvgFilterContext * ctx, RsvgDrawingCtx *draw_ctx);
 
 /**
  * rsvg_filter_get_result:
@@ -138,7 +139,9 @@ cairo_surface_t *rsvg_filter_get_in (GString * name, RsvgFilterContext * ctx);
  **/
 /* Implemented in rust/src/filters/context.rs */
 G_GNUC_INTERNAL
-RsvgFilterPrimitiveOutput rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx);
+RsvgFilterPrimitiveOutput rsvg_filter_get_result (GString *name,
+                                                  RsvgFilterContext *ctx,
+                                                  RsvgDrawingCtx *draw_ctx);
 
 // G_GNUC_INTERNAL
 // void rsvg_filter_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag atts);
@@ -153,7 +156,9 @@ void rsvg_filter_primitive_free (gpointer impl);
 
 /* Implemented in rust/src/filters/context.rs */
 G_GNUC_INTERNAL
-RsvgIRect rsvg_filter_primitive_get_bounds (const RsvgFilterPrimitive * self, const RsvgFilterContext * ctx);
+RsvgIRect rsvg_filter_primitive_get_bounds (const RsvgFilterPrimitive * self,
+                                            const RsvgFilterContext * ctx,
+                                            RsvgDrawingCtx *draw_ctx);
 
 /* Implemented in rust/src/filters/context.rs */
 G_GNUC_INTERNAL
@@ -162,35 +167,12 @@ gint rsvg_filter_context_get_width (const RsvgFilterContext *ctx);
 G_GNUC_INTERNAL
 gint rsvg_filter_context_get_height (const RsvgFilterContext *ctx);
 
-G_GNUC_INTERNAL
-cairo_surface_t *rsvg_filter_context_get_source_surface (RsvgFilterContext *ctx);
-
-G_GNUC_INTERNAL
-cairo_surface_t *rsvg_filter_context_get_bg_surface (RsvgFilterContext *ctx);
-
-G_GNUC_INTERNAL
-RsvgFilterPrimitiveOutput rsvg_filter_context_get_lastresult (RsvgFilterContext *ctx);
-
-G_GNUC_INTERNAL
-cairo_matrix_t rsvg_filter_context_get_affine (const RsvgFilterContext *ctx);
-
 G_GNUC_INTERNAL
 cairo_matrix_t rsvg_filter_context_get_paffine (const RsvgFilterContext *ctx);
 
 G_GNUC_INTERNAL
 const int *rsvg_filter_context_get_channelmap (const RsvgFilterContext *ctx);
 
-G_GNUC_INTERNAL
-RsvgDrawingCtx *rsvg_filter_context_get_drawing_ctx (RsvgFilterContext *ctx);
-
-G_GNUC_INTERNAL
-RsvgNode *rsvg_filter_context_get_node_being_filtered (RsvgFilterContext *ctx);
-
-G_GNUC_INTERNAL
-int rsvg_filter_context_get_previous_result (GString *name,
-                                             const RsvgFilterContext *ctx,
-                                             RsvgFilterPrimitiveOutput *output);
-
 G_GNUC_INTERNAL
 void rsvg_filter_store_output (GString * name, RsvgFilterPrimitiveOutput result, RsvgFilterContext * ctx);
 
diff --git a/librsvg/filters/convolve_matrix.c b/librsvg/filters/convolve_matrix.c
index 8f22ddfb..6ba933ff 100644
--- a/librsvg/filters/convolve_matrix.c
+++ b/librsvg/filters/convolve_matrix.c
@@ -51,7 +51,10 @@ struct _RsvgFilterPrimitiveConvolveMatrix {
 };
 
 static void
-rsvg_filter_primitive_convolve_matrix_render (RsvgNode *node, RsvgComputedValues *values, 
RsvgFilterPrimitive *primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_convolve_matrix_render (RsvgNode *node, RsvgComputedValues *values,
+                                              RsvgFilterPrimitive *primitive,
+                                              RsvgFilterContext *ctx,
+                                              RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveConvolveMatrix *convolve = (RsvgFilterPrimitiveConvolveMatrix *) primitive;
 
@@ -73,9 +76,9 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgNode *node, RsvgComputedValues
 
     gint tempresult;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
diff --git a/librsvg/filters/diffuse_lighting.c b/librsvg/filters/diffuse_lighting.c
index 0b67736c..24d2b3ef 100644
--- a/librsvg/filters/diffuse_lighting.c
+++ b/librsvg/filters/diffuse_lighting.c
@@ -41,7 +41,11 @@ struct _RsvgFilterPrimitiveDiffuseLighting {
 };
 
 static void
-rsvg_filter_primitive_diffuse_lighting_render (RsvgNode *node, RsvgComputedValues *values, 
RsvgFilterPrimitive *primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_diffuse_lighting_render (RsvgNode *node,
+                                               RsvgComputedValues *values,
+                                               RsvgFilterPrimitive *primitive,
+                                               RsvgFilterContext *ctx,
+                                               RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveDiffuseLighting *diffuse_lighting = (RsvgFilterPrimitiveDiffuseLighting *) primitive;
 
@@ -71,9 +75,9 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgNode *node, RsvgComputedValue
     if (cairo_matrix_invert (&iaffine) != CAIRO_STATUS_SUCCESS)
       return;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
@@ -118,16 +122,15 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgNode *node, RsvgComputedValue
     }
 
     const int *ctx_channelmap = rsvg_filter_context_get_channelmap(ctx);
-    RsvgDrawingCtx *drawing_ctx = rsvg_filter_context_get_drawing_ctx(ctx);
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
             z = surfaceScale * (double) in_pixels[y * rowstride + x * 4 + ctx_channelmap[3]];
-            L = get_light_direction (values, source, x, y, z, &iaffine, drawing_ctx);
+            L = get_light_direction (values, source, x, y, z, &iaffine, draw_ctx);
             N = get_surface_normal (in_pixels, boundarys, x, y,
                                     dx, dy, rawdx, rawdy, diffuse_lighting->surfaceScale,
                                     rowstride, ctx_channelmap[3]);
-            lightcolor = get_light_color (values, source, color, x, y, z, &iaffine, drawing_ctx);
+            lightcolor = get_light_color (values, source, color, x, y, z, &iaffine, draw_ctx);
             factor = dotproduct (N, L);
 
             output_pixels[y * rowstride + x * 4 + ctx_channelmap[0]] =
diff --git a/librsvg/filters/displacement_map.c b/librsvg/filters/displacement_map.c
index d95d0a3d..75f65e1f 100644
--- a/librsvg/filters/displacement_map.c
+++ b/librsvg/filters/displacement_map.c
@@ -41,7 +41,11 @@ struct _RsvgFilterPrimitiveDisplacementMap {
 };
 
 static void
-rsvg_filter_primitive_displacement_map_render (RsvgNode *node, RsvgComputedValues *values, 
RsvgFilterPrimitive *primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_displacement_map_render (RsvgNode *node,
+                                               RsvgComputedValues *values,
+                                               RsvgFilterPrimitive *primitive,
+                                               RsvgFilterContext *ctx,
+                                               RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveDisplacementMap *displacement_map = (RsvgFilterPrimitiveDisplacementMap *) primitive;
     guchar ch, xch, ych;
@@ -57,15 +61,15 @@ rsvg_filter_primitive_displacement_map_render (RsvgNode *node, RsvgComputedValue
 
     double ox, oy;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
     cairo_surface_flush (in);
 
-    in2 = rsvg_filter_get_in (displacement_map->in2, ctx);
+    in2 = rsvg_filter_get_in (displacement_map->in2, ctx, draw_ctx);
     if (in2 == NULL) {
         cairo_surface_destroy (in);
         return;
diff --git a/librsvg/filters/erode.c b/librsvg/filters/erode.c
index f15a6c33..d2e9dde1 100644
--- a/librsvg/filters/erode.c
+++ b/librsvg/filters/erode.c
@@ -40,7 +40,11 @@ struct _RsvgFilterPrimitiveErode {
 };
 
 static void
-rsvg_filter_primitive_erode_render (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive 
*primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_erode_render (RsvgNode *node,
+                                    RsvgComputedValues *values,
+                                    RsvgFilterPrimitive *primitive,
+                                    RsvgFilterContext *ctx,
+                                    RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveErode *erode = (RsvgFilterPrimitiveErode *) primitive;
 
@@ -58,9 +62,9 @@ rsvg_filter_primitive_erode_render (RsvgNode *node, RsvgComputedValues *values,
     gint kx, ky;
     guchar val;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
diff --git a/librsvg/filters/gaussian_blur.c b/librsvg/filters/gaussian_blur.c
index c0d0615c..dfd3f63a 100644
--- a/librsvg/filters/gaussian_blur.c
+++ b/librsvg/filters/gaussian_blur.c
@@ -581,7 +581,11 @@ gaussian_blur_surface (cairo_surface_t *in,
 }
 
 static void
-rsvg_filter_primitive_gaussian_blur_render (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive 
*primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_gaussian_blur_render (RsvgNode *node,
+                                            RsvgComputedValues *values,
+                                            RsvgFilterPrimitive *primitive,
+                                            RsvgFilterContext *ctx,
+                                            RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveGaussianBlur *gaussian = (RsvgFilterPrimitiveGaussianBlur *) primitive;
 
@@ -592,9 +596,9 @@ rsvg_filter_primitive_gaussian_blur_render (RsvgNode *node, RsvgComputedValues *
     RsvgFilterPrimitiveOutput op;
     cairo_t *cr;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL) {
         return;
     }
diff --git a/librsvg/filters/specular_lighting.c b/librsvg/filters/specular_lighting.c
index e0770687..2e19d0e4 100644
--- a/librsvg/filters/specular_lighting.c
+++ b/librsvg/filters/specular_lighting.c
@@ -41,7 +41,11 @@ struct _RsvgFilterPrimitiveSpecularLighting {
 };
 
 static void
-rsvg_filter_primitive_specular_lighting_render (RsvgNode *node, RsvgComputedValues *values, 
RsvgFilterPrimitive *primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_specular_lighting_render (RsvgNode *node,
+                                                RsvgComputedValues *values,
+                                                RsvgFilterPrimitive *primitive,
+                                                RsvgFilterContext *ctx,
+                                                RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveSpecularLighting *specular_lighting = (RsvgFilterPrimitiveSpecularLighting *) 
primitive;
 
@@ -71,9 +75,9 @@ rsvg_filter_primitive_specular_lighting_render (RsvgNode *node, RsvgComputedValu
     if (cairo_matrix_invert (&iaffine) != CAIRO_STATUS_SUCCESS)
       return;
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
@@ -104,16 +108,15 @@ rsvg_filter_primitive_specular_lighting_render (RsvgNode *node, RsvgComputedValu
     surfaceScale = specular_lighting->surfaceScale / 255.0;
 
     const int *ctx_channelmap = rsvg_filter_context_get_channelmap(ctx);
-    RsvgDrawingCtx *drawing_ctx = rsvg_filter_context_get_drawing_ctx(ctx);
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
             z = in_pixels[y * rowstride + x * 4 + 3] * surfaceScale;
-            L = get_light_direction (values, source, x, y, z, &iaffine, drawing_ctx);
+            L = get_light_direction (values, source, x, y, z, &iaffine, draw_ctx);
             L.z += 1;
             L = normalise (L);
 
-            lightcolor = get_light_color (values, source, color, x, y, z, &iaffine, drawing_ctx);
+            lightcolor = get_light_color (values, source, color, x, y, z, &iaffine, draw_ctx);
             base = dotproduct (get_surface_normal (in_pixels, boundarys, x, y,
                                                    1, 1, 1.0 / ctx_paffine.xx,
                                                    1.0 / ctx_paffine.yy, specular_lighting->surfaceScale,
diff --git a/librsvg/filters/tile.c b/librsvg/filters/tile.c
index d973b97f..c7a85e7c 100644
--- a/librsvg/filters/tile.c
+++ b/librsvg/filters/tile.c
@@ -45,7 +45,11 @@ mod (int a, int b)
 }
 
 static void
-rsvg_filter_primitive_tile_render (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive 
*primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_tile_render (RsvgNode *node,
+                                   RsvgComputedValues *values,
+                                   RsvgFilterPrimitive *primitive,
+                                   RsvgFilterContext *ctx,
+                                   RsvgDrawingCtx *draw_ctx)
 {
     guchar i;
     gint x, y, rowstride;
@@ -58,9 +62,9 @@ rsvg_filter_primitive_tile_render (RsvgNode *node, RsvgComputedValues *values, R
 
     cairo_surface_t *output, *in;
 
-    oboundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    oboundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
-    input = rsvg_filter_get_result (primitive->in, ctx);
+    input = rsvg_filter_get_result (primitive->in, ctx, draw_ctx);
     in = input.surface;
     if (in == NULL) {
         return;
diff --git a/librsvg/filters/turbulence.c b/librsvg/filters/turbulence.c
index cf8d2e97..35e51f63 100644
--- a/librsvg/filters/turbulence.c
+++ b/librsvg/filters/turbulence.c
@@ -266,7 +266,11 @@ feTurbulence_turbulence (RsvgFilterPrimitiveTurbulence * filter,
 }
 
 static void
-rsvg_filter_primitive_turbulence_render (RsvgNode *node, RsvgComputedValues *values, RsvgFilterPrimitive 
*primitive, RsvgFilterContext *ctx)
+rsvg_filter_primitive_turbulence_render (RsvgNode *node,
+                                         RsvgComputedValues *values,
+                                         RsvgFilterPrimitive *primitive,
+                                         RsvgFilterContext *ctx,
+                                         RsvgDrawingCtx *draw_ctx)
 {
     RsvgFilterPrimitiveTurbulence *turbulence = (RsvgFilterPrimitiveTurbulence *) primitive;
 
@@ -281,7 +285,7 @@ rsvg_filter_primitive_turbulence_render (RsvgNode *node, RsvgComputedValues *val
     if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
       return;
 
-    in = rsvg_filter_get_in (primitive->in, ctx);
+    in = rsvg_filter_get_in (primitive->in, ctx, draw_ctx);
     if (in == NULL)
         return;
 
@@ -291,7 +295,7 @@ rsvg_filter_primitive_turbulence_render (RsvgNode *node, RsvgComputedValues *val
     width = cairo_image_surface_get_width (in);
     rowstride = cairo_image_surface_get_stride (in);
 
-    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx);
+    boundarys = rsvg_filter_primitive_get_bounds (primitive, ctx, draw_ctx);
 
     tileWidth = (boundarys.x1 - boundarys.x0);
     tileHeight = (boundarys.y1 - boundarys.y0);
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 2563fd5e..33820b03 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -193,7 +193,11 @@ impl<'a> DrawingCtx {
     }
 
     fn acquired_nodes_contains(&self, node: &RsvgNode) -> bool {
-        self.acquired_nodes.borrow().iter().find(|n| rc_node_ptr_eq(n, node)).is_some()
+        self.acquired_nodes
+            .borrow()
+            .iter()
+            .find(|n| rc_node_ptr_eq(n, node))
+            .is_some()
     }
 
     // Use this function when looking up urls to other nodes, and when you expect
@@ -247,7 +251,8 @@ impl<'a> DrawingCtx {
             let affine = original_cr.get_matrix();
 
             let (clip_node, clip_units) = {
-                let clip_node = self.get_acquired_node_of_type(clip_uri, NodeType::ClipPath)
+                let clip_node = self
+                    .get_acquired_node_of_type(clip_uri, NodeType::ClipPath)
                     .and_then(|acquired| Some(acquired.get()));
 
                 let mut clip_units = Default::default();
@@ -270,7 +275,9 @@ impl<'a> DrawingCtx {
                 }
             }
 
-            let needs_temporary_surface = !(opacity == 1.0 && filter.is_none() && mask.is_none()
+            let needs_temporary_surface = !(opacity == 1.0
+                && filter.is_none()
+                && mask.is_none()
                 && (clip_units == None || clip_units == Some(CoordUnits::UserSpaceOnUse))
                 && comp_op == CompOp::SrcOver
                 && enable_background == EnableBackground::Accumulate);
diff --git a/rsvg_internals/src/filters/blend.rs b/rsvg_internals/src/filters/blend.rs
index 327d5c08..efd6d0f9 100644
--- a/rsvg_internals/src/filters/blend.rs
+++ b/rsvg_internals/src/filters/blend.rs
@@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell};
 use cairo;
 
 use attributes::Attribute;
+use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use handle::RsvgHandle;
 use node::{NodeResult, NodeTrait, RsvgCNodeImpl, RsvgNode};
@@ -72,15 +73,20 @@ impl NodeTrait for Blend {
 }
 
 impl Filter for Blend {
-    fn render(&self, _node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
-        let input = make_result(self.base.get_input(ctx))?;
-        let input_2 = make_result(ctx.get_input(self.in2.borrow().as_ref()))?;
+    fn render(
+        &self,
+        _node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError> {
+        let input = make_result(self.base.get_input(ctx, draw_ctx))?;
+        let input_2 = make_result(ctx.get_input(draw_ctx, self.in2.borrow().as_ref()))?;
         let bounds = self
             .base
             .get_bounds(ctx)
             .add_input(&input)
             .add_input(&input_2)
-            .into_irect();
+            .into_irect(draw_ctx);
 
         // It's important to linearize sRGB before doing any blending, since otherwise the colors
         // will be darker than they should be.
diff --git a/rsvg_internals/src/filters/bounds.rs b/rsvg_internals/src/filters/bounds.rs
index 7de53872..4c629cbc 100644
--- a/rsvg_internals/src/filters/bounds.rs
+++ b/rsvg_internals/src/filters/bounds.rs
@@ -2,6 +2,7 @@
 use cairo::{self, MatrixTrait};
 
 use bbox::BoundingBox;
+use drawing_ctx::DrawingCtx;
 use length::RsvgLength;
 
 use super::context::{FilterContext, FilterInput, FilterOutput, IRect};
@@ -10,7 +11,7 @@ use super::context::{FilterContext, FilterInput, FilterOutput, IRect};
 #[derive(Clone, Copy)]
 pub struct BoundsBuilder<'a> {
     /// The filter context.
-    ctx: &'a FilterContext<'a>,
+    ctx: &'a FilterContext,
 
     /// The current bounding box.
     bbox: BoundingBox,
@@ -82,8 +83,8 @@ impl<'a> BoundsBuilder<'a> {
 
     /// Returns the final pixel bounds.
     #[inline]
-    pub fn into_irect(self) -> IRect {
-        let (mut bbox, needs_clipping) = self.apply_properties();
+    pub fn into_irect(self, draw_ctx: &mut DrawingCtx) -> IRect {
+        let (mut bbox, needs_clipping) = self.apply_properties(draw_ctx);
 
         if needs_clipping {
             let effects_region = self.ctx.effects_region();
@@ -97,12 +98,12 @@ impl<'a> BoundsBuilder<'a> {
     ///
     /// Used by feImage.
     #[inline]
-    pub fn into_irect_without_clipping(self) -> IRect {
-        self.apply_properties().0.rect.unwrap().into()
+    pub fn into_irect_without_clipping(self, draw_ctx: &mut DrawingCtx) -> IRect {
+        self.apply_properties(draw_ctx).0.rect.unwrap().into()
     }
 
     /// Applies the filter primitive properties.
-    fn apply_properties(mut self) -> (BoundingBox, bool) {
+    fn apply_properties(mut self, draw_ctx: &mut DrawingCtx) -> (BoundingBox, bool) {
         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();
@@ -117,7 +118,7 @@ impl<'a> BoundsBuilder<'a> {
 
         // If any of the properties were specified, we need to respect them.
         if self.x.is_some() || self.y.is_some() || self.width.is_some() || self.height.is_some() {
-            self.ctx.with_primitive_units(|normalize| {
+            self.ctx.with_primitive_units(draw_ctx, |normalize| {
                 // These replacements are correct only because self.bbox is used with the paffine
                 // matrix.
                 let rect = self.bbox.rect.as_mut().unwrap();
diff --git a/rsvg_internals/src/filters/component_transfer.rs 
b/rsvg_internals/src/filters/component_transfer.rs
index 15cf8725..10b969b3 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -4,6 +4,7 @@ use std::cmp::min;
 use cairo::{self, ImageSurface};
 
 use attributes::Attribute;
+use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use handle::RsvgHandle;
 use node::{NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
@@ -272,9 +273,18 @@ impl NodeTrait for FuncX {
 }
 
 impl Filter for ComponentTransfer {
-    fn render(&self, node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
-        let input = make_result(self.base.get_input(ctx))?;
-        let bounds = self.base.get_bounds(ctx).add_input(&input).into_irect();
+    fn render(
+        &self,
+        node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError> {
+        let input = make_result(self.base.get_input(ctx, draw_ctx))?;
+        let bounds = self
+            .base
+            .get_bounds(ctx)
+            .add_input(&input)
+            .into_irect(draw_ctx);
 
         let input_surface =
             linearize_surface(input.surface(), bounds).map_err(FilterError::BadInputSurfaceStatus)?;
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index 9b4a995a..4bc3f067 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -4,6 +4,7 @@ use cairo::{self, ImageSurface};
 use cssparser::{CowRcStr, Parser, Token};
 
 use attributes::Attribute;
+use drawing_ctx::DrawingCtx;
 use error::{AttributeError, NodeError};
 use handle::RsvgHandle;
 use node::{NodeResult, NodeTrait, RsvgCNodeImpl, RsvgNode};
@@ -96,15 +97,20 @@ impl NodeTrait for Composite {
 }
 
 impl Filter for Composite {
-    fn render(&self, _node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
-        let input = make_result(self.base.get_input(ctx))?;
-        let input_2 = make_result(ctx.get_input(self.in2.borrow().as_ref()))?;
+    fn render(
+        &self,
+        _node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError> {
+        let input = make_result(self.base.get_input(ctx, draw_ctx))?;
+        let input_2 = make_result(ctx.get_input(draw_ctx, self.in2.borrow().as_ref()))?;
         let bounds = self
             .base
             .get_bounds(ctx)
             .add_input(&input)
             .add_input(&input_2)
-            .into_irect();
+            .into_irect(draw_ctx);
 
         // It's important to linearize sRGB before doing any blending, since otherwise the colors
         // will be darker than they should be.
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index b9a26184..b2c2e8e0 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -1,6 +1,5 @@
 use std::cell::UnsafeCell;
 use std::collections::HashMap;
-use std::ffi::CStr;
 use std::{mem, ptr};
 
 use cairo::prelude::SurfaceExt;
@@ -13,7 +12,7 @@ use bbox::BoundingBox;
 use coord_units::CoordUnits;
 use drawing_ctx::{DrawingCtx, RsvgDrawingCtx};
 use length::RsvgLength;
-use node::{box_node, RsvgNode};
+use node::RsvgNode;
 use paint_server::{self, PaintServer};
 use unitinterval::UnitInterval;
 
@@ -73,10 +72,10 @@ pub enum FilterInput {
     PrimitiveOutput(FilterOutput),
 }
 
-pub type RsvgFilterContext<'a> = FilterContext<'a>;
+pub type RsvgFilterContext = FilterContext;
 
 /// The filter rendering context.
-pub struct FilterContext<'a> {
+pub struct FilterContext {
     /// The <filter> node.
     node: RsvgNode,
     /// The node which referenced this filter.
@@ -89,8 +88,6 @@ pub struct FilterContext<'a> {
     previous_results: HashMap<String, FilterOutput>,
     /// The background surface. Computed lazily.
     background_surface: UnsafeCell<Option<Result<cairo::ImageSurface, cairo::Status>>>,
-    /// The drawing context.
-    draw_ctx: &'a mut DrawingCtx,
     /// The filter effects region.
     effects_region: BoundingBox,
 
@@ -220,13 +217,13 @@ impl IRect {
     }
 }
 
-impl<'a> FilterContext<'a> {
+impl FilterContext {
     /// Creates a new `FilterContext`.
     pub fn new(
         filter_node: &RsvgNode,
         node_being_filtered: &RsvgNode,
         source_surface: cairo::ImageSurface,
-        draw_ctx: &'a mut DrawingCtx,
+        draw_ctx: &mut DrawingCtx,
         channelmap: [i32; 4],
     ) -> Self {
         let cr_affine = draw_ctx.get_cairo_context().get_matrix();
@@ -284,7 +281,6 @@ impl<'a> FilterContext<'a> {
             last_result: None,
             previous_results: HashMap::new(),
             background_surface: UnsafeCell::new(None),
-            draw_ctx,
             effects_region,
             affine,
             paffine,
@@ -331,19 +327,22 @@ impl<'a> FilterContext<'a> {
     }
 
     /// Computes and returns the background image snapshot.
-    fn compute_background_image(&self) -> Result<cairo::ImageSurface, cairo::Status> {
+    fn compute_background_image(
+        &self,
+        draw_ctx: &DrawingCtx,
+    ) -> Result<cairo::ImageSurface, cairo::Status> {
         let surface = cairo::ImageSurface::create(
             cairo::Format::ARgb32,
             self.source_surface.get_width(),
             self.source_surface.get_height(),
         )?;
 
-        let (x, y) = self.draw_ctx.get_raw_offset();
-        let stack = self.draw_ctx.get_cr_stack();
+        let (x, y) = draw_ctx.get_raw_offset();
+        let stack = draw_ctx.get_cr_stack();
 
         let cr = cairo::Context::new(&surface);
         for draw in stack.into_iter().rev() {
-            let nested = self.draw_ctx.is_cairo_context_nested(&draw);
+            let nested = draw_ctx.is_cairo_context_nested(&draw);
             cr.set_source_surface(
                 &draw.get_target(),
                 if nested { 0f64 } else { -x },
@@ -356,7 +355,10 @@ impl<'a> FilterContext<'a> {
     }
 
     /// Returns the surface corresponding to the background image snapshot.
-    pub fn background_image(&self) -> Result<&cairo::ImageSurface, cairo::Status> {
+    pub fn background_image(
+        &self,
+        draw_ctx: &DrawingCtx,
+    ) -> Result<&cairo::ImageSurface, cairo::Status> {
         {
             // At this point either no, or only immutable references to background_surface exist, so
             // it's ok to make an immutable reference.
@@ -373,7 +375,7 @@ impl<'a> FilterContext<'a> {
         // no references to it and we can create a mutable reference.
         let bg = unsafe { &mut *self.background_surface.get() };
 
-        *bg = Some(self.compute_background_image());
+        *bg = Some(self.compute_background_image(draw_ctx));
 
         // Return the only existing reference as immutable.
         bg.as_ref().unwrap().as_ref().map_err(|&s| s)
@@ -381,8 +383,12 @@ impl<'a> FilterContext<'a> {
 
     /// Returns the surface containing the background image snapshot alpha.
     #[inline]
-    pub fn background_alpha(&self, bounds: IRect) -> Result<cairo::ImageSurface, cairo::Status> {
-        self.background_image()
+    pub fn background_alpha(
+        &self,
+        draw_ctx: &DrawingCtx,
+        bounds: IRect,
+    ) -> Result<cairo::ImageSurface, cairo::Status> {
+        self.background_image(draw_ctx)
             .and_then(|surface| extract_alpha(surface, bounds))
     }
 
@@ -411,12 +417,6 @@ impl<'a> FilterContext<'a> {
         self.last_result = Some(result.output);
     }
 
-    /// Returns the drawing context for this filter context.
-    #[inline]
-    pub fn draw_context(&mut self) -> &mut DrawingCtx {
-        self.draw_ctx
-    }
-
     /// Returns the paffine matrix.
     #[inline]
     pub fn paffine(&self) -> cairo::Matrix {
@@ -430,7 +430,7 @@ impl<'a> FilterContext<'a> {
     }
 
     /// Calls the given function with correct behavior for the value of `primitiveUnits`.
-    pub fn with_primitive_units<F, T>(&self, 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(&RsvgLength) -> f64 + 'b>) -> T,
@@ -443,21 +443,22 @@ impl<'a> FilterContext<'a> {
 
         // See comments in compute_effects_region() for how this works.
         if filter.primitiveunits.get() == CoordUnits::ObjectBoundingBox {
-            self.draw_ctx.push_view_box(1.0, 1.0);
+            draw_ctx.push_view_box(1.0, 1.0);
             let rv = f(Box::new(RsvgLength::get_unitless));
-            self.draw_ctx.pop_view_box();
+            draw_ctx.pop_view_box();
 
             rv
         } else {
             f(Box::new(|length: &RsvgLength| {
-                length.normalize(values, self.draw_ctx)
+                length.normalize(values, draw_ctx)
             }))
         }
     }
 
     /// Computes and returns a surface corresponding to the given paint server.
     fn get_paint_server_surface(
-        &mut self,
+        &self,
+        draw_ctx: &mut DrawingCtx,
         paint_server: &PaintServer,
         opacity: UnitInterval,
     ) -> Result<cairo::ImageSurface, cairo::Status> {
@@ -467,17 +468,17 @@ impl<'a> FilterContext<'a> {
             self.source_surface.get_height(),
         )?;
 
-        let cr_save = self.draw_ctx.get_cairo_context();
+        let cr_save = draw_ctx.get_cairo_context();
         let cr = cairo::Context::new(&surface);
-        self.draw_ctx.set_cairo_context(&cr);
+        draw_ctx.set_cairo_context(&cr);
 
         let cascaded = self.node_being_filtered.get_cascaded_values();
         let values = cascaded.get();
 
-        let bbox = self.draw_ctx.get_bbox().clone();
+        let bbox = draw_ctx.get_bbox().clone();
 
         if paint_server::set_source_paint_server(
-            self.draw_ctx,
+            draw_ctx,
             paint_server,
             &opacity,
             &bbox,
@@ -486,12 +487,12 @@ impl<'a> FilterContext<'a> {
             cr.paint();
         }
 
-        self.draw_ctx.set_cairo_context(&cr_save);
+        draw_ctx.set_cairo_context(&cr_save);
         Ok(surface)
     }
 
     /// Retrieves the filter input surface according to the SVG rules.
-    pub fn get_input(&self, in_: Option<&Input>) -> Option<FilterInput> {
+    pub fn get_input(&self, draw_ctx: &mut DrawingCtx, in_: Option<&Input>) -> Option<FilterInput> {
         if in_.is_none() {
             // No value => use the last result.
             // As per the SVG spec, if the filter primitive is the first in the chain, return the
@@ -513,21 +514,21 @@ impl<'a> FilterContext<'a> {
                 .ok()
                 .map(FilterInput::StandardInput),
             Input::BackgroundImage => self
-                .background_image()
+                .background_image(draw_ctx)
                 .ok()
                 .cloned()
                 .map(FilterInput::StandardInput),
             Input::BackgroundAlpha => self
-                .background_alpha(self.effects_region().rect.unwrap().into())
+                .background_alpha(draw_ctx, self.effects_region().rect.unwrap().into())
                 .ok()
                 .map(FilterInput::StandardInput),
 
             Input::FillPaint => self
-                .get_paint_server_surface(&values.fill.0, values.fill_opacity.0)
+                .get_paint_server_surface(draw_ctx, &values.fill.0, values.fill_opacity.0)
                 .ok()
                 .map(FilterInput::StandardInput),
             Input::StrokePaint => self
-                .get_paint_server_surface(&values.stroke.0, values.stroke_opacity.0)
+                .get_paint_server_surface(draw_ctx, &values.stroke.0, values.stroke_opacity.0)
                 .ok()
                 .map(FilterInput::StandardInput),
 
@@ -569,15 +570,6 @@ impl From<cairo::Rectangle> for IRect {
     }
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_filter_context_get_affine(
-    ctx: *const RsvgFilterContext,
-) -> cairo::Matrix {
-    assert!(!ctx.is_null());
-
-    (*ctx).affine
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_filter_context_get_paffine(
     ctx: *const RsvgFilterContext,
@@ -587,15 +579,6 @@ pub unsafe extern "C" fn rsvg_filter_context_get_paffine(
     (*ctx).paffine
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_filter_context_get_drawing_ctx(
-    ctx: *mut RsvgFilterContext,
-) -> *mut RsvgDrawingCtx {
-    assert!(!ctx.is_null());
-
-    (*ctx).draw_ctx as *const _ as *mut RsvgDrawingCtx
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_filter_context_get_width(ctx: *const RsvgFilterContext) -> i32 {
     assert!(!ctx.is_null());
@@ -610,15 +593,6 @@ pub unsafe extern "C" fn rsvg_filter_context_get_height(ctx: *const RsvgFilterCo
     (*ctx).source_surface.get_height()
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_filter_context_get_node_being_filtered(
-    ctx: *const RsvgFilterContext,
-) -> *mut RsvgNode {
-    assert!(!ctx.is_null());
-
-    box_node((*ctx).get_node_being_filtered())
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_filter_context_get_channelmap(
     ctx: *const RsvgFilterContext,
@@ -637,66 +611,6 @@ pub unsafe extern "C" fn rsvg_filter_context_get_source_surface(
     (*ctx).source_surface.to_glib_none().0
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_filter_context_get_bg_surface(
-    ctx: *mut RsvgFilterContext,
-) -> *mut cairo_surface_t {
-    assert!(!ctx.is_null());
-
-    (*ctx)
-        .background_image()
-        .map(|surface| surface.to_glib_none().0)
-        .unwrap_or_else(|_| ptr::null_mut())
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_filter_context_get_lastresult(
-    ctx: *mut RsvgFilterContext,
-) -> RsvgFilterPrimitiveOutput {
-    assert!(!ctx.is_null());
-
-    let ctx = &*ctx;
-
-    match ctx.last_result {
-        Some(FilterOutput {
-            ref surface,
-            ref bounds,
-        }) => RsvgFilterPrimitiveOutput {
-            surface: surface.to_glib_none().0,
-            bounds: *bounds,
-        },
-        None => RsvgFilterPrimitiveOutput {
-            surface: ctx.source_surface.to_glib_none().0,
-            bounds: ctx.effects_region().rect.unwrap().into(),
-        },
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_filter_context_get_previous_result(
-    name: *mut GString,
-    ctx: *mut RsvgFilterContext,
-    output: *mut RsvgFilterPrimitiveOutput,
-) -> i32 {
-    assert!(!name.is_null());
-    assert!(!ctx.is_null());
-    assert!(!output.is_null());
-
-    if let Some(&FilterOutput {
-        ref surface,
-        ref bounds,
-    }) = (*ctx).filter_output(&CStr::from_ptr((*name).str).to_string_lossy())
-    {
-        *output = RsvgFilterPrimitiveOutput {
-            surface: surface.to_glib_none().0,
-            bounds: *bounds,
-        };
-        1
-    } else {
-        0
-    }
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_filter_store_output(
     name: *mut GString,
@@ -728,10 +642,13 @@ pub unsafe extern "C" fn rsvg_filter_store_output(
 pub unsafe extern "C" fn rsvg_filter_primitive_get_bounds(
     primitive: *const RsvgFilterPrimitive,
     ctx: *const RsvgFilterContext,
+    raw_draw_ctx: *mut RsvgDrawingCtx,
 ) -> IRect {
     assert!(!ctx.is_null());
+    assert!(!raw_draw_ctx.is_null());
 
     let ctx = &*ctx;
+    let draw_ctx = &mut *(raw_draw_ctx as *mut DrawingCtx);
 
     let mut x = None;
     let mut y = None;
@@ -757,16 +674,20 @@ pub unsafe extern "C" fn rsvg_filter_primitive_get_bounds(
     }
 
     // Doesn't take referenced nodes into account, which is wrong.
-    BoundsBuilder::new(ctx, x, y, width, height).into_irect()
+    BoundsBuilder::new(ctx, x, y, width, height).into_irect(draw_ctx)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_filter_get_result(
     name: *const GString,
     ctx: *const RsvgFilterContext,
+    raw_draw_ctx: *const RsvgDrawingCtx,
 ) -> RsvgFilterPrimitiveOutput {
     assert!(!name.is_null());
     assert!(!ctx.is_null());
+    assert!(!raw_draw_ctx.is_null());
+
+    let draw_ctx = &mut *(raw_draw_ctx as *mut DrawingCtx);
 
     let name: String = from_glib_none((*name).str);
     let input = match &name[..] {
@@ -782,7 +703,7 @@ pub unsafe extern "C" fn rsvg_filter_get_result(
 
     let ctx = &*ctx;
 
-    match ctx.get_input(input.as_ref()) {
+    match ctx.get_input(draw_ctx, input.as_ref()) {
         None => RsvgFilterPrimitiveOutput {
             surface: ptr::null_mut(),
             bounds: IRect {
@@ -815,8 +736,9 @@ pub unsafe extern "C" fn rsvg_filter_get_result(
 pub unsafe extern "C" fn rsvg_filter_get_in(
     name: *const GString,
     ctx: *const RsvgFilterContext,
+    raw_draw_ctx: *mut RsvgDrawingCtx,
 ) -> *mut cairo_surface_t {
-    rsvg_filter_get_result(name, ctx).surface
+    rsvg_filter_get_result(name, ctx, raw_draw_ctx).surface
 }
 
 #[cfg(test)]
diff --git a/rsvg_internals/src/filters/ffi.rs b/rsvg_internals/src/filters/ffi.rs
index 36920004..6c703025 100644
--- a/rsvg_internals/src/filters/ffi.rs
+++ b/rsvg_internals/src/filters/ffi.rs
@@ -40,14 +40,15 @@ pub struct RsvgFilterPrimitive {
 
 /// The type of the render function below.
 pub(super) type RenderFunctionType =
-    fn(&RsvgNode, &FilterContext) -> Result<FilterResult, FilterError>;
+    fn(&RsvgNode, &FilterContext, &mut DrawingCtx) -> Result<FilterResult, FilterError>;
 
 /// Downcasts the given `node` to the type `T` and calls `Filter::render()` on it.
 pub(super) fn render<T: Filter>(
     node: &RsvgNode,
     ctx: &FilterContext,
+    draw_ctx: &mut DrawingCtx,
 ) -> Result<FilterResult, FilterError> {
-    node.with_impl(|filter: &T| filter.render(node, ctx))
+    node.with_impl(|filter: &T| filter.render(node, ctx, draw_ctx))
 }
 
 /// Creates a new surface applied the filter. This function will create a context for itself, set up
@@ -98,7 +99,7 @@ pub fn filter_render(
                 let render = unsafe {
                     *(&c.get_c_impl() as *const *const RsvgCNodeImpl as *const RenderFunctionType)
                 };
-                match render(&c, &filter_ctx) {
+                match render(&c, &filter_ctx, draw_ctx) {
                     Ok(result) => filter_ctx.store_result(result),
                     Err(_) => { /* Do nothing for now */ }
                 }
diff --git a/rsvg_internals/src/filters/flood.rs b/rsvg_internals/src/filters/flood.rs
index f5189d80..3f1e14c2 100644
--- a/rsvg_internals/src/filters/flood.rs
+++ b/rsvg_internals/src/filters/flood.rs
@@ -1,6 +1,7 @@
 use cairo::{self, ImageSurface};
 use cssparser;
 
+use drawing_ctx::DrawingCtx;
 use handle::RsvgHandle;
 use node::{NodeResult, NodeTrait, RsvgCNodeImpl, RsvgNode};
 use property_bag::PropertyBag;
@@ -41,8 +42,13 @@ impl NodeTrait for Flood {
 }
 
 impl Filter for Flood {
-    fn render(&self, node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
-        let bounds = self.base.get_bounds(ctx).into_irect();
+    fn render(
+        &self,
+        node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError> {
+        let bounds = self.base.get_bounds(ctx).into_irect(draw_ctx);
 
         let output_surface = ImageSurface::create(
             cairo::Format::ARgb32,
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index 38fcc970..a0729476 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -10,6 +10,7 @@ use libc;
 
 use aspect_ratio::AspectRatio;
 use attributes::Attribute;
+use drawing_ctx::DrawingCtx;
 use handle::RsvgHandle;
 use node::{CascadedValues, NodeResult, NodeTrait, RsvgCNodeImpl, RsvgNode};
 use parsers::parse;
@@ -47,12 +48,12 @@ impl Image {
     fn render_node(
         &self,
         ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
         bounds: IRect,
         href: &str,
     ) -> Result<ImageSurface, FilterError> {
         // TODO: Port more of this to Rust.
         // Currently this is essentially a direct port of the C function.
-        let draw_ctx = ctx.draw_context();
         let acquired_drawable = draw_ctx
             .get_acquired_node(href)
             .ok_or(FilterError::InvalidInput)?;
@@ -66,10 +67,11 @@ impl Image {
 
         draw_ctx.get_cairo_context().set_matrix(ctx.paffine());
 
-        let cascaded = CascadedValues::new_from_values(
-            &drawable,
-            ctx.get_node_being_filtered().get_cascaded_values().get(),
-        );
+        let node_being_filtered = ctx.get_node_being_filtered();
+        let node_being_filtered_cascaded = node_being_filtered.get_cascaded_values();
+        let node_being_filtered_values = node_being_filtered_cascaded.get();
+
+        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);
 
         draw_ctx.draw_node_on_surface(
             &drawable,
@@ -104,6 +106,7 @@ impl Image {
     fn render_external_image(
         &self,
         ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
         bounds_builder: BoundsBuilder,
         href: &str,
     ) -> Result<ImageSurface, FilterError> {
@@ -141,7 +144,7 @@ impl Image {
         ).map_err(FilterError::OutputSurfaceCreation)?;
 
         // TODO: this goes through a f64->i32->f64 conversion.
-        let render_bounds = bounds_builder.into_irect_without_clipping();
+        let render_bounds = bounds_builder.into_irect_without_clipping(draw_ctx);
         let aspect = self.aspect.get();
         let (x, y, w, h) = aspect.compute(
             f64::from(surface.get_width()),
@@ -165,7 +168,7 @@ impl Image {
             matrix.invert();
             ptn.set_matrix(matrix);
 
-            let bounds = bounds_builder.into_irect();
+            let bounds = bounds_builder.into_irect(draw_ctx);
             let cr = cairo::Context::new(&output_surface);
             cr.rectangle(
                 f64::from(bounds.x0),
@@ -217,16 +220,21 @@ impl NodeTrait for Image {
 }
 
 impl Filter for Image {
-    fn render(&self, _node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
+    fn render(
+        &self,
+        _node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError> {
         let href = self.href.borrow();
         let href = href.as_ref().ok_or(FilterError::InvalidInput)?;
 
         let bounds_builder = self.base.get_bounds(ctx);
-        let bounds = bounds_builder.into_irect();
+        let bounds = bounds_builder.into_irect(draw_ctx);
 
-        let output_surface = match self.render_node(ctx, bounds, href) {
+        let output_surface = match self.render_node(ctx, draw_ctx, bounds, href) {
             Err(FilterError::InvalidInput) => {
-                self.render_external_image(ctx, bounds_builder, href)?
+                self.render_external_image(ctx, draw_ctx, bounds_builder, href)?
             }
             Err(err) => return Err(err),
             Ok(surface) => surface,
diff --git a/rsvg_internals/src/filters/merge.rs b/rsvg_internals/src/filters/merge.rs
index ef29f992..59cf3526 100644
--- a/rsvg_internals/src/filters/merge.rs
+++ b/rsvg_internals/src/filters/merge.rs
@@ -3,6 +3,7 @@ use std::cell::RefCell;
 use cairo::{self, ImageSurface};
 
 use attributes::Attribute;
+use drawing_ctx::DrawingCtx;
 use handle::RsvgHandle;
 use node::{NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
 use property_bag::PropertyBag;
@@ -84,10 +85,11 @@ impl MergeNode {
     fn render(
         &self,
         ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
         bounds: IRect,
         output_surface: Option<ImageSurface>,
     ) -> Result<ImageSurface, FilterError> {
-        let input = make_result(ctx.get_input(self.in_.borrow().as_ref()))?;
+        let input = make_result(ctx.get_input(draw_ctx, self.in_.borrow().as_ref()))?;
         let input_surface = input.surface();
         let input_surface =
             linearize_surface(&input_surface, bounds).map_err(FilterError::BadInputSurfaceStatus)?;
@@ -114,18 +116,23 @@ impl MergeNode {
 }
 
 impl Filter for Merge {
-    fn render(&self, node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
+    fn render(
+        &self,
+        node: &RsvgNode,
+        ctx: &FilterContext,
+        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);
         for child in node
             .children()
             .filter(|c| c.get_type() == NodeType::FilterPrimitiveMergeNode)
         {
-            bounds = bounds.add_input(&child.with_impl(move |c: &MergeNode| {
-                make_result(ctx.get_input(c.in_.borrow().as_ref()))
+            bounds = bounds.add_input(&child.with_impl(|c: &MergeNode| {
+                make_result(ctx.get_input(draw_ctx, c.in_.borrow().as_ref()))
             })?);
         }
-        let bounds = bounds.into_irect();
+        let bounds = bounds.into_irect(draw_ctx);
 
         // Now merge them all.
         let mut output_surface = None;
@@ -133,8 +140,9 @@ impl Filter for Merge {
             .children()
             .filter(|c| c.get_type() == NodeType::FilterPrimitiveMergeNode)
         {
-            output_surface =
-                Some(child.with_impl(move |c: &MergeNode| c.render(ctx, bounds, output_surface))?);
+            output_surface = Some(
+                child.with_impl(|c: &MergeNode| c.render(ctx, draw_ctx, bounds, output_surface))?,
+            );
         }
 
         let output_surface = output_surface
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index d7ab25a2..e363ef34 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -3,6 +3,7 @@ use std::ops::Deref;
 
 use attributes::Attribute;
 use coord_units::CoordUnits;
+use drawing_ctx::DrawingCtx;
 use error::AttributeError;
 use handle::RsvgHandle;
 use length::{LengthDir, LengthUnit, RsvgLength};
@@ -44,7 +45,12 @@ trait Filter: NodeTrait {
     ///
     /// If this filter primitive can't be rendered for whatever reason (for instance, a required
     /// property hasn't been provided), an error is returned.
-    fn render(&self, node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError>;
+    fn render(
+        &self,
+        node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError>;
 }
 
 /// The base filter primitive node containing common properties.
@@ -184,8 +190,8 @@ impl PrimitiveWithInput {
 
     /// Returns the input Cairo surface for this filter primitive.
     #[inline]
-    fn get_input(&self, ctx: &FilterContext) -> Option<FilterInput> {
-        ctx.get_input(self.in_.borrow().as_ref())
+    fn get_input(&self, ctx: &FilterContext, draw_ctx: &mut DrawingCtx) -> Option<FilterInput> {
+        ctx.get_input(draw_ctx, self.in_.borrow().as_ref())
     }
 }
 
diff --git a/rsvg_internals/src/filters/offset.rs b/rsvg_internals/src/filters/offset.rs
index 8a8b33cf..e1a16f3a 100644
--- a/rsvg_internals/src/filters/offset.rs
+++ b/rsvg_internals/src/filters/offset.rs
@@ -3,6 +3,7 @@ use std::cell::Cell;
 use cairo::{self, ImageSurface};
 
 use attributes::Attribute;
+use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use handle::RsvgHandle;
 use node::{NodeResult, NodeTrait, RsvgCNodeImpl, RsvgNode};
@@ -63,9 +64,18 @@ impl NodeTrait for Offset {
 }
 
 impl Filter for Offset {
-    fn render(&self, _node: &RsvgNode, ctx: &FilterContext) -> Result<FilterResult, FilterError> {
-        let input = make_result(self.base.get_input(ctx))?;
-        let bounds = self.base.get_bounds(ctx).add_input(&input).into_irect();
+    fn render(
+        &self,
+        _node: &RsvgNode,
+        ctx: &FilterContext,
+        draw_ctx: &mut DrawingCtx,
+    ) -> Result<FilterResult, FilterError> {
+        let input = make_result(self.base.get_input(ctx, draw_ctx))?;
+        let bounds = self
+            .base
+            .get_bounds(ctx)
+            .add_input(&input)
+            .into_irect(draw_ctx);
 
         let dx = self.dx.get();
         let dy = self.dy.get();
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index cfd6eaf3..f085d87f 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -37,15 +37,9 @@ pub use drawing_ctx::{
 };
 
 pub use filters::context::{
-    rsvg_filter_context_get_affine,
-    rsvg_filter_context_get_bg_surface,
     rsvg_filter_context_get_channelmap,
-    rsvg_filter_context_get_drawing_ctx,
     rsvg_filter_context_get_height,
-    rsvg_filter_context_get_lastresult,
-    rsvg_filter_context_get_node_being_filtered,
     rsvg_filter_context_get_paffine,
-    rsvg_filter_context_get_previous_result,
     rsvg_filter_context_get_source_surface,
     rsvg_filter_context_get_width,
     rsvg_filter_get_in,
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index 62b02891..aaf48071 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -80,11 +80,7 @@ impl NodeTrait for NodeSwitch {
 
         draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
             if let Some(child) = node.children().find(|c| c.get_cond()) {
-                dc.draw_node_from_stack(
-                    &CascadedValues::new(cascaded, &child),
-                    &child,
-                    clipping,
-                );
+                dc.draw_node_from_stack(&CascadedValues::new(cascaded, &child), &child, clipping);
             }
         });
     }


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