2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / cairo / boilerplate / cairo-boilerplate-svg.c
blob195dc7868bf02fb2b8f6d33afdd4d59e6c1745ef
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /*
3 * Copyright © 2004,2006 Red Hat, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without
7 * fee, provided that the above copyright notice appear in all copies
8 * and that both that copyright notice and this permission notice
9 * appear in supporting documentation, and that the name of
10 * Red Hat, Inc. not be used in advertising or publicity pertaining to
11 * distribution of the software without specific, written prior
12 * permission. Red Hat, Inc. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as
14 * is" without express or implied warranty.
16 * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
19 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
22 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Author: Carl D. Worth <cworth@cworth.org>
27 #include "cairo-boilerplate.h"
28 #include "cairo-boilerplate-svg-private.h"
30 #include <cairo-svg.h>
31 #include <cairo-svg-surface-private.h>
32 #include <cairo-paginated-surface-private.h>
34 #if HAVE_SIGNAL_H
35 #include <stdlib.h>
36 #include <signal.h>
37 #endif
39 static const cairo_user_data_key_t svg_closure_key;
41 typedef struct _svg_target_closure {
42 char *filename;
43 int width, height;
44 cairo_surface_t *target;
45 } svg_target_closure_t;
47 static cairo_surface_t *
48 _cairo_boilerplate_svg_create_surface (const char *name,
49 cairo_content_t content,
50 cairo_svg_version_t version,
51 int width,
52 int height,
53 int max_width,
54 int max_height,
55 cairo_boilerplate_mode_t mode,
56 int id,
57 void **closure)
59 svg_target_closure_t *ptc;
60 cairo_surface_t *surface;
61 cairo_status_t status;
63 *closure = ptc = xmalloc (sizeof (svg_target_closure_t));
65 ptc->width = width;
66 ptc->height = height;
68 xasprintf (&ptc->filename, "%s-out.svg", name);
69 xunlink (ptc->filename);
71 surface = cairo_svg_surface_create (ptc->filename, width, height);
72 if (cairo_surface_status (surface))
73 goto CLEANUP_FILENAME;
75 cairo_svg_surface_restrict_to_version (surface, version);
76 cairo_surface_set_fallback_resolution (surface, 72., 72.);
78 if (content == CAIRO_CONTENT_COLOR) {
79 ptc->target = surface;
80 surface = cairo_surface_create_similar (ptc->target,
81 CAIRO_CONTENT_COLOR,
82 width, height);
83 if (cairo_surface_status (surface))
84 goto CLEANUP_TARGET;
85 } else
86 ptc->target = NULL;
88 status = cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
89 if (status == CAIRO_STATUS_SUCCESS)
90 return surface;
92 cairo_surface_destroy (surface);
93 surface = cairo_boilerplate_surface_create_in_error (status);
95 CLEANUP_TARGET:
96 cairo_surface_destroy (ptc->target);
97 CLEANUP_FILENAME:
98 free (ptc->filename);
99 free (ptc);
100 return surface;
103 cairo_surface_t *
104 _cairo_boilerplate_svg11_create_surface (const char *name,
105 cairo_content_t content,
106 int width,
107 int height,
108 int max_width,
109 int max_height,
110 cairo_boilerplate_mode_t mode,
111 int id,
112 void **closure)
114 /* current default, but be explicit in case the default changes */
115 return _cairo_boilerplate_svg_create_surface (name, content,
116 CAIRO_SVG_VERSION_1_1,
117 width, height,
118 max_width, max_height,
119 mode, id,
120 closure);
123 cairo_surface_t *
124 _cairo_boilerplate_svg12_create_surface (const char *name,
125 cairo_content_t content,
126 int width,
127 int height,
128 int max_width,
129 int max_height,
130 cairo_boilerplate_mode_t mode,
131 int id,
132 void **closure)
134 return _cairo_boilerplate_svg_create_surface (name, content,
135 CAIRO_SVG_VERSION_1_2,
136 width, height,
137 max_width, max_height,
138 mode, id,
139 closure);
142 cairo_status_t
143 _cairo_boilerplate_svg_finish_surface (cairo_surface_t *surface)
145 svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
146 &svg_closure_key);
147 cairo_status_t status;
149 /* Both surface and ptc->target were originally created at the
150 * same dimensions. We want a 1:1 copy here, so we first clear any
151 * device offset on surface.
153 * In a more realistic use case of device offsets, the target of
154 * this copying would be of a different size than the source, and
155 * the offset would be desirable during the copy operation. */
156 cairo_surface_set_device_offset (surface, 0, 0);
158 if (ptc->target) {
159 cairo_t *cr;
160 cr = cairo_create (ptc->target);
161 cairo_set_source_surface (cr, surface, 0, 0);
162 cairo_paint (cr);
163 cairo_show_page (cr);
164 status = cairo_status (cr);
165 cairo_destroy (cr);
167 if (status)
168 return status;
170 cairo_surface_finish (surface);
171 status = cairo_surface_status (surface);
172 if (status)
173 return status;
175 surface = ptc->target;
178 cairo_surface_finish (surface);
179 status = cairo_surface_status (surface);
180 if (status)
181 return status;
183 return CAIRO_STATUS_SUCCESS;
186 cairo_status_t
187 _cairo_boilerplate_svg_surface_write_to_png (cairo_surface_t *surface, const char *filename)
189 svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
190 &svg_closure_key);
191 char command[4096];
192 int exitstatus;
194 sprintf (command, "./svg2png %s %s",
195 ptc->filename, filename);
197 exitstatus = system (command);
198 #if _XOPEN_SOURCE && HAVE_SIGNAL_H
199 if (WIFSIGNALED (exitstatus))
200 raise (WTERMSIG (exitstatus));
201 #endif
202 if (exitstatus)
203 return CAIRO_STATUS_WRITE_ERROR;
205 return CAIRO_STATUS_SUCCESS;
208 static cairo_surface_t *
209 _cairo_boilerplate_svg_convert_to_image (cairo_surface_t *surface)
211 svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
212 &svg_closure_key);
214 return cairo_boilerplate_convert_to_image (ptc->filename, 0);
217 cairo_surface_t *
218 _cairo_boilerplate_svg_get_image_surface (cairo_surface_t *surface,
219 int page,
220 int width,
221 int height)
223 cairo_surface_t *image;
225 if (page != 0)
226 return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
228 image = _cairo_boilerplate_svg_convert_to_image (surface);
229 cairo_surface_set_device_offset (image,
230 cairo_image_surface_get_width (image) - width,
231 cairo_image_surface_get_height (image) - height);
232 surface = _cairo_boilerplate_get_image_surface (image, 0, width, height);
233 cairo_surface_destroy (image);
235 return surface;
238 void
239 _cairo_boilerplate_svg_cleanup (void *closure)
241 svg_target_closure_t *ptc = closure;
242 if (ptc->target)
243 cairo_surface_destroy (ptc->target);
244 free (ptc->filename);
245 free (ptc);
248 void
249 _cairo_boilerplate_svg_force_fallbacks (cairo_surface_t *abstract_surface,
250 unsigned int flags)
252 svg_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
253 &svg_closure_key);
255 cairo_paginated_surface_t *paginated;
256 cairo_svg_surface_t *surface;
258 if (ptc->target)
259 abstract_surface = ptc->target;
261 paginated = (cairo_paginated_surface_t*) abstract_surface;
262 surface = (cairo_svg_surface_t*) paginated->target;
263 surface->force_fallbacks = TRUE;