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 FooCanvas widget
29 * FooCanvas 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 "foo-canvas-text.h"
43 #include "foo-canvas-util.h"
44 #include "foo-canvas-i18n.h"
48 /* Object argument IDs */
63 PROP_FAMILY
, PROP_FAMILY_SET
,
67 PROP_STYLE
, PROP_STYLE_SET
,
68 PROP_VARIANT
, PROP_VARIANT_SET
,
69 PROP_WEIGHT
, PROP_WEIGHT_SET
,
70 PROP_STRETCH
, PROP_STRETCH_SET
,
71 PROP_SIZE
, PROP_SIZE_SET
,
73 PROP_STRIKETHROUGH
, PROP_STRIKETHROUGH_SET
,
74 PROP_UNDERLINE
, PROP_UNDERLINE_SET
,
75 PROP_RISE
, PROP_RISE_SET
,
76 PROP_SCALE
, PROP_SCALE_SET
,
94 /* Rendered size accessors */
99 struct _FooCanvasTextPrivate
{
103 static void foo_canvas_text_class_init (FooCanvasTextClass
*klass
);
104 static void foo_canvas_text_init (FooCanvasText
*text
);
105 static void foo_canvas_text_destroy (GtkObject
*object
);
106 static void foo_canvas_text_set_property (GObject
*object
,
110 static void foo_canvas_text_get_property (GObject
*object
,
115 static void foo_canvas_text_update (FooCanvasItem
*item
,
119 static void foo_canvas_text_realize (FooCanvasItem
*item
);
120 static void foo_canvas_text_unrealize (FooCanvasItem
*item
);
121 static void foo_canvas_text_draw (FooCanvasItem
*item
,
122 GdkDrawable
*drawable
,
123 GdkEventExpose
*expose
);
124 static double foo_canvas_text_point (FooCanvasItem
*item
,
129 FooCanvasItem
**actual_item
);
130 static void foo_canvas_text_translate (FooCanvasItem
*item
,
133 static void foo_canvas_text_bounds (FooCanvasItem
*item
,
139 static void foo_canvas_text_set_markup (FooCanvasText
*textitem
,
140 const gchar
*markup
);
142 static void foo_canvas_text_set_font_desc (FooCanvasText
*textitem
,
143 PangoFontDescription
*font_desc
);
145 static void foo_canvas_text_apply_font_desc (FooCanvasText
*textitem
);
146 static void foo_canvas_text_apply_attributes (FooCanvasText
*textitem
);
148 static void add_attr (PangoAttrList
*attr_list
,
149 PangoAttribute
*attr
);
151 static FooCanvasItemClass
*parent_class
;
153 G_DEFINE_TYPE (FooCanvasText
, foo_canvas_text
, FOO_TYPE_CANVAS_ITEM
)
155 /* Class initialization function for the text item */
157 foo_canvas_text_class_init (FooCanvasTextClass
*klass
)
159 GObjectClass
*gobject_class
;
160 GtkObjectClass
*object_class
;
161 FooCanvasItemClass
*item_class
;
163 gobject_class
= (GObjectClass
*) klass
;
164 object_class
= (GtkObjectClass
*) klass
;
165 item_class
= (FooCanvasItemClass
*) klass
;
167 parent_class
= g_type_class_peek_parent (klass
);
169 gobject_class
->set_property
= foo_canvas_text_set_property
;
170 gobject_class
->get_property
= foo_canvas_text_get_property
;
173 g_object_class_install_property
176 g_param_spec_string ("text",
182 g_object_class_install_property
185 g_param_spec_string ("markup",
187 _("Marked up text to render"),
189 (G_PARAM_WRITABLE
)));
192 g_object_class_install_property
195 g_param_spec_double ("x", NULL
, NULL
,
196 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
199 g_object_class_install_property
202 g_param_spec_double ("y", NULL
, NULL
,
203 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
208 g_object_class_install_property
211 g_param_spec_string ("font",
213 _("Font description as a string"),
217 g_object_class_install_property
220 g_param_spec_boxed ("font-desc",
221 _("Font description"),
222 _("Font description as a PangoFontDescription struct"),
223 PANGO_TYPE_FONT_DESCRIPTION
,
226 g_object_class_install_property
229 g_param_spec_string ("family",
231 _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
236 g_object_class_install_property
239 g_param_spec_boxed ("attributes", NULL
, NULL
,
240 PANGO_TYPE_ATTR_LIST
,
243 g_object_class_install_property
246 g_param_spec_enum ("style",
251 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
253 g_object_class_install_property
256 g_param_spec_enum ("variant",
260 PANGO_VARIANT_NORMAL
,
261 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
263 g_object_class_install_property
266 g_param_spec_int ("weight",
272 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
275 g_object_class_install_property
278 g_param_spec_enum ("stretch",
282 PANGO_STRETCH_NORMAL
,
283 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
285 g_object_class_install_property
288 g_param_spec_int ("size",
294 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
296 g_object_class_install_property
299 g_param_spec_double ("size-points",
301 _("Font size in points"),
305 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
307 g_object_class_install_property
310 g_param_spec_int ("rise",
312 _("Offset of text above the baseline (below the baseline if rise is negative)"),
316 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
318 g_object_class_install_property
321 g_param_spec_boolean ("strikethrough",
323 _("Whether to strike through the text"),
325 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
327 g_object_class_install_property
330 g_param_spec_enum ("underline",
332 _("Style of underline for this text"),
333 PANGO_TYPE_UNDERLINE
,
334 PANGO_UNDERLINE_NONE
,
335 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
337 g_object_class_install_property
340 g_param_spec_double ("scale",
342 _("Size of font, relative to default size"),
346 G_PARAM_READABLE
| G_PARAM_WRITABLE
));
348 g_object_class_install_property
351 g_param_spec_enum ("anchor", NULL
, NULL
,
352 GTK_TYPE_ANCHOR_TYPE
,
355 g_object_class_install_property
358 g_param_spec_enum ("justification", NULL
, NULL
,
359 GTK_TYPE_JUSTIFICATION
,
362 g_object_class_install_property
365 g_param_spec_double ("clip-width", NULL
, NULL
,
366 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
368 g_object_class_install_property
371 g_param_spec_double ("clip-height", NULL
, NULL
,
372 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
374 g_object_class_install_property
377 g_param_spec_boolean ("clip", NULL
, NULL
,
380 g_object_class_install_property
383 g_param_spec_double ("wrap-width", NULL
, NULL
,
384 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
386 g_object_class_install_property
389 g_param_spec_double ("x-offset", NULL
, NULL
,
390 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
392 g_object_class_install_property
395 g_param_spec_double ("y-offset", NULL
, NULL
,
396 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
398 g_object_class_install_property
401 g_param_spec_string ("fill-color",
403 _("Text color, as string"),
406 g_object_class_install_property
409 g_param_spec_boxed ("fill-color-gdk",
411 _("Text color, as a GdkColor"),
414 g_object_class_install_property
416 PROP_FILL_COLOR_RGBA
,
417 g_param_spec_uint ("fill-color-rgba",
419 _("Text color, as an R/G/B/A combined integer"),
422 g_object_class_install_property
425 g_param_spec_object ("fill-stipple", NULL
, NULL
,
428 g_object_class_install_property
431 g_param_spec_double ("text-width",
433 _("Width of the rendered text"),
434 0.0, G_MAXDOUBLE
, 0.0,
436 g_object_class_install_property
439 g_param_spec_double ("text-height",
441 _("Height of the rendered text"),
442 0.0, G_MAXDOUBLE
, 0.0,
445 /* Style props are set (explicitly applied) or not */
446 #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))
448 ADD_SET_PROP ("family-set", PROP_FAMILY_SET
,
449 _("Font family set"),
450 _("Whether this tag affects the font family"));
452 ADD_SET_PROP ("style-set", PROP_STYLE_SET
,
454 _("Whether this tag affects the font style"));
456 ADD_SET_PROP ("variant-set", PROP_VARIANT_SET
,
457 _("Font variant set"),
458 _("Whether this tag affects the font variant"));
460 ADD_SET_PROP ("weight-set", PROP_WEIGHT_SET
,
461 _("Font weight set"),
462 _("Whether this tag affects the font weight"));
464 ADD_SET_PROP ("stretch-set", PROP_STRETCH_SET
,
465 _("Font stretch set"),
466 _("Whether this tag affects the font stretch"));
468 ADD_SET_PROP ("size-set", PROP_SIZE_SET
,
470 _("Whether this tag affects the font size"));
472 ADD_SET_PROP ("rise-set", PROP_RISE_SET
,
474 _("Whether this tag affects the rise"));
476 ADD_SET_PROP ("strikethrough-set", PROP_STRIKETHROUGH_SET
,
477 _("Strikethrough set"),
478 _("Whether this tag affects strikethrough"));
480 ADD_SET_PROP ("underline-set", PROP_UNDERLINE_SET
,
482 _("Whether this tag affects underlining"));
484 ADD_SET_PROP ("scale-set", PROP_SCALE_SET
,
486 _("Whether this tag affects font scaling"));
489 object_class
->destroy
= foo_canvas_text_destroy
;
491 item_class
->update
= foo_canvas_text_update
;
492 item_class
->realize
= foo_canvas_text_realize
;
493 item_class
->unrealize
= foo_canvas_text_unrealize
;
494 item_class
->draw
= foo_canvas_text_draw
;
495 item_class
->point
= foo_canvas_text_point
;
496 item_class
->translate
= foo_canvas_text_translate
;
497 item_class
->bounds
= foo_canvas_text_bounds
;
500 /* Object initialization function for the text item */
502 foo_canvas_text_init (FooCanvasText
*text
)
506 text
->anchor
= GTK_ANCHOR_CENTER
;
507 text
->justification
= GTK_JUSTIFY_LEFT
;
508 text
->clip_width
= 0.0;
509 text
->clip_height
= 0.0;
514 text
->font_desc
= NULL
;
516 text
->underline
= PANGO_UNDERLINE_NONE
;
517 text
->strikethrough
= FALSE
;
520 text
->underline_set
= FALSE
;
521 text
->strike_set
= FALSE
;
522 text
->rise_set
= FALSE
;
524 text
->priv
= g_new (FooCanvasTextPrivate
, 1);
527 /* Destroy handler for the text item */
529 foo_canvas_text_destroy (GtkObject
*object
)
533 g_return_if_fail (FOO_IS_CANVAS_TEXT (object
));
535 text
= FOO_CANVAS_TEXT (object
);
537 /* remember, destroy can be run multiple times! */
543 g_object_unref (G_OBJECT (text
->layout
));
546 if (text
->font_desc
) {
547 pango_font_description_free (text
->font_desc
);
548 text
->font_desc
= NULL
;
552 pango_attr_list_unref (text
->attr_list
);
553 text
->attr_list
= NULL
;
556 g_object_unref (text
->stipple
);
557 text
->stipple
= NULL
;
562 if (GTK_OBJECT_CLASS (parent_class
)->destroy
)
563 (* GTK_OBJECT_CLASS (parent_class
)->destroy
) (object
);
567 get_bounds (FooCanvasText
*text
, double *px1
, double *py1
, double *px2
, double *py2
)
572 item
= FOO_CANVAS_ITEM (text
);
574 /* Get canvas pixel coordinates for text position */
579 foo_canvas_item_i2w (item
, &wx
, &wy
);
580 foo_canvas_w2c (item
->canvas
, wx
+ text
->xofs
, wy
+ text
->yofs
, &text
->cx
, &text
->cy
);
582 /* Get canvas pixel coordinates for clip rectangle position */
584 foo_canvas_w2c (item
->canvas
, wx
, wy
, &text
->clip_cx
, &text
->clip_cy
);
585 text
->clip_cwidth
= text
->clip_width
* item
->canvas
->pixels_per_unit
;
586 text
->clip_cheight
= text
->clip_height
* item
->canvas
->pixels_per_unit
;
590 switch (text
->anchor
) {
597 case GTK_ANCHOR_CENTER
:
599 text
->cx
-= text
->max_width
/ 2;
600 text
->clip_cx
-= text
->clip_cwidth
/ 2;
606 text
->cx
-= text
->max_width
;
607 text
->clip_cx
-= text
->clip_cwidth
;
614 switch (text
->anchor
) {
621 case GTK_ANCHOR_CENTER
:
623 text
->cy
-= text
->height
/ 2;
624 text
->clip_cy
-= text
->clip_cheight
/ 2;
630 text
->cy
-= text
->height
;
631 text
->clip_cy
-= text
->clip_cheight
;
641 *px1
= text
->clip_cx
;
642 *py1
= text
->clip_cy
;
643 *px2
= text
->clip_cx
+ text
->clip_cwidth
;
644 *py2
= text
->clip_cy
+ text
->clip_cheight
;
648 *px2
= text
->cx
+ text
->max_width
;
649 *py2
= text
->cy
+ text
->height
;
653 /* Convenience function to set the text's GC's foreground color */
655 set_text_gc_foreground (FooCanvasText
*text
)
662 c
.pixel
= text
->pixel
;
663 gdk_gc_set_foreground (text
->gc
, &c
);
666 /* Sets the stipple pattern for the text */
668 set_stipple (FooCanvasText
*text
, GdkBitmap
*stipple
, int reconfigure
)
670 if (text
->stipple
&& !reconfigure
)
671 g_object_unref (text
->stipple
);
673 text
->stipple
= stipple
;
674 if (stipple
&& !reconfigure
)
675 g_object_ref (stipple
);
679 gdk_gc_set_stipple (text
->gc
, stipple
);
680 gdk_gc_set_fill (text
->gc
, GDK_STIPPLED
);
682 gdk_gc_set_fill (text
->gc
, GDK_SOLID
);
687 get_property_font_set_mask (guint prop_id
)
691 case PROP_FAMILY_SET
:
692 return PANGO_FONT_MASK_FAMILY
;
694 return PANGO_FONT_MASK_STYLE
;
695 case PROP_VARIANT_SET
:
696 return PANGO_FONT_MASK_VARIANT
;
697 case PROP_WEIGHT_SET
:
698 return PANGO_FONT_MASK_WEIGHT
;
699 case PROP_STRETCH_SET
:
700 return PANGO_FONT_MASK_STRETCH
;
702 return PANGO_FONT_MASK_SIZE
;
709 ensure_font (FooCanvasText
*text
)
711 if (!text
->font_desc
)
712 text
->font_desc
= pango_font_description_new ();
715 /* Set_arg handler for the text item */
717 foo_canvas_text_set_property (GObject
*object
,
724 GdkColor color
= { 0, 0, 0, 0, };
726 gboolean color_changed
;
728 PangoAlignment align
;
730 g_return_if_fail (object
!= NULL
);
731 g_return_if_fail (FOO_IS_CANVAS_TEXT (object
));
733 item
= FOO_CANVAS_ITEM (object
);
734 text
= FOO_CANVAS_TEXT (object
);
736 color_changed
= FALSE
;
741 text
->layout
= gtk_widget_create_pango_layout (GTK_WIDGET (item
->canvas
), NULL
);
749 text
->text
= g_value_dup_string (value
);
750 pango_layout_set_text (text
->layout
, text
->text
, -1);
755 foo_canvas_text_set_markup (text
,
756 g_value_get_string (value
));
760 text
->x
= g_value_get_double (value
);
764 text
->y
= g_value_get_double (value
);
768 const char *font_name
;
769 PangoFontDescription
*font_desc
;
771 font_name
= g_value_get_string (value
);
773 font_desc
= pango_font_description_from_string (font_name
);
777 foo_canvas_text_set_font_desc (text
, font_desc
);
779 pango_font_description_free (font_desc
);
785 foo_canvas_text_set_font_desc (text
, g_value_peek_pointer (value
));
794 case PROP_SIZE_POINTS
:
799 pango_font_description_set_family (text
->font_desc
,
800 g_value_get_string (value
));
803 pango_font_description_set_style (text
->font_desc
,
804 g_value_get_enum (value
));
807 pango_font_description_set_variant (text
->font_desc
,
808 g_value_get_enum (value
));
811 pango_font_description_set_weight (text
->font_desc
,
812 g_value_get_int (value
));
815 pango_font_description_set_stretch (text
->font_desc
,
816 g_value_get_enum (value
));
819 /* FIXME: This is bogus! It should be pixels, not points/PANGO_SCALE! */
820 pango_font_description_set_size (text
->font_desc
,
821 g_value_get_int (value
));
823 case PROP_SIZE_POINTS
:
824 pango_font_description_set_size (text
->font_desc
,
825 g_value_get_double (value
) * PANGO_SCALE
);
829 foo_canvas_text_apply_font_desc (text
);
832 case PROP_FAMILY_SET
:
834 case PROP_VARIANT_SET
:
835 case PROP_WEIGHT_SET
:
836 case PROP_STRETCH_SET
:
838 if (!g_value_get_boolean (value
) && text
->font_desc
)
839 pango_font_description_unset_fields (text
->font_desc
,
840 get_property_font_set_mask (param_id
));
844 text
->scale
= g_value_get_double (value
);
845 text
->scale_set
= TRUE
;
847 foo_canvas_text_apply_font_desc (text
);
851 text
->scale_set
= g_value_get_boolean (value
);
853 foo_canvas_text_apply_font_desc (text
);
857 text
->underline
= g_value_get_enum (value
);
858 text
->underline_set
= TRUE
;
860 foo_canvas_text_apply_attributes (text
);
863 case PROP_UNDERLINE_SET
:
864 text
->underline_set
= g_value_get_boolean (value
);
866 foo_canvas_text_apply_attributes (text
);
869 case PROP_STRIKETHROUGH
:
870 text
->strikethrough
= g_value_get_boolean (value
);
871 text
->strike_set
= TRUE
;
873 foo_canvas_text_apply_attributes (text
);
876 case PROP_STRIKETHROUGH_SET
:
877 text
->strike_set
= g_value_get_boolean (value
);
879 foo_canvas_text_apply_attributes (text
);
883 text
->rise
= g_value_get_int (value
);
884 text
->rise_set
= TRUE
;
886 foo_canvas_text_apply_attributes (text
);
890 text
->rise_set
= TRUE
;
892 foo_canvas_text_apply_attributes (text
);
895 case PROP_ATTRIBUTES
:
897 pango_attr_list_unref (text
->attr_list
);
899 text
->attr_list
= g_value_peek_pointer (value
);
901 pango_attr_list_ref (text
->attr_list
);
903 foo_canvas_text_apply_attributes (text
);
907 text
->anchor
= g_value_get_enum (value
);
910 case PROP_JUSTIFICATION
:
911 text
->justification
= g_value_get_enum (value
);
913 switch (text
->justification
) {
914 case GTK_JUSTIFY_LEFT
:
915 align
= PANGO_ALIGN_LEFT
;
917 case GTK_JUSTIFY_CENTER
:
918 align
= PANGO_ALIGN_CENTER
;
920 case GTK_JUSTIFY_RIGHT
:
921 align
= PANGO_ALIGN_RIGHT
;
924 /* GTK_JUSTIFY_FILL isn't supported yet. */
925 align
= PANGO_ALIGN_LEFT
;
928 pango_layout_set_alignment (text
->layout
, align
);
931 case PROP_CLIP_WIDTH
:
932 text
->clip_width
= fabs (g_value_get_double (value
));
935 case PROP_CLIP_HEIGHT
:
936 text
->clip_height
= fabs (g_value_get_double (value
));
940 text
->clip
= g_value_get_boolean (value
);
943 case PROP_WRAP_WIDTH
: {
944 double w
= fabs (g_value_get_double (value
));
945 pango_layout_set_width (text
->layout
,
946 w
* text
->item
.canvas
->pixels_per_unit
* PANGO_SCALE
);
952 text
->xofs
= g_value_get_double (value
);
956 text
->yofs
= g_value_get_double (value
);
959 case PROP_FILL_COLOR
: {
960 const char *color_name
;
962 color_name
= g_value_get_string (value
);
964 gdk_color_parse (color_name
, &color
);
966 text
->rgba
= ((color
.red
& 0xff00) << 16 |
967 (color
.green
& 0xff00) << 8 |
968 (color
.blue
& 0xff00) |
970 color_changed
= TRUE
;
975 case PROP_FILL_COLOR_GDK
:
976 pcolor
= g_value_get_boxed (value
);
978 GdkColormap
*colormap
;
981 colormap
= gtk_widget_get_colormap (GTK_WIDGET (item
->canvas
));
982 gdk_rgb_find_color (colormap
, &color
);
986 text
->rgba
= ((color
.red
& 0xff00) << 16 |
987 (color
.green
& 0xff00) << 8|
988 (color
.blue
& 0xff00) |
990 color_changed
= TRUE
;
993 case PROP_FILL_COLOR_RGBA
:
994 text
->rgba
= g_value_get_uint (value
);
995 color_changed
= TRUE
;
998 case PROP_FILL_STIPPLE
:
999 set_stipple (text
, (GdkBitmap
*)g_value_get_object (value
), FALSE
);
1003 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
1007 if (color_changed
) {
1009 text
->pixel
= color
.pixel
;
1011 text
->pixel
= foo_canvas_get_color_pixel (item
->canvas
, text
->rgba
);
1013 set_text_gc_foreground (text
);
1016 /* Calculate text dimensions */
1019 pango_layout_get_pixel_size (text
->layout
,
1023 text
->max_width
= 0;
1027 foo_canvas_item_request_update (item
);
1030 /* Get_arg handler for the text item */
1032 foo_canvas_text_get_property (GObject
*object
,
1037 FooCanvasText
*text
;
1039 g_return_if_fail (object
!= NULL
);
1040 g_return_if_fail (FOO_IS_CANVAS_TEXT (object
));
1042 text
= FOO_CANVAS_TEXT (object
);
1046 g_value_set_string (value
, text
->text
);
1050 g_value_set_double (value
, text
->x
);
1054 g_value_set_double (value
, text
->y
);
1058 case PROP_FONT_DESC
:
1065 case PROP_SIZE_POINTS
:
1071 /* FIXME GValue imposes a totally gratuitous string copy
1072 * here, we could just hand off string ownership
1076 str
= pango_font_description_to_string (text
->font_desc
);
1077 g_value_set_string (value
, str
);
1083 case PROP_FONT_DESC
:
1084 g_value_set_boxed (value
, text
->font_desc
);
1088 g_value_set_string (value
, pango_font_description_get_family (text
->font_desc
));
1092 g_value_set_enum (value
, pango_font_description_get_style (text
->font_desc
));
1096 g_value_set_enum (value
, pango_font_description_get_variant (text
->font_desc
));
1100 g_value_set_int (value
, pango_font_description_get_weight (text
->font_desc
));
1104 g_value_set_enum (value
, pango_font_description_get_stretch (text
->font_desc
));
1108 g_value_set_int (value
, pango_font_description_get_size (text
->font_desc
));
1111 case PROP_SIZE_POINTS
:
1112 g_value_set_double (value
, ((double)pango_font_description_get_size (text
->font_desc
)) / (double)PANGO_SCALE
);
1117 case PROP_FAMILY_SET
:
1118 case PROP_STYLE_SET
:
1119 case PROP_VARIANT_SET
:
1120 case PROP_WEIGHT_SET
:
1121 case PROP_STRETCH_SET
:
1124 PangoFontMask set_mask
= text
->font_desc
? pango_font_description_get_set_fields (text
->font_desc
) : 0;
1125 PangoFontMask test_mask
= get_property_font_set_mask (param_id
);
1126 g_value_set_boolean (value
, (set_mask
& test_mask
) != 0);
1132 g_value_set_double (value
, text
->scale
);
1134 case PROP_SCALE_SET
:
1135 g_value_set_boolean (value
, text
->scale_set
);
1138 case PROP_UNDERLINE
:
1139 g_value_set_enum (value
, text
->underline
);
1141 case PROP_UNDERLINE_SET
:
1142 g_value_set_boolean (value
, text
->underline_set
);
1145 case PROP_STRIKETHROUGH
:
1146 g_value_set_boolean (value
, text
->strikethrough
);
1148 case PROP_STRIKETHROUGH_SET
:
1149 g_value_set_boolean (value
, text
->strike_set
);
1153 g_value_set_int (value
, text
->rise
);
1156 g_value_set_boolean (value
, text
->rise_set
);
1159 case PROP_ATTRIBUTES
:
1160 g_value_set_boxed (value
, text
->attr_list
);
1164 g_value_set_enum (value
, text
->anchor
);
1167 case PROP_JUSTIFICATION
:
1168 g_value_set_enum (value
, text
->justification
);
1171 case PROP_CLIP_WIDTH
:
1172 g_value_set_double (value
, text
->clip_width
);
1175 case PROP_CLIP_HEIGHT
:
1176 g_value_set_double (value
, text
->clip_height
);
1180 g_value_set_boolean (value
, text
->clip
);
1183 case PROP_WRAP_WIDTH
:
1184 g_value_set_double (value
,
1185 pango_layout_get_width (text
->layout
) / PANGO_SCALE
);
1189 g_value_set_double (value
, text
->xofs
);
1193 g_value_set_double (value
, text
->yofs
);
1196 case PROP_FILL_COLOR
:
1197 g_value_take_string (value
,
1198 g_strdup_printf ("#%02x%02x%02x",
1200 (text
->rgba
>> 16) & 0xff,
1201 (text
->rgba
>> 8) & 0xff));
1204 case PROP_FILL_COLOR_GDK
: {
1205 FooCanvas
*canvas
= FOO_CANVAS_ITEM (text
)->canvas
;
1206 GdkColormap
*colormap
= gtk_widget_get_colormap (GTK_WIDGET (canvas
));
1209 gdk_colormap_query_color (colormap
, text
->pixel
, &color
);
1210 g_value_set_boxed (value
, &color
);
1213 case PROP_FILL_COLOR_RGBA
:
1214 g_value_set_uint (value
, text
->rgba
);
1217 case PROP_FILL_STIPPLE
:
1218 g_value_set_object (value
, text
->stipple
);
1221 case PROP_TEXT_WIDTH
:
1222 g_value_set_double (value
, text
->max_width
/ text
->item
.canvas
->pixels_per_unit
);
1225 case PROP_TEXT_HEIGHT
:
1226 g_value_set_double (value
, text
->height
/ text
->item
.canvas
->pixels_per_unit
);
1230 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
1237 foo_canvas_text_apply_font_desc (FooCanvasText
*text
)
1239 PangoFontDescription
*font_desc
=
1240 pango_font_description_copy (
1241 GTK_WIDGET (FOO_CANVAS_ITEM (text
)->canvas
)->style
->font_desc
);
1243 if (text
->font_desc
)
1244 pango_font_description_merge (font_desc
, text
->font_desc
, TRUE
);
1246 pango_layout_set_font_description (text
->layout
, font_desc
);
1247 pango_font_description_free (font_desc
);
1251 add_attr (PangoAttrList
*attr_list
,
1252 PangoAttribute
*attr
)
1254 attr
->start_index
= 0;
1255 attr
->end_index
= G_MAXINT
;
1257 pango_attr_list_insert (attr_list
, attr
);
1262 foo_canvas_text_apply_attributes (FooCanvasText
*text
)
1264 PangoAttrList
*attr_list
;
1267 if (text
->attr_list
)
1268 attr_list
= pango_attr_list_copy (text
->attr_list
);
1270 attr_list
= pango_attr_list_new ();
1272 if (text
->underline_set
)
1273 add_attr (attr_list
, pango_attr_underline_new (text
->underline
));
1274 if (text
->strike_set
)
1275 add_attr (attr_list
, pango_attr_strikethrough_new (text
->strikethrough
));
1277 add_attr (attr_list
, pango_attr_rise_new (text
->rise
));
1279 zoom
= text
->item
.canvas
->pixels_per_unit
;
1280 if (fabs (zoom
- 1.) > 1e-4) {
1281 PangoAttribute
*attr
= pango_attr_scale_new (zoom
);
1282 attr
->start_index
= 0;
1283 attr
->end_index
= -1;
1284 pango_attr_list_insert_before (attr_list
, attr
);
1287 pango_layout_set_attributes (text
->layout
, attr_list
);
1288 pango_attr_list_unref (attr_list
);
1292 foo_canvas_text_set_font_desc (FooCanvasText
*text
,
1293 PangoFontDescription
*font_desc
)
1295 if (text
->font_desc
)
1296 pango_font_description_free (text
->font_desc
);
1299 text
->font_desc
= pango_font_description_copy (font_desc
);
1301 text
->font_desc
= NULL
;
1303 foo_canvas_text_apply_font_desc (text
);
1306 /* Setting the text from a Pango markup string */
1308 foo_canvas_text_set_markup (FooCanvasText
*textitem
,
1309 const gchar
*markup
)
1311 PangoAttrList
*attr_list
= NULL
;
1313 GError
*error
= NULL
;
1316 g_free (textitem
->text
);
1317 if (textitem
->attr_list
)
1318 pango_attr_list_unref (textitem
->attr_list
);
1320 if (markup
&& !pango_parse_markup (markup
, -1,
1322 &attr_list
, &text
, NULL
,
1325 g_warning ("Failed to set cell text from markup due to error parsing markup: %s",
1327 g_error_free (error
);
1331 textitem
->text
= text
;
1332 textitem
->attr_list
= attr_list
;
1334 pango_layout_set_text (textitem
->layout
, text
, -1);
1336 foo_canvas_text_apply_attributes (textitem
);
1339 /* Update handler for the text item */
1341 foo_canvas_text_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, int flags
)
1343 FooCanvasText
*text
;
1344 double x1
, y1
, x2
, y2
;
1346 text
= FOO_CANVAS_TEXT (item
);
1348 if (parent_class
->update
)
1349 (* parent_class
->update
) (item
, i2w_dx
, i2w_dy
, flags
);
1351 set_text_gc_foreground (text
);
1352 set_stipple (text
, text
->stipple
, TRUE
);
1353 get_bounds (text
, &x1
, &y1
, &x2
, &y2
);
1355 foo_canvas_update_bbox (item
,
1356 floor (x1
+.5), floor (y1
+.5),
1357 floor (x2
+.5), floor (y2
+.5));
1360 /* Realize handler for the text item */
1362 foo_canvas_text_realize (FooCanvasItem
*item
)
1364 FooCanvasText
*text
;
1366 text
= FOO_CANVAS_TEXT (item
);
1368 if (parent_class
->realize
)
1369 (* parent_class
->realize
) (item
);
1371 text
->gc
= gdk_gc_new (item
->canvas
->layout
.bin_window
);
1374 /* Unrealize handler for the text item */
1376 foo_canvas_text_unrealize (FooCanvasItem
*item
)
1378 FooCanvasText
*text
;
1380 text
= FOO_CANVAS_TEXT (item
);
1382 g_object_unref (text
->gc
);
1385 if (parent_class
->unrealize
)
1386 (* parent_class
->unrealize
) (item
);
1389 /* Draw handler for the text item */
1391 foo_canvas_text_draw (FooCanvasItem
*item
, GdkDrawable
*drawable
,
1392 GdkEventExpose
*expose
)
1394 FooCanvasText
*text
;
1397 text
= FOO_CANVAS_TEXT (item
);
1403 rect
.x
= text
->clip_cx
;
1404 rect
.y
= text
->clip_cy
;
1405 rect
.width
= text
->clip_cwidth
;
1406 rect
.height
= text
->clip_cheight
;
1408 gdk_gc_set_clip_rectangle (text
->gc
, &rect
);
1411 gdk_draw_layout (drawable
, text
->gc
, text
->cx
, text
->cy
, text
->layout
);
1414 gdk_gc_set_clip_rectangle (text
->gc
, NULL
);
1417 /* Point handler for the text item */
1419 foo_canvas_text_point (FooCanvasItem
*item
, double x
, double y
,
1420 int cx
, int cy
, FooCanvasItem
**actual_item
)
1422 FooCanvasText
*text
;
1423 PangoLayoutIter
*iter
;
1428 text
= FOO_CANVAS_TEXT (item
);
1430 *actual_item
= item
;
1432 /* The idea is to build bounding rectangles for each of the lines of
1433 * text (clipped by the clipping rectangle, if it is activated) and see
1434 * whether the point is inside any of these. If it is, we are done.
1435 * Otherwise, calculate the distance to the nearest rectangle.
1440 iter
= pango_layout_get_iter (text
->layout
);
1442 PangoRectangle log_rect
;
1444 pango_layout_iter_get_line_extents (iter
, NULL
, &log_rect
);
1447 x1
= PANGO_PIXELS (log_rect
.x
);
1448 y1
= PANGO_PIXELS (log_rect
.y
);
1449 x2
= PANGO_PIXELS (log_rect
.x
+log_rect
.width
);
1450 y2
= PANGO_PIXELS (log_rect
.y
+log_rect
.height
);
1453 if (x1
< text
->clip_cx
)
1456 if (y1
< text
->clip_cy
)
1459 if (x2
> (text
->clip_cx
+ text
->clip_width
))
1460 x2
= text
->clip_cx
+ text
->clip_width
;
1462 if (y2
> (text
->clip_cy
+ text
->clip_height
))
1463 y2
= text
->clip_cy
+ text
->clip_height
;
1465 if ((x1
>= x2
) || (y1
>= y2
))
1470 x2
= log_rect
.width
;
1471 y2
= log_rect
.height
;
1474 /* Calculate distance from point to rectangle */
1490 if ((dx
== 0) && (dy
== 0)) {
1491 pango_layout_iter_free(iter
);
1495 dist
= sqrt (dx
* dx
+ dy
* dy
);
1499 } while (pango_layout_iter_next_line(iter
));
1501 pango_layout_iter_free(iter
);
1503 return best
/ item
->canvas
->pixels_per_unit
;
1507 foo_canvas_text_translate (FooCanvasItem
*item
, double dx
, double dy
)
1509 FooCanvasText
*text
;
1511 text
= FOO_CANVAS_TEXT (item
);
1517 /* Bounds handler for the text item */
1519 foo_canvas_text_bounds (FooCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
)
1521 FooCanvasText
*text
;
1522 double width
, height
;
1524 text
= FOO_CANVAS_TEXT (item
);
1530 width
= text
->clip_width
;
1531 height
= text
->clip_height
;
1533 width
= text
->max_width
/ item
->canvas
->pixels_per_unit
;
1534 height
= text
->height
/ item
->canvas
->pixels_per_unit
;
1537 switch (text
->anchor
) {
1544 case GTK_ANCHOR_CENTER
:
1559 switch (text
->anchor
) {
1566 case GTK_ANCHOR_CENTER
:
1568 *y1
-= height
/ 2.0;