[librsvg] Create background pixbuf only if it's needed.
- From: Hiroyuki Ikezoe <hiikezoe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] Create background pixbuf only if it's needed.
- Date: Sun, 2 May 2010 11:43:55 +0000 (UTC)
commit ede81d3cf81b68e00d334f252e083e15525063e3
Author: Hiroyuki Ikezoe <hiikezoe gnome org>
Date: Sun May 2 20:43:07 2010 +0900
Create background pixbuf only if it's needed.
Fix for bug #614556.
rsvg-cairo-draw.c | 41 +-----------------------------
rsvg-filter.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++------
rsvg-filter.h | 2 +-
3 files changed, 67 insertions(+), 49 deletions(-)
---
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 01fca2e..5ab48df 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -923,43 +923,6 @@ rsvg_cairo_push_discrete_layer (RsvgDrawingCtx * ctx)
rsvg_cairo_push_render_stack (ctx);
}
-static GdkPixbuf *
-rsvg_compile_bg (RsvgDrawingCtx * ctx)
-{
- RsvgCairoRender *render = (RsvgCairoRender *) ctx->render;
- cairo_t *cr;
- cairo_surface_t *surface;
- 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) rsvg_pixmap_destroy,
- NULL);
-
- surface = cairo_image_surface_create_for_data (pixels,
- CAIRO_FORMAT_ARGB32,
- render->width, render->height, rowstride);
-
- 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;
- gboolean nest = draw != render->initial_cr;
- cairo_set_source_surface (cr, cairo_get_target (draw),
- nest ? 0 : -render->offset_x,
- nest ? 0 : -render->offset_y);
- cairo_paint (cr);
- }
-
- cairo_destroy (cr);
- return output;
-}
-
static void
rsvg_cairo_pop_render_stack (RsvgDrawingCtx * ctx)
{
@@ -982,14 +945,12 @@ rsvg_cairo_pop_render_stack (RsvgDrawingCtx * ctx)
if (state->filter) {
GdkPixbuf *pixbuf = render->pixbuf_stack->data;
- GdkPixbuf *bg = rsvg_compile_bg (ctx);
render->pixbuf_stack = g_list_remove (render->pixbuf_stack, pixbuf);
- output = rsvg_filter_render (state->filter, pixbuf, bg, ctx, &render->bbox, "2103");
+ output = rsvg_filter_render (state->filter, pixbuf, ctx, &render->bbox, "2103");
g_object_unref (pixbuf);
- g_object_unref (bg);
surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (output),
CAIRO_FORMAT_ARGB32,
diff --git a/rsvg-filter.c b/rsvg-filter.c
index 73cb5f2..e65be41 100644
--- a/rsvg-filter.c
+++ b/rsvg-filter.c
@@ -30,6 +30,7 @@
#include "rsvg-styles.h"
#include "rsvg-image.h"
#include "rsvg-css.h"
+#include "rsvg-cairo-render.h"
#include <string.h>
#include <math.h>
@@ -440,11 +441,22 @@ rsvg_filter_free_pair (gpointer value)
g_free (output);
}
+static void
+rsvg_filter_context_free (RsvgFilterContext * ctx)
+{
+ if (!ctx)
+ return;
+
+ if (ctx->bg)
+ g_object_unref (ctx->bg);
+
+ g_free (ctx);
+}
+
/**
- * rsvg_filter_render: Copy the source to the bg using a filter.
+ * rsvg_filter_render: Create a new pixbuf applied the filter.
* @self: a pointer to the filter to use
* @source: a pointer to the source pixbuf
- * @bg: the background pixbuf
* @context: the context
*
* This function will create a context for itself, set up the coordinate systems
@@ -452,7 +464,7 @@ rsvg_filter_free_pair (gpointer value)
**/
GdkPixbuf *
rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
- GdkPixbuf * bg, RsvgDrawingCtx * context, RsvgBbox * bounds, char *channelmap)
+ RsvgDrawingCtx * context, RsvgBbox * bounds, char *channelmap)
{
RsvgFilterContext *ctx;
RsvgFilterPrimitive *current;
@@ -463,7 +475,7 @@ rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
ctx = g_new (RsvgFilterContext, 1);
ctx->filter = self;
ctx->source = source;
- ctx->bg = bg;
+ ctx->bg = NULL;
ctx->results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, rsvg_filter_free_pair);
ctx->ctx = context;
@@ -491,7 +503,7 @@ rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
g_hash_table_destroy (ctx->results);
- g_free (ctx);
+ rsvg_filter_context_free (ctx);
return out;
}
@@ -564,6 +576,52 @@ pixbuf_get_alpha (GdkPixbuf * pb, RsvgFilterContext * ctx)
return output;
}
+static GdkPixbuf *
+rsvg_compile_bg (RsvgDrawingCtx * ctx)
+{
+ RsvgCairoRender *render = (RsvgCairoRender *) ctx->render;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ 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);
+
+ 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;
+ gboolean nest = draw != render->initial_cr;
+ cairo_set_source_surface (cr, cairo_get_target (draw),
+ nest ? 0 : -render->offset_x,
+ nest ? 0 : -render->offset_y);
+ cairo_paint (cr);
+ }
+
+ cairo_destroy (cr);
+ return output;
+}
+
+static GdkPixbuf *
+rsvg_filter_get_bg (RsvgFilterContext * ctx)
+{
+ if (!ctx->bg)
+ ctx->bg = rsvg_compile_bg (ctx->ctx);
+
+ return ctx->bg;
+}
+
/**
* rsvg_filter_get_in: Gets a pixbuf for a primative.
* @name: The name of the pixbuf
@@ -585,8 +643,7 @@ rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx)
output.Rused = output.Gused = output.Bused = output.Aused = 1;
return output;
} else if (!strcmp (name->str, "BackgroundImage")) {
- g_object_ref (ctx->bg);
- output.result = ctx->bg;
+ output.result = g_object_ref (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) {
@@ -601,7 +658,7 @@ rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx)
} else if (!strcmp (name->str, "BackgroundAlpha")) {
output.Rused = output.Gused = output.Bused = 0;
output.Aused = 1;
- output.result = pixbuf_get_alpha (ctx->bg, ctx);
+ output.result = pixbuf_get_alpha (rsvg_filter_get_bg (ctx), ctx);
return output;
}
diff --git a/rsvg-filter.h b/rsvg-filter.h
index b8e3e73..25dac75 100644
--- a/rsvg-filter.h
+++ b/rsvg-filter.h
@@ -42,7 +42,7 @@ struct _RsvgFilter {
RsvgFilterUnits primitiveunits;
};
-GdkPixbuf *rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source, GdkPixbuf * bg,
+GdkPixbuf *rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
RsvgDrawingCtx * context, RsvgBbox * dimentions, char *channelmap);
RsvgNode *rsvg_new_filter (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]