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);
202 gl_debug (DEBUG_LABEL, "START");
204 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
206 g_free (label_object->priv->name);
207 g_free (label_object->priv);
209 G_OBJECT_CLASS (gl_label_object_parent_class)->finalize (object);
211 gl_debug (DEBUG_LABEL, "END");
214 /*****************************************************************************/
215 /* New label object. */
216 /*****************************************************************************/
218 gl_label_object_new (glLabel *label)
220 glLabelObject *object;
222 gl_debug (DEBUG_LABEL, "START");
224 object = g_object_new (gl_label_object_get_type(), NULL);
226 gl_label_object_set_parent (object, label);
228 gl_debug (DEBUG_LABEL, "END");
230 return G_OBJECT (object);
233 /*****************************************************************************/
234 /* Duplicate object. */
235 /*****************************************************************************/
237 gl_label_object_dup (glLabelObject *src_object,
240 glLabelObject *dst_object;
242 cairo_matrix_t matrix;
243 gboolean shadow_state;
244 gdouble shadow_x, shadow_y;
245 glColorNode *shadow_color_node;
246 gdouble shadow_opacity;
248 gl_debug (DEBUG_LABEL, "START");
250 g_return_val_if_fail (src_object && GL_IS_LABEL_OBJECT (src_object), NULL);
252 dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
254 gl_label_object_set_parent (dst_object, label);
256 gl_label_object_get_position (src_object, &x, &y);
257 gl_label_object_get_size (src_object, &w, &h);
258 gl_label_object_get_matrix (src_object, &matrix);
259 gl_label_object_get_shadow_offset (src_object, &shadow_x, &shadow_y);
260 shadow_color_node = gl_label_object_get_shadow_color (src_object);
261 shadow_opacity = gl_label_object_get_shadow_opacity (src_object);
262 shadow_state = gl_label_object_get_shadow_state (src_object);
264 gl_label_object_set_position (dst_object, x, y);
265 gl_label_object_set_size (dst_object, w, h);
266 gl_label_object_set_matrix (dst_object, &matrix);
267 gl_label_object_set_shadow_offset (dst_object, shadow_x, shadow_y);
268 gl_label_object_set_shadow_color (dst_object, shadow_color_node);
269 gl_label_object_set_shadow_opacity (dst_object, shadow_opacity);
270 gl_label_object_set_shadow_state (dst_object, shadow_state);
272 gl_color_node_free (&shadow_color_node);
274 if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL ) {
276 /* We have an object specific method, use it */
277 GL_LABEL_OBJECT_GET_CLASS(src_object)->copy (dst_object, src_object);
281 gl_debug (DEBUG_LABEL, "END");
286 /*****************************************************************************/
287 /* Emit "changed" signal (for derived objects). */
288 /*****************************************************************************/
290 gl_label_object_emit_changed (glLabelObject *object)
292 gl_debug (DEBUG_LABEL, "START");
294 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
296 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
298 gl_debug (DEBUG_LABEL, "END");
301 /*****************************************************************************/
302 /* Set parent label of object. */
303 /*****************************************************************************/
305 gl_label_object_set_parent (glLabelObject *object,
310 gl_debug (DEBUG_LABEL, "START");
312 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
313 g_return_if_fail (label && GL_IS_LABEL (label));
315 old_parent = object->parent;
316 if ( old_parent != NULL ) {
317 g_signal_handlers_disconnect_by_func (old_parent,
318 G_CALLBACK(merge_changed_cb),
320 gl_label_remove_object( old_parent, object );
322 gl_label_add_object( label, object );
324 g_signal_connect (G_OBJECT(label), "merge_changed",
325 G_CALLBACK(merge_changed_cb), object);
327 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
329 gl_debug (DEBUG_LABEL, "END");
332 /*****************************************************************************/
333 /* Get parent label of object. */
334 /*****************************************************************************/
336 gl_label_object_get_parent (glLabelObject *object)
338 gl_debug (DEBUG_LABEL, "START");
340 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
342 gl_debug (DEBUG_LABEL, "END");
344 return object->parent;
347 /*****************************************************************************/
348 /* Set remove object from parent. */
349 /*****************************************************************************/
351 gl_label_object_remove (glLabelObject *object)
355 gl_debug (DEBUG_LABEL, "START");
357 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
359 parent = object->parent;
360 if ( parent != NULL ) {
361 g_signal_handlers_disconnect_by_func (parent,
362 G_CALLBACK(merge_changed_cb),
364 gl_label_remove_object (parent, object);
366 g_signal_emit (G_OBJECT(object), signals[REMOVED], 0);
368 g_object_unref (G_OBJECT(object));
372 gl_debug (DEBUG_LABEL, "END");
375 /*****************************************************************************/
376 /* Set name of object. */
377 /*****************************************************************************/
379 gl_label_object_set_name (glLabelObject *object,
382 gl_debug (DEBUG_LABEL, "START");
384 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
386 g_free(object->priv->name);
387 object->priv->name = name;
389 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
391 gl_debug (DEBUG_LABEL, "END");
394 /*****************************************************************************/
395 /* Get name of object. */
396 /*****************************************************************************/
398 gl_label_object_get_name (glLabelObject *object)
400 gl_debug (DEBUG_LABEL, "START");
402 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
404 gl_debug (DEBUG_LABEL, "END");
406 return g_strdup(object->priv->name);
409 /*****************************************************************************/
410 /* Set position of object. */
411 /*****************************************************************************/
413 gl_label_object_set_position (glLabelObject *object,
419 gl_debug (DEBUG_LABEL, "START");
421 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
423 if ( (x != object->priv->x) || (y != object->priv->y) ) {
425 dx = x - object->priv->x;
426 dy = y - object->priv->y;
431 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
435 gl_debug (DEBUG_LABEL, "END");
438 /*****************************************************************************/
439 /* Set position of object relative to old position. */
440 /*****************************************************************************/
442 gl_label_object_set_position_relative (glLabelObject *object,
446 gl_debug (DEBUG_LABEL, "START");
448 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
450 if ( (dx != 0.0) || (dy != 0.0) ) {
452 object->priv->x += dx;
453 object->priv->y += dy;
455 gl_debug (DEBUG_LABEL, " x = %f, y= %f",
459 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
463 gl_debug (DEBUG_LABEL, "END");
466 /*****************************************************************************/
467 /* Get position of object. */
468 /*****************************************************************************/
470 gl_label_object_get_position (glLabelObject *object,
474 gl_debug (DEBUG_LABEL, "START");
476 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
478 *x = object->priv->x;
479 *y = object->priv->y;
481 gl_debug (DEBUG_LABEL, "END");
484 /*---------------------------------------------------------------------------*/
485 /* PRIVATE. Default set size method. */
486 /*---------------------------------------------------------------------------*/
488 set_size (glLabelObject *object,
492 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
494 if ( (object->priv->w != w) || (object->priv->h != h) ) {
499 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
503 /*****************************************************************************/
504 /* Set size of object. */
505 /*****************************************************************************/
507 gl_label_object_set_size (glLabelObject *object,
511 gl_debug (DEBUG_LABEL, "START");
513 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
515 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
517 /* We have an object specific method, use it */
518 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
520 object->priv->aspect_ratio = h / w;
525 gl_debug (DEBUG_LABEL, "END");
528 /*****************************************************************************/
529 /* Set size of object honoring current aspect ratio. */
530 /*****************************************************************************/
532 gl_label_object_set_size_honor_aspect (glLabelObject *object,
536 gl_debug (DEBUG_LABEL, "START");
538 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
540 if ( h > w*object->priv->aspect_ratio ) {
542 h = w * object->priv->aspect_ratio;
546 w = h / object->priv->aspect_ratio;
550 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
552 /* We have an object specific method, use it */
553 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
557 gl_debug (DEBUG_LABEL, "END");
560 /*****************************************************************************/
561 /* Get raw size method (don't let object content adjust size). */
562 /*****************************************************************************/
564 gl_label_object_get_raw_size (glLabelObject *object,
568 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
570 *w = object->priv->w;
571 *h = object->priv->h;
574 /*****************************************************************************/
575 /* Get size of object. */
576 /*****************************************************************************/
578 gl_label_object_get_size (glLabelObject *object,
582 gl_debug (DEBUG_LABEL, "START");
584 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
586 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL ) {
588 /* We have an object specific method, use it */
589 GL_LABEL_OBJECT_GET_CLASS(object)->get_size (object, w, h);
593 gl_label_object_get_raw_size (object, w, h);
597 gl_debug (DEBUG_LABEL, "END");
600 /*****************************************************************************/
601 /* Get extent of object. */
602 /*****************************************************************************/
604 gl_label_object_get_extent (glLabelObject *object,
605 glLabelRegion *region)
609 gdouble xa1, ya1, xa2, ya2, xa3, ya3, xa4, ya4;
610 cairo_matrix_t matrix;
612 gl_debug (DEBUG_LABEL, "START");
614 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
616 gl_label_object_get_size (object, &w, &h);
617 line_w = gl_label_object_get_line_width (object);
619 /* setup untransformed corners of bounding box, account for line width */
629 /* transform these points */
630 gl_label_object_get_matrix (object, &matrix);
631 cairo_matrix_transform_point (&matrix, &xa1, &ya1);
632 cairo_matrix_transform_point (&matrix, &xa2, &ya2);
633 cairo_matrix_transform_point (&matrix, &xa3, &ya3);
634 cairo_matrix_transform_point (&matrix, &xa4, &ya4);
636 /* now find the maximum extent of these points in x and y */
637 region->x1 = MIN (xa1, MIN (xa2, MIN (xa3, xa4))) + object->priv->x;
638 region->y1 = MIN (ya1, MIN (ya2, MIN (ya3, ya4))) + object->priv->y;
639 region->x2 = MAX (xa1, MAX (xa2, MAX (xa3, xa4))) + object->priv->x;
640 region->y2 = MAX (ya1, MAX (ya2, MAX (ya3, ya4))) + object->priv->y;
642 gl_debug (DEBUG_LABEL, "END");
645 /*****************************************************************************/
646 /* Can text properties be set for this object? */
647 /*****************************************************************************/
649 gl_label_object_can_text (glLabelObject *object)
651 gl_debug (DEBUG_LABEL, "");
653 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
655 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
667 /*****************************************************************************/
668 /* Set font family for all text contained in object. */
669 /*****************************************************************************/
671 gl_label_object_set_font_family (glLabelObject *object,
672 const gchar *font_family)
674 gl_debug (DEBUG_LABEL, "START");
676 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
678 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
680 /* We have an object specific method, use it */
681 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family);
685 gl_debug (DEBUG_LABEL, "END");
688 /****************************************************************************/
689 /* Set font size for all text contained in object. */
690 /****************************************************************************/
692 gl_label_object_set_font_size (glLabelObject *object,
695 gl_debug (DEBUG_LABEL, "START");
697 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
699 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL ) {
701 /* We have an object specific method, use it */
702 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size);
706 gl_debug (DEBUG_LABEL, "END");
709 /****************************************************************************/
710 /* Set font weight for all text contained in object. */
711 /****************************************************************************/
713 gl_label_object_set_font_weight (glLabelObject *object,
714 PangoWeight font_weight)
716 gl_debug (DEBUG_LABEL, "START");
718 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
720 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL ) {
722 /* We have an object specific method, use it */
723 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight);
727 gl_debug (DEBUG_LABEL, "END");
730 /****************************************************************************/
731 /* Set font italic flag for all text contained in object. */
732 /****************************************************************************/
734 gl_label_object_set_font_italic_flag (glLabelObject *object,
735 gboolean font_italic_flag)
737 gl_debug (DEBUG_LABEL, "START");
739 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
741 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL ) {
743 /* We have an object specific method, use it */
744 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object,
749 gl_debug (DEBUG_LABEL, "END");
752 /****************************************************************************/
753 /* Set text alignment for all text contained in object. */
754 /****************************************************************************/
756 gl_label_object_set_text_alignment (glLabelObject *object,
757 PangoAlignment text_alignment)
759 gl_debug (DEBUG_LABEL, "START");
761 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
763 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL ) {
765 /* We have an object specific method, use it */
766 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object,
771 gl_debug (DEBUG_LABEL, "END");
774 /****************************************************************************/
775 /* Set text line spacing for all text contained in object. */
776 /****************************************************************************/
778 gl_label_object_set_text_line_spacing (glLabelObject *object,
779 gdouble text_line_spacing)
781 gl_debug (DEBUG_LABEL, "START");
783 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
785 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL ) {
787 /* We have an object specific method, use it */
788 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing);
792 gl_debug (DEBUG_LABEL, "END");
795 /****************************************************************************/
796 /* Set text color for all text contained in object. */
797 /****************************************************************************/
799 gl_label_object_set_text_color (glLabelObject *object,
800 glColorNode *text_color_node)
802 gl_debug (DEBUG_LABEL, "START");
804 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
806 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL ) {
808 /* We have an object specific method, use it */
809 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node);
813 gl_debug (DEBUG_LABEL, "END");
816 /*****************************************************************************/
817 /* Get font family for all text contained in object. */
818 /*****************************************************************************/
820 gl_label_object_get_font_family (glLabelObject *object)
824 gl_debug (DEBUG_LABEL, "START");
826 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
828 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL ) {
830 /* We have an object specific method, use it */
831 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family (object);
835 gl_debug (DEBUG_LABEL, "END");
840 /****************************************************************************/
841 /* Get font size for all text contained in object. */
842 /****************************************************************************/
844 gl_label_object_get_font_size (glLabelObject *object)
848 gl_debug (DEBUG_LABEL, "START");
850 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
852 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL ) {
854 /* We have an object specific method, use it */
855 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size (object);
859 gl_debug (DEBUG_LABEL, "END");
864 /****************************************************************************/
865 /* Get font weight for all text contained in object. */
866 /****************************************************************************/
868 gl_label_object_get_font_weight (glLabelObject *object)
870 PangoWeight ret = PANGO_WEIGHT_NORMAL;
872 gl_debug (DEBUG_LABEL, "START");
874 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_WEIGHT_NORMAL);
876 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL ) {
878 /* We have an object specific method, use it */
879 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight (object);
883 gl_debug (DEBUG_LABEL, "END");
888 /****************************************************************************/
889 /* Get font italic flag for all text contained in object. */
890 /****************************************************************************/
892 gl_label_object_get_font_italic_flag (glLabelObject *object)
894 gboolean ret = FALSE;
896 gl_debug (DEBUG_LABEL, "START");
898 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
900 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL ) {
902 /* We have an object specific method, use it */
903 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag (object);
907 gl_debug (DEBUG_LABEL, "END");
912 /****************************************************************************/
913 /* Get text alignment for all text contained in object. */
914 /****************************************************************************/
916 gl_label_object_get_text_alignment (glLabelObject *object)
918 PangoAlignment ret = PANGO_ALIGN_LEFT;
920 gl_debug (DEBUG_LABEL, "START");
922 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_ALIGN_LEFT);
924 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL ) {
926 /* We have an object specific method, use it */
927 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment (object);
931 gl_debug (DEBUG_LABEL, "END");
936 /****************************************************************************/
937 /* Get text line spacing for all text contained in object. */
938 /****************************************************************************/
940 gl_label_object_get_text_line_spacing (glLabelObject *object)
944 gl_debug (DEBUG_LABEL, "START");
946 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
948 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL ) {
950 /* We have an object specific method, use it */
951 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing (object);
955 gl_debug (DEBUG_LABEL, "END");
960 /****************************************************************************/
961 /* Get text color for all text contained in object. */
962 /****************************************************************************/
964 gl_label_object_get_text_color (glLabelObject *object)
966 glColorNode *ret = NULL;
968 gl_debug (DEBUG_LABEL, "START");
970 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
972 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL ) {
974 /* We have an object specific method, use it */
975 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color (object);
979 gl_debug (DEBUG_LABEL, "END");
984 /*****************************************************************************/
985 /* Can fill properties be set for this object? */
986 /*****************************************************************************/
988 gl_label_object_can_fill (glLabelObject *object)
990 gl_debug (DEBUG_LABEL, "");
992 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
994 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
1006 /****************************************************************************/
1007 /* Set fill color for object. */
1008 /****************************************************************************/
1010 gl_label_object_set_fill_color (glLabelObject *object,
1011 glColorNode *fill_color_node)
1013 gl_debug (DEBUG_LABEL, "START");
1015 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1017 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
1019 /* We have an object specific method, use it */
1020 GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node);
1024 gl_debug (DEBUG_LABEL, "END");
1027 /****************************************************************************/
1028 /* Get fill color for object. */
1029 /****************************************************************************/
1031 gl_label_object_get_fill_color (glLabelObject *object)
1033 glColorNode *ret = NULL;
1035 gl_debug (DEBUG_LABEL, "START");
1037 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1039 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL ) {
1041 /* We have an object specific method, use it */
1042 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color (object);
1046 gl_debug (DEBUG_LABEL, "END");
1051 /*****************************************************************************/
1052 /* Can line color property be set for this object? */
1053 /*****************************************************************************/
1055 gl_label_object_can_line_color (glLabelObject *object)
1057 gl_debug (DEBUG_LABEL, "");
1059 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1061 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
1073 /****************************************************************************/
1074 /* Set line color for object. */
1075 /****************************************************************************/
1077 gl_label_object_set_line_color (glLabelObject *object,
1078 glColorNode *line_color_node)
1080 gl_debug (DEBUG_LABEL, "START");
1082 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1084 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
1086 /* We have an object specific method, use it */
1087 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node);
1091 gl_debug (DEBUG_LABEL, "END");
1094 /****************************************************************************/
1095 /* Get line color for object. */
1096 /****************************************************************************/
1098 gl_label_object_get_line_color (glLabelObject *object)
1100 glColorNode *ret = NULL;
1102 gl_debug (DEBUG_LABEL, "START");
1104 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1106 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL ) {
1108 /* We have an object specific method, use it */
1109 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color (object);
1113 gl_debug (DEBUG_LABEL, "END");
1118 /*****************************************************************************/
1119 /* Can line width property be set for this object? */
1120 /*****************************************************************************/
1122 gl_label_object_can_line_width (glLabelObject *object)
1124 gl_debug (DEBUG_LABEL, "");
1126 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1128 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1140 /****************************************************************************/
1141 /* Set line width for object. */
1142 /****************************************************************************/
1144 gl_label_object_set_line_width (glLabelObject *object,
1147 gl_debug (DEBUG_LABEL, "START");
1149 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1151 if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1153 /* We have an object specific method, use it */
1154 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width);
1158 gl_debug (DEBUG_LABEL, "END");
1161 /****************************************************************************/
1162 /* Get line width for object. */
1163 /****************************************************************************/
1165 gl_label_object_get_line_width (glLabelObject *object)
1169 gl_debug (DEBUG_LABEL, "START");
1171 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
1173 if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL ) {
1175 /* We have an object specific method, use it */
1176 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width (object);
1180 gl_debug (DEBUG_LABEL, "END");
1185 /****************************************************************************/
1186 /* Set shadow state of object. */
1187 /****************************************************************************/
1189 gl_label_object_set_shadow_state (glLabelObject *object,
1192 gl_debug (DEBUG_LABEL, "START");
1194 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1196 if (object->priv->shadow_state != state)
1198 object->priv->shadow_state = state;
1199 gl_label_object_emit_changed (object);
1202 gl_debug (DEBUG_LABEL, "END");
1205 /****************************************************************************/
1206 /* Get shadow state of object. */
1207 /****************************************************************************/
1209 gl_label_object_get_shadow_state (glLabelObject *object)
1211 gl_debug (DEBUG_LABEL, "");
1213 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1215 return object->priv->shadow_state;
1218 /****************************************************************************/
1219 /* Set offset of object's shadow. */
1220 /****************************************************************************/
1222 gl_label_object_set_shadow_offset (glLabelObject *object,
1226 gl_debug (DEBUG_LABEL, "START");
1228 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1230 if ( (x != object->priv->shadow_x) || (y != object->priv->shadow_y) )
1232 object->priv->shadow_x = x;
1233 object->priv->shadow_y = y;
1235 gl_label_object_emit_changed (object);
1238 gl_debug (DEBUG_LABEL, "END");
1241 /****************************************************************************/
1242 /* Get offset of object's shadow. */
1243 /****************************************************************************/
1245 gl_label_object_get_shadow_offset (glLabelObject *object,
1249 gl_debug (DEBUG_LABEL, "START");
1251 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1253 *x = object->priv->shadow_x;
1254 *y = object->priv->shadow_y;
1256 gl_debug (DEBUG_LABEL, "END");
1259 /****************************************************************************/
1260 /* Set color of object's shadow. */
1261 /****************************************************************************/
1263 gl_label_object_set_shadow_color (glLabelObject *object,
1264 glColorNode *color_node)
1266 gl_debug (DEBUG_LABEL, "START");
1268 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1270 if ( !gl_color_node_equal (object->priv->shadow_color_node, color_node ))
1272 gl_color_node_free (&(object->priv->shadow_color_node));
1273 object->priv->shadow_color_node = gl_color_node_dup (color_node);
1274 gl_label_object_emit_changed (GL_LABEL_OBJECT(object));
1277 gl_debug (DEBUG_LABEL, "END");
1280 /****************************************************************************/
1281 /* Get color of object's shadow. */
1282 /****************************************************************************/
1284 gl_label_object_get_shadow_color (glLabelObject *object)
1286 gl_debug (DEBUG_LABEL, "");
1288 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
1290 return gl_color_node_dup (object->priv->shadow_color_node);
1293 /****************************************************************************/
1294 /* Set opacity of object's shadow. */
1295 /****************************************************************************/
1297 gl_label_object_set_shadow_opacity (glLabelObject *object,
1300 gl_debug (DEBUG_LABEL, "START");
1302 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1304 if (object->priv->shadow_opacity != alpha)
1306 object->priv->shadow_opacity = alpha;
1307 gl_label_object_emit_changed (object);
1310 gl_debug (DEBUG_LABEL, "END");
1313 /****************************************************************************/
1314 /* Get opacity of object's shadow. */
1315 /****************************************************************************/
1317 gl_label_object_get_shadow_opacity (glLabelObject *object)
1319 gl_debug (DEBUG_LABEL, "");
1321 g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1323 return object->priv->shadow_opacity;
1326 /****************************************************************************/
1327 /* Flip object horizontally. */
1328 /****************************************************************************/
1330 gl_label_object_flip_horiz (glLabelObject *object)
1332 cairo_matrix_t flip_matrix;
1334 gl_debug (DEBUG_LABEL, "START");
1336 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1338 cairo_matrix_init_scale (&flip_matrix, -1.0, 1.0);
1339 cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1341 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1343 gl_debug (DEBUG_LABEL, "END");
1346 /****************************************************************************/
1347 /* Flip object vertically. */
1348 /****************************************************************************/
1350 gl_label_object_flip_vert (glLabelObject *object)
1352 cairo_matrix_t flip_matrix;
1354 gl_debug (DEBUG_LABEL, "START");
1356 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1358 cairo_matrix_init_scale (&flip_matrix, 1.0, -1.0);
1359 cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1361 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1363 gl_debug (DEBUG_LABEL, "END");
1366 /****************************************************************************/
1367 /* Rotate object. */
1368 /****************************************************************************/
1370 gl_label_object_rotate (glLabelObject *object,
1373 cairo_matrix_t rotate_matrix;
1375 gl_debug (DEBUG_LABEL, "START");
1377 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1379 cairo_matrix_init_rotate (&rotate_matrix, theta_degs*(G_PI/180.));
1380 cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &rotate_matrix);
1382 g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1384 gl_debug (DEBUG_LABEL, "END");
1387 /****************************************************************************/
1388 /* Set raw affine */
1389 /****************************************************************************/
1391 gl_label_object_set_matrix (glLabelObject *object,
1392 cairo_matrix_t *matrix)
1394 gl_debug (DEBUG_LABEL, "");
1396 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1398 object->priv->matrix = *matrix;
1401 /****************************************************************************/
1402 /* Get raw affine */
1403 /****************************************************************************/
1405 gl_label_object_get_matrix (glLabelObject *object,
1406 cairo_matrix_t *matrix)
1408 gl_debug (DEBUG_LABEL, "");
1410 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1412 *matrix = object->priv->matrix;
1415 /****************************************************************************/
1416 /* Bring label object to front/top. */
1417 /****************************************************************************/
1419 gl_label_object_raise_to_top (glLabelObject *object)
1423 gl_debug (DEBUG_LABEL, "START");
1425 label = object->parent;
1427 gl_label_raise_object_to_top (label, object);
1429 g_signal_emit (G_OBJECT(object), signals[TOP], 0);
1431 gl_debug (DEBUG_LABEL, "END");
1434 /****************************************************************************/
1435 /* Send label object to rear/bottom. */
1436 /****************************************************************************/
1438 gl_label_object_lower_to_bottom (glLabelObject *object)
1442 gl_debug (DEBUG_LABEL, "START");
1444 label = object->parent;
1446 gl_label_lower_object_to_bottom (label, object);
1448 g_signal_emit (G_OBJECT(object), signals[BOTTOM], 0);
1450 gl_debug (DEBUG_LABEL, "END");
1453 /*--------------------------------------------------------------------------*/
1454 /* PRIVATE. Label's merge data changed callback. */
1455 /*--------------------------------------------------------------------------*/
1457 merge_changed_cb (glLabel *label,
1458 glLabelObject *object)
1460 gl_label_object_emit_changed (object);
1463 /*****************************************************************************/
1465 /*****************************************************************************/
1467 gl_label_object_draw (glLabelObject *object,
1469 gboolean screen_flag,
1470 glMergeRecord *record)
1474 cairo_matrix_t matrix;
1475 gboolean shadow_state;
1476 gdouble shadow_x, shadow_y;
1478 gl_debug (DEBUG_LABEL, "START");
1480 g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1482 gl_label_object_get_position (object, &x0, &y0);
1483 gl_label_object_get_matrix (object, &matrix);
1486 cairo_translate (cr, x0, y0);
1488 if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow != NULL ) {
1490 shadow_state = gl_label_object_get_shadow_state (object);
1494 gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1497 cairo_translate (cr, shadow_x, shadow_y);
1498 cairo_transform (cr, &matrix);
1500 GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow (object,
1509 if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL ) {
1512 cairo_transform (cr, &matrix);
1514 GL_LABEL_OBJECT_GET_CLASS(object)->draw_object (object,
1524 gl_debug (DEBUG_LABEL, "END");