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-pdf-private.h"
30 #include <cairo-pdf.h>
31 #include <cairo-pdf-surface-private.h>
32 #include <cairo-paginated-surface-private.h>
39 cairo_user_data_key_t pdf_closure_key
;
41 typedef struct _pdf_target_closure
46 cairo_surface_t
*target
;
47 } pdf_target_closure_t
;
49 #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
52 _cairo_boilerplate_pdf_create_surface (const char *name
,
53 cairo_content_t content
,
58 cairo_boilerplate_mode_t mode
,
62 pdf_target_closure_t
*ptc
;
63 cairo_surface_t
*surface
;
64 cairo_status_t status
;
66 /* Sanitize back to a real cairo_content_t value. */
67 if (content
== CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED
)
68 content
= CAIRO_CONTENT_COLOR_ALPHA
;
70 *closure
= ptc
= xmalloc (sizeof (pdf_target_closure_t
));
75 xasprintf (&ptc
->filename
, "%s-out.pdf", name
);
76 xunlink (ptc
->filename
);
78 surface
= cairo_pdf_surface_create (ptc
->filename
, width
, height
);
79 if (cairo_surface_status (surface
))
80 goto CLEANUP_FILENAME
;
82 cairo_surface_set_fallback_resolution (surface
, 72., 72.);
84 if (content
== CAIRO_CONTENT_COLOR
) {
85 ptc
->target
= surface
;
86 surface
= cairo_surface_create_similar (ptc
->target
,
89 if (cairo_surface_status (surface
))
95 status
= cairo_surface_set_user_data (surface
, &pdf_closure_key
, ptc
, NULL
);
96 if (status
== CAIRO_STATUS_SUCCESS
)
99 cairo_surface_destroy (surface
);
100 surface
= cairo_boilerplate_surface_create_in_error (status
);
103 cairo_surface_destroy (ptc
->target
);
105 free (ptc
->filename
);
111 _cairo_boilerplate_pdf_finish_surface (cairo_surface_t
*surface
)
113 pdf_target_closure_t
*ptc
= cairo_surface_get_user_data (surface
,
115 cairo_status_t status
;
117 /* Both surface and ptc->target were originally created at the
118 * same dimensions. We want a 1:1 copy here, so we first clear any
119 * device offset on surface.
121 * In a more realistic use case of device offsets, the target of
122 * this copying would be of a different size than the source, and
123 * the offset would be desirable during the copy operation. */
124 cairo_surface_set_device_offset (surface
, 0, 0);
128 cr
= cairo_create (ptc
->target
);
129 cairo_set_source_surface (cr
, surface
, 0, 0);
131 cairo_show_page (cr
);
132 status
= cairo_status (cr
);
138 cairo_surface_finish (surface
);
139 status
= cairo_surface_status (surface
);
143 surface
= ptc
->target
;
146 cairo_surface_finish (surface
);
147 status
= cairo_surface_status (surface
);
151 return CAIRO_STATUS_SUCCESS
;
155 _cairo_boilerplate_pdf_surface_write_to_png (cairo_surface_t
*surface
, const char *filename
)
157 pdf_target_closure_t
*ptc
= cairo_surface_get_user_data (surface
, &pdf_closure_key
);
161 sprintf (command
, "./pdf2png %s %s 1",
162 ptc
->filename
, filename
);
164 exitstatus
= system (command
);
165 #if _XOPEN_SOURCE && HAVE_SIGNAL_H
166 if (WIFSIGNALED (exitstatus
))
167 raise (WTERMSIG (exitstatus
));
170 return CAIRO_STATUS_WRITE_ERROR
;
172 return CAIRO_STATUS_SUCCESS
;
175 static cairo_surface_t
*
176 _cairo_boilerplate_pdf_convert_to_image (cairo_surface_t
*surface
, int page
)
178 pdf_target_closure_t
*ptc
= cairo_surface_get_user_data (surface
,
181 return cairo_boilerplate_convert_to_image (ptc
->filename
, page
+1);
185 _cairo_boilerplate_pdf_get_image_surface (cairo_surface_t
*surface
,
190 cairo_surface_t
*image
;
192 image
= _cairo_boilerplate_pdf_convert_to_image (surface
, page
);
193 cairo_surface_set_device_offset (image
,
194 cairo_image_surface_get_width (image
) - width
,
195 cairo_image_surface_get_height (image
) - height
);
196 surface
= _cairo_boilerplate_get_image_surface (image
, 0, width
, height
);
197 cairo_surface_destroy (image
);
203 _cairo_boilerplate_pdf_cleanup (void *closure
)
205 pdf_target_closure_t
*ptc
= closure
;
207 cairo_surface_destroy (ptc
->target
);
208 free (ptc
->filename
);
214 _cairo_boilerplate_pdf_force_fallbacks (cairo_surface_t
*abstract_surface
,
217 pdf_target_closure_t
*ptc
= cairo_surface_get_user_data (abstract_surface
,
220 cairo_paginated_surface_t
*paginated
;
221 cairo_pdf_surface_t
*surface
;
224 abstract_surface
= ptc
->target
;
226 paginated
= (cairo_paginated_surface_t
*) abstract_surface
;
227 surface
= (cairo_pdf_surface_t
*) paginated
->target
;
228 surface
->force_fallbacks
= TRUE
;