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