Bug 793915 - Option to convert UTC time to local time in Reply credits
[evolution.git] / src / libgnomecanvas / gnome-canvas-text.c
blob43e6e76a783b4f6ac0c422242fc8a389131ea9a9
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * $Id$
4 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
5 * All rights reserved.
7 * This file is part of the Gnome Library.
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * published by the Free Software Foundation; either the
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * License along with the Gnome Library; see the file COPYING.LIB. If not,
22 @NOTATION@
24 /* Text item type for GnomeCanvas widget
26 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
27 * widget. Tk is copyrighted by the Regents of the University of California,
28 * Sun Microsystems, and other parties.
31 * Author: Federico Mena <federico@nuclecu.unam.mx>
32 * Port to Pango co-done by Gergõ Érdi <cactus@cactus.rulez.org>
35 #include "evolution-config.h"
37 #include <math.h>
38 #include <string.h>
39 #include "gnome-canvas-text.h"
41 #include "gnome-canvas-util.h"
42 #include "gnome-canvas-i18n.h"
44 /* Object argument IDs */
45 enum {
46 PROP_0,
48 /* Text contents */
49 PROP_TEXT,
50 PROP_MARKUP,
52 /* Position */
53 PROP_X,
54 PROP_Y,
56 /* Font */
57 PROP_FONT,
58 PROP_FONT_DESC,
59 PROP_FAMILY, PROP_FAMILY_SET,
61 /* Style */
62 PROP_ATTRIBUTES,
63 PROP_STYLE, PROP_STYLE_SET,
64 PROP_VARIANT, PROP_VARIANT_SET,
65 PROP_WEIGHT, PROP_WEIGHT_SET,
66 PROP_STRETCH, PROP_STRETCH_SET,
67 PROP_SIZE, PROP_SIZE_SET,
68 PROP_SIZE_POINTS,
69 PROP_STRIKETHROUGH, PROP_STRIKETHROUGH_SET,
70 PROP_UNDERLINE, PROP_UNDERLINE_SET,
71 PROP_RISE, PROP_RISE_SET,
72 PROP_SCALE, PROP_SCALE_SET,
74 /* Clipping */
75 PROP_JUSTIFICATION,
76 PROP_CLIP_WIDTH,
77 PROP_CLIP_HEIGHT,
78 PROP_CLIP,
79 PROP_X_OFFSET,
80 PROP_Y_OFFSET,
82 /* Coloring */
83 PROP_FILL_COLOR,
84 PROP_FILL_COLOR_GDK,
85 PROP_FILL_COLOR_RGBA,
87 /* Rendered size accessors */
88 PROP_TEXT_WIDTH,
89 PROP_TEXT_HEIGHT
92 static void gnome_canvas_text_dispose (GnomeCanvasItem *object);
93 static void gnome_canvas_text_set_property (GObject *object,
94 guint param_id,
95 const GValue *value,
96 GParamSpec *pspec);
97 static void gnome_canvas_text_get_property (GObject *object,
98 guint param_id,
99 GValue *value,
100 GParamSpec *pspec);
102 static void gnome_canvas_text_update (GnomeCanvasItem *item,
103 const cairo_matrix_t *matrix,
104 gint flags);
105 static void gnome_canvas_text_draw (GnomeCanvasItem *item, cairo_t *cr,
106 gint x, gint y, gint width, gint height);
107 static GnomeCanvasItem *gnome_canvas_text_point (GnomeCanvasItem *item,
108 gdouble x,
109 gdouble y,
110 gint cx,
111 gint cy);
112 static void gnome_canvas_text_bounds (GnomeCanvasItem *item,
113 gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2);
115 static void gnome_canvas_text_set_markup (GnomeCanvasText *textitem,
116 const gchar *markup);
118 static void gnome_canvas_text_set_font_desc (GnomeCanvasText *textitem,
119 PangoFontDescription *font_desc);
121 static void gnome_canvas_text_apply_font_desc (GnomeCanvasText *textitem);
122 static void gnome_canvas_text_apply_attributes (GnomeCanvasText *textitem);
124 static void add_attr (PangoAttrList *attr_list,
125 PangoAttribute *attr);
127 G_DEFINE_TYPE (
128 GnomeCanvasText,
129 gnome_canvas_text,
130 GNOME_TYPE_CANVAS_ITEM)
132 /* Class initialization function for the text item */
133 static void
134 gnome_canvas_text_class_init (GnomeCanvasTextClass *class)
136 GObjectClass *gobject_class;
137 GnomeCanvasItemClass *item_class;
139 gobject_class = (GObjectClass *) class;
140 item_class = (GnomeCanvasItemClass *) class;
142 gobject_class->set_property = gnome_canvas_text_set_property;
143 gobject_class->get_property = gnome_canvas_text_get_property;
145 /* Text */
146 g_object_class_install_property (
147 gobject_class,
148 PROP_TEXT,
149 g_param_spec_string (
150 "text",
151 "Text",
152 "Text to render",
153 NULL,
154 G_PARAM_READABLE |
155 G_PARAM_WRITABLE));
157 g_object_class_install_property (
158 gobject_class,
159 PROP_MARKUP,
160 g_param_spec_string (
161 "markup",
162 "Markup",
163 "Marked up text to render",
164 NULL,
165 G_PARAM_WRITABLE));
167 /* Position */
168 g_object_class_install_property (
169 gobject_class,
170 PROP_X,
171 g_param_spec_double (
172 "x",
173 NULL,
174 NULL,
175 -G_MAXDOUBLE,
176 G_MAXDOUBLE,
177 0.0,
178 G_PARAM_READABLE |
179 G_PARAM_WRITABLE));
181 g_object_class_install_property (
182 gobject_class,
183 PROP_Y,
184 g_param_spec_double (
185 "y",
186 NULL,
187 NULL,
188 -G_MAXDOUBLE,
189 G_MAXDOUBLE,
190 0.0,
191 G_PARAM_READABLE |
192 G_PARAM_WRITABLE));
194 /* Font */
195 g_object_class_install_property (
196 gobject_class,
197 PROP_FONT,
198 g_param_spec_string (
199 "font",
200 "Font",
201 "Font description as a string",
202 NULL,
203 G_PARAM_READABLE |
204 G_PARAM_WRITABLE));
206 g_object_class_install_property (
207 gobject_class,
208 PROP_FONT_DESC,
209 g_param_spec_boxed (
210 "font_desc",
211 "Font description",
212 "Font description as a PangoFontDescription struct",
213 PANGO_TYPE_FONT_DESCRIPTION,
214 G_PARAM_READABLE |
215 G_PARAM_WRITABLE));
217 g_object_class_install_property (
218 gobject_class,
219 PROP_FAMILY,
220 g_param_spec_string (
221 "family",
222 "Font family",
223 "Name of the font family, e.g. "
224 "Sans, Helvetica, Times, Monospace",
225 NULL,
226 G_PARAM_READABLE |
227 G_PARAM_WRITABLE));
229 /* Style */
230 g_object_class_install_property (
231 gobject_class,
232 PROP_ATTRIBUTES,
233 g_param_spec_boxed (
234 "attributes",
235 NULL,
236 NULL,
237 PANGO_TYPE_ATTR_LIST,
238 G_PARAM_READABLE |
239 G_PARAM_WRITABLE));
241 g_object_class_install_property (
242 gobject_class,
243 PROP_STYLE,
244 g_param_spec_enum (
245 "style",
246 "Font style",
247 "Font style",
248 PANGO_TYPE_STYLE,
249 PANGO_STYLE_NORMAL,
250 G_PARAM_READABLE |
251 G_PARAM_WRITABLE));
253 g_object_class_install_property (
254 gobject_class,
255 PROP_VARIANT,
256 g_param_spec_enum (
257 "variant",
258 "Font variant",
259 "Font variant",
260 PANGO_TYPE_VARIANT,
261 PANGO_VARIANT_NORMAL,
262 G_PARAM_READABLE |
263 G_PARAM_WRITABLE));
265 g_object_class_install_property (
266 gobject_class,
267 PROP_WEIGHT,
268 g_param_spec_int (
269 "weight",
270 "Font weight",
271 "Font weight",
273 G_MAXINT,
274 PANGO_WEIGHT_NORMAL,
275 G_PARAM_READABLE |
276 G_PARAM_WRITABLE));
278 g_object_class_install_property (
279 gobject_class,
280 PROP_STRETCH,
281 g_param_spec_enum (
282 "stretch",
283 "Font stretch",
284 "Font stretch",
285 PANGO_TYPE_STRETCH,
286 PANGO_STRETCH_NORMAL,
287 G_PARAM_READABLE |
288 G_PARAM_WRITABLE));
290 g_object_class_install_property (
291 gobject_class,
292 PROP_SIZE,
293 g_param_spec_int (
294 "size",
295 "Font size",
296 "Font size (as a multiple of PANGO_SCALE, "
297 "eg. 12*PANGO_SCALE for a 12pt font size)",
299 G_MAXINT,
301 G_PARAM_READABLE |
302 G_PARAM_WRITABLE));
304 g_object_class_install_property (
305 gobject_class,
306 PROP_SIZE_POINTS,
307 g_param_spec_double (
308 "size_points",
309 "Font points",
310 "Font size in points (eg. 12 for a 12pt font size)",
311 0.0,
312 G_MAXDOUBLE,
313 0.0,
314 G_PARAM_READABLE |
315 G_PARAM_WRITABLE));
317 g_object_class_install_property (
318 gobject_class,
319 PROP_RISE,
320 g_param_spec_int (
321 "rise",
322 "Rise",
323 "Offset of text above the baseline "
324 "(below the baseline if rise is negative)",
325 -G_MAXINT,
326 G_MAXINT,
328 G_PARAM_READABLE |
329 G_PARAM_WRITABLE));
331 g_object_class_install_property (
332 gobject_class,
333 PROP_STRIKETHROUGH,
334 g_param_spec_boolean (
335 "strikethrough",
336 "Strikethrough",
337 "Whether to strike through the text",
338 FALSE,
339 G_PARAM_READABLE |
340 G_PARAM_WRITABLE));
342 g_object_class_install_property (
343 gobject_class,
344 PROP_UNDERLINE,
345 g_param_spec_enum (
346 "underline",
347 "Underline",
348 "Style of underline for this text",
349 PANGO_TYPE_UNDERLINE,
350 PANGO_UNDERLINE_NONE,
351 G_PARAM_READABLE |
352 G_PARAM_WRITABLE));
354 g_object_class_install_property (
355 gobject_class,
356 PROP_SCALE,
357 g_param_spec_double (
358 "scale",
359 "Scale",
360 "Size of font, relative to default size",
361 0.0,
362 G_MAXDOUBLE,
363 1.0,
364 G_PARAM_READABLE |
365 G_PARAM_WRITABLE));
367 g_object_class_install_property (
368 gobject_class,
369 PROP_JUSTIFICATION,
370 g_param_spec_enum (
371 "justification",
372 NULL,
373 NULL,
374 GTK_TYPE_JUSTIFICATION,
375 GTK_JUSTIFY_LEFT,
376 G_PARAM_READABLE |
377 G_PARAM_WRITABLE));
379 g_object_class_install_property (
380 gobject_class,
381 PROP_CLIP_WIDTH,
382 g_param_spec_double (
383 "clip_width",
384 NULL,
385 NULL,
386 -G_MAXDOUBLE,
387 G_MAXDOUBLE,
388 0.0,
389 G_PARAM_READABLE |
390 G_PARAM_WRITABLE));
392 g_object_class_install_property (
393 gobject_class,
394 PROP_CLIP_HEIGHT,
395 g_param_spec_double (
396 "clip_height",
397 NULL,
398 NULL,
399 -G_MAXDOUBLE,
400 G_MAXDOUBLE,
401 0.0,
402 G_PARAM_READABLE |
403 G_PARAM_WRITABLE));
405 g_object_class_install_property (
406 gobject_class,
407 PROP_CLIP,
408 g_param_spec_boolean (
409 "clip",
410 NULL,
411 NULL,
412 FALSE,
413 G_PARAM_READABLE |
414 G_PARAM_WRITABLE));
416 g_object_class_install_property (
417 gobject_class,
418 PROP_X_OFFSET,
419 g_param_spec_double (
420 "x_offset",
421 NULL,
422 NULL,
423 -G_MAXDOUBLE,
424 G_MAXDOUBLE,
425 0.0,
426 G_PARAM_READABLE |
427 G_PARAM_WRITABLE));
429 g_object_class_install_property (
430 gobject_class,
431 PROP_Y_OFFSET,
432 g_param_spec_double (
433 "y_offset",
434 NULL,
435 NULL,
436 -G_MAXDOUBLE,
437 G_MAXDOUBLE,
438 0.0,
439 G_PARAM_READABLE |
440 G_PARAM_WRITABLE));
442 g_object_class_install_property (
443 gobject_class,
444 PROP_FILL_COLOR,
445 g_param_spec_string (
446 "fill_color",
447 "Color",
448 "Text color, as string",
449 NULL,
450 G_PARAM_WRITABLE));
452 g_object_class_install_property (
453 gobject_class,
454 PROP_FILL_COLOR_GDK,
455 g_param_spec_boxed (
456 "fill_color_gdk",
457 "Color",
458 "Text color, as a GdkColor",
459 GDK_TYPE_COLOR,
460 G_PARAM_WRITABLE));
462 g_object_class_install_property (
463 gobject_class,
464 PROP_FILL_COLOR_RGBA,
465 g_param_spec_uint (
466 "fill_color_rgba",
467 "Color",
468 "Text color, as an R/G/B/A combined integer",
469 0, G_MAXUINT, 0,
470 G_PARAM_READABLE |
471 G_PARAM_WRITABLE));
473 g_object_class_install_property (
474 gobject_class,
475 PROP_TEXT_WIDTH,
476 g_param_spec_double (
477 "text_width",
478 "Text width",
479 "Width of the rendered text",
480 0.0, G_MAXDOUBLE, 0.0,
481 G_PARAM_READABLE));
483 g_object_class_install_property (
484 gobject_class,
485 PROP_TEXT_HEIGHT,
486 g_param_spec_double (
487 "text_height",
488 "Text height",
489 "Height of the rendered text",
490 0.0, G_MAXDOUBLE, 0.0,
491 G_PARAM_READABLE));
493 /* Style props are set (explicitly applied) or not */
494 #define ADD_SET_PROP(propname, propval, nick, blurb) \
495 g_object_class_install_property ( \
496 gobject_class, propval, \
497 g_param_spec_boolean ( \
498 propname, nick, blurb, FALSE, \
499 G_PARAM_READABLE | G_PARAM_WRITABLE))
501 ADD_SET_PROP (
502 "family_set",
503 PROP_FAMILY_SET,
504 "Font family set",
505 "Whether this tag affects the font family");
507 ADD_SET_PROP (
508 "style_set",
509 PROP_STYLE_SET,
510 "Font style set",
511 "Whether this tag affects the font style");
513 ADD_SET_PROP (
514 "variant_set",
515 PROP_VARIANT_SET,
516 "Font variant set",
517 "Whether this tag affects the font variant");
519 ADD_SET_PROP (
520 "weight_set",
521 PROP_WEIGHT_SET,
522 "Font weight set",
523 "Whether this tag affects the font weight");
525 ADD_SET_PROP (
526 "stretch_set",
527 PROP_STRETCH_SET,
528 "Font stretch set",
529 "Whether this tag affects the font stretch");
531 ADD_SET_PROP (
532 "size_set",
533 PROP_SIZE_SET,
534 "Font size set",
535 "Whether this tag affects the font size");
537 ADD_SET_PROP (
538 "rise_set",
539 PROP_RISE_SET,
540 "Rise set",
541 "Whether this tag affects the rise");
543 ADD_SET_PROP (
544 "strikethrough_set",
545 PROP_STRIKETHROUGH_SET,
546 "Strikethrough set",
547 "Whether this tag affects strikethrough");
549 ADD_SET_PROP (
550 "underline_set",
551 PROP_UNDERLINE_SET,
552 "Underline set",
553 "Whether this tag affects underlining");
555 ADD_SET_PROP (
556 "scale_set",
557 PROP_SCALE_SET,
558 "Scale set",
559 "Whether this tag affects font scaling");
560 #undef ADD_SET_PROP
562 item_class->dispose = gnome_canvas_text_dispose;
563 item_class->update = gnome_canvas_text_update;
564 item_class->draw = gnome_canvas_text_draw;
565 item_class->point = gnome_canvas_text_point;
566 item_class->bounds = gnome_canvas_text_bounds;
569 /* Object initialization function for the text item */
570 static void
571 gnome_canvas_text_init (GnomeCanvasText *text)
573 text->x = 0.0;
574 text->y = 0.0;
575 text->justification = GTK_JUSTIFY_LEFT;
576 text->clip_width = 0.0;
577 text->clip_height = 0.0;
578 text->xofs = 0.0;
579 text->yofs = 0.0;
580 text->layout = NULL;
582 text->font_desc = NULL;
584 text->underline = PANGO_UNDERLINE_NONE;
585 text->strikethrough = FALSE;
586 text->rise = 0;
588 text->underline_set = FALSE;
589 text->strike_set = FALSE;
590 text->rise_set = FALSE;
593 /* Dispose handler for the text item */
594 static void
595 gnome_canvas_text_dispose (GnomeCanvasItem *object)
597 GnomeCanvasText *text;
599 g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
601 text = GNOME_CANVAS_TEXT (object);
603 g_free (text->text);
604 text->text = NULL;
606 if (text->layout != NULL) {
607 g_object_unref (text->layout);
608 text->layout = NULL;
611 if (text->font_desc != NULL) {
612 pango_font_description_free (text->font_desc);
613 text->font_desc = NULL;
616 if (text->attr_list != NULL) {
617 pango_attr_list_unref (text->attr_list);
618 text->attr_list = NULL;
621 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_text_parent_class)->
622 dispose (object);
625 static void
626 get_bounds (GnomeCanvasText *text,
627 gdouble *px1,
628 gdouble *py1,
629 gdouble *px2,
630 gdouble *py2)
632 GnomeCanvasItem *item;
633 gdouble wx, wy;
635 item = GNOME_CANVAS_ITEM (text);
637 /* Get canvas pixel coordinates for text position */
639 wx = text->x;
640 wy = text->y;
641 gnome_canvas_item_i2w (item, &wx, &wy);
642 gnome_canvas_w2c (
643 item->canvas, wx + text->xofs, wy + text->yofs,
644 &text->cx, &text->cy);
646 /* Get canvas pixel coordinates for clip rectangle position */
648 gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy);
649 text->clip_cwidth = text->clip_width;
650 text->clip_cheight = text->clip_height;
652 /* Bounds */
654 if (text->clip) {
655 *px1 = text->clip_cx;
656 *py1 = text->clip_cy;
657 *px2 = text->clip_cx + text->clip_cwidth;
658 *py2 = text->clip_cy + text->clip_cheight;
659 } else {
660 *px1 = text->cx;
661 *py1 = text->cy;
662 *px2 = text->cx + text->max_width;
663 *py2 = text->cy + text->height;
667 static PangoFontMask
668 get_property_font_set_mask (guint property_id)
670 switch (property_id) {
671 case PROP_FAMILY_SET:
672 return PANGO_FONT_MASK_FAMILY;
673 case PROP_STYLE_SET:
674 return PANGO_FONT_MASK_STYLE;
675 case PROP_VARIANT_SET:
676 return PANGO_FONT_MASK_VARIANT;
677 case PROP_WEIGHT_SET:
678 return PANGO_FONT_MASK_WEIGHT;
679 case PROP_STRETCH_SET:
680 return PANGO_FONT_MASK_STRETCH;
681 case PROP_SIZE_SET:
682 return PANGO_FONT_MASK_SIZE;
685 return 0;
688 static void
689 ensure_font (GnomeCanvasText *text)
691 if (!text->font_desc)
692 text->font_desc = pango_font_description_new ();
695 /* Set_arg handler for the text item */
696 static void
697 gnome_canvas_text_set_property (GObject *object,
698 guint param_id,
699 const GValue *value,
700 GParamSpec *pspec)
702 GnomeCanvasItem *item;
703 GnomeCanvasText *text;
704 GdkColor *pcolor;
705 PangoAlignment align;
707 g_return_if_fail (object != NULL);
708 g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
710 item = GNOME_CANVAS_ITEM (object);
711 text = GNOME_CANVAS_TEXT (object);
713 if (!text->layout)
714 text->layout = pango_layout_new (
715 gtk_widget_get_pango_context (
716 GTK_WIDGET (item->canvas)));
718 switch (param_id) {
719 case PROP_TEXT:
720 g_free (text->text);
722 text->text = g_value_dup_string (value);
723 pango_layout_set_text (text->layout, text->text, -1);
725 break;
727 case PROP_MARKUP:
728 gnome_canvas_text_set_markup (
729 text, g_value_get_string (value));
730 break;
732 case PROP_X:
733 text->x = g_value_get_double (value);
734 break;
736 case PROP_Y:
737 text->y = g_value_get_double (value);
738 break;
740 case PROP_FONT: {
741 const gchar *font_name;
742 PangoFontDescription *font_desc;
744 font_name = g_value_get_string (value);
745 if (font_name)
746 font_desc = pango_font_description_from_string (font_name);
747 else
748 font_desc = NULL;
750 gnome_canvas_text_set_font_desc (text, font_desc);
751 if (font_desc)
752 pango_font_description_free (font_desc);
754 break;
757 case PROP_FONT_DESC:
758 gnome_canvas_text_set_font_desc (text, g_value_peek_pointer (value));
759 break;
761 case PROP_FAMILY:
762 case PROP_STYLE:
763 case PROP_VARIANT:
764 case PROP_WEIGHT:
765 case PROP_STRETCH:
766 case PROP_SIZE:
767 case PROP_SIZE_POINTS:
768 ensure_font (text);
770 switch (param_id) {
771 case PROP_FAMILY:
772 pango_font_description_set_family (
773 text->font_desc,
774 g_value_get_string (value));
775 break;
776 case PROP_STYLE:
777 pango_font_description_set_style (
778 text->font_desc,
779 g_value_get_enum (value));
780 break;
781 case PROP_VARIANT:
782 pango_font_description_set_variant (
783 text->font_desc,
784 g_value_get_enum (value));
785 break;
786 case PROP_WEIGHT:
787 pango_font_description_set_weight (
788 text->font_desc,
789 g_value_get_int (value));
790 break;
791 case PROP_STRETCH:
792 pango_font_description_set_stretch (
793 text->font_desc,
794 g_value_get_enum (value));
795 break;
796 case PROP_SIZE:
797 /* FIXME: This is bogus! It should be pixels, not points/PANGO_SCALE! */
798 pango_font_description_set_size (
799 text->font_desc,
800 g_value_get_int (value));
801 break;
802 case PROP_SIZE_POINTS:
803 pango_font_description_set_size (
804 text->font_desc,
805 g_value_get_double (value) * PANGO_SCALE);
806 break;
809 gnome_canvas_text_apply_font_desc (text);
810 break;
812 case PROP_FAMILY_SET:
813 case PROP_STYLE_SET:
814 case PROP_VARIANT_SET:
815 case PROP_WEIGHT_SET:
816 case PROP_STRETCH_SET:
817 case PROP_SIZE_SET:
818 if (!g_value_get_boolean (value) && text->font_desc)
819 pango_font_description_unset_fields (
820 text->font_desc,
821 get_property_font_set_mask (param_id));
822 break;
824 case PROP_SCALE:
825 text->scale = g_value_get_double (value);
826 text->scale_set = TRUE;
828 gnome_canvas_text_apply_font_desc (text);
829 break;
831 case PROP_SCALE_SET:
832 text->scale_set = g_value_get_boolean (value);
834 gnome_canvas_text_apply_font_desc (text);
835 break;
837 case PROP_UNDERLINE:
838 text->underline = g_value_get_enum (value);
839 text->underline_set = TRUE;
841 gnome_canvas_text_apply_attributes (text);
842 break;
844 case PROP_UNDERLINE_SET:
845 text->underline_set = g_value_get_boolean (value);
847 gnome_canvas_text_apply_attributes (text);
848 break;
850 case PROP_STRIKETHROUGH:
851 text->strikethrough = g_value_get_boolean (value);
852 text->strike_set = TRUE;
854 gnome_canvas_text_apply_attributes (text);
855 break;
857 case PROP_STRIKETHROUGH_SET:
858 text->strike_set = g_value_get_boolean (value);
860 gnome_canvas_text_apply_attributes (text);
861 break;
863 case PROP_RISE:
864 text->rise = g_value_get_int (value);
865 text->rise_set = TRUE;
867 gnome_canvas_text_apply_attributes (text);
868 break;
870 case PROP_RISE_SET:
871 text->rise_set = TRUE;
873 gnome_canvas_text_apply_attributes (text);
874 break;
876 case PROP_ATTRIBUTES:
877 if (text->attr_list)
878 pango_attr_list_unref (text->attr_list);
880 text->attr_list = g_value_peek_pointer (value);
881 pango_attr_list_ref (text->attr_list);
883 gnome_canvas_text_apply_attributes (text);
884 break;
886 case PROP_JUSTIFICATION:
887 text->justification = g_value_get_enum (value);
889 switch (text->justification) {
890 case GTK_JUSTIFY_LEFT:
891 align = PANGO_ALIGN_LEFT;
892 break;
893 case GTK_JUSTIFY_CENTER:
894 align = PANGO_ALIGN_CENTER;
895 break;
896 case GTK_JUSTIFY_RIGHT:
897 align = PANGO_ALIGN_RIGHT;
898 break;
899 default:
900 /* GTK_JUSTIFY_FILL isn't supported yet. */
901 align = PANGO_ALIGN_LEFT;
902 break;
904 pango_layout_set_alignment (text->layout, align);
905 break;
907 case PROP_CLIP_WIDTH:
908 text->clip_width = fabs (g_value_get_double (value));
909 break;
911 case PROP_CLIP_HEIGHT:
912 text->clip_height = fabs (g_value_get_double (value));
913 break;
915 case PROP_CLIP:
916 text->clip = g_value_get_boolean (value);
917 break;
919 case PROP_X_OFFSET:
920 text->xofs = g_value_get_double (value);
921 break;
923 case PROP_Y_OFFSET:
924 text->yofs = g_value_get_double (value);
925 break;
927 case PROP_FILL_COLOR: {
928 const gchar *color_name;
930 color_name = g_value_get_string (value);
931 if (color_name) {
932 GdkColor color;
933 if (gdk_color_parse (color_name, &color)) {
934 text->rgba = ((color.red & 0xff00) << 16 |
935 (color.green & 0xff00) << 8 |
936 (color.blue & 0xff00) |
937 0xff);
938 } else {
939 g_warning (
940 "%s: Failed to parse color form string '%s'",
941 G_STRFUNC, color_name);
944 break;
947 case PROP_FILL_COLOR_GDK:
948 pcolor = g_value_get_boxed (value);
949 if (pcolor) {
950 text->rgba = ((pcolor->red & 0xff00) << 16 |
951 (pcolor->green & 0xff00) << 8|
952 (pcolor->blue & 0xff00) |
953 0xff);
954 } else {
955 text->rgba = 0;
957 break;
959 case PROP_FILL_COLOR_RGBA:
960 text->rgba = g_value_get_uint (value);
961 break;
963 default:
964 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
965 break;
968 /* Calculate text dimensions */
970 if (text->layout)
971 pango_layout_get_pixel_size (
972 text->layout,
973 &text->max_width,
974 &text->height);
975 else {
976 text->max_width = 0;
977 text->height = 0;
980 gnome_canvas_item_request_update (item);
983 /* Get_arg handler for the text item */
984 static void
985 gnome_canvas_text_get_property (GObject *object,
986 guint param_id,
987 GValue *value,
988 GParamSpec *pspec)
990 GnomeCanvasText *text;
992 g_return_if_fail (object != NULL);
993 g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
995 text = GNOME_CANVAS_TEXT (object);
997 switch (param_id) {
998 case PROP_TEXT:
999 g_value_set_string (value, text->text);
1000 break;
1002 case PROP_X:
1003 g_value_set_double (value, text->x);
1004 break;
1006 case PROP_Y:
1007 g_value_set_double (value, text->y);
1008 break;
1010 case PROP_FONT:
1011 case PROP_FONT_DESC:
1012 case PROP_FAMILY:
1013 case PROP_STYLE:
1014 case PROP_VARIANT:
1015 case PROP_WEIGHT:
1016 case PROP_STRETCH:
1017 case PROP_SIZE:
1018 case PROP_SIZE_POINTS:
1019 ensure_font (text);
1021 switch (param_id) {
1022 case PROP_FONT:
1024 /* FIXME GValue imposes a totally gratuitous string
1025 * copy here, we could just hand off string
1026 * ownership. */
1027 gchar *str;
1029 str = pango_font_description_to_string (text->font_desc);
1030 g_value_set_string (value, str);
1031 g_free (str);
1033 break;
1036 case PROP_FONT_DESC:
1037 g_value_set_boxed (value, text->font_desc);
1038 break;
1040 case PROP_FAMILY:
1041 g_value_set_string (
1042 value,
1043 pango_font_description_get_family (
1044 text->font_desc));
1045 break;
1047 case PROP_STYLE:
1048 g_value_set_enum (
1049 value,
1050 pango_font_description_get_style (
1051 text->font_desc));
1052 break;
1054 case PROP_VARIANT:
1055 g_value_set_enum (
1056 value,
1057 pango_font_description_get_variant (
1058 text->font_desc));
1059 break;
1061 case PROP_WEIGHT:
1062 g_value_set_int (
1063 value,
1064 pango_font_description_get_weight (
1065 text->font_desc));
1066 break;
1068 case PROP_STRETCH:
1069 g_value_set_enum (
1070 value,
1071 pango_font_description_get_stretch (
1072 text->font_desc));
1073 break;
1075 case PROP_SIZE:
1076 g_value_set_int (
1077 value,
1078 pango_font_description_get_size (
1079 text->font_desc));
1080 break;
1082 case PROP_SIZE_POINTS:
1083 g_value_set_double (
1084 value, ((gdouble)
1085 pango_font_description_get_size (
1086 text->font_desc)) / (gdouble) PANGO_SCALE);
1087 break;
1089 break;
1091 case PROP_FAMILY_SET:
1092 case PROP_STYLE_SET:
1093 case PROP_VARIANT_SET:
1094 case PROP_WEIGHT_SET:
1095 case PROP_STRETCH_SET:
1096 case PROP_SIZE_SET:
1098 PangoFontMask set_mask = text->font_desc ?
1099 pango_font_description_get_set_fields (text->font_desc) : 0;
1100 PangoFontMask test_mask = get_property_font_set_mask (param_id);
1101 g_value_set_boolean (value, (set_mask & test_mask) != 0);
1103 break;
1106 case PROP_SCALE:
1107 g_value_set_double (value, text->scale);
1108 break;
1109 case PROP_SCALE_SET:
1110 g_value_set_boolean (value, text->scale_set);
1111 break;
1113 case PROP_UNDERLINE:
1114 g_value_set_enum (value, text->underline);
1115 break;
1116 case PROP_UNDERLINE_SET:
1117 g_value_set_boolean (value, text->underline_set);
1118 break;
1120 case PROP_STRIKETHROUGH:
1121 g_value_set_boolean (value, text->strikethrough);
1122 break;
1123 case PROP_STRIKETHROUGH_SET:
1124 g_value_set_boolean (value, text->strike_set);
1125 break;
1127 case PROP_RISE:
1128 g_value_set_int (value, text->rise);
1129 break;
1130 case PROP_RISE_SET:
1131 g_value_set_boolean (value, text->rise_set);
1132 break;
1134 case PROP_ATTRIBUTES:
1135 g_value_set_boxed (value, text->attr_list);
1136 break;
1138 case PROP_JUSTIFICATION:
1139 g_value_set_enum (value, text->justification);
1140 break;
1142 case PROP_CLIP_WIDTH:
1143 g_value_set_double (value, text->clip_width);
1144 break;
1146 case PROP_CLIP_HEIGHT:
1147 g_value_set_double (value, text->clip_height);
1148 break;
1150 case PROP_CLIP:
1151 g_value_set_boolean (value, text->clip);
1152 break;
1154 case PROP_X_OFFSET:
1155 g_value_set_double (value, text->xofs);
1156 break;
1158 case PROP_Y_OFFSET:
1159 g_value_set_double (value, text->yofs);
1160 break;
1162 case PROP_FILL_COLOR_RGBA:
1163 g_value_set_uint (value, text->rgba);
1164 break;
1166 case PROP_TEXT_WIDTH:
1167 g_value_set_double (value, text->max_width);
1168 break;
1170 case PROP_TEXT_HEIGHT:
1171 g_value_set_double (value, text->height);
1172 break;
1174 default:
1175 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1176 break;
1180 /* */
1181 static void
1182 gnome_canvas_text_apply_font_desc (GnomeCanvasText *text)
1184 PangoFontDescription *font_desc;
1185 PangoContext *pango_context;
1186 GtkWidget *widget;
1188 widget = GTK_WIDGET (GNOME_CANVAS_ITEM (text)->canvas);
1189 pango_context = gtk_widget_create_pango_context (widget);
1190 font_desc = pango_font_description_copy (pango_context_get_font_description (pango_context));
1191 g_object_unref (pango_context);
1193 if (text->font_desc)
1194 pango_font_description_merge (font_desc, text->font_desc, TRUE);
1196 pango_layout_set_font_description (text->layout, font_desc);
1197 pango_font_description_free (font_desc);
1200 static void
1201 add_attr (PangoAttrList *attr_list,
1202 PangoAttribute *attr)
1204 attr->start_index = 0;
1205 attr->end_index = G_MAXINT;
1207 pango_attr_list_insert (attr_list, attr);
1210 /* */
1211 static void
1212 gnome_canvas_text_apply_attributes (GnomeCanvasText *text)
1214 PangoAttrList *attr_list;
1216 if (text->attr_list)
1217 attr_list = pango_attr_list_copy (text->attr_list);
1218 else
1219 attr_list = pango_attr_list_new ();
1221 if (text->underline_set)
1222 add_attr (attr_list, pango_attr_underline_new (text->underline));
1223 if (text->strike_set)
1224 add_attr (attr_list, pango_attr_strikethrough_new (text->strikethrough));
1225 if (text->rise_set)
1226 add_attr (attr_list, pango_attr_rise_new (text->rise));
1228 pango_layout_set_attributes (text->layout, attr_list);
1229 pango_attr_list_unref (attr_list);
1232 static void
1233 gnome_canvas_text_set_font_desc (GnomeCanvasText *text,
1234 PangoFontDescription *font_desc)
1236 if (text->font_desc)
1237 pango_font_description_free (text->font_desc);
1239 if (font_desc)
1240 text->font_desc = pango_font_description_copy (font_desc);
1241 else
1242 text->font_desc = NULL;
1244 gnome_canvas_text_apply_font_desc (text);
1247 /* Setting the text from a Pango markup string */
1248 static void
1249 gnome_canvas_text_set_markup (GnomeCanvasText *textitem,
1250 const gchar *markup)
1252 PangoAttrList *attr_list = NULL;
1253 gchar *text = NULL;
1254 GError *error = NULL;
1256 if (markup && !pango_parse_markup (markup, -1,
1258 &attr_list, &text, NULL,
1259 &error))
1261 g_warning (
1262 "Failed to set cell text from markup due to "
1263 "error parsing markup: %s", error->message);
1264 g_error_free (error);
1265 return;
1268 g_free (textitem->text);
1269 if (textitem->attr_list)
1270 pango_attr_list_unref (textitem->attr_list);
1272 textitem->text = text;
1273 textitem->attr_list = attr_list;
1275 pango_layout_set_text (textitem->layout, text, -1);
1277 gnome_canvas_text_apply_attributes (textitem);
1280 /* Update handler for the text item */
1281 static void
1282 gnome_canvas_text_update (GnomeCanvasItem *item,
1283 const cairo_matrix_t *matrix,
1284 gint flags)
1286 GnomeCanvasText *text;
1287 gdouble x1, y1, x2, y2;
1289 text = GNOME_CANVAS_TEXT (item);
1291 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_text_parent_class)->
1292 update (item, matrix, flags);
1294 get_bounds (text, &x1, &y1, &x2, &y2);
1296 gnome_canvas_update_bbox (
1297 item,
1298 floor (x1), floor (y1),
1299 ceil (x2), ceil (y2));
1302 /* Draw handler for the text item */
1303 static void
1304 gnome_canvas_text_draw (GnomeCanvasItem *item,
1305 cairo_t *cr,
1306 gint x,
1307 gint y,
1308 gint width,
1309 gint height)
1311 GnomeCanvasText *text = GNOME_CANVAS_TEXT (item);
1313 if (!text->text)
1314 return;
1316 cairo_save (cr);
1318 if (text->clip) {
1319 cairo_rectangle (
1321 text->clip_cx - x,
1322 text->clip_cy - y,
1323 text->clip_cwidth,
1324 text->clip_cheight);
1325 cairo_clip (cr);
1328 cairo_set_source_rgba (
1330 ((text->rgba >> 24) & 0xff) / 255.0,
1331 ((text->rgba >> 16) & 0xff) / 255.0,
1332 ((text->rgba >> 8) & 0xff) / 255.0,
1333 ( text->rgba & 0xff) / 255.0);
1335 cairo_move_to (cr, text->cx - x, text->cy - y);
1336 pango_cairo_show_layout (cr, text->layout);
1338 cairo_restore (cr);
1341 /* Point handler for the text item */
1342 static GnomeCanvasItem *
1343 gnome_canvas_text_point (GnomeCanvasItem *item,
1344 gdouble x,
1345 gdouble y,
1346 gint cx,
1347 gint cy)
1349 GnomeCanvasText *text;
1350 PangoLayoutIter *iter;
1351 gint x1, y1, x2, y2;
1353 text = GNOME_CANVAS_TEXT (item);
1355 /* The idea is to build bounding rectangles for each of the lines of
1356 * text (clipped by the clipping rectangle, if it is activated) and see
1357 * whether the point is inside any of these. If it is, we are done.
1358 * Otherwise, calculate the distance to the nearest rectangle.
1361 iter = pango_layout_get_iter (text->layout);
1362 do {
1363 PangoRectangle log_rect;
1365 pango_layout_iter_get_line_extents (iter, NULL, &log_rect);
1367 x1 = text->cx + PANGO_PIXELS (log_rect.x);
1368 y1 = text->cy + PANGO_PIXELS (log_rect.y);
1369 x2 = x1 + PANGO_PIXELS (log_rect.width);
1370 y2 = y1 + PANGO_PIXELS (log_rect.height);
1372 if (text->clip) {
1373 if (x1 < text->clip_cx)
1374 x1 = text->clip_cx;
1376 if (y1 < text->clip_cy)
1377 y1 = text->clip_cy;
1379 if (x2 > (text->clip_cx + text->clip_width))
1380 x2 = text->clip_cx + text->clip_width;
1382 if (y2 > (text->clip_cy + text->clip_height))
1383 y2 = text->clip_cy + text->clip_height;
1385 if ((x1 >= x2) || (y1 >= y2))
1386 continue;
1389 /* Calculate distance from point to rectangle */
1391 if (cx >= x1 && cx < x2 && cy >= y1 && cy < y2) {
1392 pango_layout_iter_free (iter);
1393 return item;
1396 } while (pango_layout_iter_next_line (iter));
1398 pango_layout_iter_free (iter);
1400 return NULL;
1403 /* Bounds handler for the text item */
1404 static void
1405 gnome_canvas_text_bounds (GnomeCanvasItem *item,
1406 gdouble *x1,
1407 gdouble *y1,
1408 gdouble *x2,
1409 gdouble *y2)
1411 GnomeCanvasText *text;
1412 gdouble width, height;
1414 text = GNOME_CANVAS_TEXT (item);
1416 *x1 = text->x;
1417 *y1 = text->y;
1419 if (text->clip) {
1420 width = text->clip_width;
1421 height = text->clip_height;
1422 } else {
1423 width = text->max_width;
1424 height = text->height;
1427 *x2 = *x1 + width;
1428 *y2 = *y1 + height;