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