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.
23 #include "gdkprivate.h"
25 #define GDK_INFO_KEY "gdk-info"
27 typedef struct _GdkPangoContextInfo GdkPangoContextInfo;
29 struct _GdkPangoContextInfo
31 GdkColormap *colormap;
34 static PangoAttrType gdk_pango_attr_stipple_type;
35 static PangoAttrType gdk_pango_attr_embossed_type;
37 static void gdk_pango_get_item_properties (PangoItem *item,
38 PangoUnderline *uline,
47 PangoRectangle *ink_rect,
48 PangoRectangle *logical_rect);
51 gdk_pango_context_destroy (GdkPangoContextInfo *info)
53 gdk_colormap_unref (info->colormap);
57 static GdkPangoContextInfo *
58 gdk_pango_context_get_info (PangoContext *context, gboolean create)
60 GdkPangoContextInfo *info =
61 g_object_get_qdata (G_OBJECT (context),
62 g_quark_try_string (GDK_INFO_KEY));
65 info = g_new (GdkPangoContextInfo, 1);
66 info->colormap = NULL;
68 g_object_set_qdata_full (G_OBJECT (context),
69 g_quark_from_static_string (GDK_INFO_KEY),
70 info, (GDestroyNotify)gdk_pango_context_destroy);
77 gdk_pango_get_gc (PangoContext *context,
84 GdkPangoContextInfo *info;
86 g_return_val_if_fail (context != NULL, NULL);
88 info = gdk_pango_context_get_info (context, FALSE);
90 if (info == NULL || info->colormap == NULL)
92 g_warning ("you must set the colormap on a PangoContext before using it to draw a layout");
96 color.red = fg_color->red;
97 color.green = fg_color->green;
98 color.blue = fg_color->blue;
100 result = gdk_gc_new (gdk_parent_root);
101 gdk_gc_copy (result, base_gc);
102 gdk_rgb_find_color (info->colormap, &color);
103 gdk_gc_set_foreground (result, &color);
107 gdk_gc_set_fill (result, GDK_STIPPLED);
108 gdk_gc_set_stipple (result, stipple);
115 gdk_pango_free_gc (PangoContext *context,
122 gdk_pango_context_set_colormap (PangoContext *context,
123 GdkColormap *colormap)
125 GdkPangoContextInfo *info;
127 g_return_if_fail (context != NULL);
129 info = gdk_pango_context_get_info (context, TRUE);
130 g_return_if_fail (info != NULL);
132 if (info->colormap != colormap)
135 gdk_colormap_unref (info->colormap);
137 info->colormap = colormap;
140 gdk_colormap_ref (info->colormap);
145 * gdk_draw_layout_line:
146 * @drawable: the drawable on which to draw the line
147 * @gc: base graphics to use
148 * @x: the x position of start of string (in pixels)
149 * @y: the y position of baseline (in pixels)
150 * @line: a #PangoLayoutLine
152 * Render a #PangoLayoutLine onto an GDK drawable
155 gdk_draw_layout_line (GdkDrawable *drawable,
159 PangoLayoutLine *line)
161 GSList *tmp_list = line->runs;
162 PangoRectangle overall_rect;
163 PangoRectangle logical_rect;
164 PangoRectangle ink_rect;
165 PangoContext *context;
171 g_return_if_fail (drawable != NULL);
172 g_return_if_fail (gc != NULL);
173 g_return_if_fail (line != NULL);
175 context = pango_layout_get_context (line->layout);
177 pango_layout_line_get_extents (line,NULL, &overall_rect);
181 PangoUnderline uline = PANGO_UNDERLINE_NONE;
182 PangoLayoutRun *run = tmp_list->data;
183 PangoColor fg_color, bg_color;
184 gboolean fg_set, bg_set, shape_set;
188 tmp_list = tmp_list->next;
190 gdk_pango_get_item_properties (run->item, &uline,
200 /* we subtract the rise because X coordinates are upside down */
201 risen_y = y - rise / PANGO_SCALE;
205 if (uline == PANGO_UNDERLINE_NONE)
206 pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
207 NULL, &logical_rect);
209 pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
210 &ink_rect, &logical_rect);
215 GdkGC *bg_gc = gdk_pango_get_gc (context, &bg_color, stipple, gc);
217 gdk_draw_rectangle (drawable, bg_gc, TRUE,
218 x + (x_off + logical_rect.x) / PANGO_SCALE,
219 risen_y + overall_rect.y / PANGO_SCALE,
220 logical_rect.width / PANGO_SCALE,
221 overall_rect.height / PANGO_SCALE);
224 gdk_gc_set_fill (bg_gc, GDK_SOLID);
226 gdk_pango_free_gc (context, bg_gc);
229 if (fg_set || stipple)
230 fg_gc = gdk_pango_get_gc (context, &fg_color, stipple, gc);
238 gx = x + x_off / PANGO_SCALE;
243 PangoColor color = { 65535, 65535, 65535 };
244 GdkGC *white_gc = gdk_pango_get_gc (context, &color, stipple, fg_gc);
245 gdk_draw_glyphs (drawable, white_gc, run->item->analysis.font,
249 gdk_pango_free_gc (context, white_gc);
252 gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font,
259 case PANGO_UNDERLINE_NONE:
261 case PANGO_UNDERLINE_DOUBLE:
262 gdk_draw_line (drawable, fg_gc,
263 x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
265 x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
268 case PANGO_UNDERLINE_SINGLE:
269 gdk_draw_line (drawable, fg_gc,
270 x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
272 x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
275 case PANGO_UNDERLINE_LOW:
276 gdk_draw_line (drawable, fg_gc,
277 x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
278 risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1,
279 x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
280 risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1);
285 gdk_pango_free_gc (context, fg_gc);
287 x_off += logical_rect.width;
293 * @drawable: the drawable on which to draw string
294 * @gc: base graphics context to use
295 * @x: the X position of the left of the layout (in pixels)
296 * @y: the Y position of the top of the layout (in pixels)
297 * @layout: a #PangoLayout
299 * Render a #PangoLayout onto a GDK drawable
302 gdk_draw_layout (GdkDrawable *drawable,
308 PangoLayoutIter *iter;
310 g_return_if_fail (drawable != NULL);
311 g_return_if_fail (gc != NULL);
312 g_return_if_fail (layout != NULL);
314 iter = pango_layout_get_iter (layout);
318 PangoRectangle logical_rect;
319 PangoLayoutLine *line;
322 line = pango_layout_iter_get_line (iter);
324 pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
325 baseline = pango_layout_iter_get_baseline (iter);
327 gdk_draw_layout_line (drawable, gc,
328 x + logical_rect.x / PANGO_SCALE,
329 y + baseline / PANGO_SCALE,
332 while (pango_layout_iter_next_line (iter));
334 pango_layout_iter_free (iter);
338 gdk_pango_get_item_properties (PangoItem *item,
339 PangoUnderline *uline,
341 PangoColor *fg_color,
343 PangoColor *bg_color,
348 PangoRectangle *ink_rect,
349 PangoRectangle *logical_rect)
351 GSList *tmp_list = item->extra_attrs;
373 PangoAttribute *attr = tmp_list->data;
375 switch (attr->klass->type)
377 case PANGO_ATTR_UNDERLINE:
379 *uline = ((PangoAttrInt *)attr)->value;
382 case PANGO_ATTR_FOREGROUND:
384 *fg_color = ((PangoAttrColor *)attr)->color;
390 case PANGO_ATTR_BACKGROUND:
392 *bg_color = ((PangoAttrColor *)attr)->color;
398 case PANGO_ATTR_SHAPE:
402 *logical_rect = ((PangoAttrShape *)attr)->logical_rect;
404 *ink_rect = ((PangoAttrShape *)attr)->ink_rect;
407 case PANGO_ATTR_RISE:
409 *rise = ((PangoAttrInt *)attr)->value;
413 /* stipple_type and embossed_type aren't necessarily
414 * initialized, but they are 0, which is an
415 * invalid type so won't occur.
417 if (stipple && attr->klass->type == gdk_pango_attr_stipple_type)
419 *stipple = ((GdkPangoAttrStipple*)attr)->stipple;
421 else if (embossed && attr->klass->type == gdk_pango_attr_embossed_type)
423 *embossed = ((GdkPangoAttrEmbossed*)attr);
427 tmp_list = tmp_list->next;
432 static PangoAttribute *
433 gdk_pango_attr_stipple_copy (const PangoAttribute *attr)
435 const GdkPangoAttrStipple *src = (const GdkPangoAttrStipple*) attr;
437 return gdk_pango_attr_stipple_new (src->stipple);
441 gdk_pango_attr_stipple_destroy (PangoAttribute *attr)
443 GdkPangoAttrStipple *st = (GdkPangoAttrStipple*) attr;
446 g_object_unref (G_OBJECT (st->stipple));
452 gdk_pango_attr_stipple_compare (const PangoAttribute *attr1,
453 const PangoAttribute *attr2)
455 const GdkPangoAttrStipple *a = (const GdkPangoAttrStipple*) attr1;
456 const GdkPangoAttrStipple *b = (const GdkPangoAttrStipple*) attr2;
458 return a->stipple == b->stipple;
462 * gdk_pango_attr_stipple_new:
463 * @stipple: a bitmap to be set as stipple
465 * Creates a new attribute containing a stipple bitmap to be used when
466 * rendering the text.
468 * Return value: new #PangoAttribute
472 gdk_pango_attr_stipple_new (GdkBitmap *stipple)
474 GdkPangoAttrStipple *result;
476 static PangoAttrClass klass = {
478 gdk_pango_attr_stipple_copy,
479 gdk_pango_attr_stipple_destroy,
480 gdk_pango_attr_stipple_compare
484 klass.type = gdk_pango_attr_stipple_type =
485 pango_attr_type_register ("GdkPangoAttrStipple");
487 result = g_new (GdkPangoAttrStipple, 1);
488 result->attr.klass = &klass;
491 g_object_ref (stipple);
493 result->stipple = stipple;
495 return (PangoAttribute *)result;
498 static PangoAttribute *
499 gdk_pango_attr_embossed_copy (const PangoAttribute *attr)
501 const GdkPangoAttrEmbossed *e = (const GdkPangoAttrEmbossed*) attr;
503 return gdk_pango_attr_embossed_new (e->embossed);
507 gdk_pango_attr_embossed_destroy (PangoAttribute *attr)
513 gdk_pango_attr_embossed_compare (const PangoAttribute *attr1,
514 const PangoAttribute *attr2)
516 const GdkPangoAttrEmbossed *e1 = (const GdkPangoAttrEmbossed*) attr1;
517 const GdkPangoAttrEmbossed *e2 = (const GdkPangoAttrEmbossed*) attr2;
519 return e1->embossed == e2->embossed;
523 * gdk_pango_attr_embossed_new:
524 * @embossed: a bitmap to be set as embossed
526 * Creates a new attribute containing a embossed bitmap to be used when
527 * rendering the text.
529 * Return value: new #PangoAttribute
533 gdk_pango_attr_embossed_new (gboolean embossed)
535 GdkPangoAttrEmbossed *result;
537 static PangoAttrClass klass = {
539 gdk_pango_attr_embossed_copy,
540 gdk_pango_attr_embossed_destroy,
541 gdk_pango_attr_embossed_compare
545 klass.type = gdk_pango_attr_embossed_type =
546 pango_attr_type_register ("GdkPangoAttrEmbossed");
548 result = g_new (GdkPangoAttrEmbossed, 1);
549 result->attr.klass = &klass;
550 result->embossed = embossed;
552 return (PangoAttribute *)result;