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