]> git.sur5r.net Git - glabels/blob - glabels2/src/label-object.c
2007-09-14 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / label-object.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  label_object.c:  GLabels label object base class
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
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.
14  *
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.
19  *
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
23  */
24 #include <config.h>
25
26 #include "label-object.h"
27
28 #include <glib/gmem.h>
29 #include <glib/gstrfuncs.h>
30 #include <glib/gmessages.h>
31 #include <math.h>
32
33 #include "marshal.h"
34
35 #include "debug.h"
36
37
38 /*========================================================*/
39 /* Private defines.                                       */
40 /*========================================================*/
41
42 #define DEFAULT_SHADOW_X_OFFSET (3.6)
43 #define DEFAULT_SHADOW_Y_OFFSET (3.6)
44 #define DEFAULT_SHADOW_OPACITY  (0.5)
45
46 /*========================================================*/
47 /* Private types.                                         */
48 /*========================================================*/
49
50 struct _glLabelObjectPrivate {
51         gchar             *name;
52         gdouble            x, y;
53         gdouble            w, h;
54         cairo_matrix_t     matrix;
55
56         gdouble            aspect_ratio;
57
58         gboolean           shadow_state;
59         gdouble            shadow_x;
60         gdouble            shadow_y;
61         glColorNode       *shadow_color_node;
62         gdouble            shadow_opacity;
63 };
64
65 enum {
66         CHANGED,
67         MOVED,
68         FLIP_ROTATE,
69         TOP,
70         BOTTOM,
71         REMOVED,
72         LAST_SIGNAL
73 };
74
75 /*========================================================*/
76 /* Private globals.                                       */
77 /*========================================================*/
78
79 static guint signals[LAST_SIGNAL] = {0};
80
81 static guint instance = 0;
82
83 /*========================================================*/
84 /* Private function prototypes.                           */
85 /*========================================================*/
86
87 static void gl_label_object_finalize      (GObject            *object);
88
89 static void merge_changed_cb              (glLabel            *label,
90                                            glLabelObject      *object);
91
92 static void set_size                      (glLabelObject      *object,
93                                            gdouble             w,
94                                            gdouble             h);
95
96
97 \f
98 /*****************************************************************************/
99 /* Boilerplate object stuff.                                                 */
100 /*****************************************************************************/
101 G_DEFINE_TYPE (glLabelObject, gl_label_object, G_TYPE_OBJECT);
102
103 static void
104 gl_label_object_class_init (glLabelObjectClass *class)
105 {
106         GObjectClass       *object_class = G_OBJECT_CLASS (class);
107
108         gl_debug (DEBUG_LABEL, "START");
109
110         gl_label_object_parent_class = g_type_class_peek_parent (class);
111
112         object_class->finalize = gl_label_object_finalize;
113
114         class->set_size = set_size;
115
116         signals[CHANGED] =
117                 g_signal_new ("changed",
118                               G_OBJECT_CLASS_TYPE (object_class),
119                               G_SIGNAL_RUN_LAST,
120                               G_STRUCT_OFFSET (glLabelObjectClass, changed),
121                               NULL, NULL,
122                               gl_marshal_VOID__VOID,
123                               G_TYPE_NONE,
124                               0);
125
126         signals[MOVED] =
127                 g_signal_new ("moved",
128                               G_OBJECT_CLASS_TYPE (object_class),
129                               G_SIGNAL_RUN_LAST,
130                               G_STRUCT_OFFSET (glLabelObjectClass, moved),
131                               NULL, NULL,
132                               gl_marshal_VOID__DOUBLE_DOUBLE,
133                               G_TYPE_NONE,
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),
138                               G_SIGNAL_RUN_LAST,
139                               G_STRUCT_OFFSET (glLabelObjectClass, flip_rotate),
140                               NULL, NULL,
141                               gl_marshal_VOID__VOID,
142                               G_TYPE_NONE,
143                               0);
144         signals[TOP] =
145                 g_signal_new ("top",
146                               G_OBJECT_CLASS_TYPE (object_class),
147                               G_SIGNAL_RUN_LAST,
148                               G_STRUCT_OFFSET (glLabelObjectClass, top),
149                               NULL, NULL,
150                               gl_marshal_VOID__VOID,
151                               G_TYPE_NONE,
152                               0);
153
154         signals[BOTTOM] =
155                 g_signal_new ("bottom",
156                               G_OBJECT_CLASS_TYPE (object_class),
157                               G_SIGNAL_RUN_LAST,
158                               G_STRUCT_OFFSET (glLabelObjectClass, bottom),
159                               NULL, NULL,
160                               gl_marshal_VOID__VOID,
161                               G_TYPE_NONE,
162                               0);
163         signals[REMOVED] =
164                 g_signal_new ("removed",
165                               G_OBJECT_CLASS_TYPE (object_class),
166                               G_SIGNAL_RUN_LAST,
167                               G_STRUCT_OFFSET (glLabelObjectClass, removed),
168                               NULL, NULL,
169                               gl_marshal_VOID__VOID,
170                               G_TYPE_NONE,
171                               0);
172
173         gl_debug (DEBUG_LABEL, "END");
174 }
175
176 static void
177 gl_label_object_init (glLabelObject *object)
178 {
179         gl_debug (DEBUG_LABEL, "START");
180
181         object->priv = g_new0 (glLabelObjectPrivate, 1);
182
183         object->priv->name = g_strdup_printf ("object%d", instance++);
184
185         cairo_matrix_init_identity (&object->priv->matrix);
186
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;
192
193         gl_debug (DEBUG_LABEL, "END");
194 }
195
196 static void
197 gl_label_object_finalize (GObject *object)
198 {
199         glLabelObject *label_object = GL_LABEL_OBJECT (object);
200         glLabel       *parent;
201
202         gl_debug (DEBUG_LABEL, "START");
203
204         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
205
206         g_free (label_object->priv->name);
207         g_free (label_object->priv);
208
209         G_OBJECT_CLASS (gl_label_object_parent_class)->finalize (object);
210
211         gl_debug (DEBUG_LABEL, "END");
212 }
213
214 /*****************************************************************************/
215 /* New label object.                                                         */
216 /*****************************************************************************/
217 GObject *
218 gl_label_object_new (glLabel *label)
219 {
220         glLabelObject *object;
221
222         gl_debug (DEBUG_LABEL, "START");
223
224         object = g_object_new (gl_label_object_get_type(), NULL);
225
226         gl_label_object_set_parent (object, label);
227
228         gl_debug (DEBUG_LABEL, "END");
229
230         return G_OBJECT (object);
231 }
232
233 /*****************************************************************************/
234 /* Duplicate object.                                                         */
235 /*****************************************************************************/
236 glLabelObject *
237 gl_label_object_dup (glLabelObject *src_object,
238                      glLabel       *label)
239 {
240         glLabelObject    *dst_object;
241         gdouble           x, y, w, h;
242         cairo_matrix_t    matrix;
243         gboolean          shadow_state;
244         gdouble           shadow_x, shadow_y;
245         glColorNode      *shadow_color_node;
246         gdouble           shadow_opacity;
247
248         gl_debug (DEBUG_LABEL, "START");
249
250         g_return_val_if_fail (src_object && GL_IS_LABEL_OBJECT (src_object), NULL);
251
252         dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
253
254         gl_label_object_set_parent (dst_object, label);
255
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);
263
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);
271
272         gl_color_node_free (&shadow_color_node);
273
274         if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL ) {
275
276                 /* We have an object specific method, use it */
277                 GL_LABEL_OBJECT_GET_CLASS(src_object)->copy (dst_object, src_object);
278
279         }
280
281         gl_debug (DEBUG_LABEL, "END");
282
283         return dst_object;
284 }
285
286 /*****************************************************************************/
287 /* Emit "changed" signal (for derived objects).                              */
288 /*****************************************************************************/
289 void
290 gl_label_object_emit_changed (glLabelObject *object)
291 {
292         gl_debug (DEBUG_LABEL, "START");
293
294         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
295
296         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
297
298         gl_debug (DEBUG_LABEL, "END");
299 }
300
301 /*****************************************************************************/
302 /* Set parent label of object.                                               */
303 /*****************************************************************************/
304 void
305 gl_label_object_set_parent (glLabelObject *object,
306                             glLabel       *label)
307 {
308         glLabel *old_parent;
309
310         gl_debug (DEBUG_LABEL, "START");
311
312         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
313         g_return_if_fail (label && GL_IS_LABEL (label));
314
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),
319                                                       object);
320                 gl_label_remove_object( old_parent, object );
321         }
322         gl_label_add_object( label, object );
323
324         g_signal_connect (G_OBJECT(label), "merge_changed",
325                           G_CALLBACK(merge_changed_cb), object);
326
327         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
328
329         gl_debug (DEBUG_LABEL, "END");
330 }
331
332 /*****************************************************************************/
333 /* Get parent label of object.                                               */
334 /*****************************************************************************/
335 glLabel *
336 gl_label_object_get_parent (glLabelObject *object)
337 {
338         gl_debug (DEBUG_LABEL, "START");
339
340         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
341
342         gl_debug (DEBUG_LABEL, "END");
343
344         return object->parent;
345 }
346
347 /*****************************************************************************/
348 /* Set remove object from parent.                                            */
349 /*****************************************************************************/
350 void
351 gl_label_object_remove (glLabelObject *object)
352 {
353         glLabel *parent;
354
355         gl_debug (DEBUG_LABEL, "START");
356
357         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
358
359         parent = object->parent;
360         if ( parent != NULL ) {
361                 g_signal_handlers_disconnect_by_func (parent,
362                                                       G_CALLBACK(merge_changed_cb),
363                                                       object);
364                 gl_label_remove_object (parent, object);
365
366                 g_signal_emit (G_OBJECT(object), signals[REMOVED], 0);
367
368                 g_object_unref (G_OBJECT(object));
369         }
370
371
372         gl_debug (DEBUG_LABEL, "END");
373 }
374
375 /*****************************************************************************/
376 /* Set name of object.                                                       */
377 /*****************************************************************************/
378 void
379 gl_label_object_set_name (glLabelObject *object,
380                           gchar         *name)
381 {
382         gl_debug (DEBUG_LABEL, "START");
383
384         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
385
386         g_free(object->priv->name);
387         object->priv->name = name;
388
389         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
390
391         gl_debug (DEBUG_LABEL, "END");
392 }
393
394 /*****************************************************************************/
395 /* Get name of object.                                                       */
396 /*****************************************************************************/
397 gchar *
398 gl_label_object_get_name (glLabelObject *object)
399 {
400         gl_debug (DEBUG_LABEL, "START");
401
402         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
403
404         gl_debug (DEBUG_LABEL, "END");
405
406         return g_strdup(object->priv->name);
407 }
408
409 /*****************************************************************************/
410 /* Set position of object.                                                   */
411 /*****************************************************************************/
412 void
413 gl_label_object_set_position (glLabelObject *object,
414                               gdouble        x,
415                               gdouble        y)
416 {
417         gdouble dx, dy;
418
419         gl_debug (DEBUG_LABEL, "START");
420
421         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
422
423         if ( (x != object->priv->x) || (y != object->priv->y) ) {
424
425                 dx = x - object->priv->x;
426                 dy = y - object->priv->y;
427
428                 object->priv->x = x;
429                 object->priv->y = y;
430
431                 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
432
433         }
434
435         gl_debug (DEBUG_LABEL, "END");
436 }
437
438 /*****************************************************************************/
439 /* Set position of object relative to old position.                          */
440 /*****************************************************************************/
441 void
442 gl_label_object_set_position_relative (glLabelObject *object,
443                                        gdouble        dx,
444                                        gdouble        dy)
445 {
446         gl_debug (DEBUG_LABEL, "START");
447
448         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
449
450         if ( (dx != 0.0) || (dy != 0.0) ) {
451
452                 object->priv->x += dx;
453                 object->priv->y += dy;
454
455                 gl_debug (DEBUG_LABEL, "       x = %f, y= %f",
456                           object->priv->x,
457                           object->priv->y);
458
459                 g_signal_emit (G_OBJECT(object), signals[MOVED], 0, dx, dy);
460
461         }
462
463         gl_debug (DEBUG_LABEL, "END");
464 }
465
466 /*****************************************************************************/
467 /* Get position of object.                                                   */
468 /*****************************************************************************/
469 void
470 gl_label_object_get_position (glLabelObject *object,
471                               gdouble       *x,
472                               gdouble       *y)
473 {
474         gl_debug (DEBUG_LABEL, "START");
475
476         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
477
478         *x = object->priv->x;
479         *y = object->priv->y;
480
481         gl_debug (DEBUG_LABEL, "END");
482 }
483
484 /*---------------------------------------------------------------------------*/
485 /* PRIVATE.  Default set size method.                                        */
486 /*---------------------------------------------------------------------------*/
487 static void
488 set_size (glLabelObject *object,
489           gdouble        w,
490           gdouble        h)
491 {
492         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
493
494         if ( (object->priv->w != w) || (object->priv->h != h) ) {
495
496                 object->priv->w = w;
497                 object->priv->h = h;
498
499                 g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
500         }
501 }
502
503 /*****************************************************************************/
504 /* Set size of object.                                                       */
505 /*****************************************************************************/
506 void
507 gl_label_object_set_size (glLabelObject *object,
508                           gdouble        w,
509                           gdouble        h)
510 {
511         gl_debug (DEBUG_LABEL, "START");
512
513         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
514
515         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
516
517                 /* We have an object specific method, use it */
518                 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
519
520                 object->priv->aspect_ratio = h / w;
521
522         }
523
524
525         gl_debug (DEBUG_LABEL, "END");
526 }
527
528 /*****************************************************************************/
529 /* Set size of object honoring current aspect ratio.                         */
530 /*****************************************************************************/
531 void
532 gl_label_object_set_size_honor_aspect (glLabelObject *object,
533                                        gdouble        w,
534                                        gdouble        h)
535 {
536         gl_debug (DEBUG_LABEL, "START");
537
538         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
539
540         if ( h > w*object->priv->aspect_ratio ) {
541
542                 h = w * object->priv->aspect_ratio;
543
544         } else {
545
546                 w = h / object->priv->aspect_ratio;
547
548         }
549
550         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL ) {
551
552                 /* We have an object specific method, use it */
553                 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
554
555         }
556
557         gl_debug (DEBUG_LABEL, "END");
558 }
559
560 /*****************************************************************************/
561 /* Get raw size method (don't let object content adjust size).               */
562 /*****************************************************************************/
563 void
564 gl_label_object_get_raw_size (glLabelObject *object,
565                               gdouble       *w,
566                               gdouble       *h)
567 {
568         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
569
570         *w = object->priv->w;
571         *h = object->priv->h;
572 }
573
574 /*****************************************************************************/
575 /* Get size of object.                                                       */
576 /*****************************************************************************/
577 void
578 gl_label_object_get_size (glLabelObject *object,
579                           gdouble       *w,
580                           gdouble       *h)
581 {
582         gl_debug (DEBUG_LABEL, "START");
583
584         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
585
586         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL ) {
587
588                 /* We have an object specific method, use it */
589                 GL_LABEL_OBJECT_GET_CLASS(object)->get_size (object, w, h);
590
591         } else {
592
593                 gl_label_object_get_raw_size (object, w, h);
594
595         }
596
597         gl_debug (DEBUG_LABEL, "END");
598 }
599
600 /*****************************************************************************/
601 /* Get extent of object.                                                     */
602 /*****************************************************************************/
603 void
604 gl_label_object_get_extent (glLabelObject *object,
605                             glLabelRegion *region)
606 {
607         gdouble        w, h;
608         gdouble        line_w;
609         gdouble        xa1, ya1, xa2, ya2, xa3, ya3, xa4, ya4;
610         cairo_matrix_t matrix;
611
612         gl_debug (DEBUG_LABEL, "START");
613
614         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
615
616         gl_label_object_get_size (object, &w, &h);
617         line_w = gl_label_object_get_line_width (object);
618
619         /* setup untransformed corners of bounding box, account for line width */
620         xa1 =   - line_w/2;
621         ya1 =   - line_w/2;
622         xa2 = w + line_w/2;
623         ya2 =   - line_w/2;
624         xa3 = w + line_w/2;
625         ya3 = h + line_w/2;
626         xa4 =   - line_w/2;
627         ya4 = h + line_w/2;
628
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);
635
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;
641
642         gl_debug (DEBUG_LABEL, "END");
643 }
644
645 /*****************************************************************************/
646 /* Can text properties be set for this object?                               */
647 /*****************************************************************************/
648 gboolean
649 gl_label_object_can_text (glLabelObject     *object)
650 {
651         gl_debug (DEBUG_LABEL, "");
652
653         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
654
655         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
656
657                 return TRUE;
658
659         } else {
660
661                 return FALSE;
662
663         }
664
665 }
666
667 /*****************************************************************************/
668 /* Set font family for all text contained in object.                         */
669 /*****************************************************************************/
670 void
671 gl_label_object_set_font_family (glLabelObject     *object,
672                                  const gchar       *font_family)
673 {
674         gl_debug (DEBUG_LABEL, "START");
675
676         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
677
678         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL ) {
679
680                 /* We have an object specific method, use it */
681                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family);
682
683         }
684
685         gl_debug (DEBUG_LABEL, "END");
686 }
687
688 /****************************************************************************/
689 /* Set font size for all text contained in object.                          */
690 /****************************************************************************/
691 void
692 gl_label_object_set_font_size (glLabelObject     *object,
693                                gdouble            font_size)
694 {
695         gl_debug (DEBUG_LABEL, "START");
696
697         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
698
699         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL ) {
700
701                 /* We have an object specific method, use it */
702                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size);
703
704         }
705
706         gl_debug (DEBUG_LABEL, "END");
707 }
708
709 /****************************************************************************/
710 /* Set font weight for all text contained in object.                        */
711 /****************************************************************************/
712 void
713 gl_label_object_set_font_weight (glLabelObject     *object,
714                                  PangoWeight        font_weight)
715 {
716         gl_debug (DEBUG_LABEL, "START");
717
718         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
719
720         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL ) {
721
722                 /* We have an object specific method, use it */
723                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight);
724
725         }
726
727         gl_debug (DEBUG_LABEL, "END");
728 }
729
730 /****************************************************************************/
731 /* Set font italic flag for all text contained in object.                   */
732 /****************************************************************************/
733 void
734 gl_label_object_set_font_italic_flag (glLabelObject     *object,
735                                       gboolean           font_italic_flag)
736 {
737         gl_debug (DEBUG_LABEL, "START");
738
739         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
740
741         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL ) {
742
743                 /* We have an object specific method, use it */
744                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object,
745                                                                          font_italic_flag);
746
747         }
748
749         gl_debug (DEBUG_LABEL, "END");
750 }
751
752 /****************************************************************************/
753 /* Set text alignment for all text contained in object.                     */
754 /****************************************************************************/
755 void
756 gl_label_object_set_text_alignment (glLabelObject     *object,
757                                     PangoAlignment     text_alignment)
758 {
759         gl_debug (DEBUG_LABEL, "START");
760
761         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
762
763         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL ) {
764
765                 /* We have an object specific method, use it */
766                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object,
767                                                                        text_alignment);
768
769         }
770
771         gl_debug (DEBUG_LABEL, "END");
772 }
773
774 /****************************************************************************/
775 /* Set text line spacing for all text contained in object.                  */
776 /****************************************************************************/
777 void
778 gl_label_object_set_text_line_spacing (glLabelObject     *object,
779                                        gdouble            text_line_spacing)
780 {
781         gl_debug (DEBUG_LABEL, "START");
782
783         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
784
785         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL ) {
786
787                 /* We have an object specific method, use it */
788                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing);
789
790         }
791
792         gl_debug (DEBUG_LABEL, "END");
793 }
794
795 /****************************************************************************/
796 /* Set text color for all text contained in object.                         */
797 /****************************************************************************/
798 void
799 gl_label_object_set_text_color (glLabelObject     *object,
800                                 glColorNode       *text_color_node)
801 {
802         gl_debug (DEBUG_LABEL, "START");
803
804         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
805
806         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL ) {
807
808                 /* We have an object specific method, use it */
809                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node);
810
811         }
812
813         gl_debug (DEBUG_LABEL, "END");
814 }
815
816 /*****************************************************************************/
817 /* Get font family for all text contained in object.                         */
818 /*****************************************************************************/
819 gchar *
820 gl_label_object_get_font_family (glLabelObject     *object)
821 {
822         gchar *ret = NULL;
823
824         gl_debug (DEBUG_LABEL, "START");
825
826         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
827
828         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL ) {
829
830                 /* We have an object specific method, use it */
831                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family (object);
832
833         }
834
835         gl_debug (DEBUG_LABEL, "END");
836
837         return ret;
838 }
839
840 /****************************************************************************/
841 /* Get font size for all text contained in object.                          */
842 /****************************************************************************/
843 gdouble
844 gl_label_object_get_font_size (glLabelObject     *object)
845 {
846         gdouble ret = 0.0;
847
848         gl_debug (DEBUG_LABEL, "START");
849
850         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
851
852         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL ) {
853
854                 /* We have an object specific method, use it */
855                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size (object);
856
857         }
858
859         gl_debug (DEBUG_LABEL, "END");
860
861         return ret;
862 }
863
864 /****************************************************************************/
865 /* Get font weight for all text contained in object.                        */
866 /****************************************************************************/
867 PangoWeight    
868 gl_label_object_get_font_weight (glLabelObject     *object)
869 {
870         PangoWeight     ret = PANGO_WEIGHT_NORMAL;
871
872         gl_debug (DEBUG_LABEL, "START");
873
874         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_WEIGHT_NORMAL);
875
876         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL ) {
877
878                 /* We have an object specific method, use it */
879                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight (object);
880
881         }
882
883         gl_debug (DEBUG_LABEL, "END");
884
885         return ret;
886 }
887
888 /****************************************************************************/
889 /* Get font italic flag for all text contained in object.                   */
890 /****************************************************************************/
891 gboolean
892 gl_label_object_get_font_italic_flag (glLabelObject     *object)
893 {
894         gboolean ret = FALSE;
895
896         gl_debug (DEBUG_LABEL, "START");
897
898         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
899
900         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL ) {
901
902                 /* We have an object specific method, use it */
903                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag (object);
904
905         }
906
907         gl_debug (DEBUG_LABEL, "END");
908
909         return ret;
910 }
911
912 /****************************************************************************/
913 /* Get text alignment for all text contained in object.                     */
914 /****************************************************************************/
915 PangoAlignment
916 gl_label_object_get_text_alignment (glLabelObject     *object)
917 {
918         PangoAlignment ret = PANGO_ALIGN_LEFT;
919
920         gl_debug (DEBUG_LABEL, "START");
921
922         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_ALIGN_LEFT);
923
924         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL ) {
925
926                 /* We have an object specific method, use it */
927                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment (object);
928
929         }
930
931         gl_debug (DEBUG_LABEL, "END");
932
933         return ret;
934 }
935
936 /****************************************************************************/
937 /* Get text line spacing for all text contained in object.                  */
938 /****************************************************************************/
939 gdouble
940 gl_label_object_get_text_line_spacing (glLabelObject     *object)
941 {
942         gdouble ret = 0.0;
943
944         gl_debug (DEBUG_LABEL, "START");
945
946         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
947
948         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL ) {
949
950                 /* We have an object specific method, use it */
951                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing (object);
952
953         }
954
955         gl_debug (DEBUG_LABEL, "END");
956
957         return ret;
958 }
959
960 /****************************************************************************/
961 /* Get text color for all text contained in object.                         */
962 /****************************************************************************/
963 glColorNode*
964 gl_label_object_get_text_color (glLabelObject     *object)
965 {
966         glColorNode *ret = NULL;
967
968         gl_debug (DEBUG_LABEL, "START");
969
970         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
971
972         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL ) {
973
974                 /* We have an object specific method, use it */
975                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color (object);
976
977         }
978
979         gl_debug (DEBUG_LABEL, "END");
980
981         return ret;
982 }
983
984 /*****************************************************************************/
985 /* Can fill properties be set for this object?                               */
986 /*****************************************************************************/
987 gboolean
988 gl_label_object_can_fill (glLabelObject     *object)
989 {
990         gl_debug (DEBUG_LABEL, "");
991
992         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
993
994         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
995
996                 return TRUE;
997
998         } else {
999
1000                 return FALSE;
1001
1002         }
1003
1004 }
1005
1006 /****************************************************************************/
1007 /* Set fill color for object.                                               */
1008 /****************************************************************************/
1009 void
1010 gl_label_object_set_fill_color (glLabelObject     *object,
1011                                 glColorNode       *fill_color_node)
1012 {
1013         gl_debug (DEBUG_LABEL, "START");
1014
1015         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1016
1017         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL ) {
1018
1019                 /* We have an object specific method, use it */
1020                 GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node);
1021
1022         }
1023
1024         gl_debug (DEBUG_LABEL, "END");
1025 }
1026
1027 /****************************************************************************/
1028 /* Get fill color for object.                                               */
1029 /****************************************************************************/
1030 glColorNode*
1031 gl_label_object_get_fill_color (glLabelObject     *object)
1032 {
1033         glColorNode *ret = NULL;
1034
1035         gl_debug (DEBUG_LABEL, "START");
1036
1037         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1038
1039         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL ) {
1040
1041                 /* We have an object specific method, use it */
1042                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color (object);
1043
1044         }
1045
1046         gl_debug (DEBUG_LABEL, "END");
1047
1048         return ret;
1049 }
1050
1051 /*****************************************************************************/
1052 /* Can line color property be set for this object?                           */
1053 /*****************************************************************************/
1054 gboolean
1055 gl_label_object_can_line_color (glLabelObject     *object)
1056 {
1057         gl_debug (DEBUG_LABEL, "");
1058
1059         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1060
1061         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
1062
1063                 return TRUE;
1064
1065         } else {
1066
1067                 return FALSE;
1068
1069         }
1070
1071 }
1072
1073 /****************************************************************************/
1074 /* Set line color for object.                                               */
1075 /****************************************************************************/
1076 void
1077 gl_label_object_set_line_color (glLabelObject     *object,
1078                                 glColorNode       *line_color_node)
1079 {
1080         gl_debug (DEBUG_LABEL, "START");
1081
1082         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1083
1084         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL ) {
1085
1086                 /* We have an object specific method, use it */
1087                 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node);
1088
1089         }
1090
1091         gl_debug (DEBUG_LABEL, "END");
1092 }
1093
1094 /****************************************************************************/
1095 /* Get line color for object.                                               */
1096 /****************************************************************************/
1097 glColorNode*
1098 gl_label_object_get_line_color (glLabelObject     *object)
1099 {
1100         glColorNode *ret = NULL;
1101
1102         gl_debug (DEBUG_LABEL, "START");
1103
1104         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1105
1106         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL ) {
1107
1108                 /* We have an object specific method, use it */
1109                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color (object);
1110
1111         }
1112
1113         gl_debug (DEBUG_LABEL, "END");
1114
1115         return ret;
1116 }
1117
1118 /*****************************************************************************/
1119 /* Can line width property be set for this object?                           */
1120 /*****************************************************************************/
1121 gboolean
1122 gl_label_object_can_line_width (glLabelObject     *object)
1123 {
1124         gl_debug (DEBUG_LABEL, "");
1125
1126         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1127
1128         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1129
1130                 return TRUE;
1131
1132         } else {
1133
1134                 return FALSE;
1135
1136         }
1137
1138 }
1139
1140 /****************************************************************************/
1141 /* Set line width for object.                                               */
1142 /****************************************************************************/
1143 void
1144 gl_label_object_set_line_width (glLabelObject     *object,
1145                                 gdouble            line_width)
1146 {
1147         gl_debug (DEBUG_LABEL, "START");
1148
1149         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1150
1151         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL ) {
1152
1153                 /* We have an object specific method, use it */
1154                 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width);
1155
1156         }
1157
1158         gl_debug (DEBUG_LABEL, "END");
1159 }
1160
1161 /****************************************************************************/
1162 /* Get line width for object.                                               */
1163 /****************************************************************************/
1164 gdouble
1165 gl_label_object_get_line_width (glLabelObject     *object)
1166 {
1167         gdouble ret = 0.0;
1168
1169         gl_debug (DEBUG_LABEL, "START");
1170
1171         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
1172
1173         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL ) {
1174
1175                 /* We have an object specific method, use it */
1176                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width (object);
1177
1178         }
1179
1180         gl_debug (DEBUG_LABEL, "END");
1181
1182         return ret;
1183 }
1184
1185 /****************************************************************************/
1186 /* Set shadow state of object.                                              */
1187 /****************************************************************************/
1188 void
1189 gl_label_object_set_shadow_state (glLabelObject     *object,
1190                                   gboolean           state)
1191 {
1192         gl_debug (DEBUG_LABEL, "START");
1193
1194         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1195
1196         if (object->priv->shadow_state != state)
1197         {
1198                 object->priv->shadow_state = state;
1199                 gl_label_object_emit_changed (object);
1200         }
1201
1202         gl_debug (DEBUG_LABEL, "END");
1203 }
1204
1205 /****************************************************************************/
1206 /* Get shadow state of object.                                              */
1207 /****************************************************************************/
1208 gboolean
1209 gl_label_object_get_shadow_state (glLabelObject     *object)
1210 {
1211         gl_debug (DEBUG_LABEL, "");
1212
1213         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1214
1215         return object->priv->shadow_state;
1216 }
1217
1218 /****************************************************************************/
1219 /* Set offset of object's shadow.                                           */
1220 /****************************************************************************/
1221 void
1222 gl_label_object_set_shadow_offset (glLabelObject     *object,
1223                                    gdouble            x,
1224                                    gdouble            y)
1225 {
1226         gl_debug (DEBUG_LABEL, "START");
1227
1228         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1229
1230         if ( (x != object->priv->shadow_x) || (y != object->priv->shadow_y) )
1231         {
1232                 object->priv->shadow_x = x;
1233                 object->priv->shadow_y = y;
1234
1235                 gl_label_object_emit_changed (object);
1236         }
1237
1238         gl_debug (DEBUG_LABEL, "END");
1239 }
1240
1241 /****************************************************************************/
1242 /* Get offset of object's shadow.                                           */
1243 /****************************************************************************/
1244 void
1245 gl_label_object_get_shadow_offset (glLabelObject     *object,
1246                                    gdouble           *x,
1247                                    gdouble           *y)
1248 {
1249         gl_debug (DEBUG_LABEL, "START");
1250
1251         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1252
1253         *x = object->priv->shadow_x;
1254         *y = object->priv->shadow_y;
1255
1256         gl_debug (DEBUG_LABEL, "END");
1257 }
1258
1259 /****************************************************************************/
1260 /* Set color of object's shadow.                                            */
1261 /****************************************************************************/
1262 void
1263 gl_label_object_set_shadow_color (glLabelObject     *object,
1264                                   glColorNode       *color_node)
1265 {
1266         gl_debug (DEBUG_LABEL, "START");
1267
1268         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1269
1270         if ( !gl_color_node_equal (object->priv->shadow_color_node, color_node ))
1271         {
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));
1275         }
1276
1277         gl_debug (DEBUG_LABEL, "END");
1278 }
1279
1280 /****************************************************************************/
1281 /* Get color of object's shadow.                                            */
1282 /****************************************************************************/
1283 glColorNode*
1284 gl_label_object_get_shadow_color (glLabelObject     *object)
1285 {
1286         gl_debug (DEBUG_LABEL, "");
1287
1288         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
1289
1290         return gl_color_node_dup (object->priv->shadow_color_node);
1291 }
1292
1293 /****************************************************************************/
1294 /* Set opacity of object's shadow.                                          */
1295 /****************************************************************************/
1296 void
1297 gl_label_object_set_shadow_opacity (glLabelObject     *object,
1298                                     gdouble            alpha)
1299 {
1300         gl_debug (DEBUG_LABEL, "START");
1301
1302         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1303
1304         if (object->priv->shadow_opacity != alpha)
1305         {
1306                 object->priv->shadow_opacity = alpha;
1307                 gl_label_object_emit_changed (object);
1308         }
1309
1310         gl_debug (DEBUG_LABEL, "END");
1311 }
1312
1313 /****************************************************************************/
1314 /* Get opacity of object's shadow.                                          */
1315 /****************************************************************************/
1316 gdouble
1317 gl_label_object_get_shadow_opacity (glLabelObject     *object)
1318 {
1319         gl_debug (DEBUG_LABEL, "");
1320
1321         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1322
1323         return object->priv->shadow_opacity;
1324 }
1325
1326 /****************************************************************************/
1327 /* Flip object horizontally.                                                */
1328 /****************************************************************************/
1329 void
1330 gl_label_object_flip_horiz (glLabelObject *object)
1331 {
1332         cairo_matrix_t flip_matrix;
1333
1334         gl_debug (DEBUG_LABEL, "START");
1335
1336         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1337
1338         cairo_matrix_init_scale (&flip_matrix, -1.0, 1.0);
1339         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1340
1341         g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1342
1343         gl_debug (DEBUG_LABEL, "END");
1344 }
1345
1346 /****************************************************************************/
1347 /* Flip object vertically.                                                  */
1348 /****************************************************************************/
1349 void
1350 gl_label_object_flip_vert (glLabelObject *object)
1351 {
1352         cairo_matrix_t flip_matrix;
1353
1354         gl_debug (DEBUG_LABEL, "START");
1355
1356         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1357
1358         cairo_matrix_init_scale (&flip_matrix, 1.0, -1.0);
1359         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1360
1361         g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1362
1363         gl_debug (DEBUG_LABEL, "END");
1364 }
1365
1366 /****************************************************************************/
1367 /* Rotate object.                                                           */
1368 /****************************************************************************/
1369 void
1370 gl_label_object_rotate (glLabelObject *object,
1371                         gdouble        theta_degs)
1372 {
1373         cairo_matrix_t rotate_matrix;
1374
1375         gl_debug (DEBUG_LABEL, "START");
1376
1377         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1378
1379         cairo_matrix_init_rotate (&rotate_matrix, theta_degs*(G_PI/180.));
1380         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &rotate_matrix);
1381
1382         g_signal_emit (G_OBJECT(object), signals[FLIP_ROTATE], 0);
1383
1384         gl_debug (DEBUG_LABEL, "END");
1385 }
1386
1387 /****************************************************************************/
1388 /* Set raw affine                                                           */
1389 /****************************************************************************/
1390 void
1391 gl_label_object_set_matrix (glLabelObject  *object,
1392                             cairo_matrix_t *matrix)
1393 {
1394         gl_debug (DEBUG_LABEL, "");
1395
1396         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1397
1398         object->priv->matrix = *matrix;
1399 }
1400
1401 /****************************************************************************/
1402 /* Get raw affine                                                           */
1403 /****************************************************************************/
1404 void
1405 gl_label_object_get_matrix (glLabelObject  *object,
1406                             cairo_matrix_t *matrix)
1407 {
1408         gl_debug (DEBUG_LABEL, "");
1409
1410         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1411
1412         *matrix = object->priv->matrix;
1413 }
1414
1415 /****************************************************************************/
1416 /* Bring label object to front/top.                                         */
1417 /****************************************************************************/
1418 void
1419 gl_label_object_raise_to_top (glLabelObject *object)
1420 {
1421         glLabel *label;
1422
1423         gl_debug (DEBUG_LABEL, "START");
1424
1425         label = object->parent;
1426
1427         gl_label_raise_object_to_top (label, object);
1428
1429         g_signal_emit (G_OBJECT(object), signals[TOP], 0);
1430
1431         gl_debug (DEBUG_LABEL, "END");
1432 }
1433
1434 /****************************************************************************/
1435 /* Send label object to rear/bottom.                                        */
1436 /****************************************************************************/
1437 void
1438 gl_label_object_lower_to_bottom (glLabelObject *object)
1439 {
1440         glLabel *label;
1441
1442         gl_debug (DEBUG_LABEL, "START");
1443
1444         label = object->parent;
1445
1446         gl_label_lower_object_to_bottom (label, object);
1447
1448         g_signal_emit (G_OBJECT(object), signals[BOTTOM], 0);
1449
1450         gl_debug (DEBUG_LABEL, "END");
1451 }
1452
1453 /*--------------------------------------------------------------------------*/
1454 /* PRIVATE.  Label's merge data changed callback.                           */
1455 /*--------------------------------------------------------------------------*/
1456 static void
1457 merge_changed_cb (glLabel       *label,
1458                   glLabelObject *object)
1459 {
1460         gl_label_object_emit_changed (object);
1461 }
1462
1463 /*****************************************************************************/
1464 /* Draw object                                                               */
1465 /*****************************************************************************/
1466 void
1467 gl_label_object_draw (glLabelObject *object,
1468                       cairo_t       *cr,
1469                       gboolean       screen_flag,
1470                       glMergeRecord *record)
1471
1472 {
1473         gdouble        x0, y0;
1474         cairo_matrix_t matrix;
1475         gboolean       shadow_state;
1476         gdouble        shadow_x, shadow_y;
1477
1478         gl_debug (DEBUG_LABEL, "START");
1479
1480         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1481
1482         gl_label_object_get_position (object, &x0, &y0);
1483         gl_label_object_get_matrix (object, &matrix);
1484
1485         cairo_save (cr);
1486         cairo_translate (cr, x0, y0);
1487
1488         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow != NULL ) {
1489
1490                 shadow_state = gl_label_object_get_shadow_state (object);
1491
1492                 if ( shadow_state )
1493                 {
1494                         gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1495
1496                         cairo_save (cr);
1497                         cairo_translate (cr, shadow_x, shadow_y);
1498                         cairo_transform (cr, &matrix);
1499
1500                         GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow (object,
1501                                                                         cr,
1502                                                                         screen_flag,
1503                                                                         record);
1504
1505                         cairo_restore (cr);
1506                 }
1507         }
1508
1509         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL ) {
1510
1511                 cairo_save (cr);
1512                 cairo_transform (cr, &matrix);
1513
1514                 GL_LABEL_OBJECT_GET_CLASS(object)->draw_object (object,
1515                                                                 cr,
1516                                                                 screen_flag,
1517                                                                 record);
1518
1519                 cairo_restore (cr);
1520         }
1521
1522         cairo_restore (cr);
1523
1524         gl_debug (DEBUG_LABEL, "END");
1525 }
1526