[librsvg: 4/6] Remove RsvgRender base struct



commit fa1be476e4f1d890f6ba030b671b092ca95fa94b
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Apr 28 15:08:16 2018 +0200

    Remove RsvgRender base struct
    
    All the code is already assuming that the only render is the cairo
    render and casting back and forth. Once we are in rust we can bring
    back a Render trait, but at the moment the "base" struct only gets
    in the way.
    While at it some code is also moved around: the draw_ctx creation
    goes in base.c and the handle methods go in handle.c.

 librsvg/filters/common.c    |   2 +-
 librsvg/rsvg-base.c         | 125 +++++++++++++++++++++++---
 librsvg/rsvg-cairo-draw.c   |  49 ++++-------
 librsvg/rsvg-cairo-render.c | 209 ++++----------------------------------------
 librsvg/rsvg-cairo-render.h |   7 +-
 librsvg/rsvg-handle.c       |  74 +++++++++++++++-
 librsvg/rsvg-private.h      |  44 ++--------
 7 files changed, 226 insertions(+), 284 deletions(-)
---
diff --git a/librsvg/filters/common.c b/librsvg/filters/common.c
index 9d65d889..6354814d 100644
--- a/librsvg/filters/common.c
+++ b/librsvg/filters/common.c
@@ -579,7 +579,7 @@ surface_get_alpha (cairo_surface_t *source,
 static cairo_surface_t *
 rsvg_compile_bg (RsvgDrawingCtx * ctx)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
+    RsvgCairoRender *render = ctx->render;
     cairo_surface_t *surface;
     cairo_t *cr;
     GList *i;
diff --git a/librsvg/rsvg-base.c b/librsvg/rsvg-base.c
index ca117718..bd174b19 100644
--- a/librsvg/rsvg-base.c
+++ b/librsvg/rsvg-base.c
@@ -108,10 +108,117 @@ rsvg_error_quark (void)
     return g_quark_from_string ("rsvg-error-quark");
 }
 
+static void
+rsvg_cairo_transformed_image_bounding_box (cairo_matrix_t *affine,
+                                           double width, double height,
+                                           double *x0, double *y0, double *x1, double *y1)
+{
+    double x00 = 0, x01 = 0, x10 = width, x11 = width;
+    double y00 = 0, y01 = height, y10 = 0, y11 = height;
+    double t;
+
+    /* transform the four corners of the image */
+    cairo_matrix_transform_point (affine, &x00, &y00);
+    cairo_matrix_transform_point (affine, &x01, &y01);
+    cairo_matrix_transform_point (affine, &x10, &y10);
+    cairo_matrix_transform_point (affine, &x11, &y11);
+
+    /* find minimum and maximum coordinates */
+    t = x00  < x01 ? x00  : x01;
+    t = t < x10 ? t : x10;
+    *x0 = floor (t < x11 ? t : x11);
+
+    t = y00  < y01 ? y00  : y01;
+    t = t < y10 ? t : y10;
+    *y0 = floor (t < y11 ? t : y11);
+
+    t = x00  > x01 ? x00  : x01;
+    t = t > x10 ? t : x10;
+    *x1 = ceil (t > x11 ? t : x11);
+
+    t = y00  > y01 ? y00  : y01;
+    t = t > y10 ? t : y10;
+    *y1 = ceil (t > y11 ? t : y11);
+}
+
+RsvgDrawingCtx *
+rsvg_drawing_ctx_new (cairo_t *cr, RsvgHandle *handle)
+{
+    RsvgDimensionData data;
+    RsvgDrawingCtx *draw;
+    RsvgCairoRender *render;
+    RsvgState *state;
+    cairo_matrix_t affine;
+    cairo_matrix_t state_affine;
+    double bbx0, bby0, bbx1, bby1;
+
+    rsvg_handle_get_dimensions (handle, &data);
+    if (data.width == 0 || data.height == 0)
+        return NULL;
+
+    draw = g_new0 (RsvgDrawingCtx, 1);
+
+    cairo_get_matrix (cr, &affine);
+
+    /* find bounding box of image as transformed by the current cairo context
+     * The size of this bounding box determines the size of the intermediate
+     * surfaces allocated during drawing. */
+    rsvg_cairo_transformed_image_bounding_box (&affine,
+                                               data.width, data.height,
+                                               &bbx0, &bby0, &bbx1, &bby1);
+
+    render = rsvg_cairo_render_new (cr, bbx1 - bbx0, bby1 - bby0);
+
+    if (!render)
+        return NULL;
+
+    draw->render = render;
+    render->offset_x = bbx0;
+    render->offset_y = bby0;
+
+    draw->state = NULL;
+
+    draw->defs = handle->priv->defs;
+    draw->dpi_x = handle->priv->dpi_x;
+    draw->dpi_y = handle->priv->dpi_y;
+    draw->vb.rect.width = data.em;
+    draw->vb.rect.height = data.ex;
+    draw->pango_context = NULL;
+    draw->vb_stack = NULL;
+    draw->drawsub_stack = NULL;
+    draw->acquired_nodes = NULL;
+    draw->is_testing = handle->priv->is_testing;
+
+    rsvg_drawing_ctx_state_push (draw);
+    state = rsvg_drawing_ctx_get_current_state (draw);
+
+    state_affine = rsvg_state_get_affine (state);
+
+    /* apply cairo transformation to our affine transform */
+    cairo_matrix_multiply (&state_affine, &affine, &state_affine);
+
+    /* scale according to size set by size_func callback */
+    cairo_matrix_init_scale (&affine, data.width / data.em, data.height / data.ex);
+    cairo_matrix_multiply (&state_affine, &affine, &state_affine);
+
+    /* adjust transform so that the corner of the bounding box above is
+     * at (0,0) - we compensate for this in _set_rsvg_affine() in
+     * rsvg-cairo-render.c and a few other places */
+    state_affine.x0 -= render->offset_x;
+    state_affine.y0 -= render->offset_y;
+
+    rsvg_bbox_init (&((RsvgCairoRender *) draw->render)->bbox, &state_affine);
+    rsvg_bbox_init (&((RsvgCairoRender *) draw->render)->ink_bbox, &state_affine);
+
+    rsvg_state_set_affine (state, state_affine);
+
+    return draw;
+}
+
 void
 rsvg_drawing_ctx_free (RsvgDrawingCtx * handle)
 {
-    rsvg_render_free (handle->render);
+    rsvg_cairo_render_free (handle->render);
 
     rsvg_state_free_all (handle->state);
 
@@ -520,7 +627,7 @@ rsvg_drawing_ctx_draw_node_from_stack (RsvgDrawingCtx *ctx,
 void
 rsvg_drawing_ctx_set_affine_on_cr (RsvgDrawingCtx *draw_ctx, cairo_t *cr, cairo_matrix_t *affine)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (draw_ctx->render);
+    RsvgCairoRender *render = draw_ctx->render;
     gboolean nest = cr != render->initial_cr;
     cairo_matrix_t matrix;
 
@@ -541,17 +648,13 @@ rsvg_drawing_ctx_get_pango_context (RsvgDrawingCtx *draw_ctx)
 void
 rsvg_drawing_ctx_insert_bbox (RsvgDrawingCtx *draw_ctx, RsvgBbox *bbox)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (draw_ctx->render);
-
-    rsvg_bbox_insert (&render->bbox, bbox);
+    rsvg_bbox_insert (&draw_ctx->render->bbox, bbox);
 }
 
 void
 rsvg_drawing_ctx_insert_ink_bbox (RsvgDrawingCtx *draw_ctx, RsvgBbox *ink_bbox)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (draw_ctx->render);
-
-    rsvg_bbox_insert (&render->ink_bbox, ink_bbox);
+    rsvg_bbox_insert (&draw_ctx->render->ink_bbox, ink_bbox);
 }
 
 cairo_surface_t *
@@ -630,12 +733,6 @@ rsvg_cairo_surface_new_from_href (RsvgHandle *handle,
     return surface;
 }
 
-void
-rsvg_render_free (RsvgRender * render)
-{
-    render->free (render);
-}
-
 void
 rsvg_drawing_ctx_push_view_box (RsvgDrawingCtx * ctx, double w, double h)
 {
diff --git a/librsvg/rsvg-cairo-draw.c b/librsvg/rsvg-cairo-draw.c
index b0d512a9..da649bfb 100644
--- a/librsvg/rsvg-cairo-draw.c
+++ b/librsvg/rsvg-cairo-draw.c
@@ -120,12 +120,11 @@ rsvg_cairo_get_pango_context (RsvgDrawingCtx * ctx)
 {
     PangoFontMap *fontmap;
     PangoContext *context;
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
     double dpi_y;
 
 #ifdef HAVE_PANGOFT2
     if (ctx->is_testing) {
-        fontmap = get_font_map_for_testing (render);
+        fontmap = get_font_map_for_testing (ctx->render);
     } else {
 #endif
         fontmap = pango_cairo_font_map_get_default ();
@@ -134,7 +133,7 @@ rsvg_cairo_get_pango_context (RsvgDrawingCtx * ctx)
 #endif
 
     context = pango_font_map_create_context (fontmap);
-    pango_cairo_update_context (render->cr, context);
+    pango_cairo_update_context (ctx->render->cr, context);
 
     rsvg_drawing_ctx_get_dpi (ctx, NULL, &dpi_y);
     pango_cairo_context_set_resolution (context, dpi_y);
@@ -151,9 +150,7 @@ rsvg_cairo_get_pango_context (RsvgDrawingCtx * ctx)
 cairo_t *
 rsvg_cairo_get_cairo_context (RsvgDrawingCtx *ctx)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
-
-    return render->cr;
+    return ctx->render->cr;
 }
 
 /* FIXME: Usage of this function is more less a hack.  Some code does this:
@@ -177,15 +174,13 @@ rsvg_cairo_get_cairo_context (RsvgDrawingCtx *ctx)
 void
 rsvg_cairo_set_cairo_context (RsvgDrawingCtx *ctx, cairo_t *cr)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
-
-    render->cr = cr;
+    ctx->render->cr = cr;
 }
 
 static void
 rsvg_cairo_generate_mask (cairo_t * cr, RsvgNode *mask, RsvgDrawingCtx *ctx, RsvgBbox *bbox)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
+    RsvgCairoRender *render = ctx->render;
     cairo_surface_t *surface;
     cairo_t *mask_cr, *save_cr;
     RsvgState *state;
@@ -323,7 +318,7 @@ rsvg_cairo_generate_mask (cairo_t * cr, RsvgNode *mask, RsvgDrawingCtx *ctx, Rsv
 static void
 rsvg_cairo_clip (RsvgDrawingCtx *ctx, RsvgNode *node_clip_path, RsvgBbox *bbox)
 {
-    RsvgCairoRender *save = RSVG_CAIRO_RENDER (ctx->render);
+    RsvgCairoRender *save = ctx->render;
     cairo_matrix_t affinesave;
     RsvgState *clip_path_state;
     cairo_t *cr;
@@ -392,7 +387,7 @@ rsvg_cairo_clip (RsvgDrawingCtx *ctx, RsvgNode *node_clip_path, RsvgBbox *bbox)
 static void
 rsvg_cairo_push_render_stack (RsvgDrawingCtx * ctx)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
+    RsvgCairoRender *render = ctx->render;
     RsvgState *state;
     char *clip_path;
     char *filter;
@@ -487,20 +482,16 @@ rsvg_cairo_push_render_stack (RsvgDrawingCtx * ctx)
 void
 rsvg_cairo_push_discrete_layer (RsvgDrawingCtx * ctx, gboolean clipping)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
-
-    if (clipping) {
-        return;
+    if (!clipping) {
+        cairo_save (ctx->render->cr);
+        rsvg_cairo_push_render_stack (ctx);
     }
-
-    cairo_save (render->cr);
-    rsvg_cairo_push_render_stack (ctx);
 }
 
 static void
 rsvg_cairo_pop_render_stack (RsvgDrawingCtx * ctx)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
+    RsvgCairoRender *render = ctx->render;
     RsvgState *state;
     char *clip_path;
     char *filter;
@@ -615,14 +606,10 @@ rsvg_cairo_pop_render_stack (RsvgDrawingCtx * ctx)
 void
 rsvg_cairo_pop_discrete_layer (RsvgDrawingCtx * ctx, gboolean clipping)
 {
-    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
-
-    if (clipping) {
-        return;
+    if (!clipping) {
+        rsvg_cairo_pop_render_stack (ctx);
+        cairo_restore (ctx->render->cr);
     }
-
-    rsvg_cairo_pop_render_stack (ctx);
-    cairo_restore (render->cr);
 }
 
 cairo_surface_t *
@@ -634,7 +621,7 @@ rsvg_cairo_get_surface_of_node (RsvgDrawingCtx *ctx,
     cairo_surface_t *surface;
     cairo_t *cr;
 
-    RsvgCairoRender *save_render = (RsvgCairoRender *) ctx->render;
+    RsvgCairoRender *save_render = ctx->render;
     RsvgCairoRender *render;
 
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
@@ -646,14 +633,14 @@ rsvg_cairo_get_surface_of_node (RsvgDrawingCtx *ctx,
     cr = cairo_create (surface);
 
     render = rsvg_cairo_render_new (cr, width, height);
-    ctx->render = (RsvgRender *) render;
+    ctx->render = render;
 
     rsvg_drawing_ctx_draw_node_from_stack (ctx, drawable, 0, FALSE);
 
     cairo_destroy (cr);
 
-    rsvg_render_free (ctx->render);
-    ctx->render = (RsvgRender *) save_render;
+    rsvg_cairo_render_free (ctx->render);
+    ctx->render = save_render;
 
     return surface;
 }
diff --git a/librsvg/rsvg-cairo-render.c b/librsvg/rsvg-cairo-render.c
index a7568d5c..7bd6ed17 100644
--- a/librsvg/rsvg-cairo-render.c
+++ b/librsvg/rsvg-cairo-render.c
@@ -41,39 +41,12 @@
 #include "rsvg-styles.h"
 #include "rsvg-structure.h"
 
-static void
-rsvg_cairo_render_free (RsvgRender * self)
-{
-    RsvgCairoRender *me = RSVG_CAIRO_RENDER (self);
-
-    g_assert (me->cr_stack == NULL);
-    g_assert (me->bb_stack == NULL);
-    g_assert (me->ink_bb_stack == NULL);
-    g_assert (me->surfaces_stack == NULL);
-
-#ifdef HAVE_PANGOFT2
-    if (me->font_config_for_testing) {
-        FcConfigDestroy (me->font_config_for_testing);
-        me->font_config_for_testing = NULL;
-    }
-
-    if (me->font_map_for_testing) {
-        g_object_unref (me->font_map_for_testing);
-        me->font_map_for_testing = NULL;
-    }
-#endif
-
-    g_free (me);
-}
-
 RsvgCairoRender *
 rsvg_cairo_render_new (cairo_t * cr, double width, double height)
 {
     RsvgCairoRender *cairo_render = g_new0 (RsvgCairoRender, 1);
     cairo_matrix_t matrix;
 
-    cairo_render->super.type = RSVG_RENDER_TYPE_CAIRO;
-    cairo_render->super.free = rsvg_cairo_render_free;
     cairo_render->width = width;
     cairo_render->height = height;
     cairo_render->offset_x = 0;
@@ -97,175 +70,25 @@ rsvg_cairo_render_new (cairo_t * cr, double width, double height)
     return cairo_render;
 }
 
-static void rsvg_cairo_transformed_image_bounding_box (
-    cairo_matrix_t * transform,
-    double width, double height,
-    double *x0, double *y0, double *x1, double *y1)
+void
+rsvg_cairo_render_free (RsvgCairoRender *render)
 {
-    double x00 = 0, x01 = 0, x10 = width, x11 = width;
-    double y00 = 0, y01 = height, y10 = 0, y11 = height;
-    double t;
-
-    /* transform the four corners of the image */
-    cairo_matrix_transform_point (transform, &x00, &y00);
-    cairo_matrix_transform_point (transform, &x01, &y01);
-    cairo_matrix_transform_point (transform, &x10, &y10);
-    cairo_matrix_transform_point (transform, &x11, &y11);
-
-    /* find minimum and maximum coordinates */
-    t = x00  < x01 ? x00  : x01;
-    t = t < x10 ? t : x10;
-    *x0 = floor (t < x11 ? t : x11);
-
-    t = y00  < y01 ? y00  : y01;
-    t = t < y10 ? t : y10;
-    *y0 = floor (t < y11 ? t : y11);
-
-    t = x00  > x01 ? x00  : x01;
-    t = t > x10 ? t : x10;
-    *x1 = ceil (t > x11 ? t : x11);
-
-    t = y00  > y01 ? y00  : y01;
-    t = t > y10 ? t : y10;
-    *y1 = ceil (t > y11 ? t : y11);
-}
-
-RsvgDrawingCtx *
-rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle)
-{
-    RsvgDimensionData data;
-    RsvgDrawingCtx *draw;
-    RsvgCairoRender *render;
-    RsvgState *state;
-    cairo_matrix_t affine;
-    cairo_matrix_t state_affine;
-    double bbx0, bby0, bbx1, bby1;
-
-    rsvg_handle_get_dimensions (handle, &data);
-    if (data.width == 0 || data.height == 0)
-        return NULL;
-
-    draw = g_new0 (RsvgDrawingCtx, 1);
-
-    cairo_get_matrix (cr, &affine);
-
-    /* find bounding box of image as transformed by the current cairo context
-     * The size of this bounding box determines the size of the intermediate
-     * surfaces allocated during drawing. */
-    rsvg_cairo_transformed_image_bounding_box (&affine,
-                                               data.width, data.height,
-                                               &bbx0, &bby0, &bbx1, &bby1);
-
-    render = rsvg_cairo_render_new (cr, bbx1 - bbx0, bby1 - bby0);
-
-    if (!render)
-        return NULL;
-
-    draw->render = (RsvgRender *) render;
-    render->offset_x = bbx0;
-    render->offset_y = bby0;
-
-    draw->state = NULL;
+    g_assert (render->cr_stack == NULL);
+    g_assert (render->bb_stack == NULL);
+    g_assert (render->ink_bb_stack == NULL);
+    g_assert (render->surfaces_stack == NULL);
 
-    draw->defs = handle->priv->defs;
-    draw->dpi_x = handle->priv->dpi_x;
-    draw->dpi_y = handle->priv->dpi_y;
-    draw->vb.rect.width = data.em;
-    draw->vb.rect.height = data.ex;
-    draw->pango_context = NULL;
-    draw->vb_stack = NULL;
-    draw->drawsub_stack = NULL;
-    draw->acquired_nodes = NULL;
-    draw->is_testing = handle->priv->is_testing;
-
-    rsvg_drawing_ctx_state_push (draw);
-    state = rsvg_drawing_ctx_get_current_state (draw);
-
-    state_affine = rsvg_state_get_affine (state);
-
-    /* apply cairo transformation to our affine transform */
-    cairo_matrix_multiply (&state_affine, &affine, &state_affine);
-
-    /* scale according to size set by size_func callback */
-    cairo_matrix_init_scale (&affine, data.width / data.em, data.height / data.ex);
-    cairo_matrix_multiply (&state_affine, &affine, &state_affine);
-
-    /* adjust transform so that the corner of the bounding box above is
-     * at (0,0) - we compensate for this in _set_rsvg_affine() in
-     * rsvg-cairo-render.c and a few other places */
-    state_affine.x0 -= render->offset_x;
-    state_affine.y0 -= render->offset_y;
-
-    rsvg_bbox_init (&((RsvgCairoRender *) draw->render)->bbox, &state_affine);
-    rsvg_bbox_init (&((RsvgCairoRender *) draw->render)->ink_bbox, &state_affine);
-
-    rsvg_state_set_affine (state, state_affine);
-
-    return draw;
-}
-
-/**
- * rsvg_handle_render_cairo_sub:
- * @handle: A #RsvgHandle
- * @cr: A Cairo renderer
- * @id: (nullable): An element's id within the SVG, or %NULL to render
- *   the whole SVG. For example, if you have a layer called "layer1"
- *   that you wish to render, pass "##layer1" as the id.
- *
- * Draws a subset of a SVG to a Cairo surface
- *
- * Returns: %TRUE if drawing succeeded.
- *
- * Since: 2.14
- */
-gboolean
-rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
-{
-    RsvgDrawingCtx *draw;
-    RsvgNode *drawsub = NULL;
-
-    g_return_val_if_fail (handle != NULL, FALSE);
-
-    if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
-        return FALSE;
-
-    if (id && *id)
-        drawsub = rsvg_defs_lookup (handle->priv->defs, id);
-
-    if (drawsub == NULL && id != NULL) {
-        /* todo: there's no way to signal that @id doesn't exist */
-        return FALSE;
+#ifdef HAVE_PANGOFT2
+    if (render->font_config_for_testing) {
+        FcConfigDestroy (render->font_config_for_testing);
+        render->font_config_for_testing = NULL;
     }
 
-    draw = rsvg_cairo_new_drawing_ctx (cr, handle);
-    if (!draw)
-        return FALSE;
-
-    rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, drawsub);
-
-    cairo_save (cr);
-
-    rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0, FALSE);
-
-    cairo_restore (cr);
-
-    rsvg_drawing_ctx_free (draw);
-
-    return TRUE;
-}
+    if (render->font_map_for_testing) {
+        g_object_unref (render->font_map_for_testing);
+        render->font_map_for_testing = NULL;
+    }
+#endif
 
-/**
- * rsvg_handle_render_cairo:
- * @handle: A #RsvgHandle
- * @cr: A Cairo renderer
- *
- * Draws a SVG to a Cairo surface
- *
- * Returns: %TRUE if drawing succeeded.
- * Since: 2.14
- */
-gboolean
-rsvg_handle_render_cairo (RsvgHandle * handle, cairo_t * cr)
-{
-    return rsvg_handle_render_cairo_sub (handle, cr, NULL);
+    g_free (render);
 }
diff --git a/librsvg/rsvg-cairo-render.h b/librsvg/rsvg-cairo-render.h
index a2365455..14402b32 100644
--- a/librsvg/rsvg-cairo-render.h
+++ b/librsvg/rsvg-cairo-render.h
@@ -35,10 +35,9 @@
 #include <pango/pangofc-fontmap.h>
 #endif
 
-G_BEGIN_DECLS typedef struct _RsvgCairoRender RsvgCairoRender;
+G_BEGIN_DECLS
 
 struct _RsvgCairoRender {
-    RsvgRender super;
     cairo_t *cr;
     double width;
     double height;
@@ -69,13 +68,11 @@ struct _RsvgCairoRender {
 #endif
 };
 
-#define RSVG_CAIRO_RENDER(render) (_RSVG_RENDER_CIC ((render), RSVG_RENDER_TYPE_CAIRO, RsvgCairoRender))
-
 G_GNUC_INTERNAL
 RsvgCairoRender *rsvg_cairo_render_new (cairo_t *cr, double width, double height);
 
 G_GNUC_INTERNAL
-RsvgDrawingCtx *rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle);
+void rsvg_cairo_render_free (RsvgCairoRender *render);
 
 G_END_DECLS
 
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 126fd505..da0af8b8 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -744,6 +744,72 @@ rsvg_handle_get_desc (RsvgHandle * handle)
     return NULL;
 }
 
+/**
+ * rsvg_handle_render_cairo_sub:
+ * @handle: A #RsvgHandle
+ * @cr: A Cairo renderer
+ * @id: (nullable): An element's id within the SVG, or %NULL to render
+ *   the whole SVG. For example, if you have a layer called "layer1"
+ *   that you wish to render, pass "##layer1" as the id.
+ *
+ * Draws a subset of a SVG to a Cairo surface
+ *
+ * Returns: %TRUE if drawing succeeded.
+ *
+ * Since: 2.14
+ */
+gboolean
+rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
+{
+    RsvgDrawingCtx *draw;
+    RsvgNode *drawsub = NULL;
+
+    g_return_val_if_fail (handle != NULL, FALSE);
+
+    if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
+        return FALSE;
+
+    if (id && *id)
+        drawsub = rsvg_defs_lookup (handle->priv->defs, id);
+
+    if (drawsub == NULL && id != NULL) {
+        /* todo: there's no way to signal that @id doesn't exist */
+        return FALSE;
+    }
+
+    draw = rsvg_drawing_ctx_new (cr, handle);
+    if (!draw)
+        return FALSE;
+
+    rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, drawsub);
+
+    cairo_save (cr);
+
+    rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0, FALSE);
+
+    cairo_restore (cr);
+
+    rsvg_drawing_ctx_free (draw);
+
+    return TRUE;
+}
+
+/**
+ * rsvg_handle_render_cairo:
+ * @handle: A #RsvgHandle
+ * @cr: A Cairo renderer
+ *
+ * Draws a SVG to a Cairo surface
+ *
+ * Returns: %TRUE if drawing succeeded.
+ * Since: 2.14
+ */
+gboolean
+rsvg_handle_render_cairo (RsvgHandle * handle, cairo_t * cr)
+{
+    return rsvg_handle_render_cairo_sub (handle, cr, NULL);
+}
+
 /**
  * rsvg_handle_get_dimensions:
  * @handle: A #RsvgHandle
@@ -835,7 +901,7 @@ rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimensi
                                              1, 1);
         cr = cairo_create  (target);
 
-        draw = rsvg_cairo_new_drawing_ctx (cr, handle);
+        draw = rsvg_drawing_ctx_new (cr, handle);
 
         if (!draw) {
             cairo_destroy (cr);
@@ -848,7 +914,7 @@ rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimensi
         rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, sself);
 
         rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0, FALSE);
-        ink_bbox = RSVG_CAIRO_RENDER (draw->render)->ink_bbox;
+        ink_bbox = draw->render->ink_bbox;
 
         rsvg_drawing_ctx_free (draw);
         cairo_destroy (cr);
@@ -927,7 +993,7 @@ rsvg_handle_get_position_sub (RsvgHandle * handle, RsvgPositionData * position_d
 
     target = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);
     cr = cairo_create  (target);
-    draw = rsvg_cairo_new_drawing_ctx (cr, handle);
+    draw = rsvg_drawing_ctx_new (cr, handle);
     if (!draw)
         goto bail;
 
@@ -935,7 +1001,7 @@ rsvg_handle_get_position_sub (RsvgHandle * handle, RsvgPositionData * position_d
     rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, node);
 
     rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0, FALSE);
-    ink_bbox = RSVG_CAIRO_RENDER (draw->render)->ink_bbox;
+    ink_bbox = draw->render->ink_bbox;
 
     rsvg_drawing_ctx_free (draw);
 
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 9c51e546..42d04665 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -46,8 +46,8 @@
 G_BEGIN_DECLS 
 
 typedef struct RsvgSaxHandler RsvgSaxHandler;
+typedef struct _RsvgCairoRender RsvgCairoRender;
 typedef struct RsvgDrawingCtx RsvgDrawingCtx;
-typedef struct RsvgRender RsvgRender;
 typedef void   *RsvgPropertyBag;
 typedef struct _RsvgState RsvgState;
 typedef struct _RsvgDefs RsvgDefs;
@@ -169,7 +169,7 @@ typedef struct {
 /*Contextual information for the drawing phase*/
 
 struct RsvgDrawingCtx {
-    RsvgRender *render;
+    RsvgCairoRender *render;
     RsvgState *state;
     GError **error;
     RsvgDefs *defs;
@@ -189,34 +189,6 @@ typedef struct {
     gboolean virgin;
 } RsvgBbox;
 
-/*Abstract base class for context for our backends (one as yet)*/
-
-typedef enum {
-  RSVG_RENDER_TYPE_INVALID,
-
-  RSVG_RENDER_TYPE_BASE,
-
-  RSVG_RENDER_TYPE_CAIRO = 8,
-  RSVG_RENDER_TYPE_CAIRO_CLIP
-} RsvgRenderType;
-
-struct RsvgRender {
-    RsvgRenderType type;
-
-    void (*free) (RsvgRender * self);
-};
-
-static inline RsvgRender *
-_rsvg_render_check_type (RsvgRender *render,
-                         RsvgRenderType type)
-{
-  g_assert ((render->type & type) == type);
-  return render;
-}
-
-#define _RSVG_RENDER_CIC(render, render_type, RenderCType) \
-  ((RenderCType*) _rsvg_render_check_type ((render), (render_type)))
-
 /* Keep this in sync with rust/src/length.rs:LengthUnit */
 typedef enum {
     LENGTH_UNIT_DEFAULT,
@@ -444,6 +416,12 @@ void rsvg_pop_discrete_layer    (RsvgDrawingCtx *ctx, gboolean clipping);
 G_GNUC_INTERNAL
 void rsvg_push_discrete_layer   (RsvgDrawingCtx *ctx, gboolean clipping);
 
+G_GNUC_INTERNAL
+RsvgDrawingCtx *rsvg_drawing_ctx_new (cairo_t *cr, RsvgHandle *handle);
+
+G_GNUC_INTERNAL
+void rsvg_drawing_ctx_free (RsvgDrawingCtx *draw_ctx);
+
 G_GNUC_INTERNAL
 RsvgState *rsvg_drawing_ctx_get_current_state   (RsvgDrawingCtx * ctx);
 G_GNUC_INTERNAL
@@ -470,9 +448,6 @@ void rsvg_drawing_ctx_draw_node_from_stack (RsvgDrawingCtx *ctx,
                                             int dominate,
                                             gboolean clipping);
 
-G_GNUC_INTERNAL
-void rsvg_render_free           (RsvgRender * render);
-
 G_GNUC_INTERNAL
 cairo_surface_t *rsvg_cairo_surface_from_pixbuf (const GdkPixbuf *pixbuf);
 G_GNUC_INTERNAL
@@ -487,9 +462,6 @@ void rsvg_drawing_ctx_insert_ink_bbox (RsvgDrawingCtx *draw_ctx, RsvgBbox *ink_b
 G_GNUC_INTERNAL
 cairo_surface_t *rsvg_cairo_surface_new_from_href (RsvgHandle *handle, const char *href, GError ** error);
 
-G_GNUC_INTERNAL
-void rsvg_drawing_ctx_free (RsvgDrawingCtx * handle);
-
 /* Implemented in rust/src/bbox.rs */
 G_GNUC_INTERNAL
 void rsvg_bbox_init     (RsvgBbox * self, cairo_matrix_t *matrix);


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