1 /* GTK - The GIMP Toolkit
2 * gtkprintcontext.c: Print Context
3 * Copyright (C) 2006, Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 #include "gtkprintoperation-private.h"
24 * SECTION:gtkprintcontext
25 * @Short_description: Encapsulates context for drawing pages
26 * @Title: GtkPrintContext
28 * A GtkPrintContext encapsulates context information that is required when
29 * drawing pages for printing, such as the cairo context and important
30 * parameters like page size and resolution. It also lets you easily
31 * create #PangoLayout and #PangoContext objects that match the font metrics
32 * of the cairo surface.
34 * GtkPrintContext objects gets passed to the #GtkPrintOperation::begin-print,
35 * #GtkPrintOperation::end-print, #GtkPrintOperation::request-page-setup and
36 * #GtkPrintOperation::draw-page signals on the #GtkPrintOperation.
39 * <title>Using GtkPrintContext in a #GtkPrintOperation::draw-page callback</title>
42 * draw_page (GtkPrintOperation *operation,
43 * GtkPrintContext *context,
47 * PangoLayout *layout;
48 * PangoFontDescription *desc;
50 * cr = gtk_print_context_get_cairo_context (context);
52 * // Draw a red rectangle, as wide as the paper (inside the margins)
53 * cairo_set_source_rgb (cr, 1.0, 0, 0);
54 * cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50);
59 * cairo_move_to (cr, 20, 10);
60 * cairo_line_to (cr, 40, 20);
61 * cairo_arc (cr, 60, 60, 20, 0, M_PI);
62 * cairo_line_to (cr, 80, 20);
64 * cairo_set_source_rgb (cr, 0, 0, 0);
65 * cairo_set_line_width (cr, 5);
66 * cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
67 * cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
72 * layout = gtk_print_context_create_layout (context);
73 * pango_layout_set_text (layout, "Hello World! Printing is easy", -1);
74 * desc = pango_font_description_from_string ("sans 28");
75 * pango_layout_set_font_description (layout, desc);
76 * pango_font_description_free (desc);
78 * cairo_move_to (cr, 30, 20);
79 * pango_cairo_layout_path (cr, layout);
82 * cairo_set_source_rgb (cr, 0.93, 1.0, 0.47);
83 * cairo_set_line_width (cr, 0.5);
84 * cairo_stroke_preserve (cr);
87 * cairo_set_source_rgb (cr, 0, 0.0, 1.0);
90 * g_object_unref (layout);
95 * Printing support was added in GTK+ 2.10.
99 typedef struct _GtkPrintContextClass GtkPrintContextClass;
101 #define GTK_IS_PRINT_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_CONTEXT))
102 #define GTK_PRINT_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
103 #define GTK_PRINT_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
105 #define MM_PER_INCH 25.4
106 #define POINTS_PER_INCH 72
108 struct _GtkPrintContext
110 GObject parent_instance;
112 GtkPrintOperation *op;
114 GtkPageSetup *page_setup;
116 gdouble surface_dpi_x;
117 gdouble surface_dpi_y;
119 gdouble pixels_per_unit_x;
120 gdouble pixels_per_unit_y;
122 gboolean has_hard_margins;
123 gdouble hard_margin_top;
124 gdouble hard_margin_bottom;
125 gdouble hard_margin_left;
126 gdouble hard_margin_right;
130 struct _GtkPrintContextClass
132 GObjectClass parent_class;
135 G_DEFINE_TYPE (GtkPrintContext, gtk_print_context, G_TYPE_OBJECT)
138 gtk_print_context_finalize (GObject *object)
140 GtkPrintContext *context = GTK_PRINT_CONTEXT (object);
142 if (context->page_setup)
143 g_object_unref (context->page_setup);
146 cairo_destroy (context->cr);
148 G_OBJECT_CLASS (gtk_print_context_parent_class)->finalize (object);
152 gtk_print_context_init (GtkPrintContext *context)
157 gtk_print_context_class_init (GtkPrintContextClass *class)
159 GObjectClass *gobject_class = (GObjectClass *)class;
161 gobject_class->finalize = gtk_print_context_finalize;
166 _gtk_print_context_new (GtkPrintOperation *op)
168 GtkPrintContext *context;
170 context = g_object_new (GTK_TYPE_PRINT_CONTEXT, NULL);
174 context->has_hard_margins = FALSE;
179 static PangoFontMap *
180 _gtk_print_context_get_fontmap (GtkPrintContext *context)
182 return pango_cairo_font_map_get_default ();
186 * gtk_print_context_set_cairo_context:
187 * @context: a #GtkPrintContext
188 * @cr: the cairo context
189 * @dpi_x: the horizontal resolution to use with @cr
190 * @dpi_y: the vertical resolution to use with @cr
192 * Sets a new cairo context on a print context.
194 * This function is intended to be used when implementing
195 * an internal print preview, it is not needed for printing,
196 * since GTK+ itself creates a suitable cairo context in that
202 gtk_print_context_set_cairo_context (GtkPrintContext *context,
208 cairo_destroy (context->cr);
210 context->cr = cairo_reference (cr);
211 context->surface_dpi_x = dpi_x;
212 context->surface_dpi_y = dpi_y;
214 switch (context->op->priv->unit)
218 /* Do nothing, this is the cairo default unit */
219 context->pixels_per_unit_x = 1.0;
220 context->pixels_per_unit_y = 1.0;
222 case GTK_UNIT_POINTS:
223 context->pixels_per_unit_x = dpi_x / POINTS_PER_INCH;
224 context->pixels_per_unit_y = dpi_y / POINTS_PER_INCH;
227 context->pixels_per_unit_x = dpi_x;
228 context->pixels_per_unit_y = dpi_y;
231 context->pixels_per_unit_x = dpi_x / MM_PER_INCH;
232 context->pixels_per_unit_y = dpi_y / MM_PER_INCH;
235 cairo_scale (context->cr,
236 context->pixels_per_unit_x,
237 context->pixels_per_unit_y);
242 _gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context)
244 cairo_t *cr = context->cr;
245 cairo_matrix_t matrix;
246 GtkPaperSize *paper_size;
247 gdouble width, height;
249 paper_size = gtk_page_setup_get_paper_size (context->page_setup);
251 width = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
252 width = width * context->surface_dpi_x / context->pixels_per_unit_x;
253 height = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
254 height = height * context->surface_dpi_y / context->pixels_per_unit_y;
256 switch (gtk_page_setup_get_orientation (context->page_setup))
259 case GTK_PAGE_ORIENTATION_PORTRAIT:
261 case GTK_PAGE_ORIENTATION_LANDSCAPE:
262 cairo_translate (cr, 0, height);
263 cairo_matrix_init (&matrix,
267 cairo_transform (cr, &matrix);
269 case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
270 cairo_translate (cr, width, height);
271 cairo_matrix_init (&matrix,
275 cairo_transform (cr, &matrix);
277 case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
278 cairo_translate (cr, width, 0);
279 cairo_matrix_init (&matrix,
283 cairo_transform (cr, &matrix);
289 _gtk_print_context_translate_into_margin (GtkPrintContext *context)
293 g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
295 /* We do it this way to also handle GTK_UNIT_PIXELS */
296 left = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
297 top = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
299 cairo_translate (context->cr,
300 left * context->surface_dpi_x / context->pixels_per_unit_x,
301 top * context->surface_dpi_y / context->pixels_per_unit_y);
305 _gtk_print_context_set_page_setup (GtkPrintContext *context,
306 GtkPageSetup *page_setup)
308 g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
309 g_return_if_fail (page_setup == NULL ||
310 GTK_IS_PAGE_SETUP (page_setup));
312 g_object_ref (page_setup);
314 if (context->page_setup != NULL)
315 g_object_unref (context->page_setup);
317 context->page_setup = page_setup;
321 * gtk_print_context_get_cairo_context:
322 * @context: a #GtkPrintContext
324 * Obtains the cairo context that is associated with the
327 * Return value: (transfer none): the cairo context of @context
332 gtk_print_context_get_cairo_context (GtkPrintContext *context)
334 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
340 * gtk_print_context_get_page_setup:
341 * @context: a #GtkPrintContext
343 * Obtains the #GtkPageSetup that determines the page
344 * dimensions of the #GtkPrintContext.
346 * Return value: (transfer none): the page setup of @context
351 gtk_print_context_get_page_setup (GtkPrintContext *context)
353 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
355 return context->page_setup;
359 * gtk_print_context_get_width:
360 * @context: a #GtkPrintContext
362 * Obtains the width of the #GtkPrintContext, in pixels.
364 * Return value: the width of @context
369 gtk_print_context_get_width (GtkPrintContext *context)
371 GtkPrintOperationPrivate *priv;
374 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
376 priv = context->op->priv;
378 if (priv->use_full_page)
379 width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
381 width = gtk_page_setup_get_page_width (context->page_setup, GTK_UNIT_INCH);
383 /* Really dpi_x? What about landscape? what does dpi_x mean in that case? */
384 return width * context->surface_dpi_x / context->pixels_per_unit_x;
388 * gtk_print_context_get_height:
389 * @context: a #GtkPrintContext
391 * Obtains the height of the #GtkPrintContext, in pixels.
393 * Return value: the height of @context
398 gtk_print_context_get_height (GtkPrintContext *context)
400 GtkPrintOperationPrivate *priv;
403 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
405 priv = context->op->priv;
407 if (priv->use_full_page)
408 height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
410 height = gtk_page_setup_get_page_height (context->page_setup, GTK_UNIT_INCH);
412 /* Really dpi_y? What about landscape? what does dpi_y mean in that case? */
413 return height * context->surface_dpi_y / context->pixels_per_unit_y;
417 * gtk_print_context_get_dpi_x:
418 * @context: a #GtkPrintContext
420 * Obtains the horizontal resolution of the #GtkPrintContext,
423 * Return value: the horizontal resolution of @context
428 gtk_print_context_get_dpi_x (GtkPrintContext *context)
430 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
432 return context->surface_dpi_x;
436 * gtk_print_context_get_dpi_y:
437 * @context: a #GtkPrintContext
439 * Obtains the vertical resolution of the #GtkPrintContext,
442 * Return value: the vertical resolution of @context
447 gtk_print_context_get_dpi_y (GtkPrintContext *context)
449 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
451 return context->surface_dpi_y;
455 * gtk_print_context_get_hard_margins:
456 * @context: a #GtkPrintContext
457 * @top: (out): top hardware printer margin
458 * @bottom: (out): bottom hardware printer margin
459 * @left: (out): left hardware printer margin
460 * @right: (out): right hardware printer margin
462 * Obtains the hardware printer margins of the #GtkPrintContext, in units.
464 * Return value: %TRUE if the hard margins were retrieved
469 gtk_print_context_get_hard_margins (GtkPrintContext *context,
475 if (context->has_hard_margins)
477 *top = context->hard_margin_top / context->pixels_per_unit_y;
478 *bottom = context->hard_margin_bottom / context->pixels_per_unit_y;
479 *left = context->hard_margin_left / context->pixels_per_unit_x;
480 *right = context->hard_margin_right / context->pixels_per_unit_x;
483 return context->has_hard_margins;
487 * gtk_print_context_set_hard_margins:
488 * @context: a #GtkPrintContext
489 * @top: top hardware printer margin
490 * @bottom: bottom hardware printer margin
491 * @left: left hardware printer margin
492 * @right: right hardware printer margin
494 * set the hard margins in pixel coordinates
497 _gtk_print_context_set_hard_margins (GtkPrintContext *context,
503 context->hard_margin_top = top;
504 context->hard_margin_bottom = bottom;
505 context->hard_margin_left = left;
506 context->hard_margin_right = right;
507 context->has_hard_margins = TRUE;
511 * gtk_print_context_get_pango_fontmap:
512 * @context: a #GtkPrintContext
514 * Returns a #PangoFontMap that is suitable for use
515 * with the #GtkPrintContext.
517 * Return value: (transfer none): the font map of @context
522 gtk_print_context_get_pango_fontmap (GtkPrintContext *context)
524 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
526 return _gtk_print_context_get_fontmap (context);
530 * gtk_print_context_create_pango_context:
531 * @context: a #GtkPrintContext
533 * Creates a new #PangoContext that can be used with the
536 * Return value: (transfer full): a new Pango context for @context
541 gtk_print_context_create_pango_context (GtkPrintContext *context)
543 PangoContext *pango_context;
544 cairo_font_options_t *options;
546 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
548 pango_context = pango_font_map_create_context (_gtk_print_context_get_fontmap (context));
550 options = cairo_font_options_create ();
551 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
552 pango_cairo_context_set_font_options (pango_context, options);
553 cairo_font_options_destroy (options);
555 /* We use the unit-scaled resolution, as we still want
556 * fonts given in points to work
558 pango_cairo_context_set_resolution (pango_context,
559 context->surface_dpi_y / context->pixels_per_unit_y);
560 return pango_context;
564 * gtk_print_context_create_pango_layout:
565 * @context: a #GtkPrintContext
567 * Creates a new #PangoLayout that is suitable for use
568 * with the #GtkPrintContext.
570 * Return value: (transfer full): a new Pango layout for @context
575 gtk_print_context_create_pango_layout (GtkPrintContext *context)
577 PangoContext *pango_context;
580 g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
582 pango_context = gtk_print_context_create_pango_context (context);
583 layout = pango_layout_new (pango_context);
585 pango_cairo_update_context (context->cr, pango_context);
586 g_object_unref (pango_context);