2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / cairo / boilerplate / cairo-boilerplate-pdf.c
blob7000238589f6627722cb3e5449aa8ca892bdb634
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-pdf-private.h"
30 #include <cairo-pdf.h>
31 #include <cairo-pdf-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 cairo_user_data_key_t pdf_closure_key;
41 typedef struct _pdf_target_closure
43 char *filename;
44 int width;
45 int height;
46 cairo_surface_t *target;
47 } pdf_target_closure_t;
49 #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
51 cairo_surface_t *
52 _cairo_boilerplate_pdf_create_surface (const char *name,
53 cairo_content_t content,
54 int width,
55 int height,
56 int max_width,
57 int max_height,
58 cairo_boilerplate_mode_t mode,
59 int id,
60 void **closure)
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));
72 ptc->width = width;
73 ptc->height = height;
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,
87 CAIRO_CONTENT_COLOR,
88 width, height);
89 if (cairo_surface_status (surface))
90 goto CLEANUP_TARGET;
91 } else {
92 ptc->target = NULL;
95 status = cairo_surface_set_user_data (surface, &pdf_closure_key, ptc, NULL);
96 if (status == CAIRO_STATUS_SUCCESS)
97 return surface;
99 cairo_surface_destroy (surface);
100 surface = cairo_boilerplate_surface_create_in_error (status);
102 CLEANUP_TARGET:
103 cairo_surface_destroy (ptc->target);
104 CLEANUP_FILENAME:
105 free (ptc->filename);
106 free (ptc);
107 return surface;
110 cairo_status_t
111 _cairo_boilerplate_pdf_finish_surface (cairo_surface_t *surface)
113 pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface,
114 &pdf_closure_key);
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);
126 if (ptc->target) {
127 cairo_t *cr;
128 cr = cairo_create (ptc->target);
129 cairo_set_source_surface (cr, surface, 0, 0);
130 cairo_paint (cr);
131 cairo_show_page (cr);
132 status = cairo_status (cr);
133 cairo_destroy (cr);
135 if (status)
136 return status;
138 cairo_surface_finish (surface);
139 status = cairo_surface_status (surface);
140 if (status)
141 return status;
143 surface = ptc->target;
146 cairo_surface_finish (surface);
147 status = cairo_surface_status (surface);
148 if (status)
149 return status;
151 return CAIRO_STATUS_SUCCESS;
154 cairo_status_t
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);
158 char command[4096];
159 int exitstatus;
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));
168 #endif
169 if (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,
179 &pdf_closure_key);
181 return cairo_boilerplate_convert_to_image (ptc->filename, page+1);
184 cairo_surface_t *
185 _cairo_boilerplate_pdf_get_image_surface (cairo_surface_t *surface,
186 int page,
187 int width,
188 int height)
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);
199 return surface;
202 void
203 _cairo_boilerplate_pdf_cleanup (void *closure)
205 pdf_target_closure_t *ptc = closure;
206 if (ptc->target)
207 cairo_surface_destroy (ptc->target);
208 free (ptc->filename);
209 free (ptc);
213 void
214 _cairo_boilerplate_pdf_force_fallbacks (cairo_surface_t *abstract_surface,
215 unsigned int flags)
217 pdf_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
218 &pdf_closure_key);
220 cairo_paginated_surface_t *paginated;
221 cairo_pdf_surface_t *surface;
223 if (ptc->target)
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;