]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintcontext.c
Documentation additions and fixes.
[~andy/gtk] / gtk / gtkprintcontext.c
1 /* GTK - The GIMP Toolkit
2  * gtkprintcontext.c: Print Context
3  * Copyright (C) 2006, Red Hat, Inc.
4  *
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.
9  *
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.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #include "gtkprintoperation-private.h"
23 #include "gtkalias.h"
24
25 typedef struct _GtkPrintContextClass GtkPrintContextClass;
26
27 #define GTK_IS_PRINT_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_CONTEXT))
28 #define GTK_PRINT_CONTEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
29 #define GTK_PRINT_CONTEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
30
31 #define MM_PER_INCH 25.4
32 #define POINTS_PER_INCH 72
33
34 struct _GtkPrintContext
35 {
36   GObject parent_instance;
37
38   GtkPrintOperation *op;
39   cairo_t *cr;
40   GtkPageSetup *page_setup;
41   PangoFontMap *fontmap;
42
43   gdouble surface_dpi_x;
44   gdouble surface_dpi_y;
45   
46   gdouble pixels_per_unit_x;
47   gdouble pixels_per_unit_y;
48 };
49
50 struct _GtkPrintContextClass
51 {
52   GObjectClass parent_class;
53 };
54
55 G_DEFINE_TYPE (GtkPrintContext, gtk_print_context, G_TYPE_OBJECT)
56
57 static void
58 gtk_print_context_finalize (GObject *object)
59 {
60   GtkPrintContext *context = GTK_PRINT_CONTEXT (object);
61
62   g_object_unref (context->fontmap);
63   if (context->page_setup)
64     g_object_unref (context->page_setup);
65
66   if (context->cr)
67     cairo_destroy (context->cr);
68   
69   G_OBJECT_CLASS (gtk_print_context_parent_class)->finalize (object);
70 }
71
72 static void
73 gtk_print_context_init (GtkPrintContext *context)
74 {
75 }
76
77 static void
78 gtk_print_context_class_init (GtkPrintContextClass *class)
79 {
80   GObjectClass *gobject_class = (GObjectClass *)class;
81
82   gobject_class->finalize = gtk_print_context_finalize;
83 }
84
85
86 GtkPrintContext *
87 _gtk_print_context_new (GtkPrintOperation *op)
88 {
89   GtkPrintContext *context;
90
91   context = g_object_new (GTK_TYPE_PRINT_CONTEXT, NULL);
92
93   context->op = op;
94   context->cr = NULL;
95   context->fontmap = pango_cairo_font_map_new ();
96   
97   return context;
98 }
99 /**
100  * gtk_print_context_set_cairo_context:
101  * @context: a #GtkPrintContext
102  * @cr: the cairo context
103  * @dpi_x: the horizontal resolution to use with @cr
104  * @dpi_y: the vertical resolution to use with @cr
105  *
106  * Sets a new cairo context on a print context. 
107  * 
108  * This function is intended to be used when implementing
109  * an internal print preview, it is not needed for printing,
110  * since GTK+ itself creates a suitable cairo context in that
111  * case.
112  *
113  * Since: 2.10 
114  */
115 void
116 gtk_print_context_set_cairo_context (GtkPrintContext *context,
117                                      cairo_t         *cr,
118                                      double           dpi_x,
119                                      double           dpi_y)
120 {
121   if (context->cr)
122     cairo_destroy (context->cr);
123
124   context->cr = cairo_reference (cr);
125   context->surface_dpi_x = dpi_x;
126   context->surface_dpi_y = dpi_y;
127
128   switch (context->op->priv->unit)
129     {
130     default:
131     case GTK_UNIT_PIXEL:
132       /* Do nothing, this is the cairo default unit */
133       context->pixels_per_unit_x = 1.0;
134       context->pixels_per_unit_y = 1.0;
135       break;
136     case GTK_UNIT_POINTS:
137       context->pixels_per_unit_x = dpi_x / POINTS_PER_INCH;
138       context->pixels_per_unit_y = dpi_y / POINTS_PER_INCH;
139       break;
140     case GTK_UNIT_INCH:
141       context->pixels_per_unit_x = dpi_x;
142       context->pixels_per_unit_y = dpi_y;
143       break;
144     case GTK_UNIT_MM:
145       context->pixels_per_unit_x = dpi_x / MM_PER_INCH;
146       context->pixels_per_unit_y = dpi_y / MM_PER_INCH;
147       break;
148     }
149   cairo_scale (context->cr,
150                context->pixels_per_unit_x,
151                context->pixels_per_unit_y);
152     
153   /* We use the unit-scaled resolution, as we still want 
154    * fonts given in points to work 
155    */
156   pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (context->fontmap),
157                                        dpi_y / context->pixels_per_unit_y);
158 }
159
160
161 void
162 _gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context)
163 {
164   cairo_t *cr = context->cr;
165   cairo_matrix_t matrix;
166   GtkPaperSize *paper_size;
167   gdouble width, height;
168
169   paper_size = gtk_page_setup_get_paper_size (context->page_setup);
170
171   width = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
172   width = width * context->surface_dpi_x / context->pixels_per_unit_x;
173   height = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
174   height = height * context->surface_dpi_y / context->pixels_per_unit_y;
175   
176   switch (gtk_page_setup_get_orientation (context->page_setup))
177     {
178     default:
179     case GTK_PAGE_ORIENTATION_PORTRAIT:
180       break;
181     case GTK_PAGE_ORIENTATION_LANDSCAPE:
182       cairo_translate (cr, width, 0);
183       cairo_matrix_init (&matrix,
184                           0,  1,
185                          -1,  0,
186                           0,  0);
187       cairo_transform (cr, &matrix);
188       break;
189     case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
190       cairo_translate (cr, width, height);
191       cairo_matrix_init (&matrix,
192                          -1,  0,
193                           0, -1,
194                           0,  0);
195       cairo_transform (cr, &matrix);
196       break;
197     case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
198       cairo_translate (cr, 0, height);
199       cairo_matrix_init (&matrix,
200                          0, -1,
201                          1,  0,
202                          0,  0);
203       cairo_transform (cr, &matrix);
204       break;
205     }
206 }
207
208 void
209 _gtk_print_context_translate_into_margin (GtkPrintContext *context)
210 {
211   GtkPrintOperationPrivate *priv;
212   gdouble left, top;
213
214   g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
215
216   priv = context->op->priv;
217
218   /* We do it this way to also handle GTK_UNIT_PIXELS */
219   
220   left = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
221   top = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
222
223   cairo_translate (context->cr,
224                    left * context->surface_dpi_x / context->pixels_per_unit_x,
225                    top * context->surface_dpi_y / context->pixels_per_unit_y);
226 }
227
228 void
229 _gtk_print_context_set_page_setup (GtkPrintContext *context,
230                                    GtkPageSetup    *page_setup)
231 {
232   g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
233   g_return_if_fail (page_setup == NULL ||
234                     GTK_IS_PAGE_SETUP (page_setup));
235   
236   g_object_ref (page_setup);
237
238   if (context->page_setup != NULL)
239     g_object_unref (context->page_setup);
240
241   context->page_setup = page_setup;
242 }
243
244 /**
245  * gtk_print_context_get_cairo_context:
246  * @context: a #GtkPrintContext
247  *
248  * Obtains the cairo context that is associated with the
249  * #GtkPrintContext.
250  *
251  * Return value: the cairo context of @context
252  *
253  * Since: 2.10
254  */
255 cairo_t *
256 gtk_print_context_get_cairo_context (GtkPrintContext *context)
257 {
258   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
259
260   return context->cr;
261 }
262
263 /**
264  * gtk_print_context_get_page_setup:
265  * @context: a #GtkPrintContext
266  *
267  * Obtains the #GtkPageSetup that determines the page
268  * dimensions of the #GtkPrintContext.
269  *
270  * Return value: the page setup of @context
271  *
272  * Since: 2.10
273  */
274 GtkPageSetup *
275 gtk_print_context_get_page_setup (GtkPrintContext *context)
276 {
277   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
278
279   return context->page_setup;
280 }
281
282 /**
283  * gtk_print_context_get_width:
284  * @context: a #GtkPrintContext
285  *
286  * Obtains the width of the #GtkPrintContext, in pixels.
287  *
288  * Return value: the width of @context
289  *
290  * Since: 2.10 
291  */
292 gdouble
293 gtk_print_context_get_width (GtkPrintContext *context)
294 {
295   GtkPrintOperationPrivate *priv;
296   gdouble width;
297
298   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
299
300   priv = context->op->priv;
301
302   if (priv->use_full_page)
303     width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
304   else
305     width = gtk_page_setup_get_page_width (context->page_setup, GTK_UNIT_INCH);
306
307   /* Really dpi_x? What about landscape? what does dpi_x mean in that case? */
308   return width * context->surface_dpi_x / context->pixels_per_unit_x;
309 }
310
311 /**
312  * gtk_print_context_get_height:
313  * @context: a #GtkPrintContext
314  * 
315  * Obtains the width of the #GtkPrintContext, in pixels.
316  *
317  * Return value: the height of @context
318  *
319  * Since: 2.10
320  */
321 gdouble
322 gtk_print_context_get_height (GtkPrintContext *context)
323 {
324   GtkPrintOperationPrivate *priv;
325   gdouble height;
326
327   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
328
329   priv = context->op->priv;
330
331   if (priv->use_full_page)
332     height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
333   else
334     height = gtk_page_setup_get_page_height (context->page_setup, GTK_UNIT_INCH);
335
336   /* Really dpi_y? What about landscape? what does dpi_y mean in that case? */
337   return height * context->surface_dpi_y / context->pixels_per_unit_y;
338 }
339
340 /**
341  * gtk_print_context_get_dpi_x:
342  * @context: a #GtkPrintContext
343  * 
344  * Obtains the horizontal resolution of the #GtkPrintContext,
345  * in dots per inch.
346  *
347  * Return value: the horizontal resolution of @context
348  *
349  * Since: 2.10
350  */
351 gdouble
352 gtk_print_context_get_dpi_x (GtkPrintContext *context)
353 {
354   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
355
356   return context->surface_dpi_x;
357 }
358
359 /**
360  * gtk_print_context_get_dpi_y:
361  * @context: a #GtkPrintContext
362  * 
363  * Obtains the vertical resolution of the #GtkPrintContext,
364  * in dots per inch.
365  *
366  * Return value: the vertical resolution of @context
367  *
368  * Since: 2.10
369  */
370 gdouble
371 gtk_print_context_get_dpi_y (GtkPrintContext *context)
372 {
373   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
374
375   return context->surface_dpi_y;
376 }
377
378 /**
379  * gtk_print_context_get_pango_fontmap:
380  * @context: a #GtkPrintContext
381  *
382  * Returns a #PangoFontMap that is suitable for use 
383  * with the #GtkPrintContext.
384  *
385  * Return value: the font map of @context
386  *
387  * Since: 2.10
388  */
389 PangoFontMap *
390 gtk_print_context_get_pango_fontmap (GtkPrintContext *context)
391 {
392   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
393
394   return context->fontmap;
395 }
396
397 /**
398  * gtk_print_context_create_pango_context:
399  * @context: a #GtkPrintContext 
400  *
401  * Creates a new #PangoContext that can be used with the
402  * #GtkPrintContext.
403  *
404  * Return value: a new Pango context for @context
405  * 
406  * Since: 2.10
407  */
408 PangoContext *
409 gtk_print_context_create_pango_context (GtkPrintContext *context)
410 {
411   PangoContext *pango_context;
412   cairo_font_options_t *options;
413
414   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
415   
416   pango_context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (context->fontmap));
417
418   options = cairo_font_options_create ();
419   cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
420   pango_cairo_context_set_font_options (pango_context, options);
421   cairo_font_options_destroy (options);
422   
423   return pango_context;
424 }
425
426 /**
427  * gtk_print_context_create_pango_layout:
428  * @context: a #GtkPrintContext
429  *
430  * Creates a new #PangoLayout that is suitable for use
431  * with the #GtkPrintContext.
432  * 
433  * Return value: a new Pango layout for @context
434  *
435  * Since: 2.10
436  */
437 PangoLayout *
438 gtk_print_context_create_pango_layout (GtkPrintContext *context)
439 {
440   PangoContext *pango_context;
441   PangoLayout *layout;
442
443   g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
444
445   pango_context = gtk_print_context_create_pango_context (context);
446   layout = pango_layout_new (pango_context);
447
448   pango_cairo_update_context (context->cr, pango_context);
449   g_object_unref (pango_context);
450
451   return layout;
452 }
453
454
455 #define __GTK_PRINT_CONTEXT_C__
456 #include "gtkaliasdef.c"