[dia] perf: Cache a cairo surface in DiaImage to avoid regenerating every frame
- From: Zander <zbrown src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] perf: Cache a cairo surface in DiaImage to avoid regenerating every frame
- Date: Tue, 23 Jul 2019 00:09:19 +0000 (UTC)
commit b2a5f66a9e65749a4adab3b20118c3c87160710f
Author: Zander Brown <zbrown gnome org>
Date: Tue Jul 23 01:06:41 2019 +0100
perf: Cache a cairo surface in DiaImage to avoid regenerating every frame
Significantly improves performance with big images
lib/dia_image.h | 2 +-
lib/renderer/diacairo-renderer.c | 136 ++-------------------------------------
2 files changed, 5 insertions(+), 133 deletions(-)
---
diff --git a/lib/dia_image.h b/lib/dia_image.h
index e30fe01c..5defb3b9 100644
--- a/lib/dia_image.h
+++ b/lib/dia_image.h
@@ -66,7 +66,7 @@ void dia_image_set_mime_type (DiaImage *image,
GdkPixbuf *dia_image_get_scaled_pixbuf (DiaImage *image,
int width,
int height);
-GdkPixbuf *dia_image_get_scaled_pixbuf (DiaImage *image, int width, int height);
+cairo_surface_t *dia_image_get_surface (DiaImage *self);
G_END_DECLS
diff --git a/lib/renderer/diacairo-renderer.c b/lib/renderer/diacairo-renderer.c
index 6b14e74c..2bcf1dc6 100644
--- a/lib/renderer/diacairo-renderer.c
+++ b/lib/renderer/diacairo-renderer.c
@@ -1064,54 +1064,6 @@ dia_cairo_renderer_draw_string (DiaRenderer *self,
DIAG_STATE (renderer->cr)
}
-static cairo_surface_t *
-_image_to_mime_surface (DiaCairoRenderer *renderer,
- DiaImage *image)
-{
- cairo_surface_type_t st;
- const char *fname = dia_image_filename (image);
- int w = dia_image_width (image);
- int h = dia_image_height (image);
- const char *mime_type = NULL;
-
- if (!renderer->surface) {
- return NULL;
- }
-
- /* We only use the "mime" surface if:
- * - the target supports it
- * - we have a file name with a supported format
- * - the cairo version is new enough including
- * http://cgit.freedesktop.org/cairo/commit/?id=35e0a2685134
- */
- if (g_str_has_suffix (fname, ".jpg") || g_str_has_suffix (fname, ".jpeg")) {
- mime_type = CAIRO_MIME_TYPE_JPEG;
- } else if (g_str_has_suffix (fname, ".png")) {
- mime_type = CAIRO_MIME_TYPE_PNG;
- }
- st = cairo_surface_get_type (renderer->surface);
- if ( mime_type
- && cairo_version () >= CAIRO_VERSION_ENCODE (1, 12, 18)
- && (CAIRO_SURFACE_TYPE_PDF == st || CAIRO_SURFACE_TYPE_SVG == st)) {
- cairo_surface_t *surface;
- gchar *data = NULL;
- gsize length = 0;
-
- /* we still ned to create the image surface, but dont need to fill it */
- surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
- cairo_surface_mark_dirty (surface); /* no effect */
- if ( g_file_get_contents (fname, &data, &length, NULL)
- && cairo_surface_set_mime_data (surface, mime_type,
- (unsigned char *) data,
- length, g_free, data) == CAIRO_STATUS_SUCCESS) {
- return surface;
- }
- cairo_surface_destroy (surface);
- g_free (data);
- }
- return NULL;
-}
-
static void
dia_cairo_renderer_draw_rotated_image (DiaRenderer *self,
Point *point,
@@ -1121,98 +1073,21 @@ dia_cairo_renderer_draw_rotated_image (DiaRenderer *self,
DiaImage *image)
{
DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self);
- cairo_surface_t *surface;
- guint8 *data;
int w = dia_image_width (image);
int h = dia_image_height (image);
- int rs = dia_image_rowstride (image);
DIAG_NOTE (g_message ("draw_image %fx%f [%d(%d),%d] @%f,%f",
width, height, w, rs, h, point->x, point->y));
- if ((surface = _image_to_mime_surface (renderer, image)) != NULL) {
- data = NULL;
- } else if (dia_image_rgba_data (image)) {
- const guint8 *p1 = dia_image_rgba_data (image);
- /* we need to make a copy to rearrange channels ... */
- guint8 *p2 = data = g_try_malloc (h * rs);
- int i;
-
- if (!data) {
- message_warning (_("Not enough memory for image drawing."));
- return;
- }
-
- for (i = 0; i < (h * rs) / 4; i++) {
-# if G_BYTE_ORDER == G_LITTLE_ENDIAN
- p2[0] = p1[2]; /* b */
- p2[1] = p1[1]; /* g */
- p2[2] = p1[0]; /* r */
- p2[3] = p1[3]; /* a */
-# else
- p2[3] = p1[2]; /* b */
- p2[2] = p1[1]; /* g */
- p2[1] = p1[0]; /* r */
- p2[0] = p1[3]; /* a */
-# endif
- p1+=4;
- p2+=4;
- }
-
- surface = cairo_image_surface_create_for_data (data,
- CAIRO_FORMAT_ARGB32,
- w,
- h,
- rs);
- } else {
- guint8 *p = NULL, *p2;
- guint8 *p1 = data = dia_image_rgb_data (image);
- /* cairo wants RGB24 32 bit aligned, so copy ... */
- int x, y;
-
- if (data) {
- p = p2 = g_try_malloc(h*w*4);
- }
-
- if (!p) {
- message_warning (_("Not enough memory for image drawing."));
- return;
- }
-
- for (y = 0; y < h; y++) {
- for (x = 0; x < w; x++) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- /* apparently BGR is required */
- p2[x*4 ] = p1[x*3+2];
- p2[x*4+1] = p1[x*3+1];
- p2[x*4+2] = p1[x*3 ];
- p2[x*4+3] = 0x80; /* should not matter */
-#else
- p2[x*4+3] = p1[x*3+2];
- p2[x*4+2] = p1[x*3+1];
- p2[x*4+1] = p1[x*3 ];
- p2[x*4+0] = 0x80; /* should not matter */
-#endif
- }
- p2 += (w*4);
- p1 += rs;
- }
- surface = cairo_image_surface_create_for_data (p,
- CAIRO_FORMAT_RGB24,
- w,
- h,
- w * 4);
- g_free (data);
- data = p;
- }
cairo_save (renderer->cr);
cairo_translate (renderer->cr, point->x, point->y);
- cairo_scale (renderer->cr, width/w, height/h);
+ cairo_scale (renderer->cr, width / w, height / h);
cairo_move_to (renderer->cr, 0.0, 0.0);
- cairo_set_source_surface (renderer->cr, surface, 0.0, 0.0);
+ cairo_set_source_surface (renderer->cr, dia_image_get_surface (image), 0.0, 0.0);
+
if (angle != 0.0) {
DiaMatrix rotate;
- Point center = { w/2, h/2 };
+ Point center = { w / 2, h / 2 };
dia_matrix_set_rotate_around (&rotate, -G_PI * angle / 180.0, ¢er);
cairo_pattern_set_matrix (cairo_get_source (renderer->cr), (cairo_matrix_t *) &rotate);
@@ -1227,9 +1102,6 @@ dia_cairo_renderer_draw_rotated_image (DiaRenderer *self,
#endif
cairo_paint (renderer->cr);
cairo_restore (renderer->cr);
- cairo_surface_destroy (surface);
-
- g_free (data);
DIAG_STATE (renderer->cr);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]