1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
7 * This file is part of the Gnome Library.
9 * The Gnome Library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * The Gnome Library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with the Gnome Library; see the file COPYING.LIB. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
27 /* Text item type for GnomeCanvas widget
29 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
30 * widget. Tk is copyrighted by the Regents of the University of California,
31 * Sun Microsystems, and other parties.
34 * Author: Federico Mena <federico@nuclecu.unam.mx>
35 * Port to Pango co-done by Gerg� �rdi <cactus@cactus.rulez.org>
41 #include "gnome-canvas-text.h"
42 #include <pango/pangoft2.h>
44 #include "libart_lgpl/art_affine.h"
45 #include "libart_lgpl/art_rgb_a_affine.h"
46 #include "libart_lgpl/art_rgb.h"
47 #include "libart_lgpl/art_rgb_bitmap_affine.h"
48 #include "gnome-canvas-util.h"
49 #include "gnome-canvas-i18n.h"
53 /* Object argument IDs */
68 PROP_FAMILY, PROP_FAMILY_SET,
72 PROP_STYLE, PROP_STYLE_SET,
73 PROP_VARIANT, PROP_VARIANT_SET,
74 PROP_WEIGHT, PROP_WEIGHT_SET,
75 PROP_STRETCH, PROP_STRETCH_SET,
76 PROP_SIZE, PROP_SIZE_SET,
78 PROP_STRIKETHROUGH, PROP_STRIKETHROUGH_SET,
79 PROP_UNDERLINE, PROP_UNDERLINE_SET,
80 PROP_RISE, PROP_RISE_SET,
81 PROP_SCALE, PROP_SCALE_SET,
98 /* Rendered size accessors */
103 struct _GnomeCanvasTextPrivate {
104 guint render_dirty : 1;
109 static void gnome_canvas_text_class_init (GnomeCanvasTextClass *class);
110 static void gnome_canvas_text_init (GnomeCanvasText *text);
111 static void gnome_canvas_text_destroy (GtkObject *object);
112 static void gnome_canvas_text_set_property (GObject *object,
116 static void gnome_canvas_text_get_property (GObject *object,
121 static void gnome_canvas_text_update (GnomeCanvasItem *item, double *affine,
122 ArtSVP *clip_path, int flags);
123 static void gnome_canvas_text_realize (GnomeCanvasItem *item);
124 static void gnome_canvas_text_unrealize (GnomeCanvasItem *item);
125 static void gnome_canvas_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
126 int x, int y, int width, int height);
127 static double gnome_canvas_text_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
128 GnomeCanvasItem **actual_item);
129 static void gnome_canvas_text_bounds (GnomeCanvasItem *item,
130 double *x1, double *y1, double *x2, double *y2);
131 static void gnome_canvas_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
133 static void gnome_canvas_text_set_markup (GnomeCanvasText *textitem,
134 const gchar *markup);
136 static void gnome_canvas_text_set_font_desc (GnomeCanvasText *textitem,
137 PangoFontDescription *font_desc);
139 static void gnome_canvas_text_apply_font_desc (GnomeCanvasText *textitem);
140 static void gnome_canvas_text_apply_attributes (GnomeCanvasText *textitem);
142 static void add_attr (PangoAttrList *attr_list,
143 PangoAttribute *attr);
145 static GnomeCanvasItemClass *parent_class;
150 * gnome_canvas_text_get_type:
153 * Registers the &GnomeCanvasText class if necessary, and returns the type ID
156 * Return value: The type ID of the &GnomeCanvasText class.
159 gnome_canvas_text_get_type (void)
161 static GType text_type;
164 const GTypeInfo object_info = {
165 sizeof (GnomeCanvasTextClass),
166 (GBaseInitFunc) NULL,
167 (GBaseFinalizeFunc) NULL,
168 (GClassInitFunc) gnome_canvas_text_class_init,
169 (GClassFinalizeFunc) NULL,
170 NULL, /* class_data */
171 sizeof (GnomeCanvasText),
173 (GInstanceInitFunc) gnome_canvas_text_init,
174 NULL /* value_table */
177 text_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasText",
184 /* Class initialization function for the text item */
186 gnome_canvas_text_class_init (GnomeCanvasTextClass *class)
188 GObjectClass *gobject_class;
189 GtkObjectClass *object_class;
190 GnomeCanvasItemClass *item_class;
192 gobject_class = (GObjectClass *) class;
193 object_class = (GtkObjectClass *) class;
194 item_class = (GnomeCanvasItemClass *) class;
196 parent_class = g_type_class_peek_parent (class);
198 gobject_class->set_property = gnome_canvas_text_set_property;
199 gobject_class->get_property = gnome_canvas_text_get_property;
202 g_object_class_install_property
205 g_param_spec_string ("text",
209 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
211 g_object_class_install_property
214 g_param_spec_string ("markup",
216 _("Marked up text to render"),
218 (G_PARAM_WRITABLE)));
221 g_object_class_install_property
224 g_param_spec_double ("x", NULL, NULL,
225 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
226 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
228 g_object_class_install_property
231 g_param_spec_double ("y", NULL, NULL,
232 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
233 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
237 g_object_class_install_property
240 g_param_spec_string ("font",
242 _("Font description as a string"),
244 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
246 g_object_class_install_property
249 g_param_spec_boxed ("font_desc",
250 _("Font description"),
251 _("Font description as a PangoFontDescription struct"),
252 PANGO_TYPE_FONT_DESCRIPTION,
253 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
255 g_object_class_install_property
258 g_param_spec_string ("family",
260 _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
262 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
265 g_object_class_install_property
268 g_param_spec_boxed ("attributes", NULL, NULL,
269 PANGO_TYPE_ATTR_LIST,
270 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
272 g_object_class_install_property
275 g_param_spec_enum ("style",
280 G_PARAM_READABLE | G_PARAM_WRITABLE));
282 g_object_class_install_property
285 g_param_spec_enum ("variant",
289 PANGO_VARIANT_NORMAL,
290 G_PARAM_READABLE | G_PARAM_WRITABLE));
292 g_object_class_install_property
295 g_param_spec_int ("weight",
301 G_PARAM_READABLE | G_PARAM_WRITABLE));
304 g_object_class_install_property
307 g_param_spec_enum ("stretch",
311 PANGO_STRETCH_NORMAL,
312 G_PARAM_READABLE | G_PARAM_WRITABLE));
314 g_object_class_install_property
317 g_param_spec_int ("size",
319 _("Font size (as a multiple of PANGO_SCALE, eg. 12*PANGO_SCALE for a 12pt font size)"),
323 G_PARAM_READABLE | G_PARAM_WRITABLE));
325 g_object_class_install_property
328 g_param_spec_double ("size_points",
330 _("Font size in points (eg. 12 for a 12pt font size)"),
334 G_PARAM_READABLE | G_PARAM_WRITABLE));
336 g_object_class_install_property
339 g_param_spec_int ("rise",
341 _("Offset of text above the baseline (below the baseline if rise is negative)"),
345 G_PARAM_READABLE | G_PARAM_WRITABLE));
347 g_object_class_install_property
350 g_param_spec_boolean ("strikethrough",
352 _("Whether to strike through the text"),
354 G_PARAM_READABLE | G_PARAM_WRITABLE));
356 g_object_class_install_property
359 g_param_spec_enum ("underline",
361 _("Style of underline for this text"),
362 PANGO_TYPE_UNDERLINE,
363 PANGO_UNDERLINE_NONE,
364 G_PARAM_READABLE | G_PARAM_WRITABLE));
366 g_object_class_install_property
369 g_param_spec_double ("scale",
371 _("Size of font, relative to default size"),
375 G_PARAM_READABLE | G_PARAM_WRITABLE));
377 g_object_class_install_property
380 g_param_spec_enum ("anchor", NULL, NULL,
381 GTK_TYPE_ANCHOR_TYPE,
383 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
384 g_object_class_install_property
387 g_param_spec_enum ("justification", NULL, NULL,
388 GTK_TYPE_JUSTIFICATION,
390 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
391 g_object_class_install_property
394 g_param_spec_double ("clip_width", NULL, NULL,
395 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
396 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
397 g_object_class_install_property
400 g_param_spec_double ("clip_height", NULL, NULL,
401 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
402 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
403 g_object_class_install_property
406 g_param_spec_boolean ("clip", NULL, NULL,
408 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
409 g_object_class_install_property
412 g_param_spec_double ("x_offset", NULL, NULL,
413 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
414 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
415 g_object_class_install_property
418 g_param_spec_double ("y_offset", NULL, NULL,
419 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
420 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
421 g_object_class_install_property
424 g_param_spec_string ("fill_color",
426 _("Text color, as string"),
428 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
429 g_object_class_install_property
432 g_param_spec_boxed ("fill_color_gdk",
434 _("Text color, as a GdkColor"),
436 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
437 g_object_class_install_property
439 PROP_FILL_COLOR_RGBA,
440 g_param_spec_uint ("fill_color_rgba",
442 _("Text color, as an R/G/B/A combined integer"),
444 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
445 g_object_class_install_property
448 g_param_spec_object ("fill_stipple", NULL, NULL,
450 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
451 g_object_class_install_property
454 g_param_spec_double ("text_width",
456 _("Width of the rendered text"),
457 0.0, G_MAXDOUBLE, 0.0,
459 g_object_class_install_property
462 g_param_spec_double ("text_height",
464 _("Height of the rendered text"),
465 0.0, G_MAXDOUBLE, 0.0,
468 /* Style props are set (explicitly applied) or not */
469 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))
471 ADD_SET_PROP ("family_set", PROP_FAMILY_SET,
472 _("Font family set"),
473 _("Whether this tag affects the font family"));
475 ADD_SET_PROP ("style_set", PROP_STYLE_SET,
477 _("Whether this tag affects the font style"));
479 ADD_SET_PROP ("variant_set", PROP_VARIANT_SET,
480 _("Font variant set"),
481 _("Whether this tag affects the font variant"));
483 ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET,
484 _("Font weight set"),
485 _("Whether this tag affects the font weight"));
487 ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET,
488 _("Font stretch set"),
489 _("Whether this tag affects the font stretch"));
491 ADD_SET_PROP ("size_set", PROP_SIZE_SET,
493 _("Whether this tag affects the font size"));
495 ADD_SET_PROP ("rise_set", PROP_RISE_SET,
497 _("Whether this tag affects the rise"));
499 ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET,
500 _("Strikethrough set"),
501 _("Whether this tag affects strikethrough"));
503 ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET,
505 _("Whether this tag affects underlining"));
507 ADD_SET_PROP ("scale_set", PROP_SCALE_SET,
509 _("Whether this tag affects font scaling"));
512 object_class->destroy = gnome_canvas_text_destroy;
514 item_class->update = gnome_canvas_text_update;
515 item_class->realize = gnome_canvas_text_realize;
516 item_class->unrealize = gnome_canvas_text_unrealize;
517 item_class->draw = gnome_canvas_text_draw;
518 item_class->point = gnome_canvas_text_point;
519 item_class->bounds = gnome_canvas_text_bounds;
520 item_class->render = gnome_canvas_text_render;
523 /* Object initialization function for the text item */
525 gnome_canvas_text_init (GnomeCanvasText *text)
529 text->anchor = GTK_ANCHOR_CENTER;
530 text->justification = GTK_JUSTIFY_LEFT;
531 text->clip_width = 0.0;
532 text->clip_height = 0.0;
537 text->font_desc = NULL;
539 text->underline = PANGO_UNDERLINE_NONE;
540 text->strikethrough = FALSE;
543 text->underline_set = FALSE;
544 text->strike_set = FALSE;
545 text->rise_set = FALSE;
547 text->priv = g_new (GnomeCanvasTextPrivate, 1);
548 text->priv->bitmap.buffer = NULL;
549 text->priv->render_dirty = 1;
552 /* Destroy handler for the text item */
554 gnome_canvas_text_destroy (GtkObject *object)
556 GnomeCanvasText *text;
558 g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
560 text = GNOME_CANVAS_TEXT (object);
562 /* remember, destroy can be run multiple times! */
568 g_object_unref (G_OBJECT (text->layout));
571 if (text->font_desc) {
572 pango_font_description_free (text->font_desc);
573 text->font_desc = NULL;
577 pango_attr_list_unref (text->attr_list);
578 text->attr_list = NULL;
581 g_object_unref (text->stipple);
582 text->stipple = NULL;
584 if (text->priv && text->priv->bitmap.buffer) {
585 g_free (text->priv->bitmap.buffer);
590 if (GTK_OBJECT_CLASS (parent_class)->destroy)
591 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
595 get_bounds (GnomeCanvasText *text, double *px1, double *py1, double *px2, double *py2)
597 GnomeCanvasItem *item;
600 item = GNOME_CANVAS_ITEM (text);
602 /* Get canvas pixel coordinates for text position */
607 gnome_canvas_item_i2w (item, &wx, &wy);
608 gnome_canvas_w2c (item->canvas, wx + text->xofs, wy + text->yofs, &text->cx, &text->cy);
610 /* Get canvas pixel coordinates for clip rectangle position */
612 gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy);
613 text->clip_cwidth = text->clip_width * item->canvas->pixels_per_unit;
614 text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit;
618 switch (text->anchor) {
625 case GTK_ANCHOR_CENTER:
627 text->cx -= text->max_width / 2;
628 text->clip_cx -= text->clip_cwidth / 2;
634 text->cx -= text->max_width;
635 text->clip_cx -= text->clip_cwidth;
642 switch (text->anchor) {
649 case GTK_ANCHOR_CENTER:
651 text->cy -= text->height / 2;
652 text->clip_cy -= text->clip_cheight / 2;
658 text->cy -= text->height;
659 text->clip_cy -= text->clip_cheight;
669 *px1 = text->clip_cx;
670 *py1 = text->clip_cy;
671 *px2 = text->clip_cx + text->clip_cwidth;
672 *py2 = text->clip_cy + text->clip_cheight;
676 *px2 = text->cx + text->max_width;
677 *py2 = text->cy + text->height;
681 /* Convenience function to set the text's GC's foreground color */
683 set_text_gc_foreground (GnomeCanvasText *text)
690 c.pixel = text->pixel;
691 gdk_gc_set_foreground (text->gc, &c);
694 /* Sets the stipple pattern for the text */
696 set_stipple (GnomeCanvasText *text, GdkBitmap *stipple, int reconfigure)
698 if (text->stipple && !reconfigure)
699 g_object_unref (text->stipple);
701 text->stipple = stipple;
702 if (stipple && !reconfigure)
703 g_object_ref (stipple);
707 gdk_gc_set_stipple (text->gc, stipple);
708 gdk_gc_set_fill (text->gc, GDK_STIPPLED);
710 gdk_gc_set_fill (text->gc, GDK_SOLID);
715 get_property_font_set_mask (guint prop_id)
719 case PROP_FAMILY_SET:
720 return PANGO_FONT_MASK_FAMILY;
722 return PANGO_FONT_MASK_STYLE;
723 case PROP_VARIANT_SET:
724 return PANGO_FONT_MASK_VARIANT;
725 case PROP_WEIGHT_SET:
726 return PANGO_FONT_MASK_WEIGHT;
727 case PROP_STRETCH_SET:
728 return PANGO_FONT_MASK_STRETCH;
730 return PANGO_FONT_MASK_SIZE;
737 ensure_font (GnomeCanvasText *text)
739 if (!text->font_desc)
740 text->font_desc = pango_font_description_new ();
743 /* Set_arg handler for the text item */
745 gnome_canvas_text_set_property (GObject *object,
750 GnomeCanvasItem *item;
751 GnomeCanvasText *text;
752 GdkColor color = { 0, 0, 0, 0, };
754 gboolean color_changed;
756 PangoAlignment align;
758 g_return_if_fail (object != NULL);
759 g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
761 item = GNOME_CANVAS_ITEM (object);
762 text = GNOME_CANVAS_TEXT (object);
764 color_changed = FALSE;
770 PangoContext *gtk_context, *context;
771 gtk_context = gtk_widget_get_pango_context (GTK_WIDGET (item->canvas));
773 if (item->canvas->aa) {
774 PangoLanguage *language;
779 pixels = gdk_screen_width ();
780 mm = gdk_screen_width_mm ();
781 dpi_x = (((double) pixels * 25.4) / (double) mm);
783 pixels = gdk_screen_height ();
784 mm = gdk_screen_height_mm ();
785 dpi_y = (((double) pixels * 25.4) / (double) mm);
787 context = pango_ft2_get_context (dpi_x, dpi_y);
788 language = pango_context_get_language (gtk_context);
789 pango_context_set_language (context, language);
790 pango_context_set_base_dir (context,
791 pango_context_get_base_dir (gtk_context));
792 pango_context_set_font_description (context,
793 pango_context_get_font_description (gtk_context));
796 context = gtk_context;
799 text->layout = pango_layout_new (context);
801 if (item->canvas->aa)
802 g_object_unref (G_OBJECT (context));
809 text->text = g_value_dup_string (value);
810 pango_layout_set_text (text->layout, text->text, -1);
812 text->priv->render_dirty = 1;
816 gnome_canvas_text_set_markup (text,
817 g_value_get_string (value));
818 text->priv->render_dirty = 1;
822 text->x = g_value_get_double (value);
826 text->y = g_value_get_double (value);
830 const char *font_name;
831 PangoFontDescription *font_desc;
833 font_name = g_value_get_string (value);
835 font_desc = pango_font_description_from_string (font_name);
839 gnome_canvas_text_set_font_desc (text, font_desc);
841 pango_font_description_free (font_desc);
847 gnome_canvas_text_set_font_desc (text, g_value_peek_pointer (value));
856 case PROP_SIZE_POINTS:
861 pango_font_description_set_family (text->font_desc,
862 g_value_get_string (value));
865 pango_font_description_set_style (text->font_desc,
866 g_value_get_enum (value));
869 pango_font_description_set_variant (text->font_desc,
870 g_value_get_enum (value));
873 pango_font_description_set_weight (text->font_desc,
874 g_value_get_int (value));
877 pango_font_description_set_stretch (text->font_desc,
878 g_value_get_enum (value));
881 /* FIXME: This is bogus! It should be pixels, not points/PANGO_SCALE! */
882 pango_font_description_set_size (text->font_desc,
883 g_value_get_int (value));
885 case PROP_SIZE_POINTS:
886 pango_font_description_set_size (text->font_desc,
887 g_value_get_double (value) * PANGO_SCALE);
891 gnome_canvas_text_apply_font_desc (text);
892 text->priv->render_dirty = 1;
895 case PROP_FAMILY_SET:
897 case PROP_VARIANT_SET:
898 case PROP_WEIGHT_SET:
899 case PROP_STRETCH_SET:
901 if (!g_value_get_boolean (value) && text->font_desc)
902 pango_font_description_unset_fields (text->font_desc,
903 get_property_font_set_mask (param_id));
907 text->scale = g_value_get_double (value);
908 text->scale_set = TRUE;
910 gnome_canvas_text_apply_font_desc (text);
911 text->priv->render_dirty = 1;
915 text->scale_set = g_value_get_boolean (value);
917 gnome_canvas_text_apply_font_desc (text);
918 text->priv->render_dirty = 1;
922 text->underline = g_value_get_enum (value);
923 text->underline_set = TRUE;
925 gnome_canvas_text_apply_attributes (text);
926 text->priv->render_dirty = 1;
929 case PROP_UNDERLINE_SET:
930 text->underline_set = g_value_get_boolean (value);
932 gnome_canvas_text_apply_attributes (text);
933 text->priv->render_dirty = 1;
936 case PROP_STRIKETHROUGH:
937 text->strikethrough = g_value_get_boolean (value);
938 text->strike_set = TRUE;
940 gnome_canvas_text_apply_attributes (text);
941 text->priv->render_dirty = 1;
944 case PROP_STRIKETHROUGH_SET:
945 text->strike_set = g_value_get_boolean (value);
947 gnome_canvas_text_apply_attributes (text);
948 text->priv->render_dirty = 1;
952 text->rise = g_value_get_int (value);
953 text->rise_set = TRUE;
955 gnome_canvas_text_apply_attributes (text);
956 text->priv->render_dirty = 1;
960 text->rise_set = TRUE;
962 gnome_canvas_text_apply_attributes (text);
963 text->priv->render_dirty = 1;
966 case PROP_ATTRIBUTES:
968 pango_attr_list_unref (text->attr_list);
970 text->attr_list = g_value_peek_pointer (value);
971 pango_attr_list_ref (text->attr_list);
973 gnome_canvas_text_apply_attributes (text);
974 text->priv->render_dirty = 1;
978 text->anchor = g_value_get_enum (value);
981 case PROP_JUSTIFICATION:
982 text->justification = g_value_get_enum (value);
984 switch (text->justification) {
985 case GTK_JUSTIFY_LEFT:
986 align = PANGO_ALIGN_LEFT;
988 case GTK_JUSTIFY_CENTER:
989 align = PANGO_ALIGN_CENTER;
991 case GTK_JUSTIFY_RIGHT:
992 align = PANGO_ALIGN_RIGHT;
995 /* GTK_JUSTIFY_FILL isn't supported yet. */
996 align = PANGO_ALIGN_LEFT;
999 pango_layout_set_alignment (text->layout, align);
1000 text->priv->render_dirty = 1;
1003 case PROP_CLIP_WIDTH:
1004 text->clip_width = fabs (g_value_get_double (value));
1005 text->priv->render_dirty = 1;
1008 case PROP_CLIP_HEIGHT:
1009 text->clip_height = fabs (g_value_get_double (value));
1010 text->priv->render_dirty = 1;
1014 text->clip = g_value_get_boolean (value);
1015 text->priv->render_dirty = 1;
1019 text->xofs = g_value_get_double (value);
1023 text->yofs = g_value_get_double (value);
1026 case PROP_FILL_COLOR: {
1027 const char *color_name;
1029 color_name = g_value_get_string (value);
1031 gdk_color_parse (color_name, &color);
1033 text->rgba = ((color.red & 0xff00) << 16 |
1034 (color.green & 0xff00) << 8 |
1035 (color.blue & 0xff00) |
1037 color_changed = TRUE;
1039 text->priv->render_dirty = 1;
1043 case PROP_FILL_COLOR_GDK:
1044 pcolor = g_value_get_boxed (value);
1046 GdkColormap *colormap;
1049 colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas));
1050 gdk_rgb_find_color (colormap, &color);
1054 text->rgba = ((color.red & 0xff00) << 16 |
1055 (color.green & 0xff00) << 8|
1056 (color.blue & 0xff00) |
1058 color_changed = TRUE;
1061 case PROP_FILL_COLOR_RGBA:
1062 text->rgba = g_value_get_uint (value);
1063 color_changed = TRUE;
1064 text->priv->render_dirty = 1;
1067 case PROP_FILL_STIPPLE:
1068 set_stipple (text, (GdkBitmap *)g_value_get_object (value), FALSE);
1072 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1076 if (color_changed) {
1078 text->pixel = color.pixel;
1080 text->pixel = gnome_canvas_get_color_pixel (item->canvas, text->rgba);
1082 if (!item->canvas->aa)
1083 set_text_gc_foreground (text);
1086 /* Calculate text dimensions */
1089 pango_layout_get_pixel_size (text->layout,
1093 text->max_width = 0;
1097 gnome_canvas_item_request_update (item);
1100 /* Get_arg handler for the text item */
1102 gnome_canvas_text_get_property (GObject *object,
1107 GnomeCanvasText *text;
1109 g_return_if_fail (object != NULL);
1110 g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
1112 text = GNOME_CANVAS_TEXT (object);
1116 g_value_set_string (value, text->text);
1120 g_value_set_double (value, text->x);
1124 g_value_set_double (value, text->y);
1128 case PROP_FONT_DESC:
1135 case PROP_SIZE_POINTS:
1141 /* FIXME GValue imposes a totally gratuitous string copy
1142 * here, we could just hand off string ownership
1146 str = pango_font_description_to_string (text->font_desc);
1147 g_value_set_string (value, str);
1153 case PROP_FONT_DESC:
1154 g_value_set_boxed (value, text->font_desc);
1158 g_value_set_string (value, pango_font_description_get_family (text->font_desc));
1162 g_value_set_enum (value, pango_font_description_get_style (text->font_desc));
1166 g_value_set_enum (value, pango_font_description_get_variant (text->font_desc));
1170 g_value_set_int (value, pango_font_description_get_weight (text->font_desc));
1174 g_value_set_enum (value, pango_font_description_get_stretch (text->font_desc));
1178 g_value_set_int (value, pango_font_description_get_size (text->font_desc));
1181 case PROP_SIZE_POINTS:
1182 g_value_set_double (value, ((double)pango_font_description_get_size (text->font_desc)) / (double)PANGO_SCALE);
1187 case PROP_FAMILY_SET:
1188 case PROP_STYLE_SET:
1189 case PROP_VARIANT_SET:
1190 case PROP_WEIGHT_SET:
1191 case PROP_STRETCH_SET:
1194 PangoFontMask set_mask = text->font_desc ? pango_font_description_get_set_fields (text->font_desc) : 0;
1195 PangoFontMask test_mask = get_property_font_set_mask (param_id);
1196 g_value_set_boolean (value, (set_mask & test_mask) != 0);
1202 g_value_set_double (value, text->scale);
1204 case PROP_SCALE_SET:
1205 g_value_set_boolean (value, text->scale_set);
1208 case PROP_UNDERLINE:
1209 g_value_set_enum (value, text->underline);
1211 case PROP_UNDERLINE_SET:
1212 g_value_set_boolean (value, text->underline_set);
1215 case PROP_STRIKETHROUGH:
1216 g_value_set_boolean (value, text->strikethrough);
1218 case PROP_STRIKETHROUGH_SET:
1219 g_value_set_boolean (value, text->strike_set);
1223 g_value_set_int (value, text->rise);
1226 g_value_set_boolean (value, text->rise_set);
1229 case PROP_ATTRIBUTES:
1230 g_value_set_boxed (value, text->attr_list);
1234 g_value_set_enum (value, text->anchor);
1237 case PROP_JUSTIFICATION:
1238 g_value_set_enum (value, text->justification);
1241 case PROP_CLIP_WIDTH:
1242 g_value_set_double (value, text->clip_width);
1245 case PROP_CLIP_HEIGHT:
1246 g_value_set_double (value, text->clip_height);
1250 g_value_set_boolean (value, text->clip);
1254 g_value_set_double (value, text->xofs);
1258 g_value_set_double (value, text->yofs);
1261 case PROP_FILL_COLOR:
1262 g_value_take_string (value,
1263 g_strdup_printf ("#%02x%02x%02x",
1265 (text->rgba >> 16) & 0xff,
1266 (text->rgba >> 8) & 0xff));
1269 case PROP_FILL_COLOR_GDK: {
1270 GnomeCanvas *canvas = GNOME_CANVAS_ITEM (text)->canvas;
1271 GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (canvas));
1274 gdk_colormap_query_color (colormap, text->pixel, &color);
1275 g_value_set_boxed (value, &color);
1278 case PROP_FILL_COLOR_RGBA:
1279 g_value_set_uint (value, text->rgba);
1282 case PROP_FILL_STIPPLE:
1283 g_value_set_object (value, text->stipple);
1286 case PROP_TEXT_WIDTH:
1287 g_value_set_double (value, text->max_width / text->item.canvas->pixels_per_unit);
1290 case PROP_TEXT_HEIGHT:
1291 g_value_set_double (value, text->height / text->item.canvas->pixels_per_unit);
1295 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1302 gnome_canvas_text_apply_font_desc (GnomeCanvasText *text)
1304 PangoFontDescription *font_desc =
1305 pango_font_description_copy (
1306 GTK_WIDGET (GNOME_CANVAS_ITEM (text)->canvas)->style->font_desc);
1308 if (text->font_desc)
1309 pango_font_description_merge (font_desc, text->font_desc, TRUE);
1311 pango_layout_set_font_description (text->layout, font_desc);
1312 pango_font_description_free (font_desc);
1316 add_attr (PangoAttrList *attr_list,
1317 PangoAttribute *attr)
1319 attr->start_index = 0;
1320 attr->end_index = G_MAXINT;
1322 pango_attr_list_insert (attr_list, attr);
1327 gnome_canvas_text_apply_attributes (GnomeCanvasText *text)
1329 PangoAttrList *attr_list;
1331 if (text->attr_list)
1332 attr_list = pango_attr_list_copy (text->attr_list);
1334 attr_list = pango_attr_list_new ();
1336 if (text->underline_set)
1337 add_attr (attr_list, pango_attr_underline_new (text->underline));
1338 if (text->strike_set)
1339 add_attr (attr_list, pango_attr_strikethrough_new (text->strikethrough));
1341 add_attr (attr_list, pango_attr_rise_new (text->rise));
1343 pango_layout_set_attributes (text->layout, attr_list);
1344 pango_attr_list_unref (attr_list);
1348 gnome_canvas_text_set_font_desc (GnomeCanvasText *text,
1349 PangoFontDescription *font_desc)
1351 if (text->font_desc)
1352 pango_font_description_free (text->font_desc);
1355 text->font_desc = pango_font_description_copy (font_desc);
1357 text->font_desc = NULL;
1359 gnome_canvas_text_apply_font_desc (text);
1360 text->priv->render_dirty = 1;
1363 /* Setting the text from a Pango markup string */
1365 gnome_canvas_text_set_markup (GnomeCanvasText *textitem,
1366 const gchar *markup)
1368 PangoAttrList *attr_list = NULL;
1370 GError *error = NULL;
1372 if (markup && !pango_parse_markup (markup, -1,
1374 &attr_list, &text, NULL,
1377 g_warning ("Failed to set cell text from markup due to error parsing markup: %s",
1379 g_error_free (error);
1383 g_free (textitem->text);
1384 if (textitem->attr_list)
1385 pango_attr_list_unref (textitem->attr_list);
1387 textitem->text = text;
1388 textitem->attr_list = attr_list;
1390 pango_layout_set_text (textitem->layout, text, -1);
1392 gnome_canvas_text_apply_attributes (textitem);
1395 /* Update handler for the text item */
1397 gnome_canvas_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
1399 GnomeCanvasText *text;
1400 double x1, y1, x2, y2;
1402 text = GNOME_CANVAS_TEXT (item);
1404 if (parent_class->update)
1405 (* parent_class->update) (item, affine, clip_path, flags);
1407 set_text_gc_foreground (text);
1408 set_stipple (text, text->stipple, TRUE);
1409 get_bounds (text, &x1, &y1, &x2, &y2);
1411 gnome_canvas_update_bbox (item,
1412 floor (x1), floor (y1),
1413 ceil (x2), ceil (y2));
1416 /* Realize handler for the text item */
1418 gnome_canvas_text_realize (GnomeCanvasItem *item)
1420 GnomeCanvasText *text;
1422 text = GNOME_CANVAS_TEXT (item);
1424 if (parent_class->realize)
1425 (* parent_class->realize) (item);
1427 text->gc = gdk_gc_new (item->canvas->layout.bin_window);
1430 /* Unrealize handler for the text item */
1432 gnome_canvas_text_unrealize (GnomeCanvasItem *item)
1434 GnomeCanvasText *text;
1436 text = GNOME_CANVAS_TEXT (item);
1438 g_object_unref (text->gc);
1441 if (parent_class->unrealize)
1442 (* parent_class->unrealize) (item);
1445 /* Draw handler for the text item */
1447 gnome_canvas_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
1448 int x, int y, int width, int height)
1450 GnomeCanvasText *text;
1453 text = GNOME_CANVAS_TEXT (item);
1459 rect.x = text->clip_cx - x;
1460 rect.y = text->clip_cy - y;
1461 rect.width = text->clip_cwidth;
1462 rect.height = text->clip_cheight;
1464 gdk_gc_set_clip_rectangle (text->gc, &rect);
1468 gnome_canvas_set_stipple_origin (item->canvas, text->gc);
1471 gdk_draw_layout (drawable, text->gc, text->cx - x, text->cy - y, text->layout);
1474 gdk_gc_set_clip_rectangle (text->gc, NULL);
1478 /* Render handler for the text item */
1480 gnome_canvas_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
1482 GnomeCanvasText *text;
1484 int render_x = 0, render_y = 0; /* offsets for text rendering,
1485 * for clipping rectangles */
1491 int bm_rows, bm_width;
1493 text = GNOME_CANVAS_TEXT (item);
1498 fg_color = text->rgba;
1500 gnome_canvas_buf_ensure_buf (buf);
1502 bm_rows = (text->clip) ? text->clip_cheight : text->height;
1503 bm_width = (text->clip) ? text->clip_cwidth : text->max_width;
1504 if(text->priv->render_dirty ||
1505 bm_rows != text->priv->bitmap.rows ||
1506 bm_width != text->priv->bitmap.width) {
1507 if(text->priv->bitmap.buffer) {
1508 g_free(text->priv->bitmap.buffer);
1510 text->priv->bitmap.rows = bm_rows;
1511 text->priv->bitmap.width = bm_width;
1512 text->priv->bitmap.pitch = (text->priv->bitmap.width+3)&~3;
1513 text->priv->bitmap.buffer = g_malloc0 (text->priv->bitmap.rows * text->priv->bitmap.pitch);
1514 text->priv->bitmap.num_grays = 256;
1515 text->priv->bitmap.pixel_mode = ft_pixel_mode_grays;
1517 /* What this does is when a clipping rectangle is
1518 being used shift the rendering of the text by the
1519 correct amount so that the correct result is
1520 obtained as if all text was rendered, then clipped.
1521 In this sense we can use smaller buffers and less
1522 rendeirng since hopefully FreeType2 checks to see
1523 if the glyph falls in the bounding box before
1527 render_x = text->cx - text->clip_cx;
1528 render_y = text->cy - text->clip_cy;
1531 pango_ft2_render_layout (&text->priv->bitmap, text->layout, render_x, render_y);
1533 text->priv->render_dirty = 0;
1537 x = text->clip_cx - buf->rect.x0;
1538 y = text->clip_cy - buf->rect.y0;
1540 x = text->cx - buf->rect.x0;
1541 y = text->cy - buf->rect.y0;
1544 w = text->priv->bitmap.width;
1545 h = text->priv->bitmap.rows;
1547 src_dx = src_dy = 0;
1549 if (x + w > buf->rect.x1 - buf->rect.x0) {
1550 w = buf->rect.x1 - buf->rect.x0 - x;
1553 if (y + h > buf->rect.y1 - buf->rect.y0) {
1554 h = buf->rect.y1 - buf->rect.y0 - y;
1569 dst = buf->buf + y * buf->buf_rowstride + x * 3;
1570 src = text->priv->bitmap.buffer +
1571 src_dy * text->priv->bitmap.pitch + src_dx;
1575 /* FIXME: Do the libart thing instead of divide by 255 */
1576 alpha = ((fg_color & 0xff) * (*src)) / 255;
1577 dst[0] = (dst[0] * (255 - alpha) + ((fg_color >> 24) & 0xff) * alpha) / 255;
1578 dst[1] = (dst[1] * (255 - alpha) + ((fg_color >> 16) & 0xff) * alpha) / 255;
1579 dst[2] = (dst[2] * (255 - alpha) + ((fg_color >> 8) & 0xff) * alpha) / 255;
1583 dst += buf->buf_rowstride - w*3;
1584 src += text->priv->bitmap.pitch - w;
1591 /* Point handler for the text item */
1593 gnome_canvas_text_point (GnomeCanvasItem *item, double x, double y,
1594 int cx, int cy, GnomeCanvasItem **actual_item)
1596 GnomeCanvasText *text;
1597 PangoLayoutIter *iter;
1602 text = GNOME_CANVAS_TEXT (item);
1604 *actual_item = item;
1606 /* The idea is to build bounding rectangles for each of the lines of
1607 * text (clipped by the clipping rectangle, if it is activated) and see
1608 * whether the point is inside any of these. If it is, we are done.
1609 * Otherwise, calculate the distance to the nearest rectangle.
1614 iter = pango_layout_get_iter (text->layout);
1616 PangoRectangle log_rect;
1618 pango_layout_iter_get_line_extents (iter, NULL, &log_rect);
1620 x1 = text->cx + PANGO_PIXELS (log_rect.x);
1621 y1 = text->cy + PANGO_PIXELS (log_rect.y);
1622 x2 = x1 + PANGO_PIXELS (log_rect.width);
1623 y2 = y1 + PANGO_PIXELS (log_rect.height);
1626 if (x1 < text->clip_cx)
1629 if (y1 < text->clip_cy)
1632 if (x2 > (text->clip_cx + text->clip_width))
1633 x2 = text->clip_cx + text->clip_width;
1635 if (y2 > (text->clip_cy + text->clip_height))
1636 y2 = text->clip_cy + text->clip_height;
1638 if ((x1 >= x2) || (y1 >= y2))
1642 /* Calculate distance from point to rectangle */
1658 if ((dx == 0) && (dy == 0)) {
1659 pango_layout_iter_free(iter);
1663 dist = sqrt (dx * dx + dy * dy);
1667 } while (pango_layout_iter_next_line(iter));
1669 pango_layout_iter_free(iter);
1671 return best / item->canvas->pixels_per_unit;
1674 /* Bounds handler for the text item */
1676 gnome_canvas_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
1678 GnomeCanvasText *text;
1679 double width, height;
1681 text = GNOME_CANVAS_TEXT (item);
1687 width = text->clip_width;
1688 height = text->clip_height;
1690 width = text->max_width / item->canvas->pixels_per_unit;
1691 height = text->height / item->canvas->pixels_per_unit;
1694 switch (text->anchor) {
1701 case GTK_ANCHOR_CENTER:
1716 switch (text->anchor) {
1723 case GTK_ANCHOR_CENTER:
1725 *y1 -= height / 2.0;