1 /* viewer-pangocairo.c: PangoCairo viewer backend.
3 * Copyright (C) 1999,2004,2005 Red Hat, Inc.
4 * Copyright (C) 2001 Sun Microsystems
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.
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.
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.
24 #include "viewer-render.h"
25 #include "viewer-cairo.h"
27 #include <pango/pangocairo.h>
29 static int opt_annotate = 0;
33 const CairoViewerIface *iface;
37 PangoFontMap *fontmap;
38 cairo_font_options_t *font_options;
42 pangocairo_view_create (const PangoViewer *klass G_GNUC_UNUSED)
44 CairoViewer *instance;
46 instance = g_slice_new (CairoViewer);
48 instance->backend = cairo_viewer_iface_create (&instance->iface);
50 instance->fontmap = pango_cairo_font_map_new ();
51 pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (instance->fontmap), opt_dpi);
53 instance->font_options = cairo_font_options_create ();
54 if (opt_hinting != HINT_DEFAULT)
56 if (opt_hinting == HINT_NONE)
57 cairo_font_options_set_hint_style (instance->font_options, CAIRO_HINT_STYLE_NONE);
58 else if (opt_hinting == HINT_FULL)
59 cairo_font_options_set_hint_style (instance->font_options, CAIRO_HINT_STYLE_FULL);
66 pangocairo_view_destroy (gpointer instance)
68 CairoViewer *c = (CairoViewer *) instance;
70 cairo_font_options_destroy (c->font_options);
72 g_object_unref (c->fontmap);
74 c->iface->backend_class->destroy (c->backend);
76 cairo_debug_reset_static_data ();
78 g_slice_free (CairoViewer, c);
82 pangocairo_view_get_context (gpointer instance)
84 CairoViewer *c = (CairoViewer *) instance;
85 PangoContext *context;
87 context = pango_font_map_create_context (c->fontmap);
88 pango_cairo_context_set_font_options (context, c->font_options);
97 cairo_surface_t *cairo;
101 pangocairo_view_create_surface (gpointer instance,
105 CairoViewer *c = (CairoViewer *) instance;
106 CairoSurface *surface;
108 surface = g_slice_new (CairoSurface);
110 surface->backend = c->iface->backend_class->create_surface (c->backend,
113 surface->cairo = c->iface->create_surface (c->backend,
121 pangocairo_view_destroy_surface (gpointer instance,
124 CairoViewer *c = (CairoViewer *) instance;
125 CairoSurface *c_surface = (CairoSurface *) surface;
127 c->iface->backend_class->destroy_surface (c->backend, c_surface->backend);
128 cairo_surface_destroy (c_surface->cairo);
130 g_slice_free (CairoSurface, surface);
134 render_callback (PangoLayout *layout,
140 cairo_t *cr = (cairo_t *) context;
141 int annotate = (GPOINTER_TO_INT (state) + opt_annotate) % 3;
144 cairo_translate (cr, x, y);
148 cairo_pattern_t *pattern;
149 PangoRectangle ink, logical;
150 double lw = cairo_get_line_width (cr);
151 PangoLayoutIter* iter;
153 pango_layout_get_extents (layout, &ink, &logical);
157 /* draw resolved gravity "roof" in blue */
160 (double)logical.x / PANGO_SCALE,
161 (double)logical.y / PANGO_SCALE);
163 (double)logical.width / PANGO_SCALE * 0.5,
164 (double)logical.height / PANGO_SCALE * 0.5);
165 cairo_translate (cr, 1.0, 1.0);
167 pango_gravity_to_rotation (
168 pango_context_get_gravity (
169 pango_layout_get_context (layout))));
170 cairo_move_to (cr, -1.0, -1.0);
171 cairo_rel_line_to (cr, +1.0, -0.2); /* / */
172 cairo_rel_line_to (cr, +1.0, +0.2); /* \ */
173 cairo_close_path (cr); /* - */
174 pattern = cairo_pattern_create_linear (0, -1.0, 0, -1.2);
175 cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0.0, 0.0, 1.0, 0.0);
176 cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0.0, 0.0, 1.0, 0.15);
177 cairo_set_source (cr, pattern);
179 /* once more, without close_path this time */
180 cairo_move_to (cr, -1.0, -1.0);
181 cairo_rel_line_to (cr, +1.0, -0.2); /* / */
182 cairo_rel_line_to (cr, +1.0, +0.2); /* \ */
183 /* silly line_width is not locked :(. get rid of scale. */
186 cairo_set_source_rgba (cr, 0.0, 0.0, 0.7, 0.2);
191 /* draw block progression arrow in green */
194 (double)logical.x / PANGO_SCALE,
195 (double)logical.y / PANGO_SCALE);
197 (double)logical.width / PANGO_SCALE * 0.5,
198 (double)logical.height / PANGO_SCALE * 0.5);
199 cairo_translate (cr, 1.0, 1.0);
200 cairo_move_to (cr, -0.4, -0.7);
201 cairo_rel_line_to (cr, +0.8, 0.0); /* -- */
202 cairo_rel_line_to (cr, 0.0, +0.9); /* | */
203 cairo_rel_line_to (cr, +0.4, 0.0); /* - */
204 cairo_rel_line_to (cr, -0.8, +0.5); /* / */
205 cairo_rel_line_to (cr, -0.8, -0.5); /* \ */
206 cairo_rel_line_to (cr, +0.4, 0.0); /* - */
207 cairo_close_path (cr); /* | */
208 pattern = cairo_pattern_create_linear (0, -0.7, 0, 0.7);
209 cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0.0, 1.0, 0.0, 0.0);
210 cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0.0, 1.0, 0.0, 0.15);
211 cairo_set_source (cr, pattern);
212 cairo_fill_preserve (cr);
213 /* silly line_width is not locked :(. get rid of scale. */
216 cairo_set_source_rgba (cr, 0.0, 0.7, 0.0, 0.2);
221 /* draw baselines with line direction arrow in orange */
223 cairo_set_source_rgba (cr, 1.0, 0.5, 0.0, 0.5);
224 iter = pango_layout_get_iter (layout);
227 PangoLayoutLine *line = pango_layout_iter_get_line (iter);
228 double width = (double)logical.width / PANGO_SCALE;
230 y = pango_layout_iter_get_baseline (iter);
233 (double)logical.x / PANGO_SCALE + width * 0.5,
234 (double)y / PANGO_SCALE);
235 if (line->resolved_dir)
236 cairo_scale (cr, -1, 1);
237 cairo_move_to (cr, -width * .5, -lw*0.2);
238 cairo_rel_line_to (cr, +width * .9, -lw*0.3);
239 cairo_rel_line_to (cr, 0, -lw);
240 cairo_rel_line_to (cr, +width * .1, +lw*1.5);
241 cairo_rel_line_to (cr, -width * .1, +lw*1.5);
242 cairo_rel_line_to (cr, 0, -lw);
243 cairo_rel_line_to (cr, -width * .9, -lw*0.3);
244 cairo_close_path (cr);
248 while (pango_layout_iter_next_line (iter));
249 pango_layout_iter_free (iter);
252 /* draw the logical rect in red */
254 cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
256 (double)logical.x / PANGO_SCALE - lw / 2,
257 (double)logical.y / PANGO_SCALE - lw / 2,
258 (double)logical.width / PANGO_SCALE + lw,
259 (double)logical.height / PANGO_SCALE + lw);
263 /* draw the ink rect in green */
265 cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.5);
267 (double)ink.x / PANGO_SCALE - lw / 2,
268 (double)ink.y / PANGO_SCALE - lw / 2,
269 (double)ink.width / PANGO_SCALE + lw,
270 (double)ink.height / PANGO_SCALE + lw);
275 cairo_move_to (cr, 0, 0);
276 pango_cairo_show_layout (cr, layout);
282 transform_callback (PangoContext *context,
285 gpointer state G_GNUC_UNUSED)
287 cairo_t *cr = (cairo_t *)cr_context;
288 cairo_matrix_t cairo_matrix;
292 cairo_matrix.xx = matrix->xx;
293 cairo_matrix.yx = matrix->yx;
294 cairo_matrix.xy = matrix->xy;
295 cairo_matrix.yy = matrix->yy;
296 cairo_matrix.x0 = matrix->x0;
297 cairo_matrix.y0 = matrix->y0;
301 cairo_matrix_init_identity (&cairo_matrix);
304 cairo_set_matrix (cr, &cairo_matrix);
306 pango_cairo_update_context (cr, context);
310 pangocairo_view_render (gpointer instance,
312 PangoContext *context,
317 CairoViewer *c = (CairoViewer *) instance;
319 CairoSurface *c_surface = (CairoSurface *) surface;
323 cr = cairo_create (c_surface->cairo);
325 transform_callback (context, NULL, cr, state);
327 c->iface->paint_background (instance, cr);
329 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
330 cairo_set_source_rgba (cr,
331 opt_fg_color.red / 65535.,
332 opt_fg_color.green / 65535.,
333 opt_fg_color.blue / 65535.,
334 opt_fg_alpha / 65535.);
336 do_output (context, render_callback, transform_callback, cr, state, width, height);
341 #ifdef HAVE_CAIRO_PNG
342 static cairo_status_t
343 write_func (void *closure,
344 const unsigned char *data,
347 FILE *stream = (FILE *) closure;
350 l = fwrite (data, 1, length, stream);
352 return l == length ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
356 pangocairo_view_write (gpointer instance G_GNUC_UNUSED,
359 int width G_GNUC_UNUSED,
360 int height G_GNUC_UNUSED)
362 CairoSurface *c_surface = (CairoSurface *) surface;
364 cairo_surface_write_to_png_stream (c_surface->cairo, write_func, stream);
369 pangocairo_view_create_window (gpointer instance,
374 CairoViewer *c = (CairoViewer *) instance;
376 if (!c->iface->backend_class->create_window)
379 return c->iface->backend_class->create_window (c->backend,
385 pangocairo_view_destroy_window (gpointer instance,
388 CairoViewer *c = (CairoViewer *) instance;
390 c->iface->backend_class->destroy_window (c->backend,
395 pangocairo_view_display (gpointer instance,
398 int width, int height,
401 CairoViewer *c = (CairoViewer *) instance;
402 CairoSurface *c_surface = (CairoSurface *) surface;
404 return c->iface->backend_class->display (c->backend,
411 static GOptionGroup *
412 pangocairo_view_get_option_group (const PangoViewer *klass G_GNUC_UNUSED)
414 GOptionEntry entries[] =
416 {"annotate", 0, 0, G_OPTION_ARG_INT, &opt_annotate,
417 "Annotate the output", "1 or 2"},
422 group = g_option_group_new ("cairo",
423 "Cairo backend options:",
424 "Options understood by the cairo backend",
428 g_option_group_add_entries (group, entries);
430 cairo_viewer_add_options (group);
435 const PangoViewer pangocairo_viewer = {
438 #ifdef HAVE_CAIRO_PNG
443 pangocairo_view_create,
444 pangocairo_view_destroy,
445 pangocairo_view_get_context,
446 pangocairo_view_create_surface,
447 pangocairo_view_destroy_surface,
448 pangocairo_view_render,
449 #ifdef HAVE_CAIRO_PNG
450 pangocairo_view_write,
454 pangocairo_view_create_window,
455 pangocairo_view_destroy_window,
456 pangocairo_view_display,
459 pangocairo_view_get_option_group