1 | /* viewer-cairo.c: Common code for Cairo-based viewers |
2 | * |
3 | * Copyright (C) 1999,2004,2005 Red Hat, Inc. |
4 | * Copyright (C) 2001 Sun Microsystems |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public |
17 | * License along with this library; if not, write to the |
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 | * Boston, MA 02111-1307, USA. |
20 | */ |
21 | #include "config.h" |
22 | |
23 | #include "viewer-cairo.h" |
24 | #include "viewer-render.h" |
25 | |
26 | #include <cairo.h> |
27 | |
28 | #include <string.h> |
29 | |
30 | |
31 | |
32 | #ifdef HAVE_CAIRO_XLIB |
33 | #ifdef HAVE_XFT |
34 | #include "viewer-x.h" |
35 | #include <cairo-xlib.h> |
36 | |
37 | static cairo_surface_t * |
38 | cairo_x_view_iface_create_surface (gpointer instance, |
39 | gpointer surface, |
40 | int width, |
41 | int height) |
42 | { |
43 | XViewer *x = (XViewer *)instance; |
44 | Drawable drawable = (Drawable) surface; |
45 | |
46 | return cairo_xlib_surface_create (x->display, drawable, |
47 | DefaultVisual (x->display, x->screen), |
48 | width, height); |
49 | } |
50 | |
51 | static void |
52 | cairo_x_view_iface_paint_background (gpointer instance G_GNUC_UNUSED, |
53 | cairo_t *cr) |
54 | { |
55 | cairo_set_source_rgb (cr, 1, 1, 1); |
56 | cairo_paint (cr); |
57 | |
58 | if (opt_bg_set) |
59 | { |
60 | cairo_set_source_rgba (cr, |
61 | opt_bg_color.red / 65535., |
62 | opt_bg_color.green / 65535., |
63 | opt_bg_color.blue / 65535., |
64 | opt_bg_alpha / 65535.); |
65 | cairo_paint (cr); |
66 | } |
67 | } |
68 | |
69 | static CairoViewerIface cairo_x_viewer_iface = { |
70 | &x_viewer, |
71 | cairo_x_view_iface_create_surface, |
72 | cairo_x_view_iface_paint_background |
73 | }; |
74 | #endif /* HAVE_XFT */ |
75 | #endif /* HAVE_CAIRO_XLIB */ |
76 | |
77 | |
78 | |
79 | |
80 | static cairo_surface_t * |
81 | cairo_view_iface_create_surface (gpointer instance, |
82 | gpointer surface, |
83 | int width, |
84 | int height) |
85 | { |
86 | return cairo_surface_reference (surface); |
87 | } |
88 | |
89 | |
90 | |
91 | static gpointer |
92 | cairo_image_view_create (const PangoViewer *klass G_GNUC_UNUSED) |
93 | { |
94 | return NULL; |
95 | } |
96 | |
97 | static void |
98 | cairo_image_view_destroy (gpointer instance G_GNUC_UNUSED) |
99 | { |
100 | } |
101 | |
102 | static gpointer |
103 | cairo_image_view_create_surface (gpointer instance, |
104 | int width, |
105 | int height) |
106 | { |
107 | cairo_t *cr; |
108 | cairo_surface_t *surface; |
109 | |
110 | /* TODO: Be smarter about format? */ |
111 | surface = cairo_image_surface_create (format: CAIRO_FORMAT_ARGB32, width, height); |
112 | |
113 | cr = cairo_create (target: surface); |
114 | cairo_set_source_rgb (cr, red: 1.0, green: 1.0, blue: 1.0); |
115 | cairo_paint (cr); |
116 | cairo_destroy (cr); |
117 | |
118 | return surface; |
119 | } |
120 | |
121 | static void |
122 | cairo_image_view_destroy_surface (gpointer instance, |
123 | gpointer surface) |
124 | { |
125 | cairo_surface_destroy (surface); |
126 | } |
127 | |
128 | const PangoViewer cairo_image_viewer = { |
129 | "CairoImage" , |
130 | NULL, |
131 | NULL, |
132 | cairo_image_view_create, |
133 | cairo_image_view_destroy, |
134 | NULL, |
135 | cairo_image_view_create_surface, |
136 | cairo_image_view_destroy_surface, |
137 | NULL, |
138 | NULL, |
139 | NULL, |
140 | NULL, |
141 | NULL |
142 | }; |
143 | |
144 | static void |
145 | cairo_image_view_iface_paint_background (gpointer instance G_GNUC_UNUSED, |
146 | cairo_t *cr) |
147 | { |
148 | cairo_set_source_rgb (cr, red: 1, green: 1, blue: 1); |
149 | cairo_paint (cr); |
150 | |
151 | if (opt_bg_set) |
152 | { |
153 | cairo_set_operator (cr, op: CAIRO_OPERATOR_SOURCE); |
154 | cairo_set_source_rgba (cr, |
155 | red: opt_bg_color.red / 65535., |
156 | green: opt_bg_color.green / 65535., |
157 | blue: opt_bg_color.blue / 65535., |
158 | alpha: opt_bg_alpha / 65535.); |
159 | cairo_paint (cr); |
160 | } |
161 | } |
162 | |
163 | static CairoViewerIface cairo_image_viewer_iface = { |
164 | &cairo_image_viewer, |
165 | cairo_view_iface_create_surface, |
166 | cairo_image_view_iface_paint_background |
167 | }; |
168 | |
169 | |
170 | |
171 | |
172 | #ifdef CAIRO_HAS_SVG_SURFACE |
173 | # include <cairo-svg.h> |
174 | #endif |
175 | #ifdef CAIRO_HAS_PDF_SURFACE |
176 | # include <cairo-pdf.h> |
177 | #endif |
178 | #ifdef CAIRO_HAS_PS_SURFACE |
179 | # include <cairo-ps.h> |
180 | # if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0) |
181 | # define HAS_EPS 1 |
182 | |
183 | static cairo_surface_t * |
184 | _cairo_eps_surface_create (const char *filename, |
185 | double width, |
186 | double height) |
187 | { |
188 | cairo_surface_t *surface; |
189 | |
190 | surface = cairo_ps_surface_create (filename, width_in_points: width, height_in_points: height); |
191 | cairo_ps_surface_set_eps (surface, TRUE); |
192 | |
193 | return surface; |
194 | } |
195 | |
196 | # else |
197 | # undef HAS_EPS |
198 | # endif |
199 | #endif |
200 | |
201 | typedef cairo_surface_t *(*CairoVectorFileCreateFunc) (const char *filename, |
202 | double width, |
203 | double height); |
204 | |
205 | typedef struct |
206 | { |
207 | const char *filename; |
208 | CairoVectorFileCreateFunc constructor; |
209 | } CairoVectorViewer; |
210 | |
211 | static gpointer |
212 | cairo_vector_view_create (const PangoViewer *klass G_GNUC_UNUSED) |
213 | { |
214 | const char *extension = NULL; |
215 | CairoVectorFileCreateFunc constructor = NULL; |
216 | |
217 | if (opt_output) |
218 | { |
219 | extension = strrchr (s: opt_output, c: '.'); |
220 | if (extension) |
221 | extension++; /* skip the dot */ |
222 | } |
223 | |
224 | if (!extension) |
225 | return NULL; |
226 | |
227 | if (0) |
228 | {} |
229 | #ifdef CAIRO_HAS_SVG_SURFACE |
230 | else if (0 == g_ascii_strcasecmp (s1: extension, s2: "svg" )) |
231 | constructor = cairo_svg_surface_create; |
232 | #endif |
233 | #ifdef CAIRO_HAS_PDF_SURFACE |
234 | else if (0 == g_ascii_strcasecmp (s1: extension, s2: "pdf" )) |
235 | constructor = cairo_pdf_surface_create; |
236 | #endif |
237 | #ifdef CAIRO_HAS_PS_SURFACE |
238 | else if (0 == g_ascii_strcasecmp (s1: extension, s2: "ps" )) |
239 | constructor = cairo_ps_surface_create; |
240 | #ifdef HAS_EPS |
241 | else if (0 == g_ascii_strcasecmp (s1: extension, s2: "eps" )) |
242 | constructor = _cairo_eps_surface_create; |
243 | #endif |
244 | #endif |
245 | |
246 | if (constructor) |
247 | { |
248 | CairoVectorViewer *instance; |
249 | |
250 | instance = g_slice_new (CairoVectorViewer); |
251 | |
252 | /* save output filename and unset it such that the viewer layer |
253 | * doesn't try to save to file. |
254 | */ |
255 | instance->filename = opt_output; |
256 | opt_output = NULL; |
257 | |
258 | instance->constructor = constructor; |
259 | |
260 | /* Fix dpi on 72. That's what cairo vector surfaces are. */ |
261 | opt_dpi = 72; |
262 | |
263 | return instance; |
264 | } |
265 | |
266 | return NULL; |
267 | } |
268 | |
269 | static void |
270 | cairo_vector_view_destroy (gpointer instance G_GNUC_UNUSED) |
271 | { |
272 | CairoVectorViewer *c = (CairoVectorViewer *) instance; |
273 | |
274 | g_slice_free (CairoVectorViewer, c); |
275 | } |
276 | |
277 | static gpointer |
278 | cairo_vector_view_create_surface (gpointer instance, |
279 | int width, |
280 | int height) |
281 | { |
282 | CairoVectorViewer *c = (CairoVectorViewer *) instance; |
283 | cairo_surface_t *surface; |
284 | |
285 | surface = c->constructor (c->filename, width, height); |
286 | |
287 | /*cairo_surface_set_fallback_resolution (surface, fallback_resolution_x, fallback_resolution_y);*/ |
288 | |
289 | return surface; |
290 | } |
291 | |
292 | static void |
293 | cairo_vector_view_destroy_surface (gpointer instance, |
294 | gpointer surface) |
295 | { |
296 | /* TODO: check for errors */ |
297 | cairo_surface_destroy (surface); |
298 | } |
299 | |
300 | const PangoViewer cairo_vector_viewer = { |
301 | "CairoFile" , |
302 | NULL, |
303 | NULL, |
304 | cairo_vector_view_create, |
305 | cairo_vector_view_destroy, |
306 | NULL, |
307 | cairo_vector_view_create_surface, |
308 | cairo_vector_view_destroy_surface, |
309 | NULL, |
310 | NULL, |
311 | NULL, |
312 | NULL, |
313 | NULL |
314 | }; |
315 | |
316 | static void |
317 | cairo_vector_view_iface_paint_background (gpointer instance G_GNUC_UNUSED, |
318 | cairo_t *cr) |
319 | { |
320 | if (opt_bg_set) |
321 | { |
322 | cairo_set_operator (cr, op: CAIRO_OPERATOR_SOURCE); |
323 | cairo_set_source_rgba (cr, |
324 | red: opt_bg_color.red / 65535., |
325 | green: opt_bg_color.green / 65535., |
326 | blue: opt_bg_color.blue / 65535., |
327 | alpha: opt_bg_alpha / 65535.); |
328 | cairo_paint (cr); |
329 | } |
330 | } |
331 | |
332 | static CairoViewerIface cairo_vector_viewer_iface = { |
333 | &cairo_vector_viewer, |
334 | cairo_view_iface_create_surface, |
335 | cairo_vector_view_iface_paint_background |
336 | }; |
337 | |
338 | |
339 | |
340 | gpointer |
341 | cairo_viewer_iface_create (const CairoViewerIface **iface) |
342 | { |
343 | gpointer ret; |
344 | |
345 | *iface = &cairo_vector_viewer_iface; |
346 | ret = (*iface)->backend_class->create ((*iface)->backend_class); |
347 | if (ret) |
348 | return ret; |
349 | |
350 | #ifdef HAVE_CAIRO_XLIB |
351 | #ifdef HAVE_XFT |
352 | if (opt_display) |
353 | { |
354 | *iface = &cairo_x_viewer_iface; |
355 | return (*iface)->backend_class->create ((*iface)->backend_class); |
356 | } |
357 | #endif /* HAVE_XFT */ |
358 | #endif /* HAVE_CAIRO_XLIB */ |
359 | |
360 | *iface = &cairo_image_viewer_iface; |
361 | return (*iface)->backend_class->create ((*iface)->backend_class); |
362 | } |
363 | |
364 | void |
365 | cairo_viewer_add_options (GOptionGroup *group G_GNUC_UNUSED) |
366 | { |
367 | } |
368 | |