1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
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>
39 static const cairo_user_data_key_t svg_closure_key
;
41 typedef struct _svg_target_closure
{
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
,
55 cairo_boilerplate_mode_t mode
,
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
));
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
,
83 if (cairo_surface_status (surface
))
88 status
= cairo_surface_set_user_data (surface
, &svg_closure_key
, ptc
, NULL
);
89 if (status
== CAIRO_STATUS_SUCCESS
)
92 cairo_surface_destroy (surface
);
93 surface
= cairo_boilerplate_surface_create_in_error (status
);
96 cairo_surface_destroy (ptc
->target
);
104 _cairo_boilerplate_svg11_create_surface (const char *name
,
105 cairo_content_t content
,
110 cairo_boilerplate_mode_t mode
,
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
,
118 max_width
, max_height
,
124 _cairo_boilerplate_svg12_create_surface (const char *name
,
125 cairo_content_t content
,
130 cairo_boilerplate_mode_t mode
,
134 return _cairo_boilerplate_svg_create_surface (name
, content
,
135 CAIRO_SVG_VERSION_1_2
,
137 max_width
, max_height
,
143 _cairo_boilerplate_svg_finish_surface (cairo_surface_t
*surface
)
145 svg_target_closure_t
*ptc
= cairo_surface_get_user_data (surface
,
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);
160 cr
= cairo_create (ptc
->target
);
161 cairo_set_source_surface (cr
, surface
, 0, 0);
163 cairo_show_page (cr
);
164 status
= cairo_status (cr
);
170 cairo_surface_finish (surface
);
171 status
= cairo_surface_status (surface
);
175 surface
= ptc
->target
;
178 cairo_surface_finish (surface
);
179 status
= cairo_surface_status (surface
);
183 return CAIRO_STATUS_SUCCESS
;
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
,
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
));
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
,
214 return cairo_boilerplate_convert_to_image (ptc
->filename
, 0);
218 _cairo_boilerplate_svg_get_image_surface (cairo_surface_t
*surface
,
223 cairo_surface_t
*image
;
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
);
239 _cairo_boilerplate_svg_cleanup (void *closure
)
241 svg_target_closure_t
*ptc
= closure
;
243 cairo_surface_destroy (ptc
->target
);
244 free (ptc
->filename
);
249 _cairo_boilerplate_svg_force_fallbacks (cairo_surface_t
*abstract_surface
,
252 svg_target_closure_t
*ptc
= cairo_surface_get_user_data (abstract_surface
,
255 cairo_paginated_surface_t
*paginated
;
256 cairo_svg_surface_t
*surface
;
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
;