[librsvg] Use cairo image surfaces



commit e7e5622c39157f1e6880cb24b7949344a182f5fb
Author: Christian Persch <chpe gnome org>
Date:   Sun Nov 27 21:24:45 2011 +0100

    Use cairo image surfaces
    
    ... instead of GdkPixbufs to store the filter results.

 rsvg-base.c         |    9 +
 rsvg-cairo-clip.c   |   11 +
 rsvg-cairo-draw.c   |  202 +++++++++------
 rsvg-cairo-draw.h   |    2 +
 rsvg-cairo-render.c |    1 +
 rsvg-filter.c       |  726 +++++++++++++++++++++++++++------------------------
 rsvg-image.c        |   44 +++-
 rsvg-image.h        |    6 +-
 rsvg-private.h      |    5 +
 9 files changed, 569 insertions(+), 437 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 6618298..1511659 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -1963,6 +1963,15 @@ rsvg_render_image (RsvgDrawingCtx * ctx, GdkPixbuf * pb, double x, double y, dou
 }
 
 void
+rsvg_render_surface (RsvgDrawingCtx * ctx, cairo_surface_t *surface, double x, double y, double w, double h)
+{
+    /* surface must be a cairo image surface */
+    g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
+
+    ctx->render->render_surface (ctx, surface, x, y, w, h);
+}
+
+void
 rsvg_add_clipping_rect (RsvgDrawingCtx * ctx, double x, double y, double w, double h)
 {
     ctx->render->add_clipping_rect (ctx, x, y, w, h);
diff --git a/rsvg-cairo-clip.c b/rsvg-cairo-clip.c
index f634574..3e63f35 100644
--- a/rsvg-cairo-clip.c
+++ b/rsvg-cairo-clip.c
@@ -84,6 +84,16 @@ rsvg_cairo_clip_render_image (RsvgDrawingCtx * ctx,
 {
 }
 
+static void
+rsvg_cairo_clip_render_surface (RsvgDrawingCtx *ctx,
+                                cairo_surface_t *surface,
+                                double src_x,
+                                double src_y, 
+                                double w, 
+                                double h)
+{
+}
+
 
 static void
 rsvg_cairo_clip_render_free (RsvgRender * self)
@@ -122,6 +132,7 @@ rsvg_cairo_clip_render_new (cairo_t * cr, RsvgCairoRender *parent)
     render->create_pango_context = rsvg_cairo_create_pango_context;
     render->render_pango_layout = rsvg_cairo_render_pango_layout;
     render->render_image = rsvg_cairo_clip_render_image;
+    render->render_surface = rsvg_cairo_clip_render_surface;
     render->render_path = rsvg_cairo_clip_render_path;
     render->pop_discrete_layer = rsvg_cairo_clip_pop_discrete_layer;
     render->push_discrete_layer = rsvg_cairo_clip_push_discrete_layer;
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 3054a9e..6f4bdd7 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -547,103 +547,61 @@ void
 rsvg_cairo_render_image (RsvgDrawingCtx * ctx, const GdkPixbuf * pixbuf,
                          double pixbuf_x, double pixbuf_y, double w, double h)
 {
+    cairo_surface_t *surface;
+
+    if (pixbuf == NULL)
+        return;
+
+    surface = rsvg_cairo_surface_from_pixbuf (pixbuf);
+    if (surface == NULL)
+        return;
+
+    rsvg_cairo_render_surface (ctx, surface, pixbuf_x, pixbuf_y, w, h);
+    cairo_surface_destroy (surface);
+}
+
+void
+rsvg_cairo_render_surface (RsvgDrawingCtx *ctx, 
+                           cairo_surface_t *surface,
+                           double src_x, 
+                           double src_y, 
+                           double w, 
+                           double h)
+{
     RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
     RsvgState *state = rsvg_current_state (ctx);
 
-    gint width = gdk_pixbuf_get_width (pixbuf);
-    gint height = gdk_pixbuf_get_height (pixbuf);
-    double dwidth = width, dheight = height;
-    guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
-    int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-    int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
-    guchar *cairo_pixels;
-    cairo_format_t format;
-    cairo_surface_t *surface;
+    int width, height;
+    double dwidth, dheight;
     int j;
     RsvgBbox bbox;
 
-    if (pixbuf == NULL)
+    if (surface == NULL)
         return;
 
-    if (n_channels == 3)
-        format = CAIRO_FORMAT_RGB24;
-    else
-        format = CAIRO_FORMAT_ARGB32;
+    g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
 
-    surface = cairo_image_surface_create (format, width, height);
-    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
-        cairo_surface_destroy (surface);
+    dwidth = width = cairo_image_surface_get_width (surface);
+    dheight = height = cairo_image_surface_get_height (surface);
+    if (width == 0 || height == 0)
         return;
-    }
-
-    cairo_pixels = cairo_image_surface_get_data (surface);
 
     rsvg_bbox_init (&bbox, &state->affine);
-    bbox.rect.x = pixbuf_x;
-    bbox.rect.y = pixbuf_y;
+    bbox.rect.x = src_x;
+    bbox.rect.y = src_y;
     bbox.rect.width = w;
     bbox.rect.height = h;
     bbox.virgin = 0;
 
     _set_rsvg_affine (render, &state->affine);
     cairo_scale (render->cr, w / dwidth, h / dheight);
-    pixbuf_x *= dwidth / w;
-    pixbuf_y *= dheight / h;
-
-    for (j = height; j; j--) {
-        guchar *p = gdk_pixels;
-        guchar *q = cairo_pixels;
-
-        if (n_channels == 3) {
-            guchar *end = p + 3 * width;
-
-            while (p < end) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-                q[0] = p[2];
-                q[1] = p[1];
-                q[2] = p[0];
-#else
-                q[1] = p[0];
-                q[2] = p[1];
-                q[3] = p[2];
-#endif
-                p += 3;
-                q += 4;
-            }
-        } else {
-            guchar *end = p + 4 * width;
-            guint t1, t2, t3;
-
-#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END
-
-            while (p < end) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-                MULT (q[0], p[2], p[3], t1);
-                MULT (q[1], p[1], p[3], t2);
-                MULT (q[2], p[0], p[3], t3);
-                q[3] = p[3];
-#else
-                q[0] = p[3];
-                MULT (q[1], p[0], p[3], t1);
-                MULT (q[2], p[1], p[3], t2);
-                MULT (q[3], p[2], p[3], t3);
-#endif
-
-                p += 4;
-                q += 4;
-            }
-
-#undef MULT
-        }
-
-        gdk_pixels += gdk_rowstride;
-        cairo_pixels += 4 * width;
-    }
+    src_x *= dwidth / w;
+    src_y *= dheight / h;
 
     cairo_set_operator (render->cr, state->comp_op);
 
 #if 1
-    cairo_set_source_surface (render->cr, surface, pixbuf_x, pixbuf_y);
+    cairo_set_source_surface (render->cr, surface, src_x, src_y);
 #else
     {
         cairo_pattern_t *pattern;
@@ -652,7 +610,7 @@ rsvg_cairo_render_image (RsvgDrawingCtx * ctx, const GdkPixbuf * pixbuf,
         pattern = cairo_pattern_create_for_surface (surface);
         cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
 
-        cairo_matrix_init_translate (&matrix, -pixbuf_x, -pixbuf_y);
+        cairo_matrix_init_translate (&matrix, -src_x, -src_y);
         cairo_pattern_set_matrix (pattern, &matrix);
 
         cairo_set_source (render->cr, pattern);
@@ -661,7 +619,6 @@ rsvg_cairo_render_image (RsvgDrawingCtx * ctx, const GdkPixbuf * pixbuf,
 #endif
 
     cairo_paint (render->cr);
-    cairo_surface_destroy (surface);
 
     rsvg_bbox_insert (&render->bbox, &bbox);
 }
@@ -1062,3 +1019,94 @@ rsvg_pixbuf_to_cairo (guint8 * pixels, int rowstride, int height)
         }
     }
 }
+
+cairo_surface_t *
+rsvg_cairo_surface_from_pixbuf (const GdkPixbuf *pixbuf)
+{
+    gint width, height, gdk_rowstride, n_channels, cairo_rowstride;
+    guchar *gdk_pixels, *cairo_pixels;
+    cairo_format_t format;
+    cairo_surface_t *surface;
+    int j;
+
+    if (pixbuf == NULL)
+        return NULL;
+
+    width = gdk_pixbuf_get_width (pixbuf);
+    height = gdk_pixbuf_get_height (pixbuf);
+    gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+    gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+    n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+    if (n_channels == 3)
+        format = CAIRO_FORMAT_RGB24;
+    else
+        format = CAIRO_FORMAT_ARGB32;
+
+    surface = cairo_image_surface_create (format, width, height);
+    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
+        cairo_surface_destroy (surface);
+        return;
+    }
+
+    cairo_pixels = cairo_image_surface_get_data (surface);
+    cairo_rowstride = cairo_image_surface_get_stride (surface);
+
+    if (n_channels == 3) {
+        for (j = height; j; j--) {
+            guchar *p = gdk_pixels;
+            guchar *q = cairo_pixels;
+            guchar *end = p + 3 * width;
+
+            while (p < end) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+                q[0] = p[2];
+                q[1] = p[1];
+                q[2] = p[0];
+#else
+                q[1] = p[0];
+                q[2] = p[1];
+                q[3] = p[2];
+#endif
+                p += 3;
+                q += 4;
+            }
+
+            gdk_pixels += gdk_rowstride;
+            cairo_pixels += cairo_rowstride;
+        }
+    } else {
+        for (j = height; j; j--) {
+            guchar *p = gdk_pixels;
+            guchar *q = cairo_pixels;
+            guchar *end = p + 4 * width;
+            guint t1, t2, t3;
+
+#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END
+
+            while (p < end) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+                MULT (q[0], p[2], p[3], t1);
+                MULT (q[1], p[1], p[3], t2);
+                MULT (q[2], p[0], p[3], t3);
+                q[3] = p[3];
+#else
+                q[0] = p[3];
+                MULT (q[1], p[0], p[3], t1);
+                MULT (q[2], p[1], p[3], t2);
+                MULT (q[3], p[2], p[3], t3);
+#endif
+
+                p += 4;
+                q += 4;
+            }
+
+#undef MULT
+            gdk_pixels += gdk_rowstride;
+            cairo_pixels += cairo_rowstride;
+        }
+    }
+
+    cairo_surface_mark_dirty (surface);
+    return surface;
+}
diff --git a/rsvg-cairo-draw.h b/rsvg-cairo-draw.h
index 1728d1c..3a65dc2 100644
--- a/rsvg-cairo-draw.h
+++ b/rsvg-cairo-draw.h
@@ -39,6 +39,8 @@ void         rsvg_cairo_render_path             (RsvgDrawingCtx *ctx,
                                                  const cairo_path_t *path);
 void         rsvg_cairo_render_image            (RsvgDrawingCtx *ctx, const GdkPixbuf * img, 
                                                  double x, double y, double w, double h);
+void         rsvg_cairo_render_surface          (RsvgDrawingCtx *ctx, cairo_surface_t *surface,
+                                                 double x, double y, double w, double h);
 void         rsvg_cairo_push_discrete_layer	    (RsvgDrawingCtx *ctx);
 void         rsvg_cairo_pop_discrete_layer      (RsvgDrawingCtx *ctx);
 void         rsvg_cairo_add_clipping_rect       (RsvgDrawingCtx *ctx,
diff --git a/rsvg-cairo-render.c b/rsvg-cairo-render.c
index db80c48..b0cc1cb 100644
--- a/rsvg-cairo-render.c
+++ b/rsvg-cairo-render.c
@@ -59,6 +59,7 @@ rsvg_cairo_render_new (cairo_t * cr, double width, double height)
     cairo_render->super.create_pango_context = rsvg_cairo_create_pango_context;
     cairo_render->super.render_pango_layout = rsvg_cairo_render_pango_layout;
     cairo_render->super.render_image = rsvg_cairo_render_image;
+    cairo_render->super.render_surface = rsvg_cairo_render_surface;
     cairo_render->super.render_path = rsvg_cairo_render_path;
     cairo_render->super.pop_discrete_layer = rsvg_cairo_pop_discrete_layer;
     cairo_render->super.push_discrete_layer = rsvg_cairo_push_discrete_layer;
diff --git a/rsvg-filter.c b/rsvg-filter.c
index a6bf995..cfc575c 100644
--- a/rsvg-filter.c
+++ b/rsvg-filter.c
@@ -43,7 +43,7 @@
 typedef struct _RsvgFilterPrimitiveOutput RsvgFilterPrimitiveOutput;
 
 struct _RsvgFilterPrimitiveOutput {
-    GdkPixbuf *result;
+    cairo_surface_t *surface;
     RsvgIRect bounds;
     gboolean Rused;
     gboolean Gused;
@@ -57,8 +57,8 @@ struct _RsvgFilterContext {
     gint width, height;
     RsvgFilter *filter;
     GHashTable *results;
-    GdkPixbuf *source;
-    GdkPixbuf *bg;
+    cairo_surface_t *source_surface;
+    cairo_surface_t *bg_surface;
     RsvgFilterPrimitiveOutput lastresult;
     cairo_matrix_t affine;
     cairo_matrix_t paffine;
@@ -152,21 +152,22 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext
     }
 }
 
-static GdkPixbuf *
-_rsvg_pixbuf_new_cleared (int width, int height)
+static cairo_surface_t *
+_rsvg_image_surface_new (int width, int height)
 {
-    GdkPixbuf *pb;
-    guchar *data;
+    cairo_surface_t *surface;
 
-    pb = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8, width, height);
-    data = gdk_pixbuf_get_pixels (pb);
-    memset (data, 0, width * height * 4);
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
+      cairo_surface_destroy (surface);
+      return NULL;
+    }
 
-    return pb;
+    return surface;
 }
 
 static guchar
-gdk_pixbuf_get_interp_pixel (guchar * src, gdouble ox, gdouble oy, guchar ch, RsvgIRect boundarys,
+get_interp_pixel (guchar * src, gdouble ox, gdouble oy, guchar ch, RsvgIRect boundarys,
                              guint rowstride)
 {
     double xmod, ymod;
@@ -226,8 +227,8 @@ rsvg_filter_fix_coordinate_system (RsvgFilterContext * ctx, RsvgState * state, R
     width = bbox->rect.width;
     height = bbox->rect.height;
 
-    ctx->width = gdk_pixbuf_get_width (ctx->source);
-    ctx->height = gdk_pixbuf_get_height (ctx->source);
+    ctx->width = cairo_image_surface_get_width (ctx->source_surface);
+    ctx->height = cairo_image_surface_get_height (ctx->source_surface);
 
     ctx->affine = state->affine;
     if (ctx->filter->filterunits == objectBoundingBox) {
@@ -244,8 +245,14 @@ rsvg_filter_fix_coordinate_system (RsvgFilterContext * ctx, RsvgState * state, R
 }
 
 static void
-rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
-                gint srcheight, GdkPixbuf * dst, gint dstx, gint dsty)
+rsvg_alpha_blt (cairo_surface_t *src,
+                gint srcx,
+                gint srcy,
+                gint srcwidth,
+                gint srcheight,
+                cairo_surface_t *dst,
+                gint dstx,
+                gint dsty)
 {
     gint rightx;
     gint bottomy;
@@ -266,19 +273,19 @@ rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
     rightx = srcx + srcwidth;
     bottomy = srcy + srcheight;
 
-    if (rightx > gdk_pixbuf_get_width (src))
-        rightx = gdk_pixbuf_get_width (src);
-    if (bottomy > gdk_pixbuf_get_height (src))
-        bottomy = gdk_pixbuf_get_height (src);
+    if (rightx > cairo_image_surface_get_width (src))
+        rightx = cairo_image_surface_get_width (src);
+    if (bottomy > cairo_image_surface_get_height (src))
+        bottomy = cairo_image_surface_get_height (src);
     srcwidth = rightx - srcx;
     srcheight = bottomy - srcy;
 
     rightx = dstx + dstwidth;
     bottomy = dsty + dstheight;
-    if (rightx > gdk_pixbuf_get_width (dst))
-        rightx = gdk_pixbuf_get_width (dst);
-    if (bottomy > gdk_pixbuf_get_height (dst))
-        bottomy = gdk_pixbuf_get_height (dst);
+    if (rightx > cairo_image_surface_get_width (dst))
+        rightx = cairo_image_surface_get_width (dst);
+    if (bottomy > cairo_image_surface_get_height (dst))
+        bottomy = cairo_image_surface_get_height (dst);
     dstwidth = rightx - dstx;
     dstheight = bottomy - dsty;
 
@@ -312,11 +319,11 @@ rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
     if (dstoffsety > srcoffsety)
         srcoffsety = dstoffsety;
 
-    srcrowstride = gdk_pixbuf_get_rowstride (src);
-    dstrowstride = gdk_pixbuf_get_rowstride (dst);
+    srcrowstride = cairo_image_surface_get_stride (src);
+    dstrowstride = cairo_image_surface_get_stride (dst);
 
-    src_pixels = gdk_pixbuf_get_pixels (src);
-    dst_pixels = gdk_pixbuf_get_pixels (dst);
+    src_pixels = cairo_image_surface_get_data (src);
+    dst_pixels = cairo_image_surface_get_data (dst);
 
     for (y = srcoffsety; y < srcheight; y++)
         for (x = srcoffsetx; x < srcwidth; x++) {
@@ -340,11 +347,16 @@ rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
                 }
             }
         }
+
+    cairo_surface_mark_dirty (dst);
 }
 
-static void
-rsvg_art_affine_image (const GdkPixbuf * img, GdkPixbuf * intermediate,
-                       cairo_matrix_t *affine, double w, double h)
+static gboolean
+rsvg_art_affine_image (cairo_surface_t *img, 
+                       cairo_surface_t *intermediate,
+                       cairo_matrix_t *affine, 
+                       double w, 
+                       double h)
 {
     cairo_matrix_t inv_affine, raw_inv_affine;
     gint intstride;
@@ -361,27 +373,29 @@ rsvg_art_affine_image (const GdkPixbuf * img, GdkPixbuf * intermediate,
     gint iwidth, iheight;
     gint width, height;
 
-    width = gdk_pixbuf_get_width (img);
-    height = gdk_pixbuf_get_height (img);
-    iwidth = gdk_pixbuf_get_width (intermediate);
-    iheight = gdk_pixbuf_get_height (intermediate);
+    g_assert (cairo_image_surface_get_format (intermediate) == CAIRO_FORMAT_ARGB32);
 
-    has_alpha = gdk_pixbuf_get_has_alpha (img);
+    width = cairo_image_surface_get_width (img);
+    height = cairo_image_surface_get_height (img);
+    iwidth = cairo_image_surface_get_width (intermediate);
+    iheight = cairo_image_surface_get_height (intermediate);
 
-    basestride = gdk_pixbuf_get_rowstride (img);
-    intstride = gdk_pixbuf_get_rowstride (intermediate);
-    basepix = gdk_pixbuf_get_pixels (img);
-    intpix = gdk_pixbuf_get_pixels (intermediate);
+    has_alpha = cairo_image_surface_get_format (img) == CAIRO_FORMAT_ARGB32;
+
+    basestride = cairo_image_surface_get_stride (img);
+    intstride = cairo_image_surface_get_stride (intermediate);
+    basepix = cairo_image_surface_get_data (img);
+    intpix = cairo_image_surface_get_data (intermediate);
     basebpp = has_alpha ? 4 : 3;
 
     raw_inv_affine = *affine;
     if (cairo_matrix_invert (&raw_inv_affine) != CAIRO_STATUS_SUCCESS)
-      return;
+      return FALSE;
 
     cairo_matrix_init_scale (&inv_affine, w, h);
     cairo_matrix_multiply (&inv_affine, &inv_affine, affine);
     if (cairo_matrix_invert (&inv_affine) != CAIRO_STATUS_SUCCESS)
-      return;
+      return FALSE;
 
     /*apply the transformation */
     for (i = 0; i < iwidth; i++)
@@ -430,6 +444,12 @@ rsvg_art_affine_image (const GdkPixbuf * img, GdkPixbuf * intermediate,
             }
 
         }
+
+    /* Don't need cairo_surface_mark_dirty(intermediate) here since
+     * the only caller does further work and then calls that himself.
+     */
+
+    return TRUE;
 }
 
 static void
@@ -438,7 +458,7 @@ rsvg_filter_free_pair (gpointer value)
     RsvgFilterPrimitiveOutput *output;
 
     output = (RsvgFilterPrimitiveOutput *) value;
-    g_object_unref (output->result);
+    cairo_surface_destroy (output->surface);
     g_free (output);
 }
 
@@ -448,23 +468,14 @@ rsvg_filter_context_free (RsvgFilterContext * ctx)
     if (!ctx)
 	return;
 
-    if (ctx->bg)
-	g_object_unref (ctx->bg);
+    if (ctx->bg_surface)
+        cairo_surface_destroy (ctx->bg_surface);
 
     g_free (ctx);
 }
 
-static void
-unref_surface (guchar *pixels,
-               gpointer user_data)
-{
-  cairo_surface_t *surface = user_data;
-
-  cairo_surface_destroy (surface);
-}
-
 /**
- * rsvg_filter_render: Create a new pixbuf applied the filter.
+ * rsvg_filter_render: Create a new surface applied the filter.
  * @self: a pointer to the filter to use
  * @source: the a #cairo_surface_t of type %CAIRO_SURFACE_TYPE_IMAGE
  * @context: the context
@@ -481,36 +492,24 @@ rsvg_filter_render (RsvgFilter *self,
                     RsvgBbox *bounds, 
                     char *channelmap)
 {
-    static const cairo_user_data_key_t surface_pixel_data_key;
     RsvgFilterContext *ctx;
     RsvgFilterPrimitive *current;
     guint i;
-    GdkPixbuf *in, *out;
     cairo_surface_t *output;
 
     g_return_val_if_fail (source != NULL, NULL);
     g_return_val_if_fail (cairo_surface_get_type (source) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
 
-    in = gdk_pixbuf_new_from_data (cairo_image_surface_get_data (source),
-                                   GDK_COLORSPACE_RGB,
-                                   cairo_image_surface_get_format (source) == CAIRO_FORMAT_ARGB32,
-                                   8,
-                                   cairo_image_surface_get_width (source),
-                                   cairo_image_surface_get_height (source),
-                                   cairo_image_surface_get_stride (source),
-                                   (GdkPixbufDestroyNotify) unref_surface,
-                                   cairo_surface_reference (source));
-
     ctx = g_new (RsvgFilterContext, 1);
     ctx->filter = self;
-    ctx->source = in;
-    ctx->bg = NULL;
+    ctx->source_surface = source;
+    ctx->bg_surface = NULL;
     ctx->results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, rsvg_filter_free_pair);
     ctx->ctx = context;
 
     rsvg_filter_fix_coordinate_system (ctx, rsvg_current_state (context), bounds);
 
-    ctx->lastresult.result = in;
+    ctx->lastresult.surface = source;
     ctx->lastresult.Rused = 1;
     ctx->lastresult.Gused = 1;
     ctx->lastresult.Bused = 1;
@@ -526,23 +525,12 @@ rsvg_filter_render (RsvgFilter *self,
             rsvg_filter_primitive_render (current, ctx);
     }
 
-    out = ctx->lastresult.result;
+    output = ctx->lastresult.surface;
 
     g_hash_table_destroy (ctx->results);
 
     rsvg_filter_context_free (ctx);
 
-    output = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (out),
-                                                  gdk_pixbuf_get_has_alpha (out) ? CAIRO_FORMAT_ARGB32 
-                                                                                 : CAIRO_FORMAT_RGB24,
-                                                  gdk_pixbuf_get_width (out),
-                                                  gdk_pixbuf_get_height (out),
-                                                  gdk_pixbuf_get_rowstride (out));
-    /* Also keep a reference to the pixbuf which owns the pixels */
-    cairo_surface_set_user_data (output, &surface_pixel_data_key,
-                                 out /* adopt */,
-                                 (cairo_destroy_func_t) g_object_unref);
-
     return output;
 }
 
@@ -560,22 +548,24 @@ rsvg_filter_store_output (GString * name, RsvgFilterPrimitiveOutput result, Rsvg
 {
     RsvgFilterPrimitiveOutput *store;
 
-    g_object_unref (ctx->lastresult.result);
+    cairo_surface_destroy (ctx->lastresult.surface);
 
     store = g_new (RsvgFilterPrimitiveOutput, 1);
     *store = result;
 
-    if (strcmp (name->str, "")) {
-        g_object_ref (result.result);        /* increments the references for the table */
+    if (name->str[0] != '\0') {
+        cairo_surface_reference (result.surface);        /* increments the references for the table */
         g_hash_table_insert (ctx->results, g_strdup (name->str), store);
     }
 
-    g_object_ref (result.result);    /* increments the references for the last result */
+    cairo_surface_reference (result.surface);    /* increments the references for the last result */
     ctx->lastresult = result;
 }
 
 static void
-rsvg_filter_store_result (GString * name, GdkPixbuf * result, RsvgFilterContext * ctx)
+rsvg_filter_store_result (GString * name,
+                          cairo_surface_t *surface,
+                          RsvgFilterContext * ctx)
 {
     RsvgFilterPrimitiveOutput output;
     output.Rused = 1;
@@ -586,57 +576,48 @@ rsvg_filter_store_result (GString * name, GdkPixbuf * result, RsvgFilterContext
     output.bounds.y0 = 0;
     output.bounds.x1 = ctx->width;
     output.bounds.y1 = ctx->height;
-    output.result = result;
+    output.surface = surface;
 
     rsvg_filter_store_output (name, output, ctx);
 }
 
-static GdkPixbuf *
-pixbuf_get_alpha (GdkPixbuf * pb, RsvgFilterContext * ctx)
+static cairo_surface_t *
+surface_get_alpha (cairo_surface_t *source,
+                   RsvgFilterContext * ctx)
 {
     guchar *data;
     guchar *pbdata;
-    GdkPixbuf *output;
-
     gsize i, pbsize;
+    cairo_surface_t *surface;
 
-    pbsize = gdk_pixbuf_get_width (pb) * gdk_pixbuf_get_height (pb);
+    pbsize = cairo_image_surface_get_width (source) * 
+             cairo_image_surface_get_height (source);
 
-    output = _rsvg_pixbuf_new_cleared (
-                                       gdk_pixbuf_get_width (pb), gdk_pixbuf_get_height (pb));
+    surface = _rsvg_image_surface_new (cairo_image_surface_get_width (source),
+                                       cairo_image_surface_get_height (source));
 
-    data = gdk_pixbuf_get_pixels (output);
-    pbdata = gdk_pixbuf_get_pixels (pb);
+    data = cairo_image_surface_get_data (surface);
+    pbdata = cairo_image_surface_get_data (source);
 
+    /* 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]];
 
-    return output;
+    cairo_surface_mark_dirty (surface);
+    return surface;
 }
 
-static GdkPixbuf *
+static cairo_surface_t *
 rsvg_compile_bg (RsvgDrawingCtx * ctx)
 {
     RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
-    cairo_t *cr;
     cairo_surface_t *surface;
+    cairo_t *cr;
     GList *i;
-    unsigned char *pixels = g_new0 (guint8, render->width * render->height * 4);
-    int rowstride = render->width * 4;
-
-    GdkPixbuf *output = gdk_pixbuf_new_from_data (pixels,
-                                                  GDK_COLORSPACE_RGB, TRUE, 8,
-                                                  render->width, render->height,
-                                                  rowstride,
-                                                  (GdkPixbufDestroyNotify) g_free,
-                                                  NULL);
 
-    surface = cairo_image_surface_create_for_data (pixels,
-                                                   CAIRO_FORMAT_ARGB32,
-                                                   render->width, render->height, rowstride);
+    surface = _rsvg_image_surface_new (render->width, render->height);
 
     cr = cairo_create (surface);
-    cairo_surface_destroy (surface);
 
     for (i = g_list_last (render->cr_stack); i != NULL; i = g_list_previous (i)) {
         cairo_t *draw = i->data;
@@ -648,25 +629,32 @@ rsvg_compile_bg (RsvgDrawingCtx * ctx)
     }
 
     cairo_destroy (cr);
-    return output;
+
+    return surface;
 }
 
-static GdkPixbuf *
+/**
+ * rsvg_filter_get_bg:
+ * 
+ * Returns: (transfer none): a #cairo_surface_t, or %NULL
+ */
+static cairo_surface_t *
 rsvg_filter_get_bg (RsvgFilterContext * ctx)
 {
-    if (!ctx->bg)
-	ctx->bg = rsvg_compile_bg (ctx->ctx);
+    if (!ctx->bg_surface)
+        ctx->bg_surface = rsvg_compile_bg (ctx->ctx);
 
-    return ctx->bg;
+    return ctx->bg_surface;
 }
 
+/* FIXMEchpe: proper return value and out param! */
 /**
- * rsvg_filter_get_in: Gets a pixbuf for a primative.
- * @name: The name of the pixbuf
+ * rsvg_filter_get_in: Gets a surface for a primitive
+ * @name: The name of the surface
  * @ctx: the context that this was called in
- *
+ * @
  * Returns: a pointer to the result that the name refers to, a special
- * Pixbuf if the name is a special keyword or NULL if nothing was found
+ * surface if the name is a special keyword or NULL if nothing was found
  **/
 static RsvgFilterPrimitiveOutput
 rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx)
@@ -676,27 +664,28 @@ rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx)
     output.bounds.x0 = output.bounds.x1 = output.bounds.y0 = output.bounds.y1 = 0;
 
     if (!strcmp (name->str, "SourceGraphic")) {
-        g_object_ref (ctx->source);
-        output.result = ctx->source;
+        output.surface = cairo_surface_reference (ctx->source_surface);
         output.Rused = output.Gused = output.Bused = output.Aused = 1;
         return output;
     } else if (!strcmp (name->str, "BackgroundImage")) {
-        output.result = g_object_ref (rsvg_filter_get_bg (ctx));
+        /* FIXMEchpe: cope with NULL? */
+        output.surface = cairo_surface_reference (rsvg_filter_get_bg (ctx));
         output.Rused = output.Gused = output.Bused = output.Aused = 1;
         return output;
     } else if (!strcmp (name->str, "") || !strcmp (name->str, "none") || !name) {
-        g_object_ref (ctx->lastresult.result);
         output = ctx->lastresult;
+        cairo_surface_reference (output.surface);
         return output;
     } else if (!strcmp (name->str, "SourceAlpha")) {
         output.Rused = output.Gused = output.Bused = 0;
         output.Aused = 1;
-        output.result = pixbuf_get_alpha (ctx->source, ctx);
+        output.surface = surface_get_alpha (ctx->source_surface, ctx);
         return output;
     } else if (!strcmp (name->str, "BackgroundAlpha")) {
         output.Rused = output.Gused = output.Bused = 0;
         output.Aused = 1;
-        output.result = pixbuf_get_alpha (rsvg_filter_get_bg (ctx), ctx);
+        /* FIXMEchpe: cope with NULL ? */
+        output.surface = surface_get_alpha (rsvg_filter_get_bg (ctx), ctx);
         return output;
     }
 
@@ -704,22 +693,28 @@ rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx)
 
     if (outputpointer != NULL) {
         output = *outputpointer;
-        g_object_ref (output.result);
+        cairo_surface_reference (output.surface);
         return output;
     }
 
     /* g_warning (_("%s not found\n"), name->str); */
 
     output = ctx->lastresult;
-    g_object_ref (ctx->lastresult.result);
+    cairo_surface_reference (output.surface);
     return output;
 }
 
-
-static GdkPixbuf *
+/**
+ * rsvg_filter_get_in:
+ * @name:
+ * @ctx:
+ * 
+ * Returns: (transfer full): a new #cairo_surface_t, or %NULL
+ */
+static cairo_surface_t *
 rsvg_filter_get_in (GString * name, RsvgFilterContext * ctx)
 {
-    return rsvg_filter_get_result (name, ctx).result;
+    return rsvg_filter_get_result (name, ctx).surface;
 }
 
 /**
@@ -820,8 +815,12 @@ struct _RsvgFilterPrimitiveBlend {
 };
 
 static void
-rsvg_filter_blend (RsvgFilterPrimitiveBlendMode mode, GdkPixbuf * in, GdkPixbuf * in2,
-                   GdkPixbuf * output, RsvgIRect boundarys, int *channelmap)
+rsvg_filter_blend (RsvgFilterPrimitiveBlendMode mode, 
+                   cairo_surface_t *in, 
+                   cairo_surface_t *in2,
+                   cairo_surface_t* output, 
+                   RsvgIRect boundarys, 
+                   int *channelmap)
 {
     guchar i;
     gint x, y;
@@ -829,15 +828,15 @@ rsvg_filter_blend (RsvgFilterPrimitiveBlendMode mode, GdkPixbuf * in, GdkPixbuf
     guchar *in_pixels;
     guchar *in2_pixels;
     guchar *output_pixels;
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
-    rowstride = gdk_pixbuf_get_rowstride (in);
-    rowstride2 = gdk_pixbuf_get_rowstride (in2);
-    rowstrideo = gdk_pixbuf_get_rowstride (output);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
+    rowstride = cairo_image_surface_get_stride (in);
+    rowstride2 = cairo_image_surface_get_stride (in2);
+    rowstrideo = cairo_image_surface_get_stride (output);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
-    in_pixels = gdk_pixbuf_get_pixels (in);
-    in2_pixels = gdk_pixbuf_get_pixels (in2);
+    output_pixels = cairo_image_surface_get_data (output);
+    in_pixels = cairo_image_surface_get_data (in);
+    in2_pixels = cairo_image_surface_get_data (in2);
 
     if (boundarys.x0 < 0)
         boundarys.x0 = 0;
@@ -927,8 +926,9 @@ rsvg_filter_blend (RsvgFilterPrimitiveBlendMode mode, GdkPixbuf * in, GdkPixbuf
             }
             output_pixels[4 * x + y * rowstrideo + channelmap[3]] = qr * 255.0;
         }
-}
 
+    cairo_surface_mark_dirty (output);
+}
 
 static void
 rsvg_filter_primitive_blend_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
@@ -937,9 +937,7 @@ rsvg_filter_primitive_blend_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     RsvgFilterPrimitiveBlend *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
-    GdkPixbuf *in2;
+    cairo_surface_t *output, *in, *in2;
 
     upself = (RsvgFilterPrimitiveBlend *) self;
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
@@ -947,17 +945,16 @@ rsvg_filter_primitive_blend_render (RsvgFilterPrimitive * self, RsvgFilterContex
     in = rsvg_filter_get_in (self->in, ctx);
     in2 = rsvg_filter_get_in (upself->in2, ctx);
 
-    output =
-        _rsvg_pixbuf_new_cleared ( gdk_pixbuf_get_width (in),
-                                  gdk_pixbuf_get_height (in));
+    output = _rsvg_image_surface_new (cairo_image_surface_get_width (in),
+                                      cairo_image_surface_get_height (in));
 
     rsvg_filter_blend (upself->mode, in, in2, output, boundarys, ctx->channelmap);
 
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (in2);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (in2);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -1060,8 +1057,7 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgFilterPrimitive * self, RsvgFi
 
     RsvgFilterPrimitiveConvolveMatrix *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     gint sx, sy, kx, ky;
     guchar sval;
@@ -1074,10 +1070,10 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgFilterPrimitive * self, RsvgFi
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
     targetx = upself->targetx * ctx->paffine.xx;
     targety = upself->targety * ctx->paffine.yy;
@@ -1088,10 +1084,10 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgFilterPrimitive * self, RsvgFi
     } else
         dx = dy = 1;
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output = _rsvg_image_surface_new (width, height);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
@@ -1155,10 +1151,13 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgFilterPrimitive * self, RsvgFi
                     output_pixels[4 * x + y * rowstride + ctx->channelmap[3]] / 255;
             }
         }
+
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -1298,8 +1297,13 @@ struct _RsvgFilterPrimitiveGaussianBlur {
 };
 
 static void
-box_blur (GdkPixbuf * in, GdkPixbuf * output, guchar * intermediate, gint kw,
-          gint kh, RsvgIRect boundarys, RsvgFilterPrimitiveOutput op)
+box_blur (cairo_surface_t *in, 
+          cairo_surface_t *output, 
+          guchar *intermediate, 
+          gint kw,
+          gint kh, 
+          RsvgIRect boundarys, 
+          RsvgFilterPrimitiveOutput op)
 {
     gint ch;
     gint x, y;
@@ -1308,10 +1312,10 @@ box_blur (GdkPixbuf * in, GdkPixbuf * output, guchar * intermediate, gint kw,
     guchar *output_pixels;
     gint sum;
 
-    in_pixels = gdk_pixbuf_get_pixels (in);
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    in_pixels = cairo_image_surface_get_data (in);
+    output_pixels = cairo_image_surface_get_data (output);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
     if (kw > boundarys.x1 - boundarys.x0)
         kw = boundarys.x1 - boundarys.x0;
@@ -1404,8 +1408,12 @@ box_blur (GdkPixbuf * in, GdkPixbuf * output, guchar * intermediate, gint kw,
 }
 
 static void
-fast_blur (GdkPixbuf * in, GdkPixbuf * output, gfloat sx,
-           gfloat sy, RsvgIRect boundarys, RsvgFilterPrimitiveOutput op)
+fast_blur (cairo_surface_t *in, 
+           cairo_surface_t *output, 
+           gfloat sx,
+           gfloat sy, 
+           RsvgIRect boundarys, 
+           RsvgFilterPrimitiveOutput op)
 {
     gint kx, ky;
     guchar *intermediate;
@@ -1423,15 +1431,15 @@ fast_blur (GdkPixbuf * in, GdkPixbuf * output, gfloat sx,
     box_blur (output, output, intermediate, kx, ky, boundarys, op);
 
     g_free (intermediate);
+
+    cairo_surface_mark_dirty (output);
 }
 
 static void
 rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
 {
     RsvgFilterPrimitiveGaussianBlur *upself;
-
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
     RsvgIRect boundarys;
     gfloat sdx, sdy;
     RsvgFilterPrimitiveOutput op;
@@ -1440,10 +1448,10 @@ rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, RsvgFilt
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     op = rsvg_filter_get_result (self->in, ctx);
-    in = op.result;
+    in = op.surface;
 
-    output = _rsvg_pixbuf_new_cleared (
-                                       gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in));
+    output = _rsvg_image_surface_new (cairo_image_surface_get_width (in), 
+                                      cairo_image_surface_get_height (in));
 
     /* scale the SD values */
     sdx = upself->sdx * ctx->paffine.xx;
@@ -1451,12 +1459,12 @@ rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, RsvgFilt
 
     fast_blur (in, output, sdx, sdy, boundarys, op);
 
-    op.result = output;
+    op.surface = output;
     op.bounds = boundarys;
     rsvg_filter_store_output (self->result, op, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -1541,8 +1549,7 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterConte
     RsvgFilterPrimitiveOutput out;
     RsvgFilterPrimitiveOffset *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     double dx, dy;
     int ox, oy;
@@ -1551,16 +1558,16 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterConte
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
+    output = _rsvg_image_surface_new (width, height);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     dx = _rsvg_css_normalize_length (&upself->dx, ctx->ctx, 'w');
     dy = _rsvg_css_normalize_length (&upself->dy, ctx->ctx, 'v');
@@ -1581,7 +1588,9 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterConte
             }
         }
 
-    out.result = output;
+    cairo_surface_mark_dirty (output);
+
+    out.surface = output;
     out.Rused = 1;
     out.Gused = 1;
     out.Bused = 1;
@@ -1590,8 +1599,8 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterConte
 
     rsvg_filter_store_output (self->result, out, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy  (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -1670,13 +1679,12 @@ rsvg_filter_primitive_merge_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     RsvgFilterPrimitiveMerge *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     upself = (RsvgFilterPrimitiveMerge *) self;
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
-    output = _rsvg_pixbuf_new_cleared ( ctx->width, ctx->height);
+    output = _rsvg_image_surface_new (ctx->width, ctx->height);
 
     for (i = 0; i < upself->super.super.children->len; i++) {
         RsvgFilterPrimitive *mn;
@@ -1686,12 +1694,12 @@ rsvg_filter_primitive_merge_render (RsvgFilterPrimitive * self, RsvgFilterContex
         in = rsvg_filter_get_in (mn->in, ctx);
         rsvg_alpha_blt (in, boundarys.x0, boundarys.y0, boundarys.x1 - boundarys.x0,
                         boundarys.y1 - boundarys.y0, output, boundarys.x0, boundarys.y0);
-        g_object_unref (in);
+        cairo_surface_destroy (in);
     }
 
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (output);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -1810,8 +1818,7 @@ rsvg_filter_primitive_colour_matrix_render (RsvgFilterPrimitive * self, RsvgFilt
 
     RsvgFilterPrimitiveColourMatrix *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     int sum;
 
@@ -1819,15 +1826,15 @@ rsvg_filter_primitive_colour_matrix_render (RsvgFilterPrimitive * self, RsvgFilt
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output = _rsvg_image_surface_new (width, height);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
@@ -1874,10 +1881,12 @@ rsvg_filter_primitive_colour_matrix_render (RsvgFilterPrimitive * self, RsvgFilt
             }
         }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy(output);
 }
 
 static void
@@ -2130,8 +2139,7 @@ rsvg_filter_primitive_component_transfer_render (RsvgFilterPrimitive *
     gint achan = ctx->channelmap[3];
     guchar *in_pixels;
     guchar *output_pixels;
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
@@ -2157,16 +2165,16 @@ rsvg_filter_primitive_component_transfer_render (RsvgFilterPrimitive *
     }
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
+    output = _rsvg_image_surface_new (width, height);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
@@ -2193,10 +2201,13 @@ rsvg_filter_primitive_component_transfer_render (RsvgFilterPrimitive *
                     outpix[ctx->channelmap[c]] * outpix[achan] / 255;
             output_pixels[y * rowstride + x * 4 + achan] = outpix[achan];
         }
+
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -2340,8 +2351,7 @@ rsvg_filter_primitive_erode_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     RsvgFilterPrimitiveErode *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     gint kx, ky;
     guchar val;
@@ -2350,20 +2360,20 @@ rsvg_filter_primitive_erode_render (RsvgFilterPrimitive * self, RsvgFilterContex
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
     /* scale the radius values */
     kx = upself->rx * ctx->paffine.xx;
     ky = upself->ry * ctx->paffine.yy;
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
+    output = _rsvg_image_surface_new (width, height);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++)
@@ -2391,10 +2401,13 @@ rsvg_filter_primitive_erode_render (RsvgFilterPrimitive * self, RsvgFilterContex
                     }
                 output_pixels[y * rowstride + x * 4 + ch] = extreme;
             }
+
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -2493,25 +2506,23 @@ rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, RsvgFilterCo
 
     RsvgFilterPrimitiveComposite *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
-    GdkPixbuf *in2;
+    cairo_surface_t *output, *in, *in2;
 
     upself = (RsvgFilterPrimitiveComposite *) self;
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
     in2 = rsvg_filter_get_in (upself->in2, ctx);
-    in2_pixels = gdk_pixbuf_get_pixels (in2);
+    in2_pixels = cairo_image_surface_get_data (in2);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output = _rsvg_image_surface_new (width, height);
+    output_pixels = cairo_image_surface_get_data (output);
 
     if (upself->mode == COMPOSITE_MODE_ARITHMETIC)
         for (y = boundarys.y0; y < boundarys.y1; y++)
@@ -2599,11 +2610,13 @@ rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, RsvgFilterCo
                 output_pixels[4 * x + y * rowstride + 3] = qr;
             }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (in2);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (in2);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -2701,7 +2714,7 @@ rsvg_filter_primitive_flood_render (RsvgFilterPrimitive * self, RsvgFilterContex
     gint rowstride, height, width;
     RsvgIRect boundarys;
     guchar *output_pixels;
-    GdkPixbuf *output;
+    cairo_surface_t *output;
     char pixcolour[4];
     RsvgFilterPrimitiveOutput out;
 
@@ -2712,10 +2725,10 @@ rsvg_filter_primitive_flood_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     height = ctx->height;
     width = ctx->width;
-    output = _rsvg_pixbuf_new_cleared ( width, height);
-    rowstride = gdk_pixbuf_get_rowstride (output);
+    output = _rsvg_image_surface_new (width, height);
+    rowstride = cairo_image_surface_get_stride (output);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (i = 0; i < 3; i++)
         pixcolour[i] = (int) (((unsigned char *)
@@ -2727,7 +2740,9 @@ rsvg_filter_primitive_flood_render (RsvgFilterPrimitive * self, RsvgFilterContex
             for (i = 0; i < 4; i++)
                 output_pixels[4 * x + y * rowstride + ctx->channelmap[i]] = pixcolour[i];
 
-    out.result = output;
+    cairo_surface_mark_dirty (output);
+
+    out.surface = output;
     out.Rused = 1;
     out.Gused = 1;
     out.Bused = 1;
@@ -2736,7 +2751,7 @@ rsvg_filter_primitive_flood_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     rsvg_filter_store_output (self->result, out, ctx);
 
-    g_object_unref (output);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -2815,9 +2830,7 @@ rsvg_filter_primitive_displacement_map_render (RsvgFilterPrimitive * self, RsvgF
 
     RsvgFilterPrimitiveDisplacementMap *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
-    GdkPixbuf *in2;
+    cairo_surface_t *output, *in, *in2;
 
     double ox, oy;
 
@@ -2825,19 +2838,19 @@ rsvg_filter_primitive_displacement_map_render (RsvgFilterPrimitive * self, RsvgF
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
     in2 = rsvg_filter_get_in (upself->in2, ctx);
-    in2_pixels = gdk_pixbuf_get_pixels (in2);
+    in2_pixels = cairo_image_surface_get_data (in2);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
+    output = _rsvg_image_surface_new (width, height);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     switch (upself->xChannelSelector) {
     case 'R':
@@ -2891,15 +2904,17 @@ rsvg_filter_primitive_displacement_map_render (RsvgFilterPrimitive * self, RsvgF
 
             for (ch = 0; ch < 4; ch++) {
                 output_pixels[y * rowstride + x * 4 + ch] =
-                    gdk_pixbuf_get_interp_pixel (in_pixels, ox, oy, ch, boundarys, rowstride);
+                    get_interp_pixel (in_pixels, ox, oy, ch, boundarys, rowstride);
             }
         }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (in2);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (in2);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -3214,18 +3229,17 @@ rsvg_filter_primitive_turbulence_render (RsvgFilterPrimitive * self, RsvgFilterC
     gint x, y, tileWidth, tileHeight, rowstride, width, height;
     RsvgIRect boundarys;
     guchar *output_pixels;
-    GdkPixbuf *output;
+    cairo_surface_t *output, *in;
     cairo_matrix_t affine;
-    GdkPixbuf *in;
 
     affine = ctx->paffine;
     if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
       return;
 
     in = rsvg_filter_get_in (self->in, ctx);
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
     upself = (RsvgFilterPrimitiveTurbulence *) self;
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
@@ -3233,8 +3247,8 @@ rsvg_filter_primitive_turbulence_render (RsvgFilterPrimitive * self, RsvgFilterC
     tileWidth = (boundarys.x1 - boundarys.x0);
     tileHeight = (boundarys.y1 - boundarys.y0);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output = _rsvg_image_surface_new (width, height);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (y = 0; y < tileHeight; y++) {
         for (x = 0; x < tileWidth; x++) {
@@ -3268,10 +3282,12 @@ rsvg_filter_primitive_turbulence_render (RsvgFilterPrimitive * self, RsvgFilterC
         }
     }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -3357,7 +3373,7 @@ struct _RsvgFilterPrimitiveImage {
     GString *href;
 };
 
-static GdkPixbuf *
+static cairo_surface_t *
 rsvg_filter_primitive_image_render_in (RsvgFilterPrimitive * self, RsvgFilterContext * context)
 {
     RsvgDrawingCtx *ctx;
@@ -3377,17 +3393,16 @@ rsvg_filter_primitive_image_render_in (RsvgFilterPrimitive * self, RsvgFilterCon
 
     rsvg_current_state (ctx)->affine = context->paffine;
 
-    return rsvg_get_image_of_node (ctx, drawable, context->width, context->height);
+    return rsvg_get_surface_of_node (ctx, drawable, context->width, context->height);
 }
 
-static GdkPixbuf *
+static cairo_surface_t *
 rsvg_filter_primitive_image_render_ext (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
 {
     RsvgIRect boundarys;
     RsvgFilterPrimitiveImage *upself;
-    GdkPixbuf *img;
+    cairo_surface_t *img, *intermediate;
     int i;
-    GdkPixbuf *intermediate;
     unsigned char *pixels;
     int channelmap[4];
     int length;
@@ -3405,31 +3420,30 @@ rsvg_filter_primitive_image_render_ext (RsvgFilterPrimitive * self, RsvgFilterCo
     if (width == 0 || height == 0)
         return NULL;
 
-    img = rsvg_pixbuf_new_from_href (upself->href->str,
-                                     rsvg_handle_get_base_uri (upself->ctx), NULL);
-
+    img = rsvg_cairo_surface_new_from_href (upself->href->str,
+                                            rsvg_handle_get_base_uri (upself->ctx), 
+                                            NULL);
     if (!img)
         return NULL;
 
-    intermediate = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8, width, height);
-
-
-    rsvg_art_affine_image (img, intermediate,
-                           &ctx->paffine,
-                           (gdouble) width / ctx->paffine.xx,
-                           (gdouble) height / ctx->paffine.yy);
-
-    if (!intermediate) {
-        g_object_unref (img);
+    intermediate = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    if (cairo_surface_status (intermediate) != CAIRO_STATUS_SUCCESS ||
+        !rsvg_art_affine_image (img, intermediate,
+                                &ctx->paffine,
+                                (gdouble) width / ctx->paffine.xx,
+                                (gdouble) height / ctx->paffine.yy)) {
+        cairo_surface_destroy (intermediate);
+        cairo_surface_destroy (img);
         return NULL;
     }
 
-    g_object_unref (img);
+    cairo_surface_destroy (img);
 
-    length = gdk_pixbuf_get_height (intermediate) * gdk_pixbuf_get_rowstride (intermediate);
+    length = cairo_image_surface_get_height (intermediate) * 
+             cairo_image_surface_get_stride (intermediate);
     for (i = 0; i < 4; i++)
         channelmap[i] = ctx->channelmap[i];
-    pixels = gdk_pixbuf_get_pixels (intermediate);
+    pixels = cairo_image_surface_get_data (intermediate);
     for (i = 0; i < length; i += 4) {
         unsigned char alpha;
         unsigned char pixel[4];
@@ -3447,8 +3461,8 @@ rsvg_filter_primitive_image_render_ext (RsvgFilterPrimitive * self, RsvgFilterCo
             pixels[i + ch] = pixel[ch];
     }
 
+    cairo_surface_mark_dirty (intermediate);
     return intermediate;
-
 }
 
 static void
@@ -3457,8 +3471,9 @@ rsvg_filter_primitive_image_render (RsvgFilterPrimitive * self, RsvgFilterContex
     RsvgIRect boundarys;
     RsvgFilterPrimitiveImage *upself;
     RsvgFilterPrimitiveOutput op;
+    int x, y;
 
-    GdkPixbuf *output, *img;
+    cairo_surface_t *output, *img;
 
     upself = (RsvgFilterPrimitiveImage *) self;
 
@@ -3467,24 +3482,35 @@ rsvg_filter_primitive_image_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
-    output = _rsvg_pixbuf_new_cleared ( ctx->width, ctx->height);
+    output = _rsvg_image_surface_new (ctx->width, ctx->height);
+    if (output == NULL)
+        return;
 
     img = rsvg_filter_primitive_image_render_in (self, ctx);
     if (img == NULL) {
         img = rsvg_filter_primitive_image_render_ext (self, ctx);
-        if (img) {
-            gdk_pixbuf_copy_area (img, 0, 0,
-                                  boundarys.x1 - boundarys.x0,
-                                  boundarys.y1 - boundarys.y0, output, boundarys.x0, boundarys.y0);
-            g_object_unref (img);
-        }
+        x = y = 0;
     } else {
-        gdk_pixbuf_copy_area (img, boundarys.x0, boundarys.y0, boundarys.x1 - boundarys.x0,
-                              boundarys.y1 - boundarys.y0, output, boundarys.x0, boundarys.y0);
-        g_object_unref (img);
+        x = boundarys.x0;
+        y = boundarys.y0;
+    }
+    if (img) {
+        cairo_t *cr;
+
+        cr = cairo_create (output);
+        cairo_set_source_surface (cr, img, x, y);
+        cairo_rectangle (cr, 0, 0,
+                         boundarys.x1 - boundarys.x0,
+                         boundarys.y1 - boundarys.y0);
+        cairo_clip (cr);
+        cairo_translate (cr, -boundarys.x0, -boundarys.y0);
+        cairo_paint (cr);
+        cairo_destroy (cr);
+
+        cairo_surface_destroy (img);
     }
 
-    op.result = output;
+    op.surface = output;
     op.bounds = boundarys;
     op.Rused = 1;
     op.Gused = 1;
@@ -3493,7 +3519,7 @@ rsvg_filter_primitive_image_render (RsvgFilterPrimitive * self, RsvgFilterContex
 
     rsvg_filter_store_output (self->result, op, ctx);
 
-    g_object_unref (output);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -3749,59 +3775,59 @@ get_surface_normal (guchar * I, RsvgIRect boundarys, gint x, gint y,
 
     Nx = -surfaceScale * factorx * ((gdouble)
                                     (Kx[0] *
-                                     gdk_pixbuf_get_interp_pixel (I, x - dx, y - dy, chan,
+                                     get_interp_pixel (I, x - dx, y - dy, chan,
                                                                   boundarys,
                                                                   rowstride) +
-                                     Kx[1] * gdk_pixbuf_get_interp_pixel (I, x, y - dy, chan,
+                                     Kx[1] * get_interp_pixel (I, x, y - dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Kx[2] * gdk_pixbuf_get_interp_pixel (I, x + dx, y - dy, chan,
+                                     Kx[2] * get_interp_pixel (I, x + dx, y - dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Kx[3] * gdk_pixbuf_get_interp_pixel (I, x - dx, y, chan,
+                                     Kx[3] * get_interp_pixel (I, x - dx, y, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Kx[4] * gdk_pixbuf_get_interp_pixel (I, x, y, chan, boundarys,
+                                     Kx[4] * get_interp_pixel (I, x, y, chan, boundarys,
                                                                           rowstride) +
-                                     Kx[5] * gdk_pixbuf_get_interp_pixel (I, x + dx, y, chan,
+                                     Kx[5] * get_interp_pixel (I, x + dx, y, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Kx[6] * gdk_pixbuf_get_interp_pixel (I, x - dx, y + dy, chan,
+                                     Kx[6] * get_interp_pixel (I, x - dx, y + dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Kx[7] * gdk_pixbuf_get_interp_pixel (I, x, y + dy, chan,
+                                     Kx[7] * get_interp_pixel (I, x, y + dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Kx[8] * gdk_pixbuf_get_interp_pixel (I, x + dx, y + dy, chan,
+                                     Kx[8] * get_interp_pixel (I, x + dx, y + dy, chan,
                                                                           boundarys,
                                                                           rowstride))) / 255.0;
 
     Ny = -surfaceScale * factory * ((gdouble)
                                     (Ky[0] *
-                                     gdk_pixbuf_get_interp_pixel (I, x - dx, y - dy, chan,
+                                     get_interp_pixel (I, x - dx, y - dy, chan,
                                                                   boundarys,
                                                                   rowstride) +
-                                     Ky[1] * gdk_pixbuf_get_interp_pixel (I, x, y - dy, chan,
+                                     Ky[1] * get_interp_pixel (I, x, y - dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Ky[2] * gdk_pixbuf_get_interp_pixel (I, x + dx, y - dy, chan,
+                                     Ky[2] * get_interp_pixel (I, x + dx, y - dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Ky[3] * gdk_pixbuf_get_interp_pixel (I, x - dx, y, chan,
+                                     Ky[3] * get_interp_pixel (I, x - dx, y, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Ky[4] * gdk_pixbuf_get_interp_pixel (I, x, y, chan, boundarys,
+                                     Ky[4] * get_interp_pixel (I, x, y, chan, boundarys,
                                                                           rowstride) +
-                                     Ky[5] * gdk_pixbuf_get_interp_pixel (I, x + dx, y, chan,
+                                     Ky[5] * get_interp_pixel (I, x + dx, y, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Ky[6] * gdk_pixbuf_get_interp_pixel (I, x - dx, y + dy, chan,
+                                     Ky[6] * get_interp_pixel (I, x - dx, y + dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Ky[7] * gdk_pixbuf_get_interp_pixel (I, x, y + dy, chan,
+                                     Ky[7] * get_interp_pixel (I, x, y + dy, chan,
                                                                           boundarys,
                                                                           rowstride) +
-                                     Ky[8] * gdk_pixbuf_get_interp_pixel (I, x + dx, y + dy, chan,
+                                     Ky[8] * get_interp_pixel (I, x + dx, y + dy, chan,
                                                                           boundarys,
                                                                           rowstride))) / 255.0;
 
@@ -3992,8 +4018,8 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
 
     RsvgFilterPrimitiveDiffuseLighting *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
+
     unsigned int i;
 
     for (i = 0; i < self->super.children->len; i++) {
@@ -4015,16 +4041,16 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
+    output = _rsvg_image_surface_new (width, height);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     colour.x = ((guchar *) (&upself->lightingcolour))[2] / 255.0;
     colour.y = ((guchar *) (&upself->lightingcolour))[1] / 255.0;
@@ -4063,10 +4089,12 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
             output_pixels[y * rowstride + x * 4 + ctx->channelmap[3]] = 255;
         }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -4168,8 +4196,7 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
 
     RsvgFilterPrimitiveSpecularLighting *upself;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     unsigned int i;
 
@@ -4191,16 +4218,16 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     in = rsvg_filter_get_in (self->in, ctx);
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    height = gdk_pixbuf_get_height (in);
-    width = gdk_pixbuf_get_width (in);
+    height = cairo_image_surface_get_height (in);
+    width = cairo_image_surface_get_width (in);
 
-    rowstride = gdk_pixbuf_get_rowstride (in);
+    rowstride = cairo_image_surface_get_stride (in);
 
-    output = _rsvg_pixbuf_new_cleared ( width, height);
+    output = _rsvg_image_surface_new (width, height);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     colour.x = ((guchar *) (&upself->lightingcolour))[2] / 255.0;
     colour.y = ((guchar *) (&upself->lightingcolour))[1] / 255.0;
@@ -4244,10 +4271,12 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
 
         }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (in);
-    g_object_unref (output);
+    cairo_surface_destroy (in);
+    cairo_surface_destroy (output);
 }
 
 static void
@@ -4347,22 +4376,21 @@ rsvg_filter_primitive_tile_render (RsvgFilterPrimitive * self, RsvgFilterContext
     guchar *in_pixels;
     guchar *output_pixels;
 
-    GdkPixbuf *output;
-    GdkPixbuf *in;
+    cairo_surface_t *output, *in;
 
     oboundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
     input = rsvg_filter_get_result (self->in, ctx);
-    in = input.result;
+    in = input.surface;
     boundarys = input.bounds;
 
 
-    in_pixels = gdk_pixbuf_get_pixels (in);
+    in_pixels = cairo_image_surface_get_data (in);
 
-    output = _rsvg_pixbuf_new_cleared ( ctx->width, ctx->height);
-    rowstride = gdk_pixbuf_get_rowstride (output);
+    output = _rsvg_image_surface_new (ctx->width, ctx->height);
+    rowstride = cairo_image_surface_get_stride (output);
 
-    output_pixels = gdk_pixbuf_get_pixels (output);
+    output_pixels = cairo_image_surface_get_data (output);
 
     for (y = oboundarys.y0; y < oboundarys.y1; y++)
         for (x = oboundarys.x0; x < oboundarys.x1; x++)
@@ -4374,9 +4402,11 @@ rsvg_filter_primitive_tile_render (RsvgFilterPrimitive * self, RsvgFilterContext
                                boundarys.y0) * rowstride + i];
             }
 
+    cairo_surface_mark_dirty (output);
+
     rsvg_filter_store_result (self->result, output, ctx);
 
-    g_object_unref (output);
+    cairo_surface_destroy (output);
 }
 
 static void
diff --git a/rsvg-image.c b/rsvg-image.c
index 02882bd..92eef70 100644
--- a/rsvg-image.c
+++ b/rsvg-image.c
@@ -229,6 +229,24 @@ rsvg_pixbuf_new_from_href (const char *href, const char *base_uri, GError ** err
     return NULL;
 }
 
+cairo_surface_t *
+rsvg_cairo_surface_new_from_href (const char *href, 
+                                  const char *base_uri, 
+                                  GError **error)
+{
+    GdkPixbuf *pixbuf;
+    cairo_surface_t *surface;
+
+    pixbuf = rsvg_pixbuf_new_from_href (href, base_uri, error);
+    if (pixbuf == NULL)
+        return NULL;
+
+    surface = rsvg_cairo_surface_from_pixbuf (pixbuf);
+    g_object_unref (pixbuf);
+
+    return surface;
+}
+
 void
 rsvg_preserve_aspect_ratio (unsigned int aspect_ratio, double width,
                             double height, double *w, double *h, double *x, double *y)
@@ -275,8 +293,8 @@ rsvg_node_image_free (RsvgNode * self)
     rsvg_state_finalize (z->super.state);
     g_free (z->super.state);
     z->super.state = NULL;
-    if (z->img)
-        g_object_unref (z->img);
+    if (z->surface)
+        cairo_surface_destroy (z->surface);
     _rsvg_node_free(self);
 }
 
@@ -285,10 +303,10 @@ rsvg_node_image_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
 {
     RsvgNodeImage *z = (RsvgNodeImage *) self;
     unsigned int aspect_ratio = z->preserve_aspect_ratio;
-    GdkPixbuf *img = z->img;
     gdouble x, y, w, h;
+    cairo_surface_t *surface = z->surface;
 
-    if (img == NULL)
+    if (surface == NULL)
         return;
 
     x = _rsvg_css_normalize_length (&z->x, ctx, 'h');
@@ -304,10 +322,12 @@ rsvg_node_image_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
         rsvg_add_clipping_rect (ctx, x, y, w, h);
     }
 
-    rsvg_preserve_aspect_ratio (aspect_ratio, (double) gdk_pixbuf_get_width (img),
-                                (double) gdk_pixbuf_get_height (img), &w, &h, &x, &y);
+    rsvg_preserve_aspect_ratio (aspect_ratio, 
+                                (double) cairo_image_surface_get_width (surface),
+                                (double) cairo_image_surface_get_height (surface), 
+                                &w, &h, &x, &y);
 
-    rsvg_render_image (ctx, img, x, y, w, h);
+    rsvg_render_surface (ctx, surface, x, y, w, h);
 
     rsvg_pop_discrete_layer (ctx);
 }
@@ -330,11 +350,13 @@ rsvg_node_image_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * a
         /* path is used by some older adobe illustrator versions */
         if ((value = rsvg_property_bag_lookup (atts, "path"))
             || (value = rsvg_property_bag_lookup (atts, "xlink:href"))) {
-            image->img = rsvg_pixbuf_new_from_href (value, rsvg_handle_get_base_uri (ctx), NULL);
+            image->surface = rsvg_cairo_surface_new_from_href (value, 
+                                                               rsvg_handle_get_base_uri (ctx), 
+                                                               NULL);
 
-            if (!image->img) {
+            if (!image->surface) {
 #ifdef G_ENABLE_DEBUG
-                g_warning (_("Couldn't load image: %s\n"), value);
+                g_warning ("Couldn't load image: %s\n", value);
 #endif
             }
         }
@@ -358,7 +380,7 @@ rsvg_new_image (void)
     image = g_new (RsvgNodeImage, 1);
     _rsvg_node_init (&image->super, RSVG_NODE_TYPE_IMAGE);
     g_assert (image->super.state);
-    image->img = NULL;
+    image->surface = NULL;
     image->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
     image->x = image->y = image->w = image->h = _rsvg_css_parse_length ("0");
     image->super.free = rsvg_node_image_free;
diff --git a/rsvg-image.h b/rsvg-image.h
index 1971e6d..fc302d8 100644
--- a/rsvg-image.h
+++ b/rsvg-image.h
@@ -32,6 +32,8 @@
 
 #include "rsvg-structure.h"
 
+#include <cairo.h>
+
 G_BEGIN_DECLS 
 
 RsvgNode *rsvg_new_image (void);
@@ -42,7 +44,7 @@ struct _RsvgNodeImage {
     RsvgNode super;
     gint preserve_aspect_ratio;
     RsvgLength x, y, w, h;
-    GdkPixbuf *img;
+    cairo_surface_t *surface; /* a cairo image surface */
 };
 
 void rsvg_preserve_aspect_ratio (unsigned int aspect_ratio, double width,
@@ -53,6 +55,8 @@ gchar *rsvg_get_file_path (const gchar * filename, const gchar * basedir);
 
 GdkPixbuf *rsvg_pixbuf_new_from_href (const char *href, const char *base_uri, GError ** error);
 
+cairo_surface_t *rsvg_cairo_surface_new_from_href (const char *href, const char *base_uri, GError ** error);
+
 G_END_DECLS
 
 #endif                          /* RSVG_IMAGE_H */
diff --git a/rsvg-private.h b/rsvg-private.h
index ed5265a..2096864 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -218,6 +218,8 @@ struct RsvgRender {
     void             (*render_path)             (RsvgDrawingCtx * ctx, const cairo_path_t *path);
     void             (*render_image)            (RsvgDrawingCtx * ctx, const GdkPixbuf * pixbuf,
                                                  double x, double y, double w, double h);
+    void             (*render_surface)          (RsvgDrawingCtx * ctx, cairo_surface_t *surface,
+                                                 double x, double y, double w, double h);
     void             (*pop_discrete_layer)      (RsvgDrawingCtx * ctx);
     void             (*push_discrete_layer)     (RsvgDrawingCtx * ctx);
     void             (*add_clipping_rect)       (RsvgDrawingCtx * ctx, double x, double y,
@@ -376,8 +378,11 @@ void rsvg_push_discrete_layer   (RsvgDrawingCtx * ctx);
 void rsvg_render_path           (RsvgDrawingCtx * ctx, const cairo_path_t *path);
 void rsvg_render_image          (RsvgDrawingCtx * ctx, GdkPixbuf * pb,
                                  double x, double y, double w, double h);
+void rsvg_render_surface        (RsvgDrawingCtx * ctx, cairo_surface_t *surface,
+                                 double x, double y, double w, double h);
 void rsvg_render_free           (RsvgRender * render);
 void rsvg_add_clipping_rect     (RsvgDrawingCtx * ctx, double x, double y, double w, double h);
+cairo_surface_t *rsvg_cairo_surface_from_pixbuf (const GdkPixbuf *pixbuf);
 GdkPixbuf *rsvg_get_image_of_node (RsvgDrawingCtx * ctx, RsvgNode * drawable, double w, double h);
 cairo_surface_t *rsvg_get_surface_of_node (RsvgDrawingCtx * ctx, RsvgNode * drawable, double w, double h);
 



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