diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-06-29 23:42:53 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-06-29 23:42:53 +0000 |
| commit | c64911a3ecd14e5eb1a0ddcd338cd8bb2bc01ce7 (patch) | |
| tree | 912f4f14b26acf19b02313d8e430e4610364f5d1 /src/helper/png-write.cpp | |
| parent | Consolidate Cairo utils in display/cairo-utils.h. Fix icons harder. (diff) | |
| download | inkscape-c64911a3ecd14e5eb1a0ddcd338cd8bb2bc01ce7.tar.gz inkscape-c64911a3ecd14e5eb1a0ddcd338cd8bb2bc01ce7.zip | |
Fix PNG export
(bzr r9508.1.9)
Diffstat (limited to 'src/helper/png-write.cpp')
| -rw-r--r-- | src/helper/png-write.cpp | 70 |
1 files changed, 40 insertions, 30 deletions
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp index b1c135db0..908b1fb20 100644 --- a/src/helper/png-write.cpp +++ b/src/helper/png-write.cpp @@ -16,22 +16,23 @@ # include "config.h" #endif -#include <interface.h> -#include <libnr/nr-pixops.h> -#include <libnr/nr-translate-scale-ops.h> +#include "interface.h" +#include "libnr/nr-pixops.h" +#include "libnr/nr-translate-scale-ops.h" #include <2geom/rect.h> #include <glib/gmessages.h> #include <png.h> #include "png-write.h" #include "io/sys.h" -#include <display/nr-arena-item.h> -#include <display/nr-arena.h> -#include <document.h> -#include <sp-item.h> -#include <sp-root.h> -#include <sp-defs.h> +#include "display/nr-arena-item.h" +#include "display/nr-arena.h" +#include "document.h" +#include "sp-item.h" +#include "sp-root.h" +#include "sp-defs.h" #include "preferences.h" #include "rdf.h" +#include "display/cairo-utils.h" /* This is an example of how to use libpng to read and write PNG files. * The file libpng.txt is much more verbose then this. If you have not @@ -49,7 +50,7 @@ static unsigned int const MAX_STRIPE_SIZE = 1024*1024; struct SPEBP { unsigned long int width, height, sheight; - guchar r, g, b, a; + guint32 background; NRArenaItem *root; // the root arena item to show; it is assumed that all unneeded items are hidden guchar *px; unsigned (*status)(float, void *); @@ -122,7 +123,7 @@ void PngTextList::add(gchar const* key, gchar const* text) static bool sp_png_write_rgba_striped(SPDocument *doc, gchar const *filename, unsigned long int width, unsigned long int height, double xdpi, double ydpi, - int (* get_rows)(guchar const **rows, int row, int num_rows, void *data), + int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data), void *data) { struct SPEBP *ebp = (struct SPEBP *) data; @@ -272,10 +273,12 @@ sp_png_write_rgba_striped(SPDocument *doc, png_bytep* row_pointers = new png_bytep[ebp->sheight]; r = 0; - while (r < static_cast< png_uint_32 > (height) ) { - int n = get_rows((unsigned char const **) row_pointers, r, height-r, data); + while (r < static_cast<png_uint_32>(height)) { + void *to_free; + int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data); if (!n) break; png_write_rows(png_ptr, row_pointers, n); + g_free(to_free); r += n; } @@ -305,7 +308,7 @@ sp_png_write_rgba_striped(SPDocument *doc, * */ static int -sp_export_get_rows(guchar const **rows, int row, int num_rows, void *data) +sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data) { struct SPEBP *ebp = (struct SPEBP *) data; @@ -332,26 +335,36 @@ sp_export_get_rows(guchar const **rows, int row, int num_rows, void *data) nr_arena_item_invoke_update(ebp->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE); + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, ebp->width); + unsigned char *px = g_new(guchar, num_rows * stride); + + cairo_surface_t *s = cairo_image_surface_create_for_data( + px, CAIRO_FORMAT_ARGB32, ebp->width, num_rows, stride); + cairo_t *ct = cairo_create(s); + ink_cairo_set_source_rgba32(ct, ebp->background); + cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); + cairo_paint(ct); + cairo_set_operator(ct, CAIRO_OPERATOR_OVER); + NRPixBlock pb; nr_pixblock_setup_extern(&pb, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox.x0, bbox.y0, bbox.x1, bbox.y1, ebp->px, 4 * ebp->width, FALSE, FALSE); - for (int r = 0; r < num_rows; r++) { - guchar *p = NR_PIXBLOCK_PX(&pb) + r * pb.rs; - for (int c = 0; c < static_cast<int>(ebp->width); c++) { - *p++ = ebp->r; - *p++ = ebp->g; - *p++ = ebp->b; - *p++ = ebp->a; - } - } - /* Render */ - nr_arena_item_invoke_render(NULL, ebp->root, &bbox, &pb, 0); + nr_arena_item_invoke_render(ct, ebp->root, &bbox, &pb, 0); + + cairo_destroy(ct); + cairo_surface_destroy(s); + + *to_free = px; + + // PNG stores data as unpremultiplied big-endian RGBA, which means + // it's identical to the GdkPixbuf format. + convert_pixels_argb32_to_pixbuf(px, ebp->width, num_rows, stride); for (int r = 0; r < num_rows; r++) { - rows[r] = NR_PIXBLOCK_PX(&pb) + r * pb.rs; + rows[r] = px + r * stride; } nr_pixblock_release(&pb); @@ -452,10 +465,7 @@ sp_export_png_file(SPDocument *doc, gchar const *filename, struct SPEBP ebp; ebp.width = width; ebp.height = height; - ebp.r = NR_RGBA32_R(bgcolor); - ebp.g = NR_RGBA32_G(bgcolor); - ebp.b = NR_RGBA32_B(bgcolor); - ebp.a = NR_RGBA32_A(bgcolor); + ebp.background = bgcolor; /* Create new arena */ NRArena *const arena = NRArena::create(); |
