1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * label_object.c: GLabels label object base class
8 * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "label-object.h"
28 #include <glib/gmem.h>
29 #include <glib/gstrfuncs.h>
30 #include <glib/gmessages.h>
38 /*========================================================*/
39 /* Private defines. */
40 /*========================================================*/
42 #define DEFAULT_SHADOW_X_OFFSET (3.6)
43 #define DEFAULT_SHADOW_Y_OFFSET (3.6)
44 #define DEFAULT_SHADOW_OPACITY (0.5)
46 /*========================================================*/
48 /*========================================================*/
50 struct _glLabelObjectPrivate {
54 cairo_matrix_t matrix;
58 gboolean shadow_state;
61 glColorNode *shadow_color_node;
62 gdouble shadow_opacity;
75 /*========================================================*/
76 /* Private globals. */
77 /*========================================================*/
79 static guint signals[LAST_SIGNAL] = {0};
81 static guint instance = 0;
83 /*========================================================*/
84 /* Private function prototypes. */
85 /*========================================================*/
87 static void gl_label_object_finalize (GObject *object);
89 static void merge_changed_cb (glLabel *label,
90 glLabelObject *object);
92 static void set_size (glLabelObject *object,
98 /*****************************************************************************/
99 /* Boilerplate object stuff. */
100 /*****************************************************************************/
101 G_DEFINE_TYPE (glLabelObject, gl_label_object, G_TYPE_OBJECT);
104 gl_label_object_class_init (glLabelObjectClass *class)
106 GObjectClass *object_class = G_OBJECT_CLASS (class);
108 gl_debug (DEBUG_LABEL, "START");
110 gl_label_object_parent_class = g_type_class_peek_parent (class);
112 object_class->finalize = gl_label_object_finalize;
114 class->set_size = set_size;
117 g_signal_new ("changed",
118 G_OBJECT_CLASS_TYPE (object_class),
120 G_STRUCT_OFFSET (glLabelObjectClass, changed),
122 gl_marshal_VOID__VOID,
127 g_signal_new ("moved",
128 G_OBJECT_CLASS_TYPE (object_class),
130 G_STRUCT_OFFSET (glLabelObjectClass, moved),
132 gl_marshal_VOID__DOUBLE_DOUBLE,
134 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
135 signals[FLIP_ROTATE] =
136 g_signal_new ("flip_rotate",
137 G_OBJECT_CLASS_TYPE (object_class),
139 G_STRUCT_OFFSET (glLabelObjectClass, flip_rotate),
141 gl_marshal_VOID__VOID,
146 G_OBJECT_CLASS_TYPE (object_class),
148 G_STRUCT_OFFSET (glLabelObjectClass, top),
150 gl_marshal_VOID__VOID,
155 g_signal_new ("bottom",
156 G_OBJECT_CLASS_TYPE (object_class),
158 G_STRUCT_OFFSET (glLabelObjectClass, bottom),
160 gl_marshal_VOID__VOID,
164 g_signal_new ("removed",
165 G_OBJECT_CLASS_TYPE (object_class),
167 G_STRUCT_OFFSET (glLabelObjectClass, removed),
169 gl_marshal_VOID__VOID,
173 gl_debug (DEBUG_LABEL, "END");
177 gl_label_object_init (glLabelObject *object)
179 gl_debug (DEBUG_LABEL, "START");
181 object->priv = g_new0 (glLabelObjectPrivate, 1);
183 object->priv->name = g_strdup_printf ("object%d", instance++);
185 cairo_matrix_init_identity (&object->priv->matrix);
187 object->priv->shadow_state = FALSE;
188 object->priv->shadow_x = DEFAULT_SHADOW_X_OFFSET;
189 object->priv->shadow_y = DEFAULT_SHADOW_Y_OFFSET;
190 object->priv->shadow_color_node = gl_color_node_new_default ();
191 object->priv->shadow_opacity = DEFAULT_SHADOW_OPACITY;
193 gl_debug (DEBUG_LABEL, "END");
197 gl_label_object_finalize (GObject *object)
199 glLabelObject *label_object = GL_LABEL_OBJECT (object);
201 gl_debug (DEBUG_LABEL, "START");
203 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
205 g_free (label_object->priv->name);
206 g_free (label_object->priv);
208 G_OBJECT_CLASS (gl_label_object_parent_class)->finalize (object);
210 gl_debug (DEBUG_LABEL, "END");
213 /*****************************************************************************/
214 /* New label object. */
215 /*****************************************************************************/
217 gl_label_object_new (glLabel *label)
219 glLabelObject *object;
221 gl_debug (DEBUG_LABEL, "START");
223 object = g_object_new (gl_label_object_get_type(), NULL);
225 gl_label_object_set_parent (object, label);
227 gl_debug (DEBUG_LABEL, "END");
229 return G_OBJECT (object);
232 /*****************************************************************************/
233 /* Duplicate object. */
234 /*****************************************************************************/
236 gl_label_object_dup (glLabelObject *src_object,
239 glLabelObject *dst_object;
241 cairo_matrix_t matrix;
242 gboolean shadow_state;
243 gdouble shadow_x, shadow_y;
244 glColorNode *shadow_color_node;
245 gdouble shadow_opacity;
247 gl_debug (DEBUG_LABEL, "START");
249 g_return_val_if_fail (src_object && GL_IS_LABEL_OBJECT (src_object), NULL);
251 dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
253 gl_label_object_set_parent (dst_object, label);
255 gl_label_object_get_position (src_object, &x, &y);
256 gl_label_object_get_size (src_object, &w, &h);
257 gl_label_object_get_matrix (src_object, &matrix);
258 gl_label_object_get_shadow_offset (src_object, &shadow_x, &shadow_y);
259 shadow_color_node = gl_label_object_get_shadow_color (src_object);
260 shadow_opacity = gl_label_object_get_shadow_opacity (src_object);
261 shadow_state = gl_label_object_get_shadow_state (src_object);
263 gl_label_object_set_position (dst_object, x, y);
264 gl_label_object_set_size (dst_object, w, h);
265 gl_label_object_set_matrix (dst_object, &matrix);
266 gl_label_object_set_shadow_offset (dst_object, shadow_x, shadow_y);
267 gl_label_object_set_shadow_color (dst_object, shadow_color_node);
268 gl_label_object_set_shadow_opacity (dst_object, shadow_opacity);
269 gl_label_object_set_shadow_state (dst_object, shadow_state);
271 gl_color_node_free (&shadow_color_node);
273 if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL ) {
275 /* We have an object specific method, use it */
276 GL_LABEL_OBJECT_GET_CLASS(src_object)->copy (dst_object, src_object);
280 gl_debug (DEBUG_LABEL, "END");
285 /*****************************************************************************/
286 /* Emit "changed" signal (for derived objects). */
287 /*****************************************************************************/
289 gl_label_object_emit_changed (glLabelObject *object)
291 gl_debug (DEBUG_LABEL, "START");
293 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
295 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
297 gl_debug (DEBUG_LABEL, "END");
300 /*****************************************************************************/
301 /* Set parent label of object. */
302 /*****************************************************************************/
304 gl_label_object_set_parent (glLabelObject *object,
309 gl_debug (DEBUG_LABEL, "START");
311 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
312 g_return_if_fail (label && GL_IS_LABEL (label));
314 old_parent = object->parent;
315 if ( old_parent != NULL ) {
316 g_signal_handlers_disconnect_by_func (old_parent,
317 G_CALLBACK(merge_changed_cb),
319 gl_label_remove_object( old_parent, object );
321 gl_label_add_object( label, object );
323 g_signal_connect (G_OBJECT(label), "merge_changed",
324 G_CALLBACK(merge_changed_cb), object);
326 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
328 gl_debug (DEBUG_LABEL, "END");
331 /*****************************************************************************/
332 /* Get parent label of object. */
333 /*****************************************************************************/
335 gl_label_object_get_parent (glLabelObject *object)
337 gl_debug (DEBUG_LABEL, "START");
339 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
341 gl_debug (DEBUG_LABEL, "END");
343 return object->parent;
346 /*****************************************************************************/
347 /* Set remove object from parent. */
348 /*****************************************************************************/
350 gl_label_object_remove (glLabelObject *object)
354 gl_debug (DEBUG_LABEL, "START");
356 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
358 parent = object->parent;
359 if ( parent != NULL ) {
360 g_signal_handlers_disconnect_by_func (parent,
361 G_CALLBACK(merge_changed_cb),
363 gl_label_remove_object (parent, object);
365 g_signal_emit (G_OBJECT(object), signals[REMOVED], 0);
367 g_object_unref (G_OBJECT(object));
371 gl_debug (DEBUG_LABEL, "END");
374 /*****************************************************************************/
375 /* Set name of object. */
376 /*****************************************************************************/
378 gl_label_object_set_name (glLabelObject *object,
381 gl_debug (DEBUG_LABEL, "START");
383 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
385 g_free(object->priv->name);
386 object->priv->name = name;
388 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
390 gl_debug (DEBUG_LABEL, "END");
393 /*****************************************************************************/
394 /* Get name of object. */
395 /*****************************************************************************/
397 gl_label_object_get_name (glLabelObject *object)
399 gl_debug (DEBUG_LABEL, "START");
401 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
403 gl_debug (DEBUG_LABEL, "END");
405 return g_strdup(object->priv->name);
408 /*****************************************************************************/
409 /* Set position of object. */
410 /*****************************************************************************/
412 gl_label_object_set_position (glLabelObject *object,
418 gl_debug (DEBUG_LABEL, "START");
420 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
422 if ( (x != object->priv->x) || (y != object->priv->y) ) {
424 dx = x - object->priv->x;
425 dy = y - object->priv->y;
430 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
434 gl_debug (DEBUG_LABEL, "END");
437 /*****************************************************************************/
438 /* Set position of object relative to old position. */
439 /*****************************************************************************/
441 gl_label_object_set_position_relative (glLabelObject *object,
445 gl_debug (DEBUG_LABEL, "START");
447 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
449 if ( (dx != 0.0) || (dy != 0.0) ) {
451 object->priv->x += dx;
452 object->priv->y += dy;
454 gl_debug (DEBUG_LABEL, " x = %f, y= %f",
458 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
462 gl_debug (DEBUG_LABEL, "END");
465 /*****************************************************************************/
466 /* Get position of object. */
467 /*****************************************************************************/
469 gl_label_object_get_position (glLabelObject *object,
473 gl_debug (DEBUG_LABEL, "START");
475 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
477 *x = object->priv->x;
478 *y = object->priv->y;
480 gl_debug (DEBUG_LABEL, "END");
483 /*---------------------------------------------------------------------------*/
484 /* PRIVATE. Default set size method. */
485 /*---------------------------------------------------------------------------*/
487 set_size (glLabelObject *object,
491 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
493 if ( (object->priv->w != w) || (object->priv->h != h) ) {
498 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
502 /*****************************************************************************/
503 /* Set size of object. */
504 /*****************************************************************************/
506 gl_label_object_set_size (glLabelObject *object,
510 gl_debug (DEBUG_LABEL, "START");
512 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
514 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
516 /* We have an object specific method, use it */
517 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
519 object->priv->aspect_ratio = h / w;
524 gl_debug (DEBUG_LABEL, "END");
527 /*****************************************************************************/
528 /* Set size of object honoring current aspect ratio. */
529 /*****************************************************************************/
531 gl_label_object_set_size_honor_aspect (glLabelObject *object,
535 gl_debug (DEBUG_LABEL, "START");
537 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
539 if ( h > w*object->priv->aspect_ratio ) {
541 h = w * object->priv->aspect_ratio;
545 w = h / object->priv->aspect_ratio;
549 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
551 /* We have an object specific method, use it */
552 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
556 gl_debug (DEBUG_LABEL, "END");
559 /*****************************************************************************/
560 /* Get raw size method (don't let object content adjust size). */
561 /*****************************************************************************/
563 gl_label_object_get_raw_size (glLabelObject *object,
567 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
569 *w = object->priv->w;
570 *h = object->priv->h;
573 /*****************************************************************************/
574 /* Get size of object. */
575 /*****************************************************************************/
577 gl_label_object_get_size (glLabelObject *object,
581 gl_debug (DEBUG_LABEL, "START");
583 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
585 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL ) {
587 /* We have an object specific method, use it */
588 GL_LABEL_OBJECT_GET_CLASS(object)->get_size (object, w, h);
592 gl_label_object_get_raw_size (object, w, h);
596 gl_debug (DEBUG_LABEL, "END");
599 /*****************************************************************************/
600 /* Get extent of object. */
601 /*****************************************************************************/
603 gl_label_object_get_extent (glLabelObject *object,
604 glLabelRegion *region)
608 gdouble xa1, ya1, xa2, ya2, xa3, ya3, xa4, ya4;
609 cairo_matrix_t matrix;
611 gl_debug (DEBUG_LABEL, "START");
613 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
615 gl_label_object_get_size (object, &w, &h);
616 line_w = gl_label_object_get_line_width (object);
618 /* setup untransformed corners of bounding box, account for line width */
628 /* transform these points */
629 gl_label_object_get_matrix (object, &matrix);
630 cairo_matrix_transform_point (&matrix, &xa1, &ya1);
631 cairo_matrix_transform_point (&matrix, &xa2, &ya2);
632 cairo_matrix_transform_point (&matrix, &xa3, &ya3);
633 cairo_matrix_transform_point (&matrix, &xa4, &ya4);
635 /* now find the maximum extent of these points in x and y */
636 region->x1 = MIN (xa1, MIN (xa2, MIN (xa3, xa4))) + object->priv->x;
637 region->y1 = MIN (ya1, MIN (ya2, MIN (ya3, ya4))) + object->priv->y;
638 region->x2 = MAX (xa1, MAX (xa2, MAX (xa3, xa4))) + object->priv->x;
639 region->y2 = MAX (ya1, MAX (ya2, MAX (ya3, ya4))) + object->priv->y;
641 gl_debug (DEBUG_LABEL, "END");
644 /*****************************************************************************/
645 /* Can text properties be set for this object? */
646 /*****************************************************************************/
648 gl_label_object_can_text (glLabelObject *object)
650 gl_debug (DEBUG_LABEL, "");
652 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
654 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
666 /*****************************************************************************/
667 /* Set font family for all text contained in object. */
668 /*****************************************************************************/
670 gl_label_object_set_font_family (glLabelObject *object,
671 const gchar *font_family)
673 gl_debug (DEBUG_LABEL, "START");
675 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
677 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
679 /* We have an object specific method, use it */
680 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family);
684 gl_debug (DEBUG_LABEL, "END");
687 /****************************************************************************/
688 /* Set font size for all text contained in object. */
689 /****************************************************************************/
691 gl_label_object_set_font_size (glLabelObject *object,
694 gl_debug (DEBUG_LABEL, "START");
696 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
698 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL ) {
700 /* We have an object specific method, use it */
701 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size);
705 gl_debug (DEBUG_LABEL, "END");
708 /****************************************************************************/
709 /* Set font weight for all text contained in object. */
710 /****************************************************************************/
712 gl_label_object_set_font_weight (glLabelObject *object,
713 PangoWeight font_weight)
715 gl_debug (DEBUG_LABEL, "START");
717 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
719 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL ) {
721 /* We have an object specific method, use it */
722 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight);
726 gl_debug (DEBUG_LABEL, "END");
729 /****************************************************************************/
730 /* Set font italic flag for all text contained in object. */
731 /****************************************************************************/
733 gl_label_object_set_font_italic_flag (glLabelObject *object,
734 gboolean font_italic_flag)
736 gl_debug (DEBUG_LABEL, "START");
738 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
740 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL ) {
742 /* We have an object specific method, use it */
743 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object,
748 gl_debug (DEBUG_LABEL, "END");
751 /****************************************************************************/
752 /* Set text alignment for all text contained in object. */
753 /****************************************************************************/
755 gl_label_object_set_text_alignment (glLabelObject *object,
756 PangoAlignment text_alignment)
758 gl_debug (DEBUG_LABEL, "START");
760 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
762 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL ) {
764 /* We have an object specific method, use it */
765 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object,
770 gl_debug (DEBUG_LABEL, "END");
773 /****************************************************************************/
774 /* Set text line spacing for all text contained in object. */
775 /****************************************************************************/
777 gl_label_object_set_text_line_spacing (glLabelObject *object,
778 gdouble text_line_spacing)
780 gl_debug (DEBUG_LABEL, "START");
782 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
784 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL ) {
786 /* We have an object specific method, use it */
787 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing);
791 gl_debug (DEBUG_LABEL, "END");
794 /****************************************************************************/
795 /* Set text color for all text contained in object. */
796 /****************************************************************************/
798 gl_label_object_set_text_color (glLabelObject *object,
799 glColorNode *text_color_node)
801 gl_debug (DEBUG_LABEL, "START");
803 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
805 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL ) {
807 /* We have an object specific method, use it */
808 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node);
812 gl_debug (DEBUG_LABEL, "END");
815 /*****************************************************************************/
816 /* Get font family for all text contained in object. */
817 /*****************************************************************************/
819 gl_label_object_get_font_family (glLabelObject *object)
823 gl_debug (DEBUG_LABEL, "START");
825 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
827 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL ) {
829 /* We have an object specific method, use it */
830 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family (object);
834 gl_debug (DEBUG_LABEL, "END");
839 /****************************************************************************/
840 /* Get font size for all text contained in object. */
841 /****************************************************************************/
843 gl_label_object_get_font_size (glLabelObject *object)
847 gl_debug (DEBUG_LABEL, "START");
849 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
851 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL ) {
853 /* We have an object specific method, use it */
854 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size (object);
858 gl_debug (DEBUG_LABEL, "END");
863 /****************************************************************************/
864 /* Get font weight for all text contained in object. */
865 /****************************************************************************/
867 gl_label_object_get_font_weight (glLabelObject *object)
869 PangoWeight ret = PANGO_WEIGHT_NORMAL;
871 gl_debug (DEBUG_LABEL, "START");
873 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_WEIGHT_NORMAL);
875 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL ) {
877 /* We have an object specific method, use it */
878 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight (object);
882 gl_debug (DEBUG_LABEL, "END");
887 /****************************************************************************/
888 /* Get font italic flag for all text contained in object. */
889 /****************************************************************************/
891 gl_label_object_get_font_italic_flag (glLabelObject *object)
893 gboolean ret = FALSE;
895 gl_debug (DEBUG_LABEL, "START");
897 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
899 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL ) {
901 /* We have an object specific method, use it */
902 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag (object);
906 gl_debug (DEBUG_LABEL, "END");
911 /****************************************************************************/
912 /* Get text alignment for all text contained in object. */
913 /****************************************************************************/
915 gl_label_object_get_text_alignment (glLabelObject *object)
917 PangoAlignment ret = PANGO_ALIGN_LEFT;
919 gl_debug (DEBUG_LABEL, "START");
921 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_ALIGN_LEFT);
923 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL ) {
925 /* We have an object specific method, use it */
926 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment (object);
930 gl_debug (DEBUG_LABEL, "END");
935 /****************************************************************************/
936 /* Get text line spacing for all text contained in object. */
937 /****************************************************************************/
939 gl_label_object_get_text_line_spacing (glLabelObject *object)
943 gl_debug (DEBUG_LABEL, "START");
945 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
947 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL ) {
949 /* We have an object specific method, use it */
950 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing (object);
954 gl_debug (DEBUG_LABEL, "END");
959 /****************************************************************************/
960 /* Get text color for all text contained in object. */
961 /****************************************************************************/
963 gl_label_object_get_text_color (glLabelObject *object)
965 glColorNode *ret = NULL;
967 gl_debug (DEBUG_LABEL, "START");
969 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
971 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL ) {
973 /* We have an object specific method, use it */
974 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color (object);
978 gl_debug (DEBUG_LABEL, "END");
983 /*****************************************************************************/
984 /* Can fill properties be set for this object? */
985 /*****************************************************************************/
987 gl_label_object_can_fill (glLabelObject *object)
989 gl_debug (DEBUG_LABEL, "");
991 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
993 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
1005 /****************************************************************************/
1006 /* Set fill color for object. */
1007 /****************************************************************************/
1009 gl_label_object_set_fill_color (glLabelObject *object,
1010 glColorNode *fill_color_node)
1012 gl_debug (DEBUG_LABEL, "START");
1014 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1016 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
1018 /* We have an object specific method, use it */
1019 GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node);
1023 gl_debug (DEBUG_LABEL, "END");
1026 /****************************************************************************/
1027 /* Get fill color for object. */
1028 /****************************************************************************/
1030 gl_label_object_get_fill_color (glLabelObject *object)
1032 glColorNode *ret = NULL;
1034 gl_debug (DEBUG_LABEL, "START");
1036 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1038 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL ) {
1040 /* We have an object specific method, use it */
1041 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color (object);
1045 gl_debug (DEBUG_LABEL, "END");
1050 /*****************************************************************************/
1051 /* Can line color property be set for this object? */
1052 /*****************************************************************************/
1054 gl_label_object_can_line_color (glLabelObject *object)
1056 gl_debug (DEBUG_LABEL, "");
1058 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1060 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
1072 /****************************************************************************/
1073 /* Set line color for object. */
1074 /****************************************************************************/
1076 gl_label_object_set_line_color (glLabelObject *object,
1077 glColorNode *line_color_node)
1079 gl_debug (DEBUG_LABEL, "START");
1081 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1083 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
1085 /* We have an object specific method, use it */
1086 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node);
1090 gl_debug (DEBUG_LABEL, "END");
1093 /****************************************************************************/
1094 /* Get line color for object. */
1095 /****************************************************************************/
1097 gl_label_object_get_line_color (glLabelObject *object)
1099 glColorNode *ret = NULL;
1101 gl_debug (DEBUG_LABEL, "START");
1103 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1105 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL ) {
1107 /* We have an object specific method, use it */
1108 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color (object);
1112 gl_debug (DEBUG_LABEL, "END");
1117 /*****************************************************************************/
1118 /* Can line width property be set for this object? */
1119 /*****************************************************************************/
1121 gl_label_object_can_line_width (glLabelObject *object)
1123 gl_debug (DEBUG_LABEL, "");
1125 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1127 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1139 /****************************************************************************/
1140 /* Set line width for object. */
1141 /****************************************************************************/
1143 gl_label_object_set_line_width (glLabelObject *object,
1146 gl_debug (DEBUG_LABEL, "START");
1148 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1150 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1152 /* We have an object specific method, use it */
1153 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width);
1157 gl_debug (DEBUG_LABEL, "END");
1160 /****************************************************************************/
1161 /* Get line width for object. */
1162 /****************************************************************************/
1164 gl_label_object_get_line_width (glLabelObject *object)
1168 gl_debug (DEBUG_LABEL, "START");
1170 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
1172 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL ) {
1174 /* We have an object specific method, use it */
1175 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width (object);
1179 gl_debug (DEBUG_LABEL, "END");
1184 /****************************************************************************/
1185 /* Set shadow state of object. */
1186 /****************************************************************************/
1188 gl_label_object_set_shadow_state (glLabelObject *object,
1191 gl_debug (DEBUG_LABEL, "START");
1193 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1195 if (object->priv->shadow_state != state)
1197 object->priv->shadow_state = state;
1198 gl_label_object_emit_changed (object);
1201 gl_debug (DEBUG_LABEL, "END");
1204 /****************************************************************************/
1205 /* Get shadow state of object. */
1206 /****************************************************************************/
1208 gl_label_object_get_shadow_state (glLabelObject *object)
1210 gl_debug (DEBUG_LABEL, "");
1212 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1214 return object->priv->shadow_state;
1217 /****************************************************************************/
1218 /* Set offset of object's shadow. */
1219 /****************************************************************************/
1221 gl_label_object_set_shadow_offset (glLabelObject *object,
1225 gl_debug (DEBUG_LABEL, "START");
1227 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1229 if ( (x != object->priv->shadow_x) || (y != object->priv->shadow_y) )
1231 object->priv->shadow_x = x;
1232 object->priv->shadow_y = y;
1234 gl_label_object_emit_changed (object);
1237 gl_debug (DEBUG_LABEL, "END");
1240 /****************************************************************************/
1241 /* Get offset of object's shadow. */
1242 /****************************************************************************/
1244 gl_label_object_get_shadow_offset (glLabelObject *object,
1248 gl_debug (DEBUG_LABEL, "START");
1250 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1252 *x = object->priv->shadow_x;
1253 *y = object->priv->shadow_y;
1255 gl_debug (DEBUG_LABEL, "END");
1258 /****************************************************************************/
1259 /* Set color of object's shadow. */
1260 /****************************************************************************/
1262 gl_label_object_set_shadow_color (glLabelObject *object,
1263 glColorNode *color_node)
1265 gl_debug (DEBUG_LABEL, "START");
1267 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1269 if ( !gl_color_node_equal (object->priv->shadow_color_node, color_node ))
1271 gl_color_node_free (&(object->priv->shadow_color_node));
1272 object->priv->shadow_color_node = gl_color_node_dup (color_node);
1273 gl_label_object_emit_changed (GL_LABEL_OBJECT(object));
1276 gl_debug (DEBUG_LABEL, "END");
1279 /****************************************************************************/
1280 /* Get color of object's shadow. */
1281 /****************************************************************************/
1283 gl_label_object_get_shadow_color (glLabelObject *object)
1285 gl_debug (DEBUG_LABEL, "");
1287 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
1289 return gl_color_node_dup (object->priv->shadow_color_node);
1292 /****************************************************************************/
1293 /* Set opacity of object's shadow. */
1294 /****************************************************************************/
1296 gl_label_object_set_shadow_opacity (glLabelObject *object,
1299 gl_debug (DEBUG_LABEL, "START");
1301 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1303 if (object->priv->shadow_opacity != alpha)
1305 object->priv->shadow_opacity = alpha;
1306 gl_label_object_emit_changed (object);
1309 gl_debug (DEBUG_LABEL, "END");
1312 /****************************************************************************/
1313 /* Get opacity of object's shadow. */
1314 /****************************************************************************/
1316 gl_label_object_get_shadow_opacity (glLabelObject *object)
1318 gl_debug (DEBUG_LABEL, "");
1320 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1322 return object->priv->shadow_opacity;
1325 /****************************************************************************/
1326 /* Flip object horizontally. */
1327 /****************************************************************************/
1329 gl_label_object_flip_horiz (glLabelObject *object)
1331 cairo_matrix_t flip_matrix;
1333 gl_debug (DEBUG_LABEL, "START");
1335 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1337 cairo_matrix_init_scale (&flip_matrix, -1.0, 1.0);
1338 cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1340 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1342 gl_debug (DEBUG_LABEL, "END");
1345 /****************************************************************************/
1346 /* Flip object vertically. */
1347 /****************************************************************************/
1349 gl_label_object_flip_vert (glLabelObject *object)
1351 cairo_matrix_t flip_matrix;
1353 gl_debug (DEBUG_LABEL, "START");
1355 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1357 cairo_matrix_init_scale (&flip_matrix, 1.0, -1.0);
1358 cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1360 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1362 gl_debug (DEBUG_LABEL, "END");
1365 /****************************************************************************/
1366 /* Rotate object. */
1367 /****************************************************************************/
1369 gl_label_object_rotate (glLabelObject *object,
1372 cairo_matrix_t rotate_matrix;
1374 gl_debug (DEBUG_LABEL, "START");
1376 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1378 cairo_matrix_init_rotate (&rotate_matrix, theta_degs*(G_PI/180.));
1379 cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &rotate_matrix);
1381 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1383 gl_debug (DEBUG_LABEL, "END");
1386 /****************************************************************************/
1387 /* Set raw affine */
1388 /****************************************************************************/
1390 gl_label_object_set_matrix (glLabelObject *object,
1391 cairo_matrix_t *matrix)
1393 gl_debug (DEBUG_LABEL, "");
1395 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1397 object->priv->matrix = *matrix;
1400 /****************************************************************************/
1401 /* Get raw affine */
1402 /****************************************************************************/
1404 gl_label_object_get_matrix (glLabelObject *object,
1405 cairo_matrix_t *matrix)
1407 gl_debug (DEBUG_LABEL, "");
1409 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1411 *matrix = object->priv->matrix;
1414 /****************************************************************************/
1415 /* Bring label object to front/top. */
1416 /****************************************************************************/
1418 gl_label_object_raise_to_top (glLabelObject *object)
1422 gl_debug (DEBUG_LABEL, "START");
1424 label = object->parent;
1426 gl_label_raise_object_to_top (label, object);
1428 g_signal_emit (G_OBJECT(object), signals[TOP], 0);
1430 gl_debug (DEBUG_LABEL, "END");
1433 /****************************************************************************/
1434 /* Send label object to rear/bottom. */
1435 /****************************************************************************/
1437 gl_label_object_lower_to_bottom (glLabelObject *object)
1441 gl_debug (DEBUG_LABEL, "START");
1443 label = object->parent;
1445 gl_label_lower_object_to_bottom (label, object);
1447 g_signal_emit (G_OBJECT(object), signals[BOTTOM], 0);
1449 gl_debug (DEBUG_LABEL, "END");
1452 /*--------------------------------------------------------------------------*/
1453 /* PRIVATE. Label's merge data changed callback. */
1454 /*--------------------------------------------------------------------------*/
1456 merge_changed_cb (glLabel *label,
1457 glLabelObject *object)
1459 gl_label_object_emit_changed (object);
1462 /*****************************************************************************/
1464 /*****************************************************************************/
1466 gl_label_object_draw (glLabelObject *object,
1468 gboolean screen_flag,
1469 glMergeRecord *record)
1473 cairo_matrix_t matrix;
1474 gboolean shadow_state;
1475 gdouble shadow_x, shadow_y;
1477 gl_debug (DEBUG_LABEL, "START");
1479 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1481 gl_label_object_get_position (object, &x0, &y0);
1482 gl_label_object_get_matrix (object, &matrix);
1485 cairo_translate (cr, x0, y0);
1487 if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow != NULL ) {
1489 shadow_state = gl_label_object_get_shadow_state (object);
1493 gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1496 cairo_translate (cr, shadow_x, shadow_y);
1497 cairo_transform (cr, &matrix);
1499 GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow (object,
1508 if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL ) {
1511 cairo_transform (cr, &matrix);
1513 GL_LABEL_OBJECT_GET_CLASS(object)->draw_object (object,
1523 gl_debug (DEBUG_LABEL, "END");