svg text alignment
[dia.git] / app / export_png.c
blob3298f9b245d9f50ec550555a65aca76953301bdc
1 /* Dia -- a diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * export_png.c: export a diagram to a PNG file.
5 * Copyright (C) 2000 James Henstridge
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <config.h>
24 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
26 #include <stdio.h>
27 #include <png.h>
29 #include "intl.h"
30 #include "filter.h"
31 #include "render_libart.h"
32 #include "display.h"
33 #include "message.h"
35 /* the dots per centimetre to render this diagram at */
36 /* this matches the setting `100%' setting in dia. */
37 #define DPCM 20
39 /* the height of the band to use when rendering. Smaller bands mean
40 * rendering is slower, but less memory is used. Setting this to G_MAXINT
41 * should get the renderer to use one pass. */
42 #define BAND_HEIGHT 50
44 static void
45 export_png(DiagramData *data, const gchar *filename,
46 const gchar *diafilename, void* user_data)
48 Rectangle *ext = &data->extents;
49 DDisplay *ddisp;
50 RendererLibart *renderer;
51 guint32 width, height, band, row, i;
52 real band_height;
54 FILE *fp;
55 png_structp png;
56 png_infop info;
57 png_color_8 sig_bit;
58 png_bytep *row_ptr;
60 width = (guint32) ((ext->right - ext->left) * DPCM * data->paper.scaling);
61 height = (guint32) ((ext->bottom - ext->top) * DPCM * data->paper.scaling);
63 /* we render in bands to try to keep memory consumption down ... */
64 band = MIN(height, BAND_HEIGHT);
65 band_height = (real)band / (DPCM * data->paper.scaling);
67 /* create a fake ddisp to keep the renderer happy */
68 ddisp = g_new0(DDisplay, 1);
69 ddisp->zoom_factor = DPCM * data->paper.scaling;
70 ddisp->visible = *ext;
71 ddisp->visible.bottom = MIN(ddisp->visible.bottom,
72 ddisp->visible.top + band_height);
73 renderer = new_libart_renderer(ddisp, 0);
74 libart_renderer_set_size(renderer, NULL, width, band);
75 ddisp->renderer = (Renderer *)renderer;
77 fp = fopen(filename, "wb");
78 if (fp == NULL) {
79 message_error(_("Couldn't open: '%s' for writing.\n"), filename);
80 goto error;
83 png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
84 NULL, NULL, NULL);
85 if (!png) {
86 fclose(fp);
87 message_error(_("Could not create PNG write structure"));
88 goto error;
91 /* allocate/initialise the image information data */
92 info = png_create_info_struct(png);
93 if (!info) {
94 fclose(fp);
95 png_destroy_write_struct(&png, (png_infopp)NULL);
96 message_error(_("Could not create PNG header info structure"));
97 goto error;
100 /* set error handling ... */
101 if (setjmp(png->jmpbuf)) {
102 fclose(fp);
103 png_destroy_write_struct(&png, (png_infopp)NULL);
104 message_error(_("Error occurred while writing PNG"));
105 goto error;
107 /* the compiler said band may be clobbered by setjmp, so we set it again
108 * here. */
109 band = MIN(height, BAND_HEIGHT);
111 png_init_io(png, fp);
113 /* header fields */
114 png_set_IHDR(png, info, width, height, 8,
115 PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
116 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
117 sig_bit.red = 8;
118 sig_bit.green = 8;
119 sig_bit.blue = 8;
120 png_set_sBIT(png, info, &sig_bit);
122 png_write_info(png, info);
123 png_set_shift(png, &sig_bit);
124 png_set_packing(png);
126 row_ptr = g_new(png_bytep, band);
128 for (row = 0; row < height; row += band) {
129 /* render band */
130 for (i = 0; i < width*band; i++) {
131 renderer->rgb_buffer[3*i] = 0xff * data->bg_color.red;
132 renderer->rgb_buffer[3*i+1] = 0xff * data->bg_color.green;
133 renderer->rgb_buffer[3*i+2] = 0xff * data->bg_color.blue;
135 data_render(data, (Renderer *)renderer, &ddisp->visible, NULL,NULL);
136 /* write rows to png file */
137 for (i = 0; i < band; i++)
138 row_ptr[i] = renderer->rgb_buffer + 3 * i * width;
139 png_write_rows(png, row_ptr, MIN(band, height - row));
141 ddisp->visible.top += band_height;
142 ddisp->visible.bottom += band_height;
144 g_free(row_ptr);
145 png_write_end(png, info);
146 png_destroy_write_struct(&png, (png_infopp)NULL);
147 fclose(fp);
149 error:
150 destroy_libart_renderer(renderer);
151 g_free(ddisp);
152 return;
155 static const gchar *extensions[] = { "png", NULL };
156 DiaExportFilter png_export_filter = {
157 N_("Portable Network Graphics"),
158 extensions,
159 export_png
162 #endif