rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
{
    guchar ch;
    gint x, y;
    gint rowstride, height, width;
    RsvgIRect boundarys;

    guchar *in_pixels;
    guchar *output_pixels;

    RsvgFilterPrimitiveOutput out;
    RsvgFilterPrimitiveOffset *upself;

    GdkPixbuf *output;
    GdkPixbuf *in;

    double dx, dy;
    int ox, oy;

    upself = (RsvgFilterPrimitiveOffset *) self;
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);

    in = rsvg_filter_get_in (self->in, ctx);
    in_pixels = gdk_pixbuf_get_pixels (in);

    height = gdk_pixbuf_get_height (in);
    width = gdk_pixbuf_get_width (in);

    rowstride = gdk_pixbuf_get_rowstride (in);

    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);

    output_pixels = gdk_pixbuf_get_pixels (output);

    dx = _rsvg_css_normalize_length (&upself->dx, ctx->ctx, 'w');
    dy = _rsvg_css_normalize_length (&upself->dy, ctx->ctx, 'v');

    ox = ctx->paffine[0] * dx + ctx->paffine[2] * dy;
    oy = ctx->paffine[1] * dx + ctx->paffine[3] * dy;

    for (y = boundarys.y0; y < boundarys.y1; y++)
        for (x = boundarys.x0; x < boundarys.x1; x++) {
            if (x - ox < boundarys.x0 || x - ox >= boundarys.x1)
                continue;
            if (y - oy < boundarys.y0 || y - oy >= boundarys.y1)
                continue;

            for (ch = 0; ch < 4; ch++) {
                output_pixels[y * rowstride + x * 4 + ch] =
                    in_pixels[(y - oy) * rowstride + (x - ox) * 4 + ch];
            }
        }

    out.result = output;
    out.Rused = 1;
    out.Gused = 1;
    out.Bused = 1;
    out.Aused = 1;
    out.bounds = boundarys;

    rsvg_filter_store_output (self->result, out, ctx);

    g_object_unref (in);
    g_object_unref (output);
}
rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
{
    guchar ch;
    gint x, y;
    gint rowstride, height, width;
    RsvgIRect boundarys;

    guchar *in_pixels;
    guchar *output_pixels;

    RsvgFilterPrimitiveOutput out;
    RsvgFilterPrimitiveOffset *upself;

    GdkPixbuf *output;
    GdkPixbuf *in;

    double dx, dy;
    int ox, oy;

    upself = (RsvgFilterPrimitiveOffset *) self;
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);

    in = rsvg_filter_get_in (self->in, ctx);
    in_pixels = gdk_pixbuf_get_pixels (in);

    height = gdk_pixbuf_get_height (in);
    width = gdk_pixbuf_get_width (in);

    rowstride = gdk_pixbuf_get_rowstride (in);

    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);

    output_pixels = gdk_pixbuf_get_pixels (output);

    dx = _rsvg_css_normalize_length (&upself->dx, ctx->ctx, 'w');
    dy = _rsvg_css_normalize_length (&upself->dy, ctx->ctx, 'v');

    ox = ctx->paffine[0] * dx + ctx->paffine[2] * dy;
    oy = ctx->paffine[1] * dx + ctx->paffine[3] * dy;

    for (y = boundarys.y0; y < boundarys.y1; y++)
        for (x = boundarys.x0; x < boundarys.x1; x++) {
            if (x - ox < boundarys.x0 || x - ox >= boundarys.x1)
                continue;
            if (y - oy < boundarys.y0 || y - oy >= boundarys.y1)
                continue;

            for (ch = 0; ch < 4; ch++) {
                output_pixels[y * rowstride + x * 4 + ch] =
                    in_pixels[(y - oy) * rowstride + (x - ox) * 4 + ch];
            }
        }

    out.result = output;
    out.Rused = 1;
    out.Gused = 1;
    out.Bused = 1;
    out.Aused = 1;
    out.bounds = boundarys;

    rsvg_filter_store_output (self->result, out, ctx);

    g_object_unref (in);
    g_object_unref (output);
}