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