diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-08-09 20:45:22 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-08-09 20:45:22 +0000 |
| commit | 2cfc657521d2c22e9238ce1904a6a4a90d3b4517 (patch) | |
| tree | b07eb4e1fefea78fdac087e5fc6eaa3a179a6b41 /src | |
| parent | OpenMP-enabled matrix convolution (diff) | |
| download | inkscape-2cfc657521d2c22e9238ce1904a6a4a90d3b4517.tar.gz inkscape-2cfc657521d2c22e9238ce1904a6a4a90d3b4517.zip | |
Fix performance regression when displaying large images
(bzr r9508.1.54)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/cairo-utils.cpp | 11 | ||||
| -rw-r--r-- | src/display/cairo-utils.h | 1 | ||||
| -rw-r--r-- | src/display/nr-arena-image.cpp | 10 | ||||
| -rw-r--r-- | src/display/nr-arena-image.h | 3 | ||||
| -rw-r--r-- | src/sp-image.cpp | 18 |
5 files changed, 31 insertions, 12 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 15fceedae..96219e834 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -327,6 +327,14 @@ ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m) void ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y) { + cairo_surface_t *pbs = ink_cairo_surface_create_for_argb32_pixbuf(pb); + cairo_set_source_surface(ct, pbs, x, y); + cairo_surface_destroy(pbs); +} + +cairo_surface_t * +ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb) +{ guchar *data = gdk_pixbuf_get_pixels(pb); int w = gdk_pixbuf_get_width(pb); int h = gdk_pixbuf_get_height(pb); @@ -334,8 +342,7 @@ ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double cairo_surface_t *pbs = cairo_image_surface_create_for_data( data, CAIRO_FORMAT_ARGB32, w, h, stride); - cairo_set_source_surface(ct, pbs, x, y); - cairo_surface_destroy(pbs); + return pbs; } /** @brief Create an exact copy of a surface. diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index f74ceed14..0acdcb46a 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -102,6 +102,7 @@ void convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int rs); void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs); void convert_pixbuf_normal_to_argb32(GdkPixbuf *); void convert_pixbuf_argb32_to_normal(GdkPixbuf *); +cairo_surface_t *ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb); G_GNUC_CONST inline guint32 premul_alpha(guint32 color, guint32 alpha) diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp index d32b6efe0..5f30e0560 100644 --- a/src/display/nr-arena-image.cpp +++ b/src/display/nr-arena-image.cpp @@ -93,8 +93,10 @@ nr_arena_image_finalize (NRObject *object) { NRArenaImage *image = NR_ARENA_IMAGE (object); - if (image->pixbuf != NULL) + if (image->pixbuf != NULL) { g_object_unref(image->pixbuf); + cairo_surface_destroy(image->surface); + } if (image->style) sp_style_unref(image->style); @@ -159,7 +161,7 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock cairo_translate(ct, image->ox, image->oy); cairo_scale(ct, image->sx, image->sy); - gdk_cairo_set_source_pixbuf(ct, image->pixbuf, 0, 0); + cairo_set_source_surface(ct, image->surface, 0, 0); cairo_matrix_t tt; Geom::Matrix total; @@ -311,7 +313,7 @@ nr_arena_image_rect (NRArenaImage *image) /* Utility */ void -nr_arena_image_set_pixbuf (NRArenaImage *image, GdkPixbuf *pb) +nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb) { nr_return_if_fail (image != NULL); nr_return_if_fail (NR_IS_ARENA_IMAGE (image)); @@ -322,8 +324,10 @@ nr_arena_image_set_pixbuf (NRArenaImage *image, GdkPixbuf *pb) } if (image->pixbuf != NULL) { g_object_unref(image->pixbuf); + cairo_surface_destroy(image->surface); } image->pixbuf = pb; + image->surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL; nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE); } diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h index 76ff23c29..bde0d41bd 100644 --- a/src/display/nr-arena-image.h +++ b/src/display/nr-arena-image.h @@ -26,6 +26,7 @@ NRType nr_arena_image_get_type (void); struct NRArenaImage : public NRArenaItem { GdkPixbuf *pixbuf; + cairo_surface_t *surface; Geom::Matrix ctm; Geom::Rect clipbox; @@ -45,7 +46,7 @@ struct NRArenaImageClass { NRArenaItemClass parent_class; }; -void nr_arena_image_set_pixbuf (NRArenaImage *image, GdkPixbuf *pb); +void nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb); void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style); void nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip); void nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin); diff --git a/src/sp-image.cpp b/src/sp-image.cpp index 596090846..22392e635 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -26,6 +26,7 @@ #include <glibmm/i18n.h> #include "display/nr-arena-image.h" +#include "display/cairo-utils.h" #include "display/curve.h" //Added for preserveAspectRatio support -- EAF #include "enums.h" @@ -908,6 +909,8 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags) } #endif // ENABLE_LCMS image->pixbuf = pixbuf; + // convert to premultiplied native-endian ARGB for display with Cairo + convert_pixbuf_normal_to_argb32(image->pixbuf); } } } @@ -1077,11 +1080,14 @@ sp_image_print (SPItem *item, SPPrintContext *ctx) SPImage *image = SP_IMAGE(item); if (image->pixbuf && (image->width.computed > 0.0) && (image->height.computed > 0.0) ) { - guchar *px = gdk_pixbuf_get_pixels(image->pixbuf); - int w = gdk_pixbuf_get_width(image->pixbuf); - int h = gdk_pixbuf_get_height(image->pixbuf); - int rs = gdk_pixbuf_get_rowstride(image->pixbuf); - int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8; + GdkPixbuf *pb = gdk_pixbuf_copy(image->pixbuf); + convert_pixbuf_argb32_to_normal(pb); + + guchar *px = gdk_pixbuf_get_pixels(pb); + int w = gdk_pixbuf_get_width(pb); + int h = gdk_pixbuf_get_height(pb); + int rs = gdk_pixbuf_get_rowstride(pb); + int pixskip = gdk_pixbuf_get_n_channels(pb) * gdk_pixbuf_get_bits_per_sample(pb) / 8; if (image->aspect_align == SP_ASPECT_NONE) { Geom::Matrix t; @@ -1262,7 +1268,7 @@ static void sp_image_update_arenaitem (SPImage *image, NRArenaImage *ai) { nr_arena_image_set_style(ai, SP_OBJECT_STYLE(SP_OBJECT(image))); - nr_arena_image_set_pixbuf(ai, image->pixbuf); + nr_arena_image_set_argb32_pixbuf(ai, image->pixbuf); nr_arena_image_set_origin(ai, Geom::Point(image->ox, image->oy)); nr_arena_image_set_scale(ai, image->sx, image->sy); nr_arena_image_set_clipbox(ai, image->clipbox); |
