Git init
[external/pango1.0.git] / pango-view / viewer-cairo.c
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_X
34 #include "viewer-x.h"
35 #include <cairo-xlib.h>
36
37
38
39 static cairo_surface_t *
40 cairo_x_view_iface_create_surface (gpointer instance,
41                                    gpointer surface,
42                                    int      width,
43                                    int      height)
44 {
45   XViewer *x = (XViewer *)instance;
46   Drawable drawable = (Drawable) surface;
47
48   return cairo_xlib_surface_create (x->display, drawable,
49                                     DefaultVisual (x->display, x->screen),
50                                     width, height);
51 }
52
53 static void
54 cairo_x_view_iface_paint_background (gpointer  instance G_GNUC_UNUSED,
55                                      cairo_t  *cr)
56 {
57   cairo_set_source_rgb (cr, 1, 1, 1);
58   cairo_paint (cr);
59
60   if (opt_bg_set)
61     {
62       cairo_set_source_rgba (cr,
63                              opt_bg_color.red / 65535.,
64                              opt_bg_color.green / 65535.,
65                              opt_bg_color.blue / 65535.,
66                              opt_bg_alpha / 65535.);
67       cairo_paint (cr);
68     }
69 }
70
71 static CairoViewerIface cairo_x_viewer_iface = {
72   &x_viewer,
73   cairo_x_view_iface_create_surface,
74   cairo_x_view_iface_paint_background
75 };
76 #endif /* HAVE_X */
77 #endif /* HAVE_CAIRO_XLIB */
78
79
80
81
82 static cairo_surface_t *
83 cairo_view_iface_create_surface (gpointer instance,
84                                  gpointer surface,
85                                  int      width,
86                                  int      height)
87 {
88   return cairo_surface_reference (surface);
89 }
90
91
92
93 static gpointer
94 cairo_image_view_create (const PangoViewer *klass G_GNUC_UNUSED)
95 {
96   return NULL;
97 }
98
99 static void
100 cairo_image_view_destroy (gpointer instance G_GNUC_UNUSED)
101 {
102 }
103
104 static gpointer
105 cairo_image_view_create_surface (gpointer instance,
106                                  int      width,
107                                  int      height)
108 {
109   cairo_t *cr;
110   cairo_surface_t *surface;
111
112   /* TODO: Be smarter about format? */
113   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
114
115   cr = cairo_create (surface);
116   cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
117   cairo_paint (cr);
118   cairo_destroy (cr);
119
120   return surface;
121 }
122
123 static void
124 cairo_image_view_destroy_surface (gpointer instance,
125                                   gpointer surface)
126 {
127   cairo_surface_destroy (surface);
128 }
129
130 const PangoViewer cairo_image_viewer = {
131   "CairoImage",
132   NULL,
133   NULL,
134   cairo_image_view_create,
135   cairo_image_view_destroy,
136   NULL,
137   cairo_image_view_create_surface,
138   cairo_image_view_destroy_surface,
139   NULL,
140   NULL,
141   NULL,
142   NULL,
143   NULL
144 };
145
146 static void
147 cairo_image_view_iface_paint_background (gpointer  instance G_GNUC_UNUSED,
148                                          cairo_t  *cr)
149 {
150   cairo_set_source_rgb (cr, 1, 1, 1);
151   cairo_paint (cr);
152
153   if (opt_bg_set)
154     {
155       cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
156       cairo_set_source_rgba (cr,
157                              opt_bg_color.red / 65535.,
158                              opt_bg_color.green / 65535.,
159                              opt_bg_color.blue / 65535.,
160                              opt_bg_alpha / 65535.);
161       cairo_paint (cr);
162     }
163 }
164
165 static CairoViewerIface cairo_image_viewer_iface = {
166   &cairo_image_viewer,
167   cairo_view_iface_create_surface,
168   cairo_image_view_iface_paint_background
169 };
170
171
172
173
174 #ifdef CAIRO_HAS_SVG_SURFACE
175 #    include <cairo-svg.h>
176 #endif
177 #ifdef CAIRO_HAS_PDF_SURFACE
178 #    include <cairo-pdf.h>
179 #endif
180 #ifdef CAIRO_HAS_PS_SURFACE
181 #    include <cairo-ps.h>
182 #  if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0)
183 #    define HAS_EPS 1
184
185 static cairo_surface_t *
186 _cairo_eps_surface_create (const char *filename,
187                            double      width,
188                            double      height)
189 {
190   cairo_surface_t *surface;
191
192   surface = cairo_ps_surface_create (filename, width, height);
193   cairo_ps_surface_set_eps (surface, TRUE);
194
195   return surface;
196 }
197
198 #  else
199 #    undef HAS_EPS
200 #  endif
201 #endif
202
203 typedef cairo_surface_t *(*CairoVectorFileCreateFunc) (const char *filename,
204                                                        double width,
205                                                        double height);
206
207 typedef struct
208 {
209   const char *filename;
210   CairoVectorFileCreateFunc constructor;
211 } CairoVectorViewer;
212
213 static gpointer
214 cairo_vector_view_create (const PangoViewer *klass G_GNUC_UNUSED)
215 {
216   const char *extension = NULL;
217   CairoVectorFileCreateFunc constructor = NULL;
218
219   if (opt_output)
220     {
221       extension = strrchr (opt_output, '.');
222       if (extension)
223           extension++; /* skip the dot */
224     }
225
226   if (!extension)
227     return NULL;
228
229   if (0)
230     ;
231   #ifdef CAIRO_HAS_SVG_SURFACE
232     else if (0 == strcasecmp (extension, "svg"))
233       constructor = cairo_svg_surface_create;
234   #endif
235   #ifdef CAIRO_HAS_PDF_SURFACE
236     else if (0 == strcasecmp (extension, "pdf"))
237       constructor = cairo_pdf_surface_create;
238   #endif
239   #ifdef CAIRO_HAS_PS_SURFACE
240     else if (0 == strcasecmp (extension, "ps"))
241       constructor = cairo_ps_surface_create;
242    #ifdef HAS_EPS
243     else if (0 == strcasecmp (extension, "eps"))
244       constructor = _cairo_eps_surface_create;
245    #endif
246   #endif
247
248   if (constructor)
249     {
250       CairoVectorViewer *instance;
251
252       instance = g_slice_new (CairoVectorViewer);
253
254       /* save output filename and unset it such that the viewer layer
255        * doesn't try to save to file.
256        */
257      instance->filename = opt_output;
258      opt_output = NULL;
259
260      instance->constructor = constructor;
261
262      /* Fix dpi on 72.  That's what cairo vector surfaces are. */
263      opt_dpi = 72;
264
265      return instance;
266     }
267
268   return NULL;
269 }
270
271 static void
272 cairo_vector_view_destroy (gpointer instance G_GNUC_UNUSED)
273 {
274   CairoVectorViewer *c = (CairoVectorViewer *) instance;
275
276   g_slice_free (CairoVectorViewer, c);
277 }
278
279 static gpointer
280 cairo_vector_view_create_surface (gpointer instance,
281                                   int      width,
282                                   int      height)
283 {
284   CairoVectorViewer *c = (CairoVectorViewer *) instance;
285   cairo_surface_t *surface;
286
287   surface = c->constructor (c->filename, width, height);
288
289     /*cairo_surface_set_fallback_resolution (surface, fallback_resolution_x, fallback_resolution_y);*/
290
291   return surface;
292 }
293
294 static void
295 cairo_vector_view_destroy_surface (gpointer instance,
296                                    gpointer surface)
297 {
298   /* TODO: check for errors */
299   cairo_surface_destroy (surface);
300 }
301
302 const PangoViewer cairo_vector_viewer = {
303   "CairoFile",
304   NULL,
305   NULL,
306   cairo_vector_view_create,
307   cairo_vector_view_destroy,
308   NULL,
309   cairo_vector_view_create_surface,
310   cairo_vector_view_destroy_surface,
311   NULL,
312   NULL,
313   NULL,
314   NULL,
315   NULL
316 };
317
318 static void
319 cairo_vector_view_iface_paint_background (gpointer  instance G_GNUC_UNUSED,
320                                           cairo_t  *cr)
321 {
322   if (opt_bg_set)
323     {
324       cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
325       cairo_set_source_rgba (cr,
326                              opt_bg_color.red / 65535.,
327                              opt_bg_color.green / 65535.,
328                              opt_bg_color.blue / 65535.,
329                              opt_bg_alpha / 65535.);
330       cairo_paint (cr);
331     }
332 }
333
334 static CairoViewerIface cairo_vector_viewer_iface = {
335   &cairo_vector_viewer,
336   cairo_view_iface_create_surface,
337   cairo_vector_view_iface_paint_background
338 };
339
340
341
342 gpointer
343 cairo_viewer_iface_create (const CairoViewerIface **iface)
344 {
345   gpointer ret;
346
347   *iface = &cairo_vector_viewer_iface;
348   ret = (*iface)->backend_class->create ((*iface)->backend_class);
349   if (ret)
350     return ret;
351
352 #ifdef HAVE_CAIRO_XLIB
353 #ifdef HAVE_X
354   if (opt_display)
355     {
356       *iface = &cairo_x_viewer_iface;
357       return (*iface)->backend_class->create ((*iface)->backend_class);
358     }
359 #endif /* HAVE_X */
360 #endif /* HAVE_CAIRO_XLIB */
361
362   *iface = &cairo_image_viewer_iface;
363   return (*iface)->backend_class->create ((*iface)->backend_class);
364 }
365
366 void
367 cairo_viewer_add_options (GOptionGroup *group G_GNUC_UNUSED)
368 {
369 }