]> Pileus Git - ~andy/gtk/blob - gdk/gdkpango.c
Intern some more strings.
[~andy/gtk] / gdk / gdkpango.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2000 Red Hat, Inc. 
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <config.h>
21 #include <math.h>
22 #include <pango/pangocairo.h>
23 #include "gdkcairo.h"
24 #include "gdkcolor.h"
25 #include "gdkgc.h"
26 #include "gdkinternals.h"
27 #include "gdkpango.h"
28 #include "gdkrgb.h"
29 #include "gdkprivate.h"
30 #include "gdkscreen.h"
31 #include "gdkalias.h"
32
33 #include "gdkintl.h"
34
35 #define GDK_INFO_KEY "gdk-info"
36
37 /* We have various arrays indexed by render part; if PangoRenderPart
38  * is extended, we want to make sure not to overwrite the end of
39  * those arrays.
40  */
41 #define MAX_RENDER_PART  PANGO_RENDER_PART_STRIKETHROUGH
42
43 struct _GdkPangoRendererPrivate
44 {
45   GdkScreen *screen;
46
47   /* GdkPangoRenderer specific state */
48   PangoColor override_color[MAX_RENDER_PART + 1];
49   gboolean override_color_set[MAX_RENDER_PART + 1];
50   
51   GdkBitmap *stipple[MAX_RENDER_PART + 1];
52   gboolean embossed;
53
54   cairo_t *cr;
55   PangoRenderPart last_part;
56
57   /* Current target */
58   GdkDrawable *drawable;
59   GdkGC *base_gc;
60 };
61
62 static PangoAttrType gdk_pango_attr_stipple_type;
63 static PangoAttrType gdk_pango_attr_embossed_type;
64
65 enum {
66   PROP_0,
67   PROP_SCREEN
68 };
69
70 G_DEFINE_TYPE (GdkPangoRenderer, gdk_pango_renderer, PANGO_TYPE_RENDERER)
71
72 static void
73 gdk_pango_renderer_finalize (GObject *object)
74 {
75   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object);
76   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
77   int i;
78
79   if (priv->base_gc)
80     g_object_unref (priv->base_gc);
81   if (priv->drawable)
82     g_object_unref (priv->drawable);
83
84   for (i = 0; i <= MAX_RENDER_PART; i++)
85     if (priv->stipple[i])
86       g_object_unref (priv->stipple[i]);
87
88   G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object);
89 }
90
91 static GObject*
92 gdk_pango_renderer_constructor (GType                  type,
93                                 guint                  n_construct_properties,
94                                 GObjectConstructParam *construct_params)
95 {
96   GObject *object;
97   GdkPangoRenderer *gdk_renderer;
98
99   object = (* G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->constructor) (type,
100                                                                               n_construct_properties,
101                                                                               construct_params);
102
103   gdk_renderer = GDK_PANGO_RENDERER (object);
104   
105   if (!gdk_renderer->priv->screen)
106     {
107       g_warning ("Screen must be specified at construct time for GdkPangoRenderer");
108       gdk_renderer->priv->screen = gdk_screen_get_default ();
109     }
110
111   return object;
112 }
113
114 /* Adjusts matrix and color for the renderer to draw the secondary
115  * "shadow" copy for embossed text */
116 static void
117 emboss_context (cairo_t *cr)
118 {
119   cairo_matrix_t tmp_matrix;
120
121   /* The gymnastics here to adjust the matrix are because we want
122    * to offset by +1,+1 in device-space, not in user-space,
123    * so we can't just draw the layout at x + 1, y + 1
124    */
125   cairo_get_matrix (cr, &tmp_matrix);
126   tmp_matrix.x0 += 1.0;
127   tmp_matrix.y0 += 1.0;
128   cairo_set_matrix (cr, &tmp_matrix);
129
130   cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
131 }
132
133 static cairo_t *
134 get_cairo_context (GdkPangoRenderer *gdk_renderer,
135                    PangoRenderPart   part)
136 {
137   PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer);
138   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
139
140   if (!priv->cr)
141     {
142       const PangoMatrix *matrix;
143       
144       priv->cr = gdk_cairo_create (priv->drawable);
145
146       matrix = pango_renderer_get_matrix (renderer);
147       if (matrix)
148         {
149           cairo_matrix_t cairo_matrix;
150           
151           cairo_matrix_init (&cairo_matrix,
152                              matrix->xx, matrix->yx,
153                              matrix->xy, matrix->yy,
154                              matrix->x0, matrix->y0);
155           cairo_set_matrix (priv->cr, &cairo_matrix);
156         }
157     }
158   
159   priv->last_part = (PangoRenderPart)-1;
160   if (part != priv->last_part)
161     {
162       PangoColor *pango_color = pango_renderer_get_color (renderer,
163                                                           part);
164       GdkColor *color = NULL;
165       GdkColor tmp_color;
166       if (pango_color)
167         {
168           tmp_color.red = pango_color->red;
169           tmp_color.green = pango_color->green;
170           tmp_color.blue = pango_color->blue;
171           
172           color = &tmp_color;
173         }
174
175       _gdk_gc_update_context (priv->base_gc,
176                               priv->cr,
177                               color,
178                               priv->stipple[part]);
179       priv->last_part = part;
180     }
181
182   return priv->cr;
183 }
184
185 static void
186 gdk_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
187                                 PangoFont        *font,
188                                 PangoGlyphString *glyphs,
189                                 int               x,
190                                 int               y)
191 {
192   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
193   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
194   cairo_t *cr;
195
196   cr = get_cairo_context (gdk_renderer, 
197                           PANGO_RENDER_PART_FOREGROUND);
198
199   if (priv->embossed)
200     {
201       cairo_save (cr);
202       emboss_context (cr);
203       cairo_move_to (cr, x / PANGO_SCALE, y / PANGO_SCALE);
204       pango_cairo_show_glyph_string (cr, font, glyphs);
205       cairo_restore (cr);
206     }
207   
208   cairo_move_to (cr, x / PANGO_SCALE, y / PANGO_SCALE);
209   pango_cairo_show_glyph_string (cr, font, glyphs);
210 }
211
212 /* Draws an error underline that looks like one of:
213  *              H       E                H
214  *     /\      /\      /\        /\      /\               -
215  *   A/  \    /  \    /  \     A/  \    /  \              |
216  *    \   \  /    \  /   /D     \   \  /    \             |
217  *     \   \/  C   \/   /        \   \/   C  \            | height = HEIGHT_SQUARES * square
218  *      \      /\  F   /          \  F   /\   \           | 
219  *       \    /  \    /            \    /  \   \G         |
220  *        \  /    \  /              \  /    \  /          |
221  *         \/      \/                \/      \/           -
222  *         B                         B       
223  *    |----|
224  *   unit_width = (HEIGHT_SQUARES - 1) * square
225  *
226  * The x, y, width, height passed in give the desired bounding box;
227  * x/width are adjusted to make the underline a integer number of units
228  * wide.
229  */
230 #define HEIGHT_SQUARES 2.5
231
232 /* Cut-and-pasted between here and pango/pango/pangocairo-render.c */
233 static void
234 draw_error_underline (cairo_t *cr,
235                       double  x,
236                       double  y,
237                       double  width,
238                       double  height)
239 {
240   double square = height / HEIGHT_SQUARES;
241   double unit_width = (HEIGHT_SQUARES - 1) * square;
242   int width_units = (width + unit_width / 2) / unit_width;
243   double y_top, y_bottom;
244   int i;
245
246   x += (width - width_units * unit_width);
247   width = width_units * unit_width;
248
249   y_top = y;
250   y_bottom = y + height;
251   
252   /* Bottom of squiggle */
253   cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */
254   for (i = 0; i < width_units; i += 2)
255     {
256       double x_middle = x + (i + 1) * unit_width;
257       double x_right = x + (i + 2) * unit_width;
258     
259       cairo_line_to (cr, x_middle, y_bottom); /* B */
260       
261       if (i + 1 == width_units)
262         /* Nothing */;
263       else if (i + 2 == width_units)
264         cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */
265       else
266         cairo_line_to (cr, x_right, y_top + square); /* C */
267     }
268   
269   /* Top of squiggle */
270   for (i -= 2; i >= 0; i -= 2)
271     {
272       double x_left = x + i * unit_width;
273       double x_middle = x + (i + 1) * unit_width;
274       double x_right = x + (i + 2) * unit_width;
275       
276       if (i + 1 == width_units)
277         cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */
278       else {
279         if (i + 2 == width_units)
280           cairo_line_to (cr, x_right, y_top); /* E */
281         cairo_line_to (cr, x_middle, y_bottom - square); /* F */
282       }
283       
284       cairo_line_to (cr, x_left, y_top);   /* H */
285     }
286
287   cairo_close_path (cr);
288   cairo_fill (cr);
289 }
290
291 static void
292 gdk_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
293                                    PangoRenderPart   part,
294                                    int               x,
295                                    int               y,
296                                    int               width,
297                                    int               height)
298 {
299   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
300   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
301   cairo_t *cr;
302   
303   cr = get_cairo_context (gdk_renderer, part);
304
305   if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
306     {
307       cairo_save (cr);
308       emboss_context (cr);
309       cairo_rectangle (cr,
310                        (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
311                        (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
312
313       cairo_fill (cr);
314       cairo_restore (cr);
315     }
316
317   cairo_rectangle (cr,
318                    (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
319                    (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
320   cairo_fill (cr);
321 }
322
323 static void
324 gdk_pango_renderer_draw_error_underline (PangoRenderer    *renderer,
325                                          int               x,
326                                          int               y,
327                                          int               width,
328                                          int               height)
329 {
330   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
331   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
332   cairo_t *cr;
333   
334   cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE);
335   
336   if (priv->embossed)
337     {
338       cairo_save (cr);
339       emboss_context (cr);
340       draw_error_underline (cr,
341                             (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
342                             (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
343       cairo_restore (cr);
344     }
345
346   draw_error_underline (cr,
347                         (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
348                         (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
349 }
350
351 static void
352 gdk_pango_renderer_part_changed (PangoRenderer   *renderer,
353                                  PangoRenderPart  part)
354 {
355   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
356
357   if (gdk_renderer->priv->last_part == part)
358     gdk_renderer->priv->last_part = (PangoRenderPart)-1;
359 }
360
361 static void
362 gdk_pango_renderer_begin (PangoRenderer *renderer)
363 {
364   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
365   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
366   
367   if (!priv->drawable || !priv->base_gc)
368     {
369       g_warning ("gdk_pango_renderer_set_drawable() and gdk_pango_renderer_set_drawable()"
370                  "must be used to set the target drawable and GC before using the renderer\n");
371     }
372 }
373
374 static void
375 gdk_pango_renderer_end (PangoRenderer *renderer)
376 {
377   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
378   GdkPangoRendererPrivate *priv = gdk_renderer->priv;
379
380   if (priv->cr)
381     {
382       cairo_destroy (priv->cr);
383       priv->cr = NULL;
384     }
385   priv->last_part = (PangoRenderPart)-1;
386 }
387
388 static void
389 gdk_pango_renderer_prepare_run (PangoRenderer  *renderer,
390                                 PangoLayoutRun *run)
391 {
392   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
393   gboolean embossed = FALSE;
394   GdkBitmap *stipple = NULL;
395   GSList *l;
396   int i;
397   
398   embossed = FALSE;
399   stipple = NULL;
400   
401   for (l = run->item->analysis.extra_attrs; l; l = l->next)
402     {
403       PangoAttribute *attr = l->data;
404
405       /* stipple_type and embossed_type aren't necessarily
406        * initialized, but they are 0, which is an
407        * invalid type so won't occur. 
408        */
409       if (attr->klass->type == gdk_pango_attr_stipple_type)
410         {
411           stipple = ((GdkPangoAttrStipple*)attr)->stipple;
412         }
413       else if (attr->klass->type == gdk_pango_attr_embossed_type)
414         {
415           embossed = ((GdkPangoAttrEmbossed*)attr)->embossed;
416         }
417     }
418
419   gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_FOREGROUND, stipple);
420   gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_BACKGROUND, stipple);
421   gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_UNDERLINE, stipple);
422   gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_STRIKETHROUGH, stipple);
423
424   if (embossed != gdk_renderer->priv->embossed)
425     {
426       gdk_renderer->priv->embossed = embossed;
427       pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND);
428     }
429
430   PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->prepare_run (renderer, run);
431
432   for (i = 0; i <= MAX_RENDER_PART; i++)
433     {
434       if (gdk_renderer->priv->override_color_set[i])
435         pango_renderer_set_color (renderer, i, &gdk_renderer->priv->override_color[i]);
436     }
437 }
438
439 static void
440 gdk_pango_renderer_set_property (GObject         *object,
441                                  guint            prop_id,
442                                  const GValue    *value,
443                                  GParamSpec      *pspec)
444 {
445   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object);
446
447   switch (prop_id)
448     {
449     case PROP_SCREEN:
450       gdk_renderer->priv->screen = g_value_get_object (value);
451       break;
452     default:
453       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
454       break;
455     }
456 }
457
458 static void
459 gdk_pango_renderer_get_property (GObject    *object,
460                                  guint       prop_id,
461                                  GValue     *value,
462                                  GParamSpec *pspec)
463 {
464   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object);
465
466   switch (prop_id)
467     {
468     case PROP_SCREEN:
469       g_value_set_object (value, gdk_renderer->priv->screen);
470       break;
471     default:
472       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
473       break;
474     }
475 }
476
477 static void
478 gdk_pango_renderer_init (GdkPangoRenderer *renderer)
479 {
480   renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
481                                                 GDK_TYPE_PANGO_RENDERER,
482                                                 GdkPangoRendererPrivate);
483
484   renderer->priv->last_part = (PangoRenderPart)-1;
485 }
486
487 static void
488 gdk_pango_renderer_class_init (GdkPangoRendererClass *klass)
489 {
490   GObjectClass *object_class = G_OBJECT_CLASS (klass);
491   
492   PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
493   
494   renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs;
495   renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle;
496   renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline;
497   renderer_class->part_changed = gdk_pango_renderer_part_changed;
498   renderer_class->begin = gdk_pango_renderer_begin;
499   renderer_class->end = gdk_pango_renderer_end;
500   renderer_class->prepare_run = gdk_pango_renderer_prepare_run;
501
502   object_class->finalize = gdk_pango_renderer_finalize;
503   object_class->constructor = gdk_pango_renderer_constructor;
504   object_class->set_property = gdk_pango_renderer_set_property;
505   object_class->get_property = gdk_pango_renderer_get_property;
506   
507   g_object_class_install_property (object_class,
508                                    PROP_SCREEN,
509                                    g_param_spec_object ("screen",
510                                                         P_("Screen"),
511                                                         P_("the GdkScreen for the renderer"),
512                                                         GDK_TYPE_SCREEN,
513                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
514                                                         G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | 
515                                                         G_PARAM_STATIC_BLURB));
516
517   g_type_class_add_private (object_class, sizeof (GdkPangoRendererPrivate));  
518 }
519
520 /**
521  * gdk_pango_renderer_new:
522  * @screen: a #GdkScreen
523  * 
524  * Creates a new #PangoRenderer for @screen. Normally you can use the
525  * results of gdk_pango_renderer_get_default() rather than creating a new
526  * renderer.
527  * 
528  * Return value: a newly created #PangoRenderer. Free with g_object_unref().
529  *
530  * Since: 2.6
531  **/
532 PangoRenderer *
533 gdk_pango_renderer_new (GdkScreen *screen)
534 {
535   g_return_val_if_fail (screen != NULL, NULL);
536   
537   return g_object_new (GDK_TYPE_PANGO_RENDERER,
538                        "screen", screen,
539                        NULL);
540 }
541
542 static void
543 on_renderer_display_closed (GdkDisplay       *display,
544                             GdkPangoRenderer *renderer)
545 {
546   g_signal_handlers_disconnect_by_func (renderer->priv->screen,
547                                         (gpointer)on_renderer_display_closed,
548                                         renderer);
549   g_object_set_data (G_OBJECT (renderer->priv->screen), 
550                      g_intern_static_string ("gdk-pango-renderer"), NULL);
551 }
552
553 /**
554  * gdk_pango_renderer_get_default:
555  * @screen: a #GdkScreen
556  * 
557  * Gets the default #PangoRenderer for a screen. This default renderer
558  * is shared by all users of the display, so properties such as the color
559  * or transformation matrix set for the renderer may be overwritten
560  * by functions such as gdk_draw_layout().
561  *
562  * Before using the renderer, you need to call gdk_pango_renderer_set_drawable()
563  * and gdk_pango_renderer_set_gc() to set the drawable and graphics context
564  * to use for drawing.
565  * 
566  * Return value: the default #PangoRenderer for @screen. The
567  *  renderer is owned by GTK+ and will be kept around until the
568  *  screen is closed.
569  *
570  * Since: 2.6
571  **/
572 PangoRenderer *
573 gdk_pango_renderer_get_default (GdkScreen *screen)
574 {
575   PangoRenderer *renderer;
576
577   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
578   
579   renderer = g_object_get_data (G_OBJECT (screen), "gdk-pango-renderer");
580   if (!renderer)
581     {
582       renderer = gdk_pango_renderer_new (screen);
583       g_object_set_data_full (G_OBJECT (screen), 
584                               g_intern_static_string ("gdk-pango-renderer"), renderer,
585                               (GDestroyNotify)g_object_unref);
586
587       g_signal_connect (gdk_screen_get_display (screen), "closed",
588                         G_CALLBACK (on_renderer_display_closed), renderer);
589     }
590
591   return renderer;
592 }
593
594 /**
595  * gdk_pango_renderer_set_drawable:
596  * @gdk_renderer: a #GdkPangoRenderer
597  * @drawable: the new target drawable, or %NULL
598  * 
599  * Sets the drawable the renderer draws to.
600  *
601  * Since: 2.6
602  **/
603 void
604 gdk_pango_renderer_set_drawable (GdkPangoRenderer *gdk_renderer,
605                                  GdkDrawable      *drawable)
606 {
607   GdkPangoRendererPrivate *priv;
608   
609   g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
610   g_return_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable));
611
612   priv = gdk_renderer->priv;
613   
614   if (priv->drawable != drawable)
615     {
616       if (priv->drawable)
617         g_object_unref (priv->drawable);
618       priv->drawable = drawable;
619       if (priv->drawable)
620         g_object_ref (priv->drawable);
621     }
622 }
623
624 /**
625  * gdk_pango_renderer_set_gc:
626  * @gdk_renderer: a #GdkPangoRenderer
627  * @gc: the new GC to use for drawing, or %NULL
628  * 
629  * Sets the GC the renderer draws with. Note that the GC must not be
630  * modified until it is unset by calling the function again with
631  * %NULL for the @gc parameter, since GDK may make internal copies
632  * of the GC which won't be updated to follow changes to the
633  * original GC.
634  *
635  * Since: 2.6
636  **/
637 void
638 gdk_pango_renderer_set_gc (GdkPangoRenderer *gdk_renderer,
639                            GdkGC            *gc)
640 {
641   GdkPangoRendererPrivate *priv;
642   
643   g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
644   g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
645
646   priv = gdk_renderer->priv;
647   
648   if (priv->base_gc != gc)
649     {
650       if (priv->base_gc)
651         g_object_unref (priv->base_gc);
652       priv->base_gc = gc;
653       if (priv->base_gc)
654         g_object_ref (priv->base_gc);
655     }
656 }
657
658
659 /**
660  * gdk_pango_renderer_set_stipple:
661  * @gdk_renderer: a #GdkPangoRenderer
662  * @part: the part to render with the stipple
663  * @stipple: the new stipple value.
664  * 
665  * Sets the stipple for one render part (foreground, background, underline,
666  * etc.) Note that this is overwritten when iterating through the individual
667  * styled runs of a #PangoLayout or #PangoLayoutLine. This function is thus
668  * only useful when you call low level functions like pango_renderer_draw_glyphs()
669  * directly, or in the 'prepare_run' virtual function of a subclass of
670  * #GdkPangoRenderer.
671  *
672  * Since: 2.6
673  **/
674 void
675 gdk_pango_renderer_set_stipple (GdkPangoRenderer *gdk_renderer,
676                                 PangoRenderPart   part,
677                                 GdkBitmap        *stipple)
678 {
679   g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
680
681   if (part > MAX_RENDER_PART)   /* Silently ignore unknown parts */
682     return;
683
684   if (stipple != gdk_renderer->priv->stipple[part])
685     {
686       if (gdk_renderer->priv->stipple[part])
687         g_object_unref (gdk_renderer->priv->stipple[part]);
688
689       gdk_renderer->priv->stipple[part] = stipple;
690       
691       if (gdk_renderer->priv->stipple[part])
692         g_object_ref (gdk_renderer->priv->stipple[part]);
693
694       pango_renderer_part_changed (PANGO_RENDERER (gdk_renderer), part);
695     }
696 }
697
698 /**
699  * gdk_pango_renderer_set_override_color:
700  * @gdk_renderer: a #GdkPangoRenderer
701  * @part: the part to render to set the color of
702  * @color: the color to use, or %NULL to unset a previously
703  *         set override color.
704  * 
705  * Sets the color for a particular render part (foreground,
706  * background, underline, etc.), overriding any attributes on the layouts
707  * renderered with this renderer.
708  * 
709  * Since: 2.6
710  **/
711 void
712 gdk_pango_renderer_set_override_color (GdkPangoRenderer *gdk_renderer,
713                                        PangoRenderPart   part,
714                                        const GdkColor   *color)
715 {
716   GdkPangoRendererPrivate *priv;
717   
718   g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
719
720   priv = gdk_renderer->priv;
721   
722   if (part > MAX_RENDER_PART)   /* Silently ignore unknown parts */
723     return;
724
725   if (color)
726     {
727       priv->override_color[part].red = color->red;
728       priv->override_color[part].green = color->green;
729       priv->override_color[part].blue = color->blue;
730       priv->override_color_set[part] = TRUE;
731     }
732   else
733     priv->override_color_set[part] = FALSE;
734 }
735
736 /**
737  * gdk_pango_context_set_colormap:
738  * @context: a #PangoContext
739  * @colormap: a #GdkColormap
740  *
741  * This function used to set the colormap to be used for drawing with
742  * @context. The colormap is now always derived from the graphics
743  * context used for drawing, so calling this function is no longer
744  * necessary.
745  **/
746 void
747 gdk_pango_context_set_colormap (PangoContext *context,
748                                 GdkColormap  *colormap)
749 {
750   g_return_if_fail (PANGO_IS_CONTEXT (context));
751   g_return_if_fail (colormap == NULL || GDK_IS_COLORMAP (colormap));
752 }
753
754 /* Gets a renderer to draw with, setting the properties of the
755  * renderer and activating it. Note that since we activate the
756  * renderer here, the implicit setting of the matrix that
757  * pango_renderer_draw_layout_[line] normally do when they
758  * activate the renderer is suppressed. */
759 static PangoRenderer *
760 get_renderer (GdkDrawable     *drawable,
761               GdkGC           *gc,
762               const GdkColor  *foreground,
763               const GdkColor  *background)
764 {
765   GdkScreen *screen = gdk_drawable_get_screen (drawable);
766   PangoRenderer *renderer = gdk_pango_renderer_get_default (screen);
767   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
768
769   gdk_pango_renderer_set_drawable (gdk_renderer, drawable);
770   gdk_pango_renderer_set_gc (gdk_renderer, gc);  
771
772   gdk_pango_renderer_set_override_color (gdk_renderer,
773                                          PANGO_RENDER_PART_FOREGROUND,
774                                          foreground);
775   gdk_pango_renderer_set_override_color (gdk_renderer,
776                                          PANGO_RENDER_PART_UNDERLINE,
777                                          foreground);
778   gdk_pango_renderer_set_override_color (gdk_renderer,
779                                          PANGO_RENDER_PART_STRIKETHROUGH,
780                                          foreground);
781
782   gdk_pango_renderer_set_override_color (gdk_renderer,
783                                          PANGO_RENDER_PART_BACKGROUND,
784                                          background);
785
786   pango_renderer_activate (renderer);
787
788   return renderer;
789 }
790
791 /* Cleans up the renderer obtained with get_renderer() */
792 static void
793 release_renderer (PangoRenderer *renderer)
794 {
795   GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
796   
797   pango_renderer_deactivate (renderer);
798   
799   gdk_pango_renderer_set_override_color (gdk_renderer,
800                                          PANGO_RENDER_PART_FOREGROUND,
801                                          NULL);
802   gdk_pango_renderer_set_override_color (gdk_renderer,
803                                          PANGO_RENDER_PART_UNDERLINE,
804                                          NULL);
805   gdk_pango_renderer_set_override_color (gdk_renderer,
806                                          PANGO_RENDER_PART_STRIKETHROUGH,
807                                          NULL);
808   gdk_pango_renderer_set_override_color (gdk_renderer,
809                                          PANGO_RENDER_PART_BACKGROUND,
810                                          NULL);
811   
812   gdk_pango_renderer_set_drawable (gdk_renderer, NULL);
813   gdk_pango_renderer_set_gc (gdk_renderer, NULL);
814 }
815
816 /**
817  * gdk_draw_layout_line_with_colors:
818  * @drawable:  the drawable on which to draw the line
819  * @gc:        base graphics to use
820  * @x:         the x position of start of string (in pixels)
821  * @y:         the y position of baseline (in pixels)
822  * @line:      a #PangoLayoutLine
823  * @foreground: foreground override color, or %NULL for none
824  * @background: background override color, or %NULL for none
825  *
826  * Render a #PangoLayoutLine onto a #GdkDrawable, overriding the
827  * layout's normal colors with @foreground and/or @background.
828  * @foreground and @background need not be allocated.
829  *
830  * If the layout's #PangoContext has a transformation matrix set, then
831  * @x and @y specify the position of the left edge of the baseline
832  * (left is in before-tranform user coordinates) in after-transform
833  * device coordinates.
834  */
835 void 
836 gdk_draw_layout_line_with_colors (GdkDrawable      *drawable,
837                                   GdkGC            *gc,
838                                   gint              x, 
839                                   gint              y,
840                                   PangoLayoutLine  *line,
841                                   const GdkColor   *foreground,
842                                   const GdkColor   *background)
843 {
844   PangoRenderer *renderer;
845   const PangoMatrix *matrix;
846   
847   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
848   g_return_if_fail (GDK_IS_GC (gc));
849   g_return_if_fail (line != NULL);
850
851   renderer = get_renderer (drawable, gc, foreground, background);
852
853   /* When we have a matrix, we do positioning by adjusting the matrix, and
854    * clamp just pass x=0, y=0 to the lower levels. We don't want to introduce
855    * a matrix when the caller didn't provide one, however, since that adds
856    * lots of floating point arithmetic for each glyph.
857    */
858   matrix = pango_context_get_matrix (pango_layout_get_context (line->layout));
859   if (matrix)
860     {
861       PangoMatrix tmp_matrix;
862       
863       tmp_matrix = *matrix;
864       tmp_matrix.x0 = x;
865       tmp_matrix.y0 = y;
866       pango_renderer_set_matrix (renderer, &tmp_matrix);
867
868       x = 0;
869       y = 0;
870     }
871   else
872     pango_renderer_set_matrix (renderer, NULL);
873
874   pango_renderer_draw_layout_line (renderer, line, x * PANGO_SCALE, y * PANGO_SCALE);
875
876   release_renderer (renderer);
877 }
878
879 /* Gets the bounds of a layout in device coordinates. Note cut-and-paste
880  * between here and gtklabel.c */
881 static void
882 get_rotated_layout_bounds (PangoLayout  *layout,
883                            GdkRectangle *rect)
884 {
885   PangoContext *context = pango_layout_get_context (layout);
886   const PangoMatrix *matrix = pango_context_get_matrix (context);
887   gdouble x_min = 0, x_max = 0, y_min = 0, y_max = 0; /* quiet gcc */
888   PangoRectangle logical_rect;
889   gint i, j;
890
891   pango_layout_get_extents (layout, NULL, &logical_rect);
892   
893   for (i = 0; i < 2; i++)
894     {
895       gdouble x = (i == 0) ? logical_rect.x : logical_rect.x + logical_rect.width;
896       for (j = 0; j < 2; j++)
897         {
898           gdouble y = (j == 0) ? logical_rect.y : logical_rect.y + logical_rect.height;
899           
900           gdouble xt = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0;
901           gdouble yt = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0;
902           
903           if (i == 0 && j == 0)
904             {
905               x_min = x_max = xt;
906               y_min = y_max = yt;
907             }
908           else
909             {
910               if (xt < x_min)
911                 x_min = xt;
912               if (yt < y_min)
913                 y_min = yt;
914               if (xt > x_max)
915                 x_max = xt;
916               if (yt > y_max)
917                 y_max = yt;
918             }
919         }
920     }
921   
922   rect->x = floor (x_min);
923   rect->width = ceil (x_max) - rect->x;
924   rect->y = floor (y_min);
925   rect->height = floor (y_max) - rect->y;
926 }
927
928 /**
929  * gdk_draw_layout_with_colors:
930  * @drawable:  the drawable on which to draw string
931  * @gc:        base graphics context to use
932  * @x:         the X position of the left of the layout (in pixels)
933  * @y:         the Y position of the top of the layout (in pixels)
934  * @layout:    a #PangoLayout
935  * @foreground: foreground override color, or %NULL for none
936  * @background: background override color, or %NULL for none
937  *
938  * Render a #PangoLayout onto a #GdkDrawable, overriding the
939  * layout's normal colors with @foreground and/or @background.
940  * @foreground and @background need not be allocated.
941  *
942  * If the layout's #PangoContext has a transformation matrix set, then
943  * @x and @y specify the position of the top left corner of the
944  * bounding box (in device space) of the transformed layout.
945  *
946  * If you're using GTK+, the ususal way to obtain a #PangoLayout
947  * is gtk_widget_create_pango_layout().
948  */
949 void 
950 gdk_draw_layout_with_colors (GdkDrawable     *drawable,
951                              GdkGC           *gc,
952                              int              x, 
953                              int              y,
954                              PangoLayout     *layout,
955                              const GdkColor  *foreground,
956                              const GdkColor  *background)
957 {
958   PangoRenderer *renderer;
959   const PangoMatrix *matrix;
960   
961   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
962   g_return_if_fail (GDK_IS_GC (gc));
963   g_return_if_fail (PANGO_IS_LAYOUT (layout));
964
965   renderer = get_renderer (drawable, gc, foreground, background);
966
967   /* When we have a matrix, we do positioning by adjusting the matrix, and
968    * clamp just pass x=0, y=0 to the lower levels. We don't want to introduce
969    * a matrix when the caller didn't provide one, however, since that adds
970    * lots of floating point arithmetic for each glyph.
971    */
972   matrix = pango_context_get_matrix (pango_layout_get_context (layout));
973   if (matrix)
974     {
975       PangoMatrix tmp_matrix;
976       GdkRectangle rect;
977
978       get_rotated_layout_bounds (layout, &rect);
979       
980       tmp_matrix = *matrix;
981       tmp_matrix.x0 += x - rect.x;
982       tmp_matrix.y0 += y - rect.y;
983       pango_renderer_set_matrix (renderer, &tmp_matrix);
984       
985       x = 0;
986       y = 0;
987     }
988   else
989     pango_renderer_set_matrix (renderer, NULL);
990
991   pango_renderer_draw_layout (renderer, layout, x * PANGO_SCALE, y * PANGO_SCALE);
992   
993   release_renderer (renderer);
994 }
995
996 /**
997  * gdk_draw_layout_line:
998  * @drawable:  the drawable on which to draw the line
999  * @gc:        base graphics to use
1000  * @x:         the x position of start of string (in pixels)
1001  * @y:         the y position of baseline (in pixels)
1002  * @line:      a #PangoLayoutLine
1003  *
1004  * Render a #PangoLayoutLine onto an GDK drawable
1005  *
1006  * If the layout's #PangoContext has a transformation matrix set, then
1007  * @x and @y specify the position of the left edge of the baseline
1008  * (left is in before-tranform user coordinates) in after-transform
1009  * device coordinates.
1010  */
1011 void 
1012 gdk_draw_layout_line (GdkDrawable      *drawable,
1013                       GdkGC            *gc,
1014                       gint              x, 
1015                       gint              y,
1016                       PangoLayoutLine  *line)
1017 {
1018   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
1019   g_return_if_fail (GDK_IS_GC (gc));
1020   g_return_if_fail (line != NULL);
1021   
1022   gdk_draw_layout_line_with_colors (drawable, gc, x, y, line, NULL, NULL);
1023 }
1024
1025 /**
1026  * gdk_draw_layout:
1027  * @drawable:  the drawable on which to draw string
1028  * @gc:        base graphics context to use
1029  * @x:         the X position of the left of the layout (in pixels)
1030  * @y:         the Y position of the top of the layout (in pixels)
1031  * @layout:    a #PangoLayout
1032  *
1033  * Render a #PangoLayout onto a GDK drawable
1034  *
1035  * If the layout's #PangoContext has a transformation matrix set, then
1036  * @x and @y specify the position of the top left corner of the
1037  * bounding box (in device space) of the transformed layout.
1038  *
1039  * If you're using GTK+, the usual way to obtain a #PangoLayout
1040  * is gtk_widget_create_pango_layout().
1041  */
1042 void 
1043 gdk_draw_layout (GdkDrawable     *drawable,
1044                  GdkGC           *gc,
1045                  int              x, 
1046                  int              y,
1047                  PangoLayout     *layout)
1048 {
1049   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
1050   g_return_if_fail (GDK_IS_GC (gc));
1051   g_return_if_fail (PANGO_IS_LAYOUT (layout));
1052
1053   gdk_draw_layout_with_colors (drawable, gc, x, y, layout, NULL, NULL);
1054 }
1055
1056 static PangoAttribute *
1057 gdk_pango_attr_stipple_copy (const PangoAttribute *attr)
1058 {
1059   const GdkPangoAttrStipple *src = (const GdkPangoAttrStipple*) attr;
1060
1061   return gdk_pango_attr_stipple_new (src->stipple);
1062 }
1063
1064 static void
1065 gdk_pango_attr_stipple_destroy (PangoAttribute *attr)
1066 {
1067   GdkPangoAttrStipple *st = (GdkPangoAttrStipple*) attr;
1068
1069   if (st->stipple)
1070     g_object_unref (st->stipple);
1071   
1072   g_free (attr);
1073 }
1074
1075 static gboolean
1076 gdk_pango_attr_stipple_compare (const PangoAttribute *attr1,
1077                                     const PangoAttribute *attr2)
1078 {
1079   const GdkPangoAttrStipple *a = (const GdkPangoAttrStipple*) attr1;
1080   const GdkPangoAttrStipple *b = (const GdkPangoAttrStipple*) attr2;
1081
1082   return a->stipple == b->stipple;
1083 }
1084
1085 /**
1086  * gdk_pango_attr_stipple_new:
1087  * @stipple: a bitmap to be set as stipple
1088  *
1089  * Creates a new attribute containing a stipple bitmap to be used when
1090  * rendering the text.
1091  *
1092  * Return value: new #PangoAttribute
1093  **/
1094
1095 PangoAttribute *
1096 gdk_pango_attr_stipple_new (GdkBitmap *stipple)
1097 {
1098   GdkPangoAttrStipple *result;
1099   
1100   static PangoAttrClass klass = {
1101     0,
1102     gdk_pango_attr_stipple_copy,
1103     gdk_pango_attr_stipple_destroy,
1104     gdk_pango_attr_stipple_compare
1105   };
1106
1107   if (!klass.type)
1108     klass.type = gdk_pango_attr_stipple_type =
1109       pango_attr_type_register ("GdkPangoAttrStipple");
1110
1111   result = g_new (GdkPangoAttrStipple, 1);
1112   result->attr.klass = &klass;
1113
1114   if (stipple)
1115     g_object_ref (stipple);
1116   
1117   result->stipple = stipple;
1118
1119   return (PangoAttribute *)result;
1120 }
1121
1122 static PangoAttribute *
1123 gdk_pango_attr_embossed_copy (const PangoAttribute *attr)
1124 {
1125   const GdkPangoAttrEmbossed *e = (const GdkPangoAttrEmbossed*) attr;
1126
1127   return gdk_pango_attr_embossed_new (e->embossed);
1128 }
1129
1130 static void
1131 gdk_pango_attr_embossed_destroy (PangoAttribute *attr)
1132 {
1133   g_free (attr);
1134 }
1135
1136 static gboolean
1137 gdk_pango_attr_embossed_compare (const PangoAttribute *attr1,
1138                                  const PangoAttribute *attr2)
1139 {
1140   const GdkPangoAttrEmbossed *e1 = (const GdkPangoAttrEmbossed*) attr1;
1141   const GdkPangoAttrEmbossed *e2 = (const GdkPangoAttrEmbossed*) attr2;
1142
1143   return e1->embossed == e2->embossed;
1144 }
1145
1146 /**
1147  * gdk_pango_attr_embossed_new:
1148  * @embossed: a bitmap to be set as embossed
1149  *
1150  * Creates a new attribute containing a embossed bitmap to be used when
1151  * rendering the text.
1152  *
1153  * Return value: new #PangoAttribute
1154  **/
1155
1156 PangoAttribute *
1157 gdk_pango_attr_embossed_new (gboolean embossed)
1158 {
1159   GdkPangoAttrEmbossed *result;
1160   
1161   static PangoAttrClass klass = {
1162     0,
1163     gdk_pango_attr_embossed_copy,
1164     gdk_pango_attr_embossed_destroy,
1165     gdk_pango_attr_embossed_compare
1166   };
1167
1168   if (!klass.type)
1169     klass.type = gdk_pango_attr_embossed_type =
1170       pango_attr_type_register ("GdkPangoAttrEmbossed");
1171
1172   result = g_new (GdkPangoAttrEmbossed, 1);
1173   result->attr.klass = &klass;
1174   result->embossed = embossed;
1175   
1176   return (PangoAttribute *)result;
1177 }
1178
1179 /* Get a clip region to draw only part of a layout. index_ranges
1180  * contains alternating range starts/stops. The region is the
1181  * region which contains the given ranges, i.e. if you draw with the
1182  * region as clip, only the given ranges are drawn.
1183  */
1184
1185 /**
1186  * gdk_pango_layout_line_get_clip_region:
1187  * @line: a #PangoLayoutLine 
1188  * @x_origin: X pixel where you intend to draw the layout line with this clip
1189  * @y_origin: baseline pixel where you intend to draw the layout line with this clip
1190  * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
1191  * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
1192  * 
1193  * Obtains a clip region which contains the areas where the given
1194  * ranges of text would be drawn. @x_origin and @y_origin are the same
1195  * position you would pass to gdk_draw_layout_line(). @index_ranges
1196  * should contain ranges of bytes in the layout's text. The clip
1197  * region will include space to the left or right of the line (to the
1198  * layout bounding box) if you have indexes above or below the indexes
1199  * contained inside the line. This is to draw the selection all the way
1200  * to the side of the layout. However, the clip region is in line coordinates,
1201  * not layout coordinates.
1202  * 
1203  * Return value: a clip region containing the given ranges
1204  **/
1205 GdkRegion*
1206 gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
1207                                        gint             x_origin,
1208                                        gint             y_origin,
1209                                        gint            *index_ranges,
1210                                        gint             n_ranges)
1211 {
1212   GdkRegion *clip_region;
1213   gint i;
1214   PangoRectangle logical_rect;
1215   PangoLayoutIter *iter;
1216   gint baseline;
1217   
1218   g_return_val_if_fail (line != NULL, NULL);
1219   g_return_val_if_fail (index_ranges != NULL, NULL);
1220   
1221   clip_region = gdk_region_new ();
1222
1223   iter = pango_layout_get_iter (line->layout);
1224   while (pango_layout_iter_get_line (iter) != line)
1225     pango_layout_iter_next_line (iter);
1226   
1227   pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
1228   baseline = pango_layout_iter_get_baseline (iter);
1229   
1230   pango_layout_iter_free (iter);
1231   
1232   i = 0;
1233   while (i < n_ranges)
1234     {  
1235       gint *pixel_ranges = NULL;
1236       gint n_pixel_ranges = 0;
1237       gint j;
1238
1239       /* Note that get_x_ranges returns layout coordinates
1240        */
1241       if (index_ranges[i*2+1] >= line->start_index &&
1242           index_ranges[i*2] < line->start_index + line->length)
1243         pango_layout_line_get_x_ranges (line,
1244                                         index_ranges[i*2],
1245                                         index_ranges[i*2+1],
1246                                         &pixel_ranges, &n_pixel_ranges);
1247   
1248       for (j = 0; j < n_pixel_ranges; j++)
1249         {
1250           GdkRectangle rect;
1251           
1252           rect.x = x_origin + pixel_ranges[2*j] / PANGO_SCALE - logical_rect.x / PANGO_SCALE;
1253           rect.y = y_origin - (baseline / PANGO_SCALE - logical_rect.y / PANGO_SCALE);
1254           rect.width = (pixel_ranges[2*j + 1] - pixel_ranges[2*j]) / PANGO_SCALE;
1255           rect.height = logical_rect.height / PANGO_SCALE;
1256           
1257           gdk_region_union_with_rect (clip_region, &rect);
1258         }
1259
1260       g_free (pixel_ranges);
1261       ++i;
1262     }
1263
1264   return clip_region;
1265 }
1266
1267 /**
1268  * gdk_pango_layout_get_clip_region:
1269  * @layout: a #PangoLayout 
1270  * @x_origin: X pixel where you intend to draw the layout with this clip
1271  * @y_origin: Y pixel where you intend to draw the layout with this clip
1272  * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
1273  * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
1274  * 
1275  * Obtains a clip region which contains the areas where the given ranges
1276  * of text would be drawn. @x_origin and @y_origin are the same position
1277  * you would pass to gdk_draw_layout_line(). @index_ranges should contain
1278  * ranges of bytes in the layout's text.
1279  * 
1280  * Return value: a clip region containing the given ranges
1281  **/
1282 GdkRegion*
1283 gdk_pango_layout_get_clip_region (PangoLayout *layout,
1284                                   gint         x_origin,
1285                                   gint         y_origin,
1286                                   gint        *index_ranges,
1287                                   gint         n_ranges)
1288 {
1289   PangoLayoutIter *iter;  
1290   GdkRegion *clip_region;
1291   
1292   g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
1293   g_return_val_if_fail (index_ranges != NULL, NULL);
1294   
1295   clip_region = gdk_region_new ();
1296   
1297   iter = pango_layout_get_iter (layout);
1298   
1299   do
1300     {
1301       PangoRectangle logical_rect;
1302       PangoLayoutLine *line;
1303       GdkRegion *line_region;
1304       gint baseline;
1305       
1306       line = pango_layout_iter_get_line (iter);      
1307
1308       pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
1309       baseline = pango_layout_iter_get_baseline (iter);      
1310
1311       line_region = gdk_pango_layout_line_get_clip_region (line,
1312                                                            x_origin + logical_rect.x / PANGO_SCALE,
1313                                                            y_origin + baseline / PANGO_SCALE,
1314                                                            index_ranges,
1315                                                            n_ranges);
1316
1317       gdk_region_union (clip_region, line_region);
1318       gdk_region_destroy (line_region);
1319     }
1320   while (pango_layout_iter_next_line (iter));
1321
1322   pango_layout_iter_free (iter);
1323
1324   return clip_region;
1325 }
1326
1327 /**
1328  * gdk_pango_context_get:
1329  * 
1330  * Creates a #PangoContext for the default GDK screen.
1331  *
1332  * The context must be freed when you're finished with it.
1333  * 
1334  * When using GTK+, normally you should use gtk_widget_get_pango_context()
1335  * instead of this function, to get the appropriate context for
1336  * the widget you intend to render text onto.
1337  * 
1338  * The newly created context will have the default font options (see
1339  * #cairo_font_options_t) for the default screen; if these options
1340  * change it will not be updated. Using gtk_widget_get_pango_context()
1341  * is more convenient if you want to keep a context around and track
1342  * changes to the screen's font rendering settings.
1343  *
1344  * Return value: a new #PangoContext for the default display
1345  **/
1346 PangoContext *
1347 gdk_pango_context_get (void)
1348 {
1349   return gdk_pango_context_get_for_screen (gdk_screen_get_default ());
1350 }
1351
1352 /**
1353  * gdk_pango_context_get_for_screen:
1354  * @screen: the #GdkScreen for which the context is to be created.
1355  * 
1356  * Creates a #PangoContext for @screen.
1357  *
1358  * The context must be freed when you're finished with it.
1359  * 
1360  * When using GTK+, normally you should use gtk_widget_get_pango_context()
1361  * instead of this function, to get the appropriate context for
1362  * the widget you intend to render text onto.
1363  * 
1364  * The newly created context will have the default font options
1365  * (see #cairo_font_options_t) for the screen; if these options
1366  * change it will not be updated. Using gtk_widget_get_pango_context()
1367  * is more convenient if you want to keep a context around and track
1368  * changes to the screen's font rendering settings.
1369  * 
1370  * Return value: a new #PangoContext for @screen
1371  *
1372  * Since: 2.2
1373  **/
1374 PangoContext *
1375 gdk_pango_context_get_for_screen (GdkScreen *screen)
1376 {
1377   PangoFontMap *fontmap;
1378   PangoContext *context;
1379   const cairo_font_options_t *options;
1380   double dpi;
1381   
1382   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1383
1384   fontmap = pango_cairo_font_map_get_default ();
1385   
1386   context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
1387
1388   options = gdk_screen_get_font_options (screen);
1389   pango_cairo_context_set_font_options (context, options);
1390
1391   dpi = gdk_screen_get_resolution (screen);
1392   pango_cairo_context_set_resolution (context, dpi);
1393
1394   return context;
1395 }
1396
1397 #define __GDK_PANGO_C__
1398 #include "gdkaliasdef.c"