]> git.sur5r.net Git - glabels/blob - src/label-image.c
Imported Upstream version 3.2.0
[glabels] / src / label-image.c
1 /*
2  *  label-image.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-image.h"
24
25 #include <glib/gi18n.h>
26 #include <glib.h>
27 #include <gdk/gdk.h>
28 #include <librsvg/rsvg.h>
29
30 #include "pixbuf-util.h"
31 #include "file-util.h"
32 #include "pixmaps/checkerboard.xpm"
33
34 #include "debug.h"
35
36
37 #define MIN_IMAGE_SIZE 1.0
38
39
40 /*========================================================*/
41 /* Private types.                                         */
42 /*========================================================*/
43
44 typedef enum {
45         FILE_TYPE_NONE,
46         FILE_TYPE_PIXBUF,
47         FILE_TYPE_SVG
48 } FileType;
49
50
51 struct _glLabelImagePrivate {
52
53         glTextNode       *filename;
54
55         FileType          type;
56
57         GdkPixbuf        *pixbuf;
58         RsvgHandle       *svg_handle;
59 };
60
61
62 /*========================================================*/
63 /* Private globals.                                       */
64 /*========================================================*/
65
66 static GdkPixbuf *default_pixbuf = NULL;
67
68
69 /*========================================================*/
70 /* Private function prototypes.                           */
71 /*========================================================*/
72
73 static void gl_label_image_finalize      (GObject           *object);
74
75 static void copy                         (glLabelObject     *dst_object,
76                                           glLabelObject     *src_object);
77
78 static void set_size                     (glLabelObject     *object,
79                                           gdouble            w,
80                                           gdouble            h,
81                                           gboolean           checkpoint);
82
83 static void draw_object                  (glLabelObject     *object,
84                                           cairo_t           *cr,
85                                           gboolean           screen_flag,
86                                           glMergeRecord     *record);
87
88 static void draw_shadow                  (glLabelObject     *object,
89                                           cairo_t           *cr,
90                                           gboolean           screen_flag,
91                                           glMergeRecord     *record);
92
93 static gboolean object_at                (glLabelObject     *object,
94                                           cairo_t           *cr,
95                                           gdouble            x_pixels,
96                                           gdouble            y_pixels);
97
98
99 /*****************************************************************************/
100 /* Boilerplate object stuff.                                                 */
101 /*****************************************************************************/
102 G_DEFINE_TYPE (glLabelImage, gl_label_image, GL_TYPE_LABEL_OBJECT)
103
104
105 static void
106 gl_label_image_class_init (glLabelImageClass *class)
107 {
108         GObjectClass       *object_class       = G_OBJECT_CLASS (class);
109         glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
110         GdkPixbuf          *pixbuf;
111
112         gl_label_image_parent_class = g_type_class_peek_parent (class);
113
114         label_object_class->copy              = copy;
115         label_object_class->set_size          = set_size;
116         label_object_class->draw_object       = draw_object;
117         label_object_class->draw_shadow       = draw_shadow;
118         label_object_class->object_at         = object_at;
119
120         object_class->finalize = gl_label_image_finalize;
121
122         if ( default_pixbuf == NULL ) {
123                 pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)checkerboard_xpm);
124                 default_pixbuf =
125                         gdk_pixbuf_scale_simple (pixbuf, 128, 128, GDK_INTERP_NEAREST);
126                 g_object_unref (pixbuf);
127         }
128 }
129
130
131 static void
132 gl_label_image_init (glLabelImage *this)
133 {
134         this->priv = g_new0 (glLabelImagePrivate, 1);
135
136         this->priv->filename = g_new0 (glTextNode, 1);
137
138         this->priv->type       = FILE_TYPE_NONE;
139         this->priv->pixbuf     = NULL;
140         this->priv->svg_handle = NULL;
141 }
142
143
144 static void
145 gl_label_image_finalize (GObject *object)
146 {
147         glLabelObject *lobject = GL_LABEL_OBJECT (object);
148         glLabelImage  *this  = GL_LABEL_IMAGE (object);
149         glLabel       *label;
150         GHashTable    *cache;
151
152         g_return_if_fail (object && GL_IS_LABEL_IMAGE (object));
153
154         if (!this->priv->filename->field_flag) {
155                 
156                 label = gl_label_object_get_parent (lobject);
157
158                 switch ( this->priv->type )
159                 {
160
161                 case FILE_TYPE_PIXBUF:
162                         cache = gl_label_get_pixbuf_cache (label);
163                         gl_pixbuf_cache_remove_pixbuf (cache, this->priv->filename->data);
164                         break;
165
166                 case FILE_TYPE_SVG:
167                         cache = gl_label_get_svg_cache (label);
168                         gl_svg_cache_remove_svg (cache, this->priv->filename->data);
169                         break;
170
171                 default:
172                         break;
173
174                 }
175
176         }
177         gl_text_node_free (&this->priv->filename);
178         g_free (this->priv);
179
180         G_OBJECT_CLASS (gl_label_image_parent_class)->finalize (object);
181 }
182
183
184 /*****************************************************************************/
185 /* NEW label "image" object.                                                 */
186 /*****************************************************************************/
187 GObject *
188 gl_label_image_new (glLabel *label,
189                     gboolean checkpoint)
190 {
191         glLabelImage *this;
192
193         this = g_object_new (gl_label_image_get_type(), NULL);
194
195         if (label != NULL)
196         {
197                 if ( checkpoint )
198                 {
199                         gl_label_checkpoint (label, _("Create image object"));
200                 }
201
202                 gl_label_add_object (label, GL_LABEL_OBJECT (this));
203                 gl_label_object_set_parent (GL_LABEL_OBJECT (this), label);
204         }
205
206         return G_OBJECT (this);
207 }
208
209
210 /*****************************************************************************/
211 /* Copy object contents.                                                     */
212 /*****************************************************************************/
213 static void
214 copy (glLabelObject *dst_object,
215       glLabelObject *src_object)
216 {
217         glLabelImage     *src_limage = (glLabelImage *)src_object;
218         glLabelImage     *new_limage = (glLabelImage *)dst_object;
219         glTextNode       *filename;
220         GdkPixbuf        *pixbuf;
221         gchar            *contents;
222         glLabel          *src_label, *dst_label;
223         GHashTable       *cache;
224
225         gl_debug (DEBUG_LABEL, "START");
226
227         g_return_if_fail (src_limage && GL_IS_LABEL_IMAGE (src_limage));
228         g_return_if_fail (new_limage && GL_IS_LABEL_IMAGE (new_limage));
229
230         filename = gl_label_image_get_filename (src_limage);
231
232         /* Make sure destination label has data suitably cached. */
233         if ( !filename->field_flag && (src_limage->priv->type != FILE_TYPE_NONE) )
234         {
235                 src_label = gl_label_object_get_parent (src_object);
236                 dst_label = gl_label_object_get_parent (dst_object);
237
238                 switch ( src_limage->priv->type )
239                 {
240
241                 case FILE_TYPE_PIXBUF:
242                         pixbuf = src_limage->priv->pixbuf;
243                         if ( pixbuf != NULL ) {
244                                 cache = gl_label_get_pixbuf_cache (dst_label);
245                                 gl_pixbuf_cache_add_pixbuf (cache, filename->data, pixbuf);
246                         }
247                         break;
248
249                 case FILE_TYPE_SVG:
250                         cache = gl_label_get_svg_cache (src_label);
251                         contents = gl_svg_cache_get_contents (cache, filename->data);
252                         if ( contents != NULL ) {
253                                 cache = gl_label_get_svg_cache (dst_label);
254                                 gl_svg_cache_add_svg (cache, filename->data, contents);
255                                 g_free (contents);
256                         }
257                         break;
258
259                 default:
260                         break;
261
262                 }
263         }
264
265         gl_label_image_set_filename (new_limage, filename, FALSE);
266         gl_text_node_free (&filename);
267
268         gl_debug (DEBUG_LABEL, "END");
269 }
270
271
272 /*---------------------------------------------------------------------------*/
273 /* PRIVATE.  Set size method.                                                */
274 /*---------------------------------------------------------------------------*/
275 static void
276 set_size (glLabelObject *object,
277           gdouble        w,
278           gdouble        h,
279           gboolean       checkpoint)
280 {
281         g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
282
283         if (w < MIN_IMAGE_SIZE)
284         {
285                 w = MIN_IMAGE_SIZE;
286         }
287
288         if (h < MIN_IMAGE_SIZE)
289         {
290                 h = MIN_IMAGE_SIZE;
291         }
292
293         GL_LABEL_OBJECT_CLASS (gl_label_image_parent_class)->set_size (object, w, h, checkpoint);
294 }
295
296
297 /*****************************************************************************/
298 /* Set object params.                                                        */
299 /*****************************************************************************/
300 void
301 gl_label_image_set_filename (glLabelImage *this,
302                              glTextNode   *filename,
303                              gboolean      checkpoint)
304 {
305         glTextNode        *old_filename;
306         glLabel           *label;
307         GHashTable        *pixbuf_cache;
308         GHashTable        *svg_cache;
309         GdkPixbuf         *pixbuf;
310         RsvgHandle        *svg_handle;
311         RsvgDimensionData  svg_dim;
312         gdouble            image_w, image_h, aspect_ratio, w, h;
313
314         gl_debug (DEBUG_LABEL, "START");
315
316         g_return_if_fail (this && GL_IS_LABEL_IMAGE (this));
317         g_return_if_fail (filename != NULL);
318
319         old_filename = this->priv->filename;
320
321         /* If Unchanged don't do anything */
322         if ( gl_text_node_equal (filename, old_filename ) ) {
323                 return;
324         }
325
326         label = gl_label_object_get_parent (GL_LABEL_OBJECT (this));
327         pixbuf_cache = gl_label_get_pixbuf_cache (label);
328         svg_cache    = gl_label_get_svg_cache (label);
329
330         if ( checkpoint )
331         {
332                 gl_label_checkpoint (label, _("Set image"));
333         }
334
335         /* Set new filename. */
336         this->priv->filename = gl_text_node_dup(filename);
337
338         /* Remove reference to previous item. */
339         switch (this->priv->type)
340         {
341
342         case FILE_TYPE_PIXBUF:
343                 if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
344                         gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data);
345                 }
346                 break;
347
348         case FILE_TYPE_SVG:
349                 if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
350                         gl_svg_cache_remove_svg (svg_cache, old_filename->data);
351                 }
352                 break;
353
354         default:
355                 break;
356
357         }
358
359         gl_text_node_free (&old_filename);
360
361
362         /* Now set the new file type and the pixbuf or svg_handle. */
363         if ( !filename->field_flag && (filename->data != NULL) )
364         {
365
366                 if ( gl_file_util_is_extension (filename->data, ".svg") )
367                 {
368                         svg_handle = gl_svg_cache_get_handle (svg_cache, filename->data);
369
370                         if (svg_handle != NULL)
371                         {
372                                 this->priv->type       = FILE_TYPE_SVG;
373                                 this->priv->pixbuf     = NULL;
374                                 this->priv->svg_handle = svg_handle;
375                         }
376                         else
377                         {
378                                 this->priv->type       = FILE_TYPE_NONE;
379                                 this->priv->pixbuf     = NULL;
380                                 this->priv->svg_handle = NULL;
381                         }
382
383                 }
384                 else
385                 {
386
387                         pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, filename->data);
388
389                         if (pixbuf != NULL)
390                         {
391                                 this->priv->type       = FILE_TYPE_PIXBUF;
392                                 this->priv->pixbuf     = pixbuf;
393                                 this->priv->svg_handle = NULL;
394                         }
395                         else
396                         {
397                                 this->priv->type       = FILE_TYPE_NONE;
398                                 this->priv->pixbuf     = NULL;
399                                 this->priv->svg_handle = NULL;
400                         }
401
402                 }
403         }
404         else
405         {
406                 this->priv->type       = FILE_TYPE_NONE;
407                 this->priv->pixbuf     = NULL;
408                 this->priv->svg_handle = NULL;
409         }
410
411
412         /* Treat current size as a bounding box, scale image to maintain aspect
413          * ratio while fitting it in this bounding box. */
414         switch (this->priv->type)
415         {
416
417         case FILE_TYPE_PIXBUF:
418                 image_w = gdk_pixbuf_get_width (this->priv->pixbuf);
419                 image_h = gdk_pixbuf_get_height (this->priv->pixbuf);
420                 break;
421
422         case FILE_TYPE_SVG:
423                 rsvg_handle_get_dimensions (this->priv->svg_handle, &svg_dim);
424                 image_w = svg_dim.width;
425                 image_h = svg_dim.height;
426                 break;
427
428         default:
429                 image_w = gdk_pixbuf_get_width (default_pixbuf);
430                 image_h = gdk_pixbuf_get_height (default_pixbuf);
431                 break;
432
433         }
434         aspect_ratio = image_h / image_w;
435         gl_label_object_get_size (GL_LABEL_OBJECT(this), &w, &h);
436         if ( h > w*aspect_ratio ) {
437                 h = w * aspect_ratio;
438         } else {
439                 w = h / aspect_ratio;
440         }
441         gl_label_object_set_size (GL_LABEL_OBJECT(this), w, h, FALSE);
442
443         gl_label_object_emit_changed (GL_LABEL_OBJECT(this));
444
445         gl_debug (DEBUG_LABEL, "END");
446 }
447
448
449 void
450 gl_label_image_set_pixbuf (glLabelImage  *this,
451                            GdkPixbuf     *pixbuf,
452                            gboolean       checkpoint)
453 {
454         glTextNode  *old_filename;
455         glLabel     *label;
456         GHashTable  *pixbuf_cache;
457         GHashTable  *svg_cache;
458         gchar       *cs;
459         gchar       *name;
460         gdouble      image_w, image_h;
461
462         gl_debug (DEBUG_LABEL, "START");
463
464         g_return_if_fail (this && GL_IS_LABEL_IMAGE (this));
465         g_return_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf));
466
467         old_filename = this->priv->filename;
468
469         label = gl_label_object_get_parent (GL_LABEL_OBJECT (this));
470
471         if ( checkpoint )
472         {
473                 gl_label_checkpoint (label, _("Set image"));
474         }
475
476         pixbuf_cache = gl_label_get_pixbuf_cache (label);
477         svg_cache = gl_label_get_svg_cache (label);
478
479         /* Remove reference to previous item. */
480         switch (this->priv->type)
481         {
482
483         case FILE_TYPE_PIXBUF:
484                 if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
485                         gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data);
486                 }
487                 break;
488
489         case FILE_TYPE_SVG:
490                 if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
491                         gl_svg_cache_remove_svg (svg_cache, old_filename->data);
492                 }
493                 break;
494
495         default:
496                 break;
497
498         }
499
500         /* Set new filename. */
501         cs = g_compute_checksum_for_data (G_CHECKSUM_MD5,
502                                           gdk_pixbuf_get_pixels (pixbuf),
503                                           gdk_pixbuf_get_rowstride (pixbuf)*gdk_pixbuf_get_height (pixbuf));
504         name = g_strdup_printf ("%s.bitmap", cs);
505         this->priv->filename = gl_text_node_new_from_text(name);
506         gl_text_node_free (&old_filename);
507
508         this->priv->pixbuf = g_object_ref (pixbuf);
509         gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
510
511         g_free (cs);
512         g_free (name);
513
514         this->priv->type       = FILE_TYPE_PIXBUF;
515         this->priv->svg_handle = NULL;
516
517         image_w = gdk_pixbuf_get_width (this->priv->pixbuf);
518         image_h = gdk_pixbuf_get_height (this->priv->pixbuf);
519         gl_label_object_set_size (GL_LABEL_OBJECT(this), image_w, image_h, FALSE);
520
521         gl_label_object_emit_changed (GL_LABEL_OBJECT(this));
522
523         gl_debug (DEBUG_LABEL, "END");
524 }
525
526
527 /*****************************************************************************/
528 /* Get object params.                                                        */
529 /*****************************************************************************/
530 GdkPixbuf *
531 gl_label_image_get_pixbuf (glLabelImage  *this,
532                            glMergeRecord *record)
533 {
534         g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), NULL);
535
536         if ((record != NULL) && this->priv->filename->field_flag)
537         {
538
539                 GdkPixbuf   *pixbuf = NULL;
540                 gchar       *real_filename;
541
542                 /* Indirect filename, re-evaluate for given record. */
543
544                 real_filename = gl_merge_eval_key (record,
545                                                    this->priv->filename->data);
546
547                 if (real_filename != NULL)
548                 {
549                         pixbuf = gdk_pixbuf_new_from_file (real_filename, NULL);
550                 }
551                 return pixbuf;
552         }
553
554         if ( this->priv->type == FILE_TYPE_PIXBUF )
555         {
556                 return g_object_ref (this->priv->pixbuf);
557         }
558         else
559         {
560                 return NULL;
561         }
562 }
563
564
565 RsvgHandle *
566 gl_label_image_get_svg_handle (glLabelImage  *this,
567                                glMergeRecord *record)
568 {
569         g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), NULL);
570
571         if ((record != NULL) && this->priv->filename->field_flag)
572         {
573
574                 RsvgHandle  *svg_handle = NULL;
575                 gchar       *real_filename;
576
577                 /* Indirect filename, re-evaluate for given record. */
578
579                 real_filename = gl_merge_eval_key (record,
580                                                    this->priv->filename->data);
581
582                 if (real_filename != NULL)
583                 {
584                         if ( gl_file_util_is_extension (real_filename, ".svg") )
585                         {
586                                 svg_handle = rsvg_handle_new_from_file (real_filename, NULL);
587                         }
588                 }
589                 return svg_handle;
590         }
591
592         if ( this->priv->type == FILE_TYPE_SVG )
593         {
594                 return g_object_ref (this->priv->svg_handle);
595         }
596         else
597         {
598                 return NULL;
599         }
600 }
601
602
603 static FileType
604 get_type (glLabelImage  *this,
605           glMergeRecord *record)
606 {
607         g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), FALSE);
608
609         if ((record != NULL) && this->priv->filename->field_flag)
610         {
611                 gchar       *real_filename;
612
613                 real_filename = gl_merge_eval_key (record,
614                                                    this->priv->filename->data);
615
616                 if ( gl_file_util_is_extension (real_filename, ".svg") )
617                 {
618                         return FILE_TYPE_SVG;
619                 }
620                 else
621                 {
622                         /* Assume a pixbuf compat file.  If not, queries for
623                            pixbufs should return NULL and do the right thing. */
624                         return FILE_TYPE_PIXBUF;
625                 }
626         }
627         else
628         {
629                 return (this->priv->type);
630         }
631 }
632
633
634 glTextNode *
635 gl_label_image_get_filename (glLabelImage *this)
636 {
637         g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), NULL);
638
639         return gl_text_node_dup (this->priv->filename);
640 }
641
642
643 void
644 gl_label_image_get_base_size (glLabelImage *this,
645                               gdouble      *w,
646                               gdouble      *h)
647 {
648         RsvgDimensionData  svg_dim;
649
650         g_return_if_fail (this && GL_IS_LABEL_IMAGE (this));
651         g_return_if_fail (w != NULL);
652         g_return_if_fail (h != NULL);
653
654         switch (this->priv->type)
655         {
656
657         case FILE_TYPE_PIXBUF:
658                 *w = gdk_pixbuf_get_width (this->priv->pixbuf);
659                 *h = gdk_pixbuf_get_height (this->priv->pixbuf);
660                 break;
661
662         case FILE_TYPE_SVG:
663                 rsvg_handle_get_dimensions (this->priv->svg_handle, &svg_dim);
664                 *w = svg_dim.width;
665                 *h = svg_dim.height;
666                 break;
667
668         default:
669                 *w = gdk_pixbuf_get_width (default_pixbuf);
670                 *h = gdk_pixbuf_get_height (default_pixbuf);
671                 break;
672
673         }
674 }
675
676
677 /*****************************************************************************/
678 /* Draw object method.                                                       */
679 /*****************************************************************************/
680 static void
681 draw_object (glLabelObject *object,
682              cairo_t       *cr,
683              gboolean       screen_flag,
684              glMergeRecord *record)
685 {
686         glLabelImage      *this = GL_LABEL_IMAGE (object);
687         gdouble            w, h;
688         gdouble            image_w, image_h;
689         GdkPixbuf         *pixbuf;
690         RsvgHandle        *svg_handle;
691         RsvgDimensionData  svg_dim;
692
693         gl_debug (DEBUG_LABEL, "START");
694
695         gl_label_object_get_size (object, &w, &h);
696
697         cairo_save (cr);
698
699         switch (get_type (this, record))
700         {
701
702         case FILE_TYPE_PIXBUF:
703                 pixbuf = gl_label_image_get_pixbuf (this, record);
704                 if ( pixbuf )
705                 {
706                         image_w = gdk_pixbuf_get_width (pixbuf);
707                         image_h = gdk_pixbuf_get_height (pixbuf);
708                         cairo_rectangle (cr, 0.0, 0.0, w, h);
709                         cairo_scale (cr, w/image_w, h/image_h);
710                         gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
711                         cairo_fill (cr);
712                         g_object_unref (pixbuf);
713                 }
714                 break;
715
716         case FILE_TYPE_SVG:
717                 svg_handle = gl_label_image_get_svg_handle (this, record);
718                 if ( svg_handle )
719                 {
720                         rsvg_handle_get_dimensions (svg_handle, &svg_dim);
721                         cairo_scale (cr, w/svg_dim.width, h/svg_dim.height);
722                         rsvg_handle_render_cairo (svg_handle, cr);
723                 }
724                 break;
725
726         default:
727                 cairo_rectangle (cr, 0.0, 0.0, w, h);
728                 image_w = gdk_pixbuf_get_width (default_pixbuf);
729                 image_h = gdk_pixbuf_get_height (default_pixbuf);
730                 cairo_scale (cr, w/image_w, h/image_h);
731                 gdk_cairo_set_source_pixbuf (cr, default_pixbuf, 0, 0);
732                 cairo_fill (cr);
733                 break;
734
735         }
736
737         cairo_restore (cr);
738
739         gl_debug (DEBUG_LABEL, "END");
740 }
741
742
743 /*****************************************************************************/
744 /* Draw shadow method.                                                       */
745 /*****************************************************************************/
746 static void
747 draw_shadow (glLabelObject *object,
748              cairo_t       *cr,
749              gboolean       screen_flag,
750              glMergeRecord *record)
751 {
752         glLabelImage    *this = GL_LABEL_IMAGE (object);
753         gdouble          w, h;
754         GdkPixbuf       *pixbuf;
755         GdkPixbuf       *shadow_pixbuf;
756         gdouble          image_w, image_h;
757         glColorNode     *shadow_color_node;
758         guint            shadow_color;
759         gdouble          shadow_opacity;
760
761         gl_debug (DEBUG_LABEL, "START");
762
763         gl_label_object_get_size (object, &w, &h);
764
765         shadow_color_node = gl_label_object_get_shadow_color (object);
766         shadow_color = gl_color_node_expand (shadow_color_node, record);
767         if (shadow_color_node->field_flag && screen_flag)
768         {
769                 shadow_color = GL_COLOR_SHADOW_MERGE_DEFAULT;
770         }
771         shadow_opacity = gl_label_object_get_shadow_opacity (object);
772
773         cairo_save (cr);
774
775         switch (get_type (this, record))
776         {
777
778         case FILE_TYPE_PIXBUF:
779                 pixbuf = gl_label_image_get_pixbuf (this, record);
780                 if ( pixbuf )
781                 {
782                         image_w = gdk_pixbuf_get_width (pixbuf);
783                         image_h = gdk_pixbuf_get_height (pixbuf);
784
785                         shadow_pixbuf = gl_pixbuf_util_create_shadow_pixbuf (pixbuf,
786                                                                              shadow_color, shadow_opacity);
787                         cairo_rectangle (cr, 0.0, 0.0, w, h);
788                         cairo_scale (cr, w/image_w, h/image_h);
789                         gdk_cairo_set_source_pixbuf (cr, (GdkPixbuf *)shadow_pixbuf, 0, 0);
790                         cairo_fill (cr);
791
792                         g_object_unref (G_OBJECT (shadow_pixbuf));
793                         g_object_unref (G_OBJECT (pixbuf));
794                 }
795                 break;
796
797         case FILE_TYPE_SVG:
798                 /* FIXME: no shadow support, yet. */
799                 break;
800
801         default:
802                 shadow_color = gl_color_set_opacity (shadow_color, shadow_opacity);
803
804                 cairo_rectangle (cr, 0.0, 0.0, w, h);
805                 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (shadow_color));
806                 cairo_fill (cr);
807                 break;
808         }
809
810         cairo_restore (cr);
811
812         gl_debug (DEBUG_LABEL, "END");
813 }
814
815
816 /*****************************************************************************/
817 /* Is object at coordinates?                                                 */
818 /*****************************************************************************/
819 static gboolean
820 object_at (glLabelObject *object,
821            cairo_t       *cr,
822            gdouble        x,
823            gdouble        y)
824 {
825         gdouble           w, h;
826
827         gl_label_object_get_size (object, &w, &h);
828
829         cairo_new_path (cr);
830         cairo_rectangle (cr, 0.0, 0.0, w, h);
831
832         if (cairo_in_fill (cr, x, y))
833         {
834                 return TRUE;
835         }
836
837         return FALSE;
838 }
839
840
841
842
843 /*
844  * Local Variables:       -- emacs
845  * mode: C                -- emacs
846  * c-basic-offset: 8      -- emacs
847  * tab-width: 8           -- emacs
848  * indent-tabs-mode: nil  -- emacs
849  * End:                   -- emacs
850  */