]> git.sur5r.net Git - glabels/blob - src/label-object.c
8d48e53a4e7e87937bd4790fd56a16a3fdc39c56
[glabels] / src / label-object.c
1 /*
2  *  label-object.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "label-object.h"
24
25 #include <glib/gi18n.h>
26 #include <glib.h>
27 #include <math.h>
28
29 #include "marshal.h"
30
31 #include "debug.h"
32
33
34 /*========================================================*/
35 /* Private defines.                                       */
36 /*========================================================*/
37
38 #define DEFAULT_SHADOW_X_OFFSET (3.6)
39 #define DEFAULT_SHADOW_Y_OFFSET (3.6)
40 #define DEFAULT_SHADOW_COLOR    GL_COLOR_BLACK
41 #define DEFAULT_SHADOW_OPACITY  (0.5)
42
43 #define HANDLE_FILL_RGBA_ARGS      0.0,   0.75,  0.0,   0.4
44 #define HANDLE_OUTLINE_RGBA_ARGS   0.0,   0.0,   0.0,   0.8
45
46 #define HANDLE_OUTLINE_WIDTH_PIXELS   1.0
47 #define HANDLE_PIXELS 7
48
49
50 /*========================================================*/
51 /* Private types.                                         */
52 /*========================================================*/
53
54 struct _glLabelObjectPrivate {
55
56         gchar             *name;
57
58         gboolean           selected_flag;
59         glLabel           *parent;
60
61         gdouble            x, y;
62         gdouble            w, h;
63         cairo_matrix_t     matrix;
64
65         gdouble            aspect_ratio;
66
67         gboolean           shadow_state;
68         gdouble            shadow_x;
69         gdouble            shadow_y;
70         glColorNode       *shadow_color_node;
71         gdouble            shadow_opacity;
72 };
73
74 enum {
75         CHANGED,
76         MOVED,
77         LAST_SIGNAL
78 };
79
80
81 /*========================================================*/
82 /* Private globals.                                       */
83 /*========================================================*/
84
85 static guint instance = 0;
86
87 static guint signals[LAST_SIGNAL] = {0};
88
89
90 /*========================================================*/
91 /* Private function prototypes.                           */
92 /*========================================================*/
93
94 static void     gl_label_object_finalize  (GObject            *object);
95
96 static void     set_size                  (glLabelObject      *object,
97                                            gdouble             w,
98                                            gdouble             h,
99                                            gboolean            checkpoint);
100
101
102 /*****************************************************************************/
103 /* Boilerplate object stuff.                                                 */
104 /*****************************************************************************/
105 G_DEFINE_TYPE (glLabelObject, gl_label_object, G_TYPE_OBJECT)
106
107
108 static void
109 gl_label_object_class_init (glLabelObjectClass *class)
110 {
111         GObjectClass       *object_class = G_OBJECT_CLASS (class);
112
113         gl_debug (DEBUG_LABEL, "START");
114
115         gl_label_object_parent_class = g_type_class_peek_parent (class);
116
117         object_class->finalize = gl_label_object_finalize;
118
119         class->set_size     = set_size;
120         class->draw_handles = gl_label_object_draw_handles_box; /* Default style */
121         class->handle_at    = gl_label_object_box_handle_at;    /* Default style */
122
123         signals[CHANGED] =
124                 g_signal_new ("changed",
125                               G_OBJECT_CLASS_TYPE (object_class),
126                               G_SIGNAL_RUN_LAST,
127                               G_STRUCT_OFFSET (glLabelObjectClass, changed),
128                               NULL, NULL,
129                               gl_marshal_VOID__VOID,
130                               G_TYPE_NONE,
131                               0);
132
133         signals[MOVED] =
134                 g_signal_new ("moved",
135                               G_OBJECT_CLASS_TYPE (object_class),
136                               G_SIGNAL_RUN_LAST,
137                               G_STRUCT_OFFSET (glLabelObjectClass, moved),
138                               NULL, NULL,
139                               gl_marshal_VOID__VOID,
140                               G_TYPE_NONE,
141                               0);
142
143         gl_debug (DEBUG_LABEL, "END");
144 }
145
146
147 static void
148 gl_label_object_init (glLabelObject *object)
149 {
150         gl_debug (DEBUG_LABEL, "START");
151
152         object->priv = g_new0 (glLabelObjectPrivate, 1);
153
154         object->priv->name = g_strdup_printf ("object%d", instance++);
155
156         cairo_matrix_init_identity (&object->priv->matrix);
157
158         object->priv->shadow_state = FALSE;
159         object->priv->shadow_x = DEFAULT_SHADOW_X_OFFSET;
160         object->priv->shadow_y = DEFAULT_SHADOW_Y_OFFSET;
161         object->priv->shadow_color_node = gl_color_node_new_default ();
162         object->priv->shadow_color_node->color = DEFAULT_SHADOW_COLOR;
163         object->priv->shadow_opacity = DEFAULT_SHADOW_OPACITY;
164
165         gl_debug (DEBUG_LABEL, "END");
166 }
167
168
169 static void
170 gl_label_object_finalize (GObject *object)
171 {
172         glLabelObject *label_object = GL_LABEL_OBJECT (object);
173
174         gl_debug (DEBUG_LABEL, "START");
175
176         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
177
178         g_free (label_object->priv->name);
179         g_free (label_object->priv);
180
181         G_OBJECT_CLASS (gl_label_object_parent_class)->finalize (object);
182
183         gl_debug (DEBUG_LABEL, "END");
184 }
185
186
187 /*****************************************************************************/
188 /* New label object.                                                         */
189 /*****************************************************************************/
190 GObject *
191 gl_label_object_new (glLabel *label)
192 {
193         glLabelObject *object;
194
195         gl_debug (DEBUG_LABEL, "START");
196
197         object = g_object_new (gl_label_object_get_type(), NULL);
198
199         gl_label_object_set_parent (object, label);
200
201         gl_debug (DEBUG_LABEL, "END");
202
203         return G_OBJECT (object);
204 }
205
206
207 /*****************************************************************************/
208 /* Duplicate object.                                                         */
209 /*****************************************************************************/
210 glLabelObject *
211 gl_label_object_dup (glLabelObject *src_object,
212                      glLabel       *label)
213 {
214         glLabelObject    *dst_object;
215         gdouble           x, y, w, h;
216         cairo_matrix_t    matrix;
217         gboolean          shadow_state;
218         gdouble           shadow_x, shadow_y;
219         glColorNode      *shadow_color_node;
220         gdouble           shadow_opacity;
221
222         gl_debug (DEBUG_LABEL, "START");
223
224         g_return_val_if_fail (src_object && GL_IS_LABEL_OBJECT (src_object), NULL);
225
226         dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
227
228         gl_label_object_set_parent (dst_object, label);
229         dst_object->priv->selected_flag = src_object->priv->selected_flag;
230
231         gl_label_object_get_position      (src_object, &x, &y);
232         gl_label_object_get_raw_size      (src_object, &w, &h);
233         gl_label_object_get_matrix        (src_object, &matrix);
234         gl_label_object_get_shadow_offset (src_object, &shadow_x, &shadow_y);
235         shadow_color_node = gl_label_object_get_shadow_color   (src_object);
236         shadow_opacity    = gl_label_object_get_shadow_opacity (src_object);
237         shadow_state      = gl_label_object_get_shadow_state   (src_object);
238
239         gl_label_object_set_position (dst_object, x, y, FALSE);
240         gl_label_object_set_raw_size (dst_object, w, h, FALSE);
241         gl_label_object_set_matrix   (dst_object, &matrix);
242         gl_label_object_set_shadow_offset  (dst_object, shadow_x, shadow_y, FALSE);
243         gl_label_object_set_shadow_color   (dst_object, shadow_color_node, FALSE);
244         gl_label_object_set_shadow_opacity (dst_object, shadow_opacity, FALSE);
245         gl_label_object_set_shadow_state   (dst_object, shadow_state, FALSE);
246
247         gl_color_node_free (&shadow_color_node);
248
249         if ( GL_LABEL_OBJECT_GET_CLASS(src_object)->copy != NULL )
250         {
251                 /* We have an object specific method, use it */
252                 GL_LABEL_OBJECT_GET_CLASS(src_object)->copy (dst_object, src_object);
253         }
254
255         gl_debug (DEBUG_LABEL, "END");
256
257         return dst_object;
258 }
259
260
261 /*****************************************************************************/
262 /* Emit "changed" signal (for derived objects).                              */
263 /*****************************************************************************/
264 void
265 gl_label_object_emit_changed (glLabelObject *object)
266 {
267         gl_debug (DEBUG_LABEL, "START");
268
269         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
270
271         g_signal_emit (G_OBJECT(object), signals[CHANGED], 0);
272
273         gl_debug (DEBUG_LABEL, "END");
274 }
275
276
277 /*****************************************************************************/
278 /* Set parent label of object.                                               */
279 /*****************************************************************************/
280 void
281 gl_label_object_set_parent (glLabelObject *object,
282                             glLabel       *label)
283 {
284         gl_debug (DEBUG_LABEL, "START");
285
286         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
287         g_return_if_fail (label && GL_IS_LABEL (label));
288
289         object->priv->parent = label;
290 }
291
292
293 /*****************************************************************************/
294 /* Get parent label of object.                                               */
295 /*****************************************************************************/
296 glLabel *
297 gl_label_object_get_parent (glLabelObject *object)
298 {
299         gl_debug (DEBUG_LABEL, "START");
300
301         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
302
303         gl_debug (DEBUG_LABEL, "END");
304
305         return object->priv->parent;
306 }
307
308
309 /*****************************************************************************/
310 /* Select object.                                                            */
311 /*****************************************************************************/
312 void
313 gl_label_object_select (glLabelObject     *object)
314 {
315         object->priv->selected_flag = TRUE;
316 }
317
318
319 /*****************************************************************************/
320 /* Unselect object.                                                          */
321 /*****************************************************************************/
322 void
323 gl_label_object_unselect (glLabelObject     *object)
324 {
325         object->priv->selected_flag = FALSE;
326 }
327
328
329 /*****************************************************************************/
330 /* Is object selected?                                                       */
331 /*****************************************************************************/
332 gboolean
333 gl_label_object_is_selected (glLabelObject     *object)
334 {
335         return object->priv->selected_flag;
336 }
337
338
339 /*****************************************************************************/
340 /* Set name of object.                                                       */
341 /*****************************************************************************/
342 void    
343 gl_label_object_set_name (glLabelObject *object,
344                           gchar         *name)
345 {
346         gl_debug (DEBUG_LABEL, "START");
347
348         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
349
350         g_free(object->priv->name);
351         object->priv->name = name;
352
353         gl_label_object_emit_changed (object);
354
355         gl_debug (DEBUG_LABEL, "END");
356 }
357
358
359 /*****************************************************************************/
360 /* Get name of object.                                                       */
361 /*****************************************************************************/
362 gchar *
363 gl_label_object_get_name (glLabelObject *object)
364 {
365         gl_debug (DEBUG_LABEL, "START");
366
367         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
368
369         gl_debug (DEBUG_LABEL, "END");
370
371         return g_strdup(object->priv->name);
372 }
373
374
375 /*****************************************************************************/
376 /* Set position of object.                                                   */
377 /*****************************************************************************/
378 void    
379 gl_label_object_set_position (glLabelObject *object,
380                               gdouble        x,
381                               gdouble        y,
382                               gboolean       checkpoint)
383 {
384         gdouble  dx, dy;
385
386         gl_debug (DEBUG_LABEL, "START");
387
388         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
389
390         if ( (x != object->priv->x) || (y != object->priv->y) )
391         {
392                 if ( checkpoint )
393                 {
394                         gl_label_checkpoint (object->priv->parent, _("Move"));
395                 }
396
397                 dx = x - object->priv->x;
398                 dy = y - object->priv->y;
399
400                 object->priv->x = x;
401                 object->priv->y = y;
402
403                 g_signal_emit (G_OBJECT(object), signals[MOVED], 0);
404
405         }
406
407         gl_debug (DEBUG_LABEL, "END");
408 }
409
410
411 /*****************************************************************************/
412 /* Set position of object relative to old position.                          */
413 /*****************************************************************************/
414 void    
415 gl_label_object_set_position_relative (glLabelObject *object,
416                                        gdouble        dx,
417                                        gdouble        dy,
418                                        gboolean       checkpoint)
419 {
420         gl_debug (DEBUG_LABEL, "START");
421
422         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
423
424         if ( (dx != 0.0) || (dy != 0.0) )
425         {
426                 if ( checkpoint )
427                 {
428                         gl_label_checkpoint (object->priv->parent, _("Move"));
429                 }
430
431                 object->priv->x += dx;
432                 object->priv->y += dy;
433
434                 gl_debug (DEBUG_LABEL, "       x = %f, y= %f",
435                           object->priv->x,
436                           object->priv->y);
437
438                 g_signal_emit (G_OBJECT(object), signals[MOVED], 0);
439         }
440
441         gl_debug (DEBUG_LABEL, "END");
442 }
443
444
445 /*****************************************************************************/
446 /* Get position of object.                                                   */
447 /*****************************************************************************/
448 void
449 gl_label_object_get_position (glLabelObject *object,
450                               gdouble       *x,
451                               gdouble       *y)
452 {
453         gl_debug (DEBUG_LABEL, "START");
454
455         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
456
457         *x = object->priv->x;
458         *y = object->priv->y;
459
460         gl_debug (DEBUG_LABEL, "END");
461 }
462
463
464 /*---------------------------------------------------------------------------*/
465 /* PRIVATE.  Default set size method.                                        */
466 /*---------------------------------------------------------------------------*/
467 static void
468 set_size (glLabelObject *object,
469           gdouble        w,
470           gdouble        h,
471           gboolean       checkpoint)
472 {
473         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
474
475         if ( (object->priv->w != w) || (object->priv->h != h) )
476         {
477                 if ( checkpoint )
478                 {
479                         gl_label_checkpoint (object->priv->parent, _("Resize"));
480                 }
481
482                 object->priv->w = w;
483                 object->priv->h = h;
484
485                 gl_label_object_emit_changed (object);
486         }
487 }
488
489
490 /*****************************************************************************/
491 /* Set size of object.                                                       */
492 /*****************************************************************************/
493 void    
494 gl_label_object_set_size (glLabelObject *object,
495                           gdouble        w,
496                           gdouble        h,
497                           gboolean       checkpoint)
498 {
499         gl_debug (DEBUG_LABEL, "START");
500
501         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
502
503         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL )
504         {
505                 /* We have an object specific method, use it */
506                 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h, checkpoint);
507
508                 object->priv->aspect_ratio = h / w;
509         }
510
511         gl_debug (DEBUG_LABEL, "END");
512 }
513
514
515 /*****************************************************************************/
516 /* Set raw size of object.                                                   */
517 /*****************************************************************************/
518 void
519 gl_label_object_set_raw_size (glLabelObject *object,
520                               gdouble        w,
521                               gdouble        h,
522                               gboolean       checkpoint)
523 {
524         gl_debug (DEBUG_LABEL, "START");
525
526         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
527
528         set_size (object, w, h, checkpoint);
529         object->priv->aspect_ratio = h / w;
530
531         gl_debug (DEBUG_LABEL, "END");
532 }
533
534
535 /*****************************************************************************/
536 /* Set size of object honoring current aspect ratio.                         */
537 /*****************************************************************************/
538 void    
539 gl_label_object_set_size_honor_aspect (glLabelObject *object,
540                                        gdouble        w,
541                                        gdouble        h,
542                                        gboolean       checkpoint)
543 {
544         gl_debug (DEBUG_LABEL, "START");
545
546         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
547
548         if ( h > w*object->priv->aspect_ratio )
549         {
550                 h = w * object->priv->aspect_ratio;
551         }
552         else
553         {
554                 w = h / object->priv->aspect_ratio;
555         }
556
557         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL )
558         {
559                 /* We have an object specific method, use it */
560                 GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h, checkpoint);
561         }
562
563         gl_debug (DEBUG_LABEL, "END");
564 }
565
566
567 /*****************************************************************************/
568 /* Get raw size method (don't let object content adjust size).               */
569 /*****************************************************************************/
570 void
571 gl_label_object_get_raw_size (glLabelObject *object,
572                               gdouble       *w,
573                               gdouble       *h)
574 {
575         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
576
577         *w = object->priv->w;
578         *h = object->priv->h;
579 }
580
581
582 /*****************************************************************************/
583 /* Get size of object.                                                       */
584 /*****************************************************************************/
585 void
586 gl_label_object_get_size (glLabelObject *object,
587                           gdouble       *w,
588                           gdouble       *h)
589 {
590         gl_debug (DEBUG_LABEL, "START");
591
592         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
593
594         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_size != NULL )
595         {
596                 /* We have an object specific method, use it */
597                 GL_LABEL_OBJECT_GET_CLASS(object)->get_size (object, w, h);
598         }
599         else
600         {
601                 gl_label_object_get_raw_size (object, w, h);
602         }
603
604         gl_debug (DEBUG_LABEL, "END");
605 }
606
607
608 /*****************************************************************************/
609 /* Get extent of object.                                                     */
610 /*****************************************************************************/
611 void
612 gl_label_object_get_extent (glLabelObject *object,
613                             glLabelRegion *region)
614 {
615         gdouble        w, h;
616         gdouble        line_w;
617         gdouble        xa1, ya1, xa2, ya2, xa3, ya3, xa4, ya4;
618         cairo_matrix_t matrix;
619
620         gl_debug (DEBUG_LABEL, "START");
621
622         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
623
624         gl_label_object_get_size (object, &w, &h);
625         line_w = gl_label_object_get_line_width (object);
626
627         /* setup untransformed corners of bounding box, account for line width */
628         xa1 =   - line_w/2;
629         ya1 =   - line_w/2;
630         xa2 = w + line_w/2;
631         ya2 =   - line_w/2;
632         xa3 = w + line_w/2;
633         ya3 = h + line_w/2;
634         xa4 =   - line_w/2;
635         ya4 = h + line_w/2;
636
637         /* transform these points */
638         gl_label_object_get_matrix (object, &matrix);
639         cairo_matrix_transform_point (&matrix, &xa1, &ya1);
640         cairo_matrix_transform_point (&matrix, &xa2, &ya2);
641         cairo_matrix_transform_point (&matrix, &xa3, &ya3);
642         cairo_matrix_transform_point (&matrix, &xa4, &ya4);
643
644         /* now find the maximum extent of these points in x and y */
645         region->x1 = MIN (xa1, MIN (xa2, MIN (xa3, xa4))) + object->priv->x;
646         region->y1 = MIN (ya1, MIN (ya2, MIN (ya3, ya4))) + object->priv->y;
647         region->x2 = MAX (xa1, MAX (xa2, MAX (xa3, xa4))) + object->priv->x;
648         region->y2 = MAX (ya1, MAX (ya2, MAX (ya3, ya4))) + object->priv->y;
649
650         gl_debug (DEBUG_LABEL, "END");
651 }
652
653
654 /*****************************************************************************/
655 /* Can text properties be set for this object?                               */
656 /*****************************************************************************/
657 gboolean
658 gl_label_object_can_text (glLabelObject     *object)
659 {
660         gl_debug (DEBUG_LABEL, "");
661
662         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
663
664         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL )
665         {
666                 return TRUE;
667         }
668         else
669         {
670                 return FALSE;
671         }
672 }
673
674
675 /*****************************************************************************/
676 /* Set font family for all text contained in object.                         */
677 /*****************************************************************************/
678 void    
679 gl_label_object_set_font_family (glLabelObject     *object,
680                                  const gchar       *font_family,
681                                  gboolean           checkpoint)
682 {
683         gl_debug (DEBUG_LABEL, "START");
684
685         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
686
687         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL )
688         {
689                 /* We have an object specific method, use it */
690                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family, checkpoint);
691         }
692
693         gl_debug (DEBUG_LABEL, "END");
694 }
695
696
697 /****************************************************************************/
698 /* Set font size for all text contained in object.                          */
699 /****************************************************************************/
700 void    
701 gl_label_object_set_font_size (glLabelObject     *object,
702                                gdouble            font_size,
703                                gboolean           checkpoint)
704 {
705         gl_debug (DEBUG_LABEL, "START");
706
707         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
708
709         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL )
710         {
711                 /* We have an object specific method, use it */
712                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size, checkpoint);
713         }
714
715         gl_debug (DEBUG_LABEL, "END");
716 }
717
718
719 /****************************************************************************/
720 /* Set font weight for all text contained in object.                        */
721 /****************************************************************************/
722 void    
723 gl_label_object_set_font_weight (glLabelObject     *object,
724                                  PangoWeight        font_weight,
725                                  gboolean           checkpoint)
726 {
727         gl_debug (DEBUG_LABEL, "START");
728
729         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
730
731         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL )
732         {
733                 /* We have an object specific method, use it */
734                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight, checkpoint);
735         }
736
737         gl_debug (DEBUG_LABEL, "END");
738 }
739
740
741 /****************************************************************************/
742 /* Set font italic flag for all text contained in object.                   */
743 /****************************************************************************/
744 void    
745 gl_label_object_set_font_italic_flag (glLabelObject     *object,
746                                       gboolean           font_italic_flag,
747                                       gboolean           checkpoint)
748 {
749         gl_debug (DEBUG_LABEL, "START");
750
751         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
752
753         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL )
754         {
755                 /* We have an object specific method, use it */
756                 GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object, font_italic_flag, checkpoint);
757         }
758
759         gl_debug (DEBUG_LABEL, "END");
760 }
761
762
763 /****************************************************************************/
764 /* Set text alignment for all text contained in object.                     */
765 /****************************************************************************/
766 void    
767 gl_label_object_set_text_alignment (glLabelObject     *object,
768                                     PangoAlignment     text_alignment,
769                                     gboolean           checkpoint)
770 {
771         gl_debug (DEBUG_LABEL, "START");
772
773         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
774
775         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL )
776         {
777                 /* We have an object specific method, use it */
778                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object, text_alignment, checkpoint);
779         }
780
781         gl_debug (DEBUG_LABEL, "END");
782 }
783
784
785 /****************************************************************************/
786 /* Set vertical text alignment for all text contained in object.            */
787 /****************************************************************************/
788 void
789 gl_label_object_set_text_valignment (glLabelObject     *object,
790                                      glValignment       text_valignment,
791                                      gboolean           checkpoint)
792 {
793         gl_debug (DEBUG_LABEL, "START");
794
795         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
796
797         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_valignment != NULL )
798         {
799                 /* We have an object specific method, use it */
800                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_valignment (object, text_valignment, checkpoint);
801         }
802
803         gl_debug (DEBUG_LABEL, "END");
804 }
805
806
807 /****************************************************************************/
808 /* Set text line spacing for all text contained in object.                  */
809 /****************************************************************************/
810 void    
811 gl_label_object_set_text_line_spacing (glLabelObject     *object,
812                                        gdouble            text_line_spacing,
813                                        gboolean           checkpoint)
814 {
815         gl_debug (DEBUG_LABEL, "START");
816
817         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
818
819         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL )
820         {
821                 /* We have an object specific method, use it */
822                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing, checkpoint);
823         }
824
825         gl_debug (DEBUG_LABEL, "END");
826 }
827
828
829 /****************************************************************************/
830 /* Set text color for all text contained in object.                         */
831 /****************************************************************************/
832 void    
833 gl_label_object_set_text_color (glLabelObject     *object,
834                                 glColorNode       *text_color_node,
835                                 gboolean           checkpoint)
836 {
837         gl_debug (DEBUG_LABEL, "START");
838
839         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
840
841         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL )
842         {
843                 /* We have an object specific method, use it */
844                 GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node, checkpoint);
845         }
846
847         gl_debug (DEBUG_LABEL, "END");
848 }
849
850
851 /*****************************************************************************/
852 /* Get font family for all text contained in object.                         */
853 /*****************************************************************************/
854 gchar *
855 gl_label_object_get_font_family (glLabelObject     *object)
856 {
857         gchar *ret = NULL;
858
859         gl_debug (DEBUG_LABEL, "START");
860
861         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
862
863         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family != NULL )
864         {
865                 /* We have an object specific method, use it */
866                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_family (object);
867         }
868
869         gl_debug (DEBUG_LABEL, "END");
870
871         return ret;
872 }
873
874
875 /****************************************************************************/
876 /* Get font size for all text contained in object.                          */
877 /****************************************************************************/
878 gdouble
879 gl_label_object_get_font_size (glLabelObject     *object)
880 {
881         gdouble ret = 0.0;
882
883         gl_debug (DEBUG_LABEL, "START");
884
885         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
886
887         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size != NULL )
888         {
889                 /* We have an object specific method, use it */
890                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_size (object);
891         }
892
893         gl_debug (DEBUG_LABEL, "END");
894
895         return ret;
896 }
897
898
899 /****************************************************************************/
900 /* Get font weight for all text contained in object.                        */
901 /****************************************************************************/
902 PangoWeight    
903 gl_label_object_get_font_weight (glLabelObject     *object)
904 {
905         PangoWeight     ret = PANGO_WEIGHT_NORMAL;
906
907         gl_debug (DEBUG_LABEL, "START");
908
909         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_WEIGHT_NORMAL);
910
911         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight != NULL )
912         {
913                 /* We have an object specific method, use it */
914                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_weight (object);
915         }
916
917         gl_debug (DEBUG_LABEL, "END");
918
919         return ret;
920 }
921
922
923 /****************************************************************************/
924 /* Get font italic flag for all text contained in object.                   */
925 /****************************************************************************/
926 gboolean
927 gl_label_object_get_font_italic_flag (glLabelObject     *object)
928 {
929         gboolean ret = FALSE;
930
931         gl_debug (DEBUG_LABEL, "START");
932
933         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
934
935         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag != NULL )
936         {
937                 /* We have an object specific method, use it */
938                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_font_italic_flag (object);
939         }
940
941         gl_debug (DEBUG_LABEL, "END");
942
943         return ret;
944 }
945
946
947 /****************************************************************************/
948 /* Get text alignment for all text contained in object.                     */
949 /****************************************************************************/
950 PangoAlignment
951 gl_label_object_get_text_alignment (glLabelObject     *object)
952 {
953         PangoAlignment ret = PANGO_ALIGN_LEFT;
954
955         gl_debug (DEBUG_LABEL, "START");
956
957         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), PANGO_ALIGN_LEFT);
958
959         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment != NULL )
960         {
961                 /* We have an object specific method, use it */
962                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_alignment (object);
963         }
964
965         gl_debug (DEBUG_LABEL, "END");
966
967         return ret;
968 }
969
970
971 /****************************************************************************/
972 /* Get text alignment for all text contained in object.                     */
973 /****************************************************************************/
974 glValignment
975 gl_label_object_get_text_valignment (glLabelObject     *object)
976 {
977         glValignment ret = GL_VALIGN_TOP;
978
979         gl_debug (DEBUG_LABEL, "START");
980
981         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), GL_VALIGN_TOP);
982
983         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_valignment != NULL )
984         {
985                 /* We have an object specific method, use it */
986                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_valignment (object);
987         }
988
989         gl_debug (DEBUG_LABEL, "END");
990
991         return ret;
992 }
993
994
995 /****************************************************************************/
996 /* Get text line spacing for all text contained in object.                  */
997 /****************************************************************************/
998 gdouble
999 gl_label_object_get_text_line_spacing (glLabelObject     *object)
1000 {
1001         gdouble ret = 0.0;
1002
1003         gl_debug (DEBUG_LABEL, "START");
1004
1005         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
1006
1007         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing != NULL )
1008         {
1009                 /* We have an object specific method, use it */
1010                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_line_spacing (object);
1011         }
1012
1013         gl_debug (DEBUG_LABEL, "END");
1014
1015         return ret;
1016 }
1017
1018
1019 /****************************************************************************/
1020 /* Get text color for all text contained in object.                         */
1021 /****************************************************************************/
1022 glColorNode*
1023 gl_label_object_get_text_color (glLabelObject     *object)
1024 {
1025         glColorNode *ret = NULL;
1026
1027         gl_debug (DEBUG_LABEL, "START");
1028
1029         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1030
1031         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color != NULL )
1032         {
1033                 /* We have an object specific method, use it */
1034                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_text_color (object);
1035         }
1036
1037         gl_debug (DEBUG_LABEL, "END");
1038
1039         return ret;
1040 }
1041
1042
1043 /*****************************************************************************/
1044 /* Can fill properties be set for this object?                               */
1045 /*****************************************************************************/
1046 gboolean
1047 gl_label_object_can_fill (glLabelObject     *object)
1048 {
1049         gl_debug (DEBUG_LABEL, "");
1050
1051         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1052
1053         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL )
1054         {
1055                 return TRUE;
1056         }
1057         else
1058         {
1059                 return FALSE;
1060         }
1061
1062 }
1063
1064
1065 /****************************************************************************/
1066 /* Set fill color for object.                                               */
1067 /****************************************************************************/
1068 void    
1069 gl_label_object_set_fill_color (glLabelObject     *object,
1070                                 glColorNode       *fill_color_node,
1071                                 gboolean           checkpoint)
1072 {
1073         gl_debug (DEBUG_LABEL, "START");
1074
1075         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1076
1077         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL )
1078         {
1079                 /* We have an object specific method, use it */
1080                 GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node, checkpoint);
1081         }
1082
1083         gl_debug (DEBUG_LABEL, "END");
1084 }
1085
1086
1087 /****************************************************************************/
1088 /* Get fill color for object.                                               */
1089 /****************************************************************************/
1090 glColorNode*
1091 gl_label_object_get_fill_color (glLabelObject     *object)
1092 {
1093         glColorNode *ret = NULL;
1094
1095         gl_debug (DEBUG_LABEL, "START");
1096
1097         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1098
1099         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color != NULL )
1100         {
1101                 /* We have an object specific method, use it */
1102                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_fill_color (object);
1103         }
1104
1105         gl_debug (DEBUG_LABEL, "END");
1106
1107         return ret;
1108 }
1109
1110
1111 /*****************************************************************************/
1112 /* Can line color property be set for this object?                           */
1113 /*****************************************************************************/
1114 gboolean
1115 gl_label_object_can_line_color (glLabelObject     *object)
1116 {
1117         gl_debug (DEBUG_LABEL, "");
1118
1119         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1120
1121         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL )
1122         {
1123                 return TRUE;
1124         }
1125         else
1126         {
1127                 return FALSE;
1128         }
1129
1130 }
1131
1132
1133 /****************************************************************************/
1134 /* Set line color for object.                                               */
1135 /****************************************************************************/
1136 void    
1137 gl_label_object_set_line_color (glLabelObject     *object,
1138                                 glColorNode       *line_color_node,
1139                                 gboolean           checkpoint)
1140 {
1141         gl_debug (DEBUG_LABEL, "START");
1142
1143         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1144
1145         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL )
1146         {
1147                 /* We have an object specific method, use it */
1148                 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node, checkpoint);
1149         }
1150
1151         gl_debug (DEBUG_LABEL, "END");
1152 }
1153
1154
1155 /****************************************************************************/
1156 /* Get line color for object.                                               */
1157 /****************************************************************************/
1158 glColorNode*
1159 gl_label_object_get_line_color (glLabelObject     *object)
1160 {
1161         glColorNode *ret = NULL;
1162
1163         gl_debug (DEBUG_LABEL, "START");
1164
1165         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0);
1166
1167         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color != NULL )
1168         {
1169                 /* We have an object specific method, use it */
1170                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_color (object);
1171         }
1172
1173         gl_debug (DEBUG_LABEL, "END");
1174
1175         return ret;
1176 }
1177
1178
1179 /*****************************************************************************/
1180 /* Can line width property be set for this object?                           */
1181 /*****************************************************************************/
1182 gboolean
1183 gl_label_object_can_line_width (glLabelObject     *object)
1184 {
1185         gl_debug (DEBUG_LABEL, "");
1186
1187         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1188
1189         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL )
1190         {
1191                 return TRUE;
1192         }
1193         else
1194         {
1195                 return FALSE;
1196         }
1197
1198 }
1199
1200
1201 /****************************************************************************/
1202 /* Set line width for object.                                               */
1203 /****************************************************************************/
1204 void    
1205 gl_label_object_set_line_width (glLabelObject     *object,
1206                                 gdouble            line_width,
1207                                 gboolean           checkpoint)
1208 {
1209         gl_debug (DEBUG_LABEL, "START");
1210
1211         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1212
1213         if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL )
1214         {
1215                 /* We have an object specific method, use it */
1216                 GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width, checkpoint);
1217         }
1218
1219         gl_debug (DEBUG_LABEL, "END");
1220 }
1221
1222
1223 /****************************************************************************/
1224 /* Get line width for object.                                               */
1225 /****************************************************************************/
1226 gdouble
1227 gl_label_object_get_line_width (glLabelObject     *object)
1228 {
1229         gdouble ret = 0.0;
1230
1231         gl_debug (DEBUG_LABEL, "START");
1232
1233         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), 0.0);
1234
1235         if ( GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width != NULL )
1236         {
1237                 /* We have an object specific method, use it */
1238                 ret = GL_LABEL_OBJECT_GET_CLASS(object)->get_line_width (object);
1239         }
1240
1241         gl_debug (DEBUG_LABEL, "END");
1242
1243         return ret;
1244 }
1245
1246
1247 /****************************************************************************/
1248 /* Set shadow state of object.                                              */
1249 /****************************************************************************/
1250 void    
1251 gl_label_object_set_shadow_state (glLabelObject     *object,
1252                                   gboolean           state,
1253                                   gboolean           checkpoint)
1254 {
1255         gl_debug (DEBUG_LABEL, "START");
1256
1257         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1258
1259         if (object->priv->shadow_state != state)
1260         {
1261                 if ( checkpoint )
1262                 {
1263                         gl_label_checkpoint (object->priv->parent, _("Shadow state"));
1264                 }
1265
1266                 object->priv->shadow_state = state;
1267
1268                 gl_label_object_emit_changed (object);
1269         }
1270
1271         gl_debug (DEBUG_LABEL, "END");
1272 }
1273
1274
1275 /****************************************************************************/
1276 /* Get shadow state of object.                                              */
1277 /****************************************************************************/
1278 gboolean
1279 gl_label_object_get_shadow_state (glLabelObject     *object)
1280 {
1281         gl_debug (DEBUG_LABEL, "");
1282
1283         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1284
1285         return object->priv->shadow_state;
1286 }
1287
1288
1289 /****************************************************************************/
1290 /* Set offset of object's shadow.                                           */
1291 /****************************************************************************/
1292 void    
1293 gl_label_object_set_shadow_offset (glLabelObject     *object,
1294                                    gdouble            x,
1295                                    gdouble            y,
1296                                    gboolean           checkpoint)
1297 {
1298         gl_debug (DEBUG_LABEL, "START");
1299
1300         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1301
1302         if ( (x != object->priv->shadow_x) || (y != object->priv->shadow_y) )
1303         {
1304                 if ( checkpoint )
1305                 {
1306                         gl_label_checkpoint (object->priv->parent, _("Shadow offset"));
1307                 }
1308
1309                 object->priv->shadow_x = x;
1310                 object->priv->shadow_y = y;
1311
1312                 gl_label_object_emit_changed (object);
1313         }
1314
1315         gl_debug (DEBUG_LABEL, "END");
1316 }
1317
1318
1319 /****************************************************************************/
1320 /* Get offset of object's shadow.                                           */
1321 /****************************************************************************/
1322 void
1323 gl_label_object_get_shadow_offset (glLabelObject     *object,
1324                                    gdouble           *x,
1325                                    gdouble           *y)
1326 {
1327         gl_debug (DEBUG_LABEL, "START");
1328
1329         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1330
1331         *x = object->priv->shadow_x;
1332         *y = object->priv->shadow_y;
1333
1334         gl_debug (DEBUG_LABEL, "END");
1335 }
1336
1337
1338 /****************************************************************************/
1339 /* Set color of object's shadow.                                            */
1340 /****************************************************************************/
1341 void    
1342 gl_label_object_set_shadow_color (glLabelObject     *object,
1343                                   glColorNode       *color_node,
1344                                   gboolean           checkpoint)
1345 {
1346         gl_debug (DEBUG_LABEL, "START");
1347
1348         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1349
1350         if ( !gl_color_node_equal (object->priv->shadow_color_node, color_node ))
1351         {
1352                 if ( checkpoint )
1353                 {
1354                         gl_label_checkpoint (object->priv->parent, _("Shadow color"));
1355                 }
1356
1357                 gl_color_node_free (&(object->priv->shadow_color_node));
1358                 object->priv->shadow_color_node = gl_color_node_dup (color_node);
1359
1360                 gl_label_object_emit_changed (object);
1361         }
1362
1363         gl_debug (DEBUG_LABEL, "END");
1364 }
1365
1366
1367 /****************************************************************************/
1368 /* Get color of object's shadow.                                            */
1369 /****************************************************************************/
1370 glColorNode*
1371 gl_label_object_get_shadow_color (glLabelObject     *object)
1372 {
1373         gl_debug (DEBUG_LABEL, "");
1374
1375         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
1376
1377         return gl_color_node_dup (object->priv->shadow_color_node);
1378 }
1379
1380
1381 /****************************************************************************/
1382 /* Set opacity of object's shadow.                                          */
1383 /****************************************************************************/
1384 void    
1385 gl_label_object_set_shadow_opacity (glLabelObject     *object,
1386                                     gdouble            alpha,
1387                                     gboolean           checkpoint)
1388 {
1389         gl_debug (DEBUG_LABEL, "START");
1390
1391         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1392
1393         if (object->priv->shadow_opacity != alpha)
1394         {
1395                 if ( checkpoint )
1396                 {
1397                         gl_label_checkpoint (object->priv->parent, _("Shadow opacity"));
1398                 }
1399
1400                 object->priv->shadow_opacity = alpha;
1401
1402                 gl_label_object_emit_changed (object);
1403         }
1404
1405         gl_debug (DEBUG_LABEL, "END");
1406 }
1407
1408
1409 /****************************************************************************/
1410 /* Get opacity of object's shadow.                                          */
1411 /****************************************************************************/
1412 gdouble
1413 gl_label_object_get_shadow_opacity (glLabelObject     *object)
1414 {
1415         gl_debug (DEBUG_LABEL, "");
1416
1417         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1418
1419         return object->priv->shadow_opacity;
1420 }
1421
1422
1423 /****************************************************************************/
1424 /* Flip object horizontally.                                                */
1425 /****************************************************************************/
1426 void
1427 gl_label_object_flip_horiz (glLabelObject *object)
1428 {
1429         cairo_matrix_t flip_matrix;
1430
1431         gl_debug (DEBUG_LABEL, "START");
1432
1433         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1434
1435         cairo_matrix_init_scale (&flip_matrix, -1.0, 1.0);
1436         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1437
1438         gl_debug (DEBUG_LABEL, "END");
1439 }
1440
1441
1442 /****************************************************************************/
1443 /* Flip object vertically.                                                  */
1444 /****************************************************************************/
1445 void
1446 gl_label_object_flip_vert (glLabelObject *object)
1447 {
1448         cairo_matrix_t flip_matrix;
1449
1450         gl_debug (DEBUG_LABEL, "START");
1451
1452         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1453
1454         cairo_matrix_init_scale (&flip_matrix, 1.0, -1.0);
1455         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &flip_matrix);
1456
1457         gl_debug (DEBUG_LABEL, "END");
1458 }
1459
1460
1461 /****************************************************************************/
1462 /* Rotate object.                                                           */
1463 /****************************************************************************/
1464 void
1465 gl_label_object_rotate (glLabelObject *object,
1466                         gdouble        theta_degs)
1467 {
1468         cairo_matrix_t rotate_matrix;
1469
1470         gl_debug (DEBUG_LABEL, "START");
1471
1472         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1473
1474         cairo_matrix_init_rotate (&rotate_matrix, theta_degs*(G_PI/180.));
1475         cairo_matrix_multiply (&object->priv->matrix, &object->priv->matrix, &rotate_matrix);
1476
1477         gl_debug (DEBUG_LABEL, "END");
1478 }
1479
1480
1481 /****************************************************************************/
1482 /* Set raw affine                                                           */
1483 /****************************************************************************/
1484 void
1485 gl_label_object_set_matrix (glLabelObject  *object,
1486                             cairo_matrix_t *matrix)
1487 {
1488         gl_debug (DEBUG_LABEL, "");
1489
1490         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1491
1492         object->priv->matrix = *matrix;
1493 }
1494
1495
1496 /****************************************************************************/
1497 /* Get raw affine                                                           */
1498 /****************************************************************************/
1499 void
1500 gl_label_object_get_matrix (glLabelObject  *object,
1501                             cairo_matrix_t *matrix)
1502 {
1503         gl_debug (DEBUG_LABEL, "");
1504
1505         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1506
1507         *matrix = object->priv->matrix;
1508 }
1509
1510
1511 /*****************************************************************************/
1512 /* Draw object                                                               */
1513 /*****************************************************************************/
1514 void
1515 gl_label_object_draw (glLabelObject *object,
1516                       cairo_t       *cr,
1517                       gboolean       screen_flag,
1518                       glMergeRecord *record)
1519
1520 {
1521         gdouble        x0, y0;
1522         cairo_matrix_t matrix;
1523         gboolean       shadow_state;
1524         gdouble        shadow_x, shadow_y;
1525
1526         gl_debug (DEBUG_LABEL, "START");
1527
1528         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1529
1530         gl_label_object_get_position (object, &x0, &y0);
1531         gl_label_object_get_matrix (object, &matrix);
1532
1533         cairo_save (cr);
1534         cairo_translate (cr, x0, y0);
1535
1536         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow != NULL )
1537         {
1538                 shadow_state = gl_label_object_get_shadow_state (object);
1539
1540                 if ( shadow_state )
1541                 {
1542                         gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1543
1544                         cairo_save (cr);
1545                         cairo_translate (cr, shadow_x, shadow_y);
1546                         cairo_transform (cr, &matrix);
1547
1548                         GL_LABEL_OBJECT_GET_CLASS(object)->draw_shadow (object,
1549                                                                         cr,
1550                                                                         screen_flag,
1551                                                                         record);
1552
1553                         cairo_restore (cr);
1554                 }
1555         }
1556
1557         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
1558         {
1559                 cairo_save (cr);
1560                 cairo_transform (cr, &matrix);
1561
1562                 GL_LABEL_OBJECT_GET_CLASS(object)->draw_object (object,
1563                                                                 cr,
1564                                                                 screen_flag,
1565                                                                 record);
1566
1567                 cairo_restore (cr);
1568         }
1569
1570         cairo_restore (cr);
1571
1572         gl_debug (DEBUG_LABEL, "END");
1573 }
1574
1575
1576 /*****************************************************************************/
1577 /* Is object located at coordinates.                                         */
1578 /*****************************************************************************/
1579 gboolean
1580 gl_label_object_is_located_at (glLabelObject     *object,
1581                                cairo_t           *cr,
1582                                gdouble            x_pixels,
1583                                gdouble            y_pixels)
1584 {
1585         gboolean            ret_val = FALSE;
1586         gdouble             x0, y0;
1587         cairo_matrix_t      matrix;
1588         gdouble             x, y;
1589
1590         gl_debug (DEBUG_LABEL, "START");
1591
1592         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), FALSE);
1593
1594         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
1595         {
1596
1597                 gl_label_object_get_position (object, &x0, &y0);
1598                 gl_label_object_get_matrix (object, &matrix);
1599
1600                 cairo_save (cr);
1601
1602                 cairo_translate (cr, x0, y0);
1603                 cairo_transform (cr, &matrix);
1604
1605                 x = x_pixels;
1606                 y = y_pixels;
1607                 cairo_device_to_user (cr, &x, &y);
1608
1609                 ret_val = GL_LABEL_OBJECT_GET_CLASS(object)->object_at (object, cr, x, y);
1610
1611                 cairo_restore (cr);
1612         }
1613
1614         gl_debug (DEBUG_LABEL, "END");
1615
1616         return ret_val;
1617 }
1618
1619
1620 /*****************************************************************************/
1621 /* Draw object handles                                                       */
1622 /*****************************************************************************/
1623 void
1624 gl_label_object_draw_handles (glLabelObject     *object,
1625                               cairo_t           *cr)
1626 {
1627         gdouble        x0, y0;
1628         cairo_matrix_t matrix;
1629
1630         gl_debug (DEBUG_LABEL, "START");
1631
1632         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
1633
1634         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
1635         {
1636
1637                 gl_label_object_get_position (object, &x0, &y0);
1638                 gl_label_object_get_matrix (object, &matrix);
1639
1640                 cairo_save (cr);
1641
1642                 cairo_translate (cr, x0, y0);
1643                 cairo_transform (cr, &matrix);
1644
1645                 GL_LABEL_OBJECT_GET_CLASS(object)->draw_handles (object, cr);
1646
1647                 cairo_restore (cr);
1648         }
1649
1650         gl_debug (DEBUG_LABEL, "END");
1651 }
1652
1653
1654 /*--------------------------------------------------------------------------*/
1655 /* Draw individual handle                                                   */
1656 /*--------------------------------------------------------------------------*/
1657 static void
1658 draw_handle (cairo_t                *cr,
1659              glLabelObject          *object,
1660              gdouble                 x_handle,
1661              gdouble                 y_handle)
1662 {
1663         gdouble scale_x, scale_y;
1664
1665
1666         gl_debug (DEBUG_VIEW, "START");
1667
1668         cairo_save (cr);
1669
1670         cairo_translate (cr, x_handle, y_handle);
1671
1672         scale_x = 1.0;
1673         scale_y = 1.0;
1674         cairo_device_to_user_distance (cr, &scale_x, &scale_y);
1675         cairo_scale (cr, scale_x, scale_y);
1676
1677         cairo_rectangle (cr,
1678                          -HANDLE_PIXELS/2.0, -HANDLE_PIXELS/2.0,
1679                          HANDLE_PIXELS, HANDLE_PIXELS);
1680
1681         cairo_set_source_rgba (cr, HANDLE_FILL_RGBA_ARGS);
1682         cairo_fill_preserve (cr);
1683                                
1684         cairo_set_line_width (cr, HANDLE_OUTLINE_WIDTH_PIXELS);
1685         cairo_set_source_rgba (cr, HANDLE_OUTLINE_RGBA_ARGS);
1686         cairo_stroke (cr);
1687
1688         cairo_restore (cr);
1689
1690         gl_debug (DEBUG_VIEW, "END");
1691 }
1692
1693
1694 /*--------------------------------------------------------------------------*/
1695 /* Create handle path                                                       */
1696 /*--------------------------------------------------------------------------*/
1697 static void
1698 create_handle_path (cairo_t                *cr,
1699                     glLabelObject          *object,
1700                     gdouble                 x_handle,
1701                     gdouble                 y_handle)
1702 {
1703         gdouble scale_x, scale_y;
1704
1705
1706         gl_debug (DEBUG_VIEW, "START");
1707
1708         cairo_save (cr);
1709
1710         cairo_translate (cr, x_handle, y_handle);
1711
1712         scale_x = 1.0;
1713         scale_y = 1.0;
1714         cairo_device_to_user_distance (cr, &scale_x, &scale_y);
1715         cairo_scale (cr, scale_x, scale_y);
1716
1717         cairo_rectangle (cr,
1718                          -HANDLE_PIXELS/2.0, -HANDLE_PIXELS/2.0,
1719                          HANDLE_PIXELS, HANDLE_PIXELS);
1720
1721         cairo_restore (cr);
1722
1723         gl_debug (DEBUG_VIEW, "END");
1724 }
1725
1726
1727 /*****************************************************************************/
1728 /* Draw box style handles.                                                   */
1729 /*****************************************************************************/
1730 void
1731 gl_label_object_draw_handles_box (glLabelObject     *object,
1732                                   cairo_t           *cr)
1733 {
1734         gdouble w, h;
1735
1736         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1737
1738         /* North */
1739         draw_handle (cr, object, w/2, 0);
1740
1741         /* North East */
1742         draw_handle (cr, object, w, 0);
1743
1744         /* East */
1745         draw_handle (cr, object, w, h/2);
1746
1747         /* South East */
1748         draw_handle (cr, object, w, h);
1749
1750         /* South */
1751         draw_handle (cr, object, w/2, h);
1752
1753         /* South West */
1754         draw_handle (cr, object, 0, h);
1755
1756         /* West */
1757         draw_handle (cr, object, 0, h/2);
1758
1759         /* North West */
1760         draw_handle (cr, object, 0, 0);
1761 }
1762
1763
1764 /*****************************************************************************/
1765 /* Draw line style handles.                                                  */
1766 /*****************************************************************************/
1767 void
1768 gl_label_object_draw_handles_line (glLabelObject     *object,
1769                                    cairo_t           *cr)
1770 {
1771         gdouble w, h;
1772
1773         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1774
1775         /* P2 */
1776         draw_handle (cr, object, w, h);
1777
1778         /* P1 */
1779         draw_handle (cr, object, 0, 0);
1780 }
1781
1782
1783 /*****************************************************************************/
1784 /* Get handle at given coordinates, if any.                                  */
1785 /*****************************************************************************/
1786 glLabelObjectHandle
1787 gl_label_object_handle_at (glLabelObject     *object,
1788                            cairo_t           *cr,
1789                            gdouble            x_pixels,
1790                            gdouble            y_pixels)
1791 {
1792         glLabelObjectHandle handle = GL_LABEL_OBJECT_HANDLE_NONE;
1793         gdouble             x0, y0;
1794         cairo_matrix_t      matrix;
1795         gdouble             x, y;
1796
1797         gl_debug (DEBUG_LABEL, "START");
1798
1799         g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), handle);
1800
1801         if ( GL_LABEL_OBJECT_GET_CLASS(object)->draw_object != NULL )
1802         {
1803
1804                 gl_label_object_get_position (object, &x0, &y0);
1805                 gl_label_object_get_matrix (object, &matrix);
1806
1807                 cairo_save (cr);
1808
1809                 cairo_translate (cr, x0, y0);
1810                 cairo_transform (cr, &matrix);
1811
1812                 x = x_pixels;
1813                 y = y_pixels;
1814                 cairo_device_to_user (cr, &x, &y);
1815
1816                 handle = GL_LABEL_OBJECT_GET_CLASS(object)->handle_at (object, cr, x, y);
1817
1818                 cairo_restore (cr);
1819         }
1820
1821         gl_debug (DEBUG_LABEL, "END");
1822
1823         return handle;
1824 }
1825
1826
1827 /*****************************************************************************/
1828 /* Get handle at given coordinates for box style handles, if any.            */
1829 /*****************************************************************************/
1830 glLabelObjectHandle
1831 gl_label_object_box_handle_at (glLabelObject     *object,
1832                                cairo_t           *cr,
1833                                gdouble            x,
1834                                gdouble            y)
1835 {
1836         gdouble w, h;
1837
1838         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1839
1840         /* South East */
1841         create_handle_path (cr, object, w, h);
1842         if (cairo_in_fill (cr, x, y))
1843         {
1844                 return GL_LABEL_OBJECT_HANDLE_SE;
1845         }
1846         
1847         /* South West */
1848         create_handle_path (cr, object, 0, h);
1849         if (cairo_in_fill (cr, x, y))
1850         {
1851                 return GL_LABEL_OBJECT_HANDLE_SW;
1852         }
1853
1854         /* North East */
1855         create_handle_path (cr, object, w, 0);
1856         if (cairo_in_fill (cr, x, y))
1857         {
1858                 return GL_LABEL_OBJECT_HANDLE_NE;
1859         }
1860
1861         /* North West */
1862         create_handle_path (cr, object, 0, 0);
1863         if (cairo_in_fill (cr, x, y))
1864         {
1865                 return GL_LABEL_OBJECT_HANDLE_NW;
1866         }
1867
1868         /* East */
1869         create_handle_path (cr, object, w, h/2);
1870         if (cairo_in_fill (cr, x, y))
1871         {
1872                 return GL_LABEL_OBJECT_HANDLE_E;
1873         }
1874
1875         /* South */
1876         create_handle_path (cr, object, w/2, h);
1877         if (cairo_in_fill (cr, x, y))
1878         {
1879                 return GL_LABEL_OBJECT_HANDLE_S;
1880         }
1881
1882         /* West */
1883         create_handle_path (cr, object, 0, h/2);
1884         if (cairo_in_fill (cr, x, y))
1885         {
1886                 return GL_LABEL_OBJECT_HANDLE_W;
1887         }
1888
1889         /* North */
1890         create_handle_path (cr, object, w/2, 0);
1891         if (cairo_in_fill (cr, x, y))
1892         {
1893                 return GL_LABEL_OBJECT_HANDLE_N;
1894         }
1895
1896         return GL_LABEL_OBJECT_HANDLE_NONE;
1897 }
1898
1899
1900 /*****************************************************************************/
1901 /* Get handle at given coordinates for line style handles, if any.           */
1902 /*****************************************************************************/
1903 glLabelObjectHandle
1904 gl_label_object_line_handle_at (glLabelObject     *object,
1905                                 cairo_t           *cr,
1906                                 gdouble            x,
1907                                 gdouble            y)
1908 {
1909         gdouble w, h;
1910
1911         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1912
1913         /* P2 */
1914         create_handle_path (cr, object, w, h);
1915         if (cairo_in_fill (cr, x, y))
1916         {
1917                 return GL_LABEL_OBJECT_HANDLE_P2;
1918         }
1919         
1920         /* P1 */
1921         create_handle_path (cr, object, 0, h);
1922         if (cairo_in_fill (cr, x, y))
1923         {
1924                 return GL_LABEL_OBJECT_HANDLE_P1;
1925         }
1926
1927         return GL_LABEL_OBJECT_HANDLE_NONE;
1928 }
1929
1930
1931
1932
1933 /*
1934  * Local Variables:       -- emacs
1935  * mode: C                -- emacs
1936  * c-basic-offset: 8      -- emacs
1937  * tab-width: 8           -- emacs
1938  * indent-tabs-mode: nil  -- emacs
1939  * End:                   -- emacs
1940  */