1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2000 Red Hat, Inc.
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.
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.
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.
22 #include <pango/pangocairo.h>
26 #include "gdkinternals.h"
28 #include "gdkprivate.h"
29 #include "gdkscreen.h"
33 #define GDK_INFO_KEY "gdk-info"
35 /* We have various arrays indexed by render part; if PangoRenderPart
36 * is extended, we want to make sure not to overwrite the end of
39 #define MAX_RENDER_PART PANGO_RENDER_PART_STRIKETHROUGH
41 struct _GdkPangoRendererPrivate
45 /* GdkPangoRenderer specific state */
46 PangoColor override_color[MAX_RENDER_PART + 1];
47 gboolean override_color_set[MAX_RENDER_PART + 1];
49 GdkBitmap *stipple[MAX_RENDER_PART + 1];
50 PangoColor emboss_color;
54 PangoRenderPart last_part;
57 GdkDrawable *drawable;
63 static PangoAttrType gdk_pango_attr_stipple_type;
64 static PangoAttrType gdk_pango_attr_embossed_type;
65 static PangoAttrType gdk_pango_attr_emboss_color_type;
72 G_DEFINE_TYPE (GdkPangoRenderer, gdk_pango_renderer, PANGO_TYPE_RENDERER)
75 gdk_pango_renderer_finalize (GObject *object)
77 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object);
78 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
82 g_object_unref (priv->base_gc);
84 g_object_unref (priv->drawable);
86 for (i = 0; i <= MAX_RENDER_PART; i++)
88 g_object_unref (priv->stipple[i]);
90 G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object);
94 gdk_pango_renderer_constructor (GType type,
95 guint n_construct_properties,
96 GObjectConstructParam *construct_params)
99 GdkPangoRenderer *gdk_renderer;
101 object = G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->constructor (type,
102 n_construct_properties,
105 gdk_renderer = GDK_PANGO_RENDERER (object);
107 if (!gdk_renderer->priv->screen)
109 g_warning ("Screen must be specified at construct time for GdkPangoRenderer");
110 gdk_renderer->priv->screen = gdk_screen_get_default ();
116 /* Adjusts matrix and color for the renderer to draw the secondary
117 * "shadow" copy for embossed text */
119 emboss_context (GdkPangoRenderer *renderer, cairo_t *cr)
121 GdkPangoRendererPrivate *priv = renderer->priv;
122 cairo_matrix_t tmp_matrix;
123 double red, green, blue;
125 /* The gymnastics here to adjust the matrix are because we want
126 * to offset by +1,+1 in device-space, not in user-space,
127 * so we can't just draw the layout at x + 1, y + 1
129 cairo_get_matrix (cr, &tmp_matrix);
130 tmp_matrix.x0 += 1.0;
131 tmp_matrix.y0 += 1.0;
132 cairo_set_matrix (cr, &tmp_matrix);
134 red = (double) priv->emboss_color.red / 65535.;
135 green = (double) priv->emboss_color.green / 65535.;
136 blue = (double) priv->emboss_color.blue / 65535.;
138 cairo_set_source_rgb (cr, red, green, blue);
141 static inline gboolean
142 color_equal (const PangoColor *c1, const PangoColor *c2)
148 c1->red == c2->red &&
149 c1->green == c2->green &&
150 c1->blue == c2->blue)
157 get_cairo_context (GdkPangoRenderer *gdk_renderer,
158 PangoRenderPart part)
160 PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer);
161 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
165 const PangoMatrix *matrix;
167 priv->cr = gdk_cairo_create (priv->drawable);
169 matrix = pango_renderer_get_matrix (renderer);
172 cairo_matrix_t cairo_matrix;
174 cairo_matrix_init (&cairo_matrix,
175 matrix->xx, matrix->yx,
176 matrix->xy, matrix->yy,
177 matrix->x0, matrix->y0);
178 cairo_set_matrix (priv->cr, &cairo_matrix);
182 if (part != priv->last_part)
184 PangoColor *pango_color;
189 pango_color = pango_renderer_get_color (renderer, part);
191 if (priv->last_part != -1)
192 changed = priv->gc_changed ||
193 priv->stipple[priv->last_part] != priv->stipple[part] ||
194 !color_equal (pango_color,
195 pango_renderer_get_color (renderer, priv->last_part));
203 tmp_color.red = pango_color->red;
204 tmp_color.green = pango_color->green;
205 tmp_color.blue = pango_color->blue;
212 _gdk_gc_update_context (priv->base_gc,
220 priv->last_part = part;
221 priv->gc_changed = FALSE;
228 gdk_pango_renderer_draw_glyphs (PangoRenderer *renderer,
230 PangoGlyphString *glyphs,
234 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
235 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
238 cr = get_cairo_context (gdk_renderer,
239 PANGO_RENDER_PART_FOREGROUND);
244 emboss_context (gdk_renderer, cr);
245 cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
246 pango_cairo_show_glyph_string (cr, font, glyphs);
250 cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
251 pango_cairo_show_glyph_string (cr, font, glyphs);
255 gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
256 PangoRenderPart part,
262 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
263 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
266 cr = get_cairo_context (gdk_renderer, part);
268 if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
271 emboss_context (gdk_renderer, cr);
273 (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
274 (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
281 (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
282 (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
287 gdk_pango_renderer_draw_error_underline (PangoRenderer *renderer,
293 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
294 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
297 cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE);
302 emboss_context (gdk_renderer, cr);
303 pango_cairo_show_error_underline (cr,
304 (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
305 (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
309 pango_cairo_show_error_underline (cr,
310 (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
311 (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
315 gdk_pango_renderer_draw_shape (PangoRenderer *renderer,
316 PangoAttrShape *attr,
320 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
321 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
323 PangoCairoShapeRendererFunc shape_renderer;
324 gpointer shape_renderer_data;
326 double dx = (double)x / PANGO_SCALE, dy = (double)y / PANGO_SCALE;
328 layout = pango_renderer_get_layout (renderer);
333 shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
334 &shape_renderer_data);
339 cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_FOREGROUND);
346 emboss_context (gdk_renderer, cr);
348 cairo_move_to (cr, dx, dy);
349 shape_renderer (cr, attr, FALSE, shape_renderer_data);
354 cairo_move_to (cr, dx, dy);
355 shape_renderer (cr, attr, FALSE, shape_renderer_data);
361 gdk_pango_renderer_part_changed (PangoRenderer *renderer,
362 PangoRenderPart part)
364 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
366 if (gdk_renderer->priv->last_part == part)
367 gdk_renderer->priv->last_part = (PangoRenderPart)-1;
371 gdk_pango_renderer_begin (PangoRenderer *renderer)
373 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
374 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
376 if (!priv->drawable || !priv->base_gc)
378 g_warning ("gdk_pango_renderer_set_drawable() and gdk_pango_renderer_set_drawable()"
379 "must be used to set the target drawable and GC before using the renderer\n");
384 gdk_pango_renderer_end (PangoRenderer *renderer)
386 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
387 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
391 cairo_destroy (priv->cr);
394 priv->last_part = (PangoRenderPart)-1;
398 gdk_pango_renderer_prepare_run (PangoRenderer *renderer,
401 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
402 gboolean embossed = FALSE;
403 GdkBitmap *stipple = NULL;
404 gboolean changed = FALSE;
405 PangoColor emboss_color;
409 emboss_color.red = 0xffff;
410 emboss_color.green = 0xffff;
411 emboss_color.blue = 0xffff;
413 for (l = run->item->analysis.extra_attrs; l; l = l->next)
415 PangoAttribute *attr = l->data;
417 /* stipple_type and embossed_type aren't necessarily
418 * initialized, but they are 0, which is an
419 * invalid type so won't occur.
421 if (attr->klass->type == gdk_pango_attr_stipple_type)
423 stipple = ((GdkPangoAttrStipple*)attr)->stipple;
425 else if (attr->klass->type == gdk_pango_attr_embossed_type)
427 embossed = ((GdkPangoAttrEmbossed*)attr)->embossed;
429 else if (attr->klass->type == gdk_pango_attr_emboss_color_type)
431 emboss_color = ((GdkPangoAttrEmbossColor*)attr)->color;
435 gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_FOREGROUND, stipple);
436 gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_BACKGROUND, stipple);
437 gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_UNDERLINE, stipple);
438 gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_STRIKETHROUGH, stipple);
440 if (embossed != gdk_renderer->priv->embossed)
442 gdk_renderer->priv->embossed = embossed;
446 if (!color_equal (&gdk_renderer->priv->emboss_color, &emboss_color))
448 gdk_renderer->priv->emboss_color = emboss_color;
453 pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND);
455 PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->prepare_run (renderer, run);
457 for (i = 0; i <= MAX_RENDER_PART; i++)
459 if (gdk_renderer->priv->override_color_set[i])
460 pango_renderer_set_color (renderer, i, &gdk_renderer->priv->override_color[i]);
465 gdk_pango_renderer_set_property (GObject *object,
470 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object);
475 gdk_renderer->priv->screen = g_value_get_object (value);
478 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
484 gdk_pango_renderer_get_property (GObject *object,
489 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object);
494 g_value_set_object (value, gdk_renderer->priv->screen);
497 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
503 gdk_pango_renderer_init (GdkPangoRenderer *renderer)
505 renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
506 GDK_TYPE_PANGO_RENDERER,
507 GdkPangoRendererPrivate);
509 renderer->priv->last_part = (PangoRenderPart)-1;
510 renderer->priv->gc_changed = TRUE;
514 gdk_pango_renderer_class_init (GdkPangoRendererClass *klass)
516 GObjectClass *object_class = G_OBJECT_CLASS (klass);
518 PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
520 renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs;
521 renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle;
522 renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline;
523 renderer_class->draw_shape = gdk_pango_renderer_draw_shape;
524 renderer_class->part_changed = gdk_pango_renderer_part_changed;
525 renderer_class->begin = gdk_pango_renderer_begin;
526 renderer_class->end = gdk_pango_renderer_end;
527 renderer_class->prepare_run = gdk_pango_renderer_prepare_run;
529 object_class->finalize = gdk_pango_renderer_finalize;
530 object_class->constructor = gdk_pango_renderer_constructor;
531 object_class->set_property = gdk_pango_renderer_set_property;
532 object_class->get_property = gdk_pango_renderer_get_property;
534 g_object_class_install_property (object_class,
536 g_param_spec_object ("screen",
538 P_("the GdkScreen for the renderer"),
540 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
541 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
542 G_PARAM_STATIC_BLURB));
544 g_type_class_add_private (object_class, sizeof (GdkPangoRendererPrivate));
548 * gdk_pango_renderer_new:
549 * @screen: a #GdkScreen
551 * Creates a new #PangoRenderer for @screen. Normally you can use the
552 * results of gdk_pango_renderer_get_default() rather than creating a new
555 * Return value: a newly created #PangoRenderer. Free with g_object_unref().
560 gdk_pango_renderer_new (GdkScreen *screen)
562 g_return_val_if_fail (screen != NULL, NULL);
564 return g_object_new (GDK_TYPE_PANGO_RENDERER,
570 on_renderer_display_closed (GdkDisplay *display,
572 GdkPangoRenderer *renderer)
574 g_signal_handlers_disconnect_by_func (display,
575 on_renderer_display_closed,
577 g_object_set_data (G_OBJECT (renderer->priv->screen),
578 g_intern_static_string ("gdk-pango-renderer"), NULL);
582 * gdk_pango_renderer_get_default:
583 * @screen: a #GdkScreen
585 * Gets the default #PangoRenderer for a screen. This default renderer
586 * is shared by all users of the display, so properties such as the color
587 * or transformation matrix set for the renderer may be overwritten.
589 * Before using the renderer, you need to call gdk_pango_renderer_set_drawable()
590 * and gdk_pango_renderer_set_gc() to set the drawable and graphics context
591 * to use for drawing.
593 * Return value: the default #PangoRenderer for @screen. The
594 * renderer is owned by GTK+ and will be kept around until the
600 gdk_pango_renderer_get_default (GdkScreen *screen)
602 PangoRenderer *renderer;
604 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
606 renderer = g_object_get_data (G_OBJECT (screen), "gdk-pango-renderer");
609 renderer = gdk_pango_renderer_new (screen);
610 g_object_set_data_full (G_OBJECT (screen),
611 g_intern_static_string ("gdk-pango-renderer"), renderer,
612 (GDestroyNotify)g_object_unref);
614 g_signal_connect (gdk_screen_get_display (screen), "closed",
615 G_CALLBACK (on_renderer_display_closed), renderer);
622 * gdk_pango_renderer_set_drawable:
623 * @gdk_renderer: a #GdkPangoRenderer
624 * @drawable: (allow-none): the new target drawable, or %NULL
626 * Sets the drawable the renderer draws to.
631 gdk_pango_renderer_set_drawable (GdkPangoRenderer *gdk_renderer,
632 GdkDrawable *drawable)
634 GdkPangoRendererPrivate *priv;
636 g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
637 g_return_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable));
639 priv = gdk_renderer->priv;
641 if (priv->drawable != drawable)
644 g_object_unref (priv->drawable);
645 priv->drawable = drawable;
647 g_object_ref (priv->drawable);
652 * gdk_pango_renderer_set_gc:
653 * @gdk_renderer: a #GdkPangoRenderer
654 * @gc: (allow-none): the new GC to use for drawing, or %NULL
656 * Sets the GC the renderer draws with. Note that the GC must not be
657 * modified until it is unset by calling the function again with
658 * %NULL for the @gc parameter, since GDK may make internal copies
659 * of the GC which won't be updated to follow changes to the
665 gdk_pango_renderer_set_gc (GdkPangoRenderer *gdk_renderer,
668 GdkPangoRendererPrivate *priv;
670 g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
671 g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
673 priv = gdk_renderer->priv;
675 if (priv->base_gc != gc)
678 g_object_unref (priv->base_gc);
681 g_object_ref (priv->base_gc);
683 priv->gc_changed = TRUE;
689 * gdk_pango_renderer_set_stipple:
690 * @gdk_renderer: a #GdkPangoRenderer
691 * @part: the part to render with the stipple
692 * @stipple: the new stipple value.
694 * Sets the stipple for one render part (foreground, background, underline,
695 * etc.) Note that this is overwritten when iterating through the individual
696 * styled runs of a #PangoLayout or #PangoLayoutLine. This function is thus
697 * only useful when you call low level functions like pango_renderer_draw_glyphs()
698 * directly, or in the 'prepare_run' virtual function of a subclass of
704 gdk_pango_renderer_set_stipple (GdkPangoRenderer *gdk_renderer,
705 PangoRenderPart part,
708 g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
710 if (part > MAX_RENDER_PART) /* Silently ignore unknown parts */
713 if (stipple != gdk_renderer->priv->stipple[part])
715 if (gdk_renderer->priv->stipple[part])
716 g_object_unref (gdk_renderer->priv->stipple[part]);
718 gdk_renderer->priv->stipple[part] = stipple;
720 if (gdk_renderer->priv->stipple[part])
721 g_object_ref (gdk_renderer->priv->stipple[part]);
723 pango_renderer_part_changed (PANGO_RENDERER (gdk_renderer), part);
728 * gdk_pango_renderer_set_override_color:
729 * @gdk_renderer: a #GdkPangoRenderer
730 * @part: the part to render to set the color of
731 * @color: (allow-none): the color to use, or %NULL to unset a previously
732 * set override color.
734 * Sets the color for a particular render part (foreground,
735 * background, underline, etc.), overriding any attributes on the layouts
736 * renderered with this renderer.
741 gdk_pango_renderer_set_override_color (GdkPangoRenderer *gdk_renderer,
742 PangoRenderPart part,
743 const GdkColor *color)
745 GdkPangoRendererPrivate *priv;
747 g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer));
749 priv = gdk_renderer->priv;
751 if (part > MAX_RENDER_PART) /* Silently ignore unknown parts */
756 priv->override_color[part].red = color->red;
757 priv->override_color[part].green = color->green;
758 priv->override_color[part].blue = color->blue;
759 priv->override_color_set[part] = TRUE;
762 priv->override_color_set[part] = FALSE;
765 /* Gets a renderer to draw with, setting the properties of the
766 * renderer and activating it. Note that since we activate the
767 * renderer here, the implicit setting of the matrix that
768 * pango_renderer_draw_layout_[line] normally do when they
769 * activate the renderer is suppressed. */
770 static PangoRenderer *
771 get_renderer (GdkDrawable *drawable,
773 const GdkColor *foreground,
774 const GdkColor *background)
776 GdkScreen *screen = gdk_drawable_get_screen (drawable);
777 PangoRenderer *renderer = gdk_pango_renderer_get_default (screen);
778 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
780 gdk_pango_renderer_set_drawable (gdk_renderer, drawable);
781 gdk_pango_renderer_set_gc (gdk_renderer, gc);
783 gdk_pango_renderer_set_override_color (gdk_renderer,
784 PANGO_RENDER_PART_FOREGROUND,
786 gdk_pango_renderer_set_override_color (gdk_renderer,
787 PANGO_RENDER_PART_UNDERLINE,
789 gdk_pango_renderer_set_override_color (gdk_renderer,
790 PANGO_RENDER_PART_STRIKETHROUGH,
793 gdk_pango_renderer_set_override_color (gdk_renderer,
794 PANGO_RENDER_PART_BACKGROUND,
797 pango_renderer_activate (renderer);
802 /* Cleans up the renderer obtained with get_renderer() */
804 release_renderer (PangoRenderer *renderer)
806 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
808 pango_renderer_deactivate (renderer);
810 gdk_pango_renderer_set_override_color (gdk_renderer,
811 PANGO_RENDER_PART_FOREGROUND,
813 gdk_pango_renderer_set_override_color (gdk_renderer,
814 PANGO_RENDER_PART_UNDERLINE,
816 gdk_pango_renderer_set_override_color (gdk_renderer,
817 PANGO_RENDER_PART_STRIKETHROUGH,
819 gdk_pango_renderer_set_override_color (gdk_renderer,
820 PANGO_RENDER_PART_BACKGROUND,
823 gdk_pango_renderer_set_drawable (gdk_renderer, NULL);
824 gdk_pango_renderer_set_gc (gdk_renderer, NULL);
827 /* GdkPangoAttrStipple */
829 static PangoAttribute *
830 gdk_pango_attr_stipple_copy (const PangoAttribute *attr)
832 const GdkPangoAttrStipple *src = (const GdkPangoAttrStipple*) attr;
834 return gdk_pango_attr_stipple_new (src->stipple);
838 gdk_pango_attr_stipple_destroy (PangoAttribute *attr)
840 GdkPangoAttrStipple *st = (GdkPangoAttrStipple*) attr;
843 g_object_unref (st->stipple);
849 gdk_pango_attr_stipple_compare (const PangoAttribute *attr1,
850 const PangoAttribute *attr2)
852 const GdkPangoAttrStipple *a = (const GdkPangoAttrStipple*) attr1;
853 const GdkPangoAttrStipple *b = (const GdkPangoAttrStipple*) attr2;
855 return a->stipple == b->stipple;
859 * gdk_pango_attr_stipple_new:
860 * @stipple: a bitmap to be set as stipple
862 * Creates a new attribute containing a stipple bitmap to be used when
863 * rendering the text.
865 * Return value: new #PangoAttribute
869 gdk_pango_attr_stipple_new (GdkBitmap *stipple)
871 GdkPangoAttrStipple *result;
873 static PangoAttrClass klass = {
875 gdk_pango_attr_stipple_copy,
876 gdk_pango_attr_stipple_destroy,
877 gdk_pango_attr_stipple_compare
881 klass.type = gdk_pango_attr_stipple_type =
882 pango_attr_type_register ("GdkPangoAttrStipple");
884 result = g_new (GdkPangoAttrStipple, 1);
885 result->attr.klass = &klass;
888 g_object_ref (stipple);
890 result->stipple = stipple;
892 return (PangoAttribute *)result;
895 /* GdkPangoAttrEmbossed */
897 static PangoAttribute *
898 gdk_pango_attr_embossed_copy (const PangoAttribute *attr)
900 const GdkPangoAttrEmbossed *e = (const GdkPangoAttrEmbossed*) attr;
902 return gdk_pango_attr_embossed_new (e->embossed);
906 gdk_pango_attr_embossed_destroy (PangoAttribute *attr)
912 gdk_pango_attr_embossed_compare (const PangoAttribute *attr1,
913 const PangoAttribute *attr2)
915 const GdkPangoAttrEmbossed *e1 = (const GdkPangoAttrEmbossed*) attr1;
916 const GdkPangoAttrEmbossed *e2 = (const GdkPangoAttrEmbossed*) attr2;
918 return e1->embossed == e2->embossed;
922 * gdk_pango_attr_embossed_new:
923 * @embossed: if the region should be embossed
925 * Creates a new attribute flagging a region as embossed or not.
927 * Return value: new #PangoAttribute
931 gdk_pango_attr_embossed_new (gboolean embossed)
933 GdkPangoAttrEmbossed *result;
935 static PangoAttrClass klass = {
937 gdk_pango_attr_embossed_copy,
938 gdk_pango_attr_embossed_destroy,
939 gdk_pango_attr_embossed_compare
943 klass.type = gdk_pango_attr_embossed_type =
944 pango_attr_type_register ("GdkPangoAttrEmbossed");
946 result = g_new (GdkPangoAttrEmbossed, 1);
947 result->attr.klass = &klass;
948 result->embossed = embossed;
950 return (PangoAttribute *)result;
953 /* GdkPangoAttrEmbossColor */
955 static PangoAttribute *
956 gdk_pango_attr_emboss_color_copy (const PangoAttribute *attr)
958 const GdkPangoAttrEmbossColor *old = (const GdkPangoAttrEmbossColor*) attr;
959 GdkPangoAttrEmbossColor *copy;
961 copy = g_new (GdkPangoAttrEmbossColor, 1);
962 copy->attr.klass = old->attr.klass;
963 copy->color = old->color;
965 return (PangoAttribute *) copy;
969 gdk_pango_attr_emboss_color_destroy (PangoAttribute *attr)
975 gdk_pango_attr_emboss_color_compare (const PangoAttribute *attr1,
976 const PangoAttribute *attr2)
978 const GdkPangoAttrEmbossColor *c1 = (const GdkPangoAttrEmbossColor*) attr1;
979 const GdkPangoAttrEmbossColor *c2 = (const GdkPangoAttrEmbossColor*) attr2;
981 return color_equal (&c1->color, &c2->color);
985 * gdk_pango_attr_emboss_color_new:
986 * @color: a GdkColor representing the color to emboss with
988 * Creates a new attribute specifying the color to emboss text with.
990 * Return value: new #PangoAttribute
995 gdk_pango_attr_emboss_color_new (const GdkColor *color)
997 GdkPangoAttrEmbossColor *result;
999 static PangoAttrClass klass = {
1001 gdk_pango_attr_emboss_color_copy,
1002 gdk_pango_attr_emboss_color_destroy,
1003 gdk_pango_attr_emboss_color_compare
1007 klass.type = gdk_pango_attr_emboss_color_type =
1008 pango_attr_type_register ("GdkPangoAttrEmbossColor");
1010 result = g_new (GdkPangoAttrEmbossColor, 1);
1011 result->attr.klass = &klass;
1012 result->color.red = color->red;
1013 result->color.green = color->green;
1014 result->color.blue = color->blue;
1016 return (PangoAttribute *) result;
1019 /* Get a clip region to draw only part of a layout. index_ranges
1020 * contains alternating range starts/stops. The region is the
1021 * region which contains the given ranges, i.e. if you draw with the
1022 * region as clip, only the given ranges are drawn.
1024 static cairo_region_t*
1025 layout_iter_get_line_clip_region (PangoLayoutIter *iter,
1028 const gint *index_ranges,
1031 PangoLayoutLine *line;
1032 cairo_region_t *clip_region;
1033 PangoRectangle logical_rect;
1037 line = pango_layout_iter_get_line_readonly (iter);
1039 clip_region = cairo_region_create ();
1041 pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
1042 baseline = pango_layout_iter_get_baseline (iter);
1045 while (i < n_ranges)
1047 gint *pixel_ranges = NULL;
1048 gint n_pixel_ranges = 0;
1051 /* Note that get_x_ranges returns layout coordinates
1053 if (index_ranges[i*2+1] >= line->start_index &&
1054 index_ranges[i*2] < line->start_index + line->length)
1055 pango_layout_line_get_x_ranges (line,
1057 index_ranges[i*2+1],
1058 &pixel_ranges, &n_pixel_ranges);
1060 for (j = 0; j < n_pixel_ranges; j++)
1065 x_off = PANGO_PIXELS (pixel_ranges[2*j] - logical_rect.x);
1066 y_off = PANGO_PIXELS (baseline - logical_rect.y);
1068 rect.x = x_origin + x_off;
1069 rect.y = y_origin - y_off;
1070 rect.width = PANGO_PIXELS (pixel_ranges[2*j + 1] - logical_rect.x) - x_off;
1071 rect.height = PANGO_PIXELS (baseline - logical_rect.y + logical_rect.height) - y_off;
1073 cairo_region_union_rectangle (clip_region, &rect);
1076 g_free (pixel_ranges);
1083 * gdk_pango_layout_line_get_clip_region:
1084 * @line: a #PangoLayoutLine
1085 * @x_origin: X pixel where you intend to draw the layout line with this clip
1086 * @y_origin: baseline pixel where you intend to draw the layout line with this clip
1087 * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
1088 * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
1090 * Obtains a clip region which contains the areas where the given
1091 * ranges of text would be drawn. @x_origin and @y_origin are the top left
1092 * position of the layout. @index_ranges
1093 * should contain ranges of bytes in the layout's text. The clip
1094 * region will include space to the left or right of the line (to the
1095 * layout bounding box) if you have indexes above or below the indexes
1096 * contained inside the line. This is to draw the selection all the way
1097 * to the side of the layout. However, the clip region is in line coordinates,
1098 * not layout coordinates.
1100 * Note that the regions returned correspond to logical extents of the text
1101 * ranges, not ink extents. So the drawn line may in fact touch areas out of
1102 * the clip region. The clip region is mainly useful for highlightling parts
1103 * of text, such as when text is selected.
1105 * Return value: a clip region containing the given ranges
1108 gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
1111 const gint *index_ranges,
1114 cairo_region_t *clip_region;
1115 PangoLayoutIter *iter;
1117 g_return_val_if_fail (line != NULL, NULL);
1118 g_return_val_if_fail (index_ranges != NULL, NULL);
1120 iter = pango_layout_get_iter (line->layout);
1121 while (pango_layout_iter_get_line_readonly (iter) != line)
1122 pango_layout_iter_next_line (iter);
1124 clip_region = layout_iter_get_line_clip_region(iter, x_origin, y_origin, index_ranges, n_ranges);
1126 pango_layout_iter_free (iter);
1132 * gdk_pango_layout_get_clip_region:
1133 * @layout: a #PangoLayout
1134 * @x_origin: X pixel where you intend to draw the layout with this clip
1135 * @y_origin: Y pixel where you intend to draw the layout with this clip
1136 * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
1137 * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
1139 * Obtains a clip region which contains the areas where the given ranges
1140 * of text would be drawn. @x_origin and @y_origin are the top left point
1141 * to center the layout. @index_ranges should contain
1142 * ranges of bytes in the layout's text.
1144 * Note that the regions returned correspond to logical extents of the text
1145 * ranges, not ink extents. So the drawn layout may in fact touch areas out of
1146 * the clip region. The clip region is mainly useful for highlightling parts
1147 * of text, such as when text is selected.
1149 * Return value: a clip region containing the given ranges
1152 gdk_pango_layout_get_clip_region (PangoLayout *layout,
1155 const gint *index_ranges,
1158 PangoLayoutIter *iter;
1159 cairo_region_t *clip_region;
1161 g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
1162 g_return_val_if_fail (index_ranges != NULL, NULL);
1164 clip_region = cairo_region_create ();
1166 iter = pango_layout_get_iter (layout);
1170 PangoRectangle logical_rect;
1171 cairo_region_t *line_region;
1174 pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
1175 baseline = pango_layout_iter_get_baseline (iter);
1177 line_region = layout_iter_get_line_clip_region(iter,
1178 x_origin + PANGO_PIXELS (logical_rect.x),
1179 y_origin + PANGO_PIXELS (baseline),
1183 cairo_region_union (clip_region, line_region);
1184 cairo_region_destroy (line_region);
1186 while (pango_layout_iter_next_line (iter));
1188 pango_layout_iter_free (iter);
1194 * gdk_pango_context_get:
1196 * Creates a #PangoContext for the default GDK screen.
1198 * The context must be freed when you're finished with it.
1200 * When using GTK+, normally you should use gtk_widget_get_pango_context()
1201 * instead of this function, to get the appropriate context for
1202 * the widget you intend to render text onto.
1204 * The newly created context will have the default font options (see
1205 * #cairo_font_options_t) for the default screen; if these options
1206 * change it will not be updated. Using gtk_widget_get_pango_context()
1207 * is more convenient if you want to keep a context around and track
1208 * changes to the screen's font rendering settings.
1210 * Return value: a new #PangoContext for the default display
1213 gdk_pango_context_get (void)
1215 return gdk_pango_context_get_for_screen (gdk_screen_get_default ());
1219 * gdk_pango_context_get_for_screen:
1220 * @screen: the #GdkScreen for which the context is to be created.
1222 * Creates a #PangoContext for @screen.
1224 * The context must be freed when you're finished with it.
1226 * When using GTK+, normally you should use gtk_widget_get_pango_context()
1227 * instead of this function, to get the appropriate context for
1228 * the widget you intend to render text onto.
1230 * The newly created context will have the default font options
1231 * (see #cairo_font_options_t) for the screen; if these options
1232 * change it will not be updated. Using gtk_widget_get_pango_context()
1233 * is more convenient if you want to keep a context around and track
1234 * changes to the screen's font rendering settings.
1236 * Return value: a new #PangoContext for @screen
1241 gdk_pango_context_get_for_screen (GdkScreen *screen)
1243 PangoFontMap *fontmap;
1244 PangoContext *context;
1245 const cairo_font_options_t *options;
1248 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1250 fontmap = pango_cairo_font_map_get_default ();
1252 context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
1254 options = gdk_screen_get_font_options (screen);
1255 pango_cairo_context_set_font_options (context, options);
1257 dpi = gdk_screen_get_resolution (screen);
1258 pango_cairo_context_set_resolution (context, dpi);