X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Flabel-image.c;h=f5e458559ea87149080b91e1e2e91dd8fb37679b;hb=cbc5b369069a355c3fa9715c059271d45dbb33e0;hp=9d0bcaf2ffd6bc8ed197f8199073dc5a3ea97639;hpb=b13649a65b7dfa46ba1ed7fe9e8afa4aaef70f79;p=glabels diff --git a/src/label-image.c b/src/label-image.c index 9d0bcaf2..f5e45855 100644 --- a/src/label-image.c +++ b/src/label-image.c @@ -1,34 +1,35 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ - /* - * (GLABELS) Label and Business Card Creation program for GNOME - * - * label_image.c: GLabels label image object + * label-image.c + * Copyright (C) 2001-2009 Jim Evins . * - * Copyright (C) 2001-2007 Jim Evins . + * This file is part of gLabels. * - * This program is free software; you can redistribute it and/or modify + * gLabels is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * gLabels is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with gLabels. If not, see . */ +#include + #include "label-image.h" -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include "pixbuf-util.h" +#include "file-util.h" #include "pixmaps/checkerboard.xpm" #include "debug.h" @@ -41,17 +42,31 @@ /* Private types. */ /*========================================================*/ +typedef enum { + FILE_TYPE_NONE, + FILE_TYPE_PIXBUF, + FILE_TYPE_SVG +} FileType; + + struct _glLabelImagePrivate { - glTextNode *filename; - GdkPixbuf *pixbuf; + + glTextNode *filename; + + FileType type; + + GdkPixbuf *pixbuf; + RsvgHandle *svg_handle; }; + /*========================================================*/ /* Private globals. */ /*========================================================*/ static GdkPixbuf *default_pixbuf = NULL; + /*========================================================*/ /* Private function prototypes. */ /*========================================================*/ @@ -59,94 +74,140 @@ static GdkPixbuf *default_pixbuf = NULL; static void gl_label_image_finalize (GObject *object); static void copy (glLabelObject *dst_object, - glLabelObject *src_object); + glLabelObject *src_object); + +static void set_size (glLabelObject *object, + gdouble w, + gdouble h, + gboolean checkpoint); -static void set_size (glLabelObject *object, - gdouble w, - gdouble h); +static void draw_object (glLabelObject *object, + cairo_t *cr, + gboolean screen_flag, + glMergeRecord *record); -static void draw_object (glLabelObject *object, +static void draw_shadow (glLabelObject *object, cairo_t *cr, gboolean screen_flag, glMergeRecord *record); +static gboolean object_at (glLabelObject *object, + cairo_t *cr, + gdouble x_pixels, + gdouble y_pixels); + - /*****************************************************************************/ /* Boilerplate object stuff. */ /*****************************************************************************/ -G_DEFINE_TYPE (glLabelImage, gl_label_image, GL_TYPE_LABEL_OBJECT); +G_DEFINE_TYPE (glLabelImage, gl_label_image, GL_TYPE_LABEL_OBJECT) + static void gl_label_image_class_init (glLabelImageClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (class); - glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class); - - gl_label_image_parent_class = g_type_class_peek_parent (class); + GObjectClass *object_class = G_OBJECT_CLASS (class); + glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class); + GdkPixbuf *pixbuf; - label_object_class->copy = copy; - label_object_class->set_size = set_size; - label_object_class->draw_object = draw_object; - label_object_class->draw_shadow = NULL; + gl_label_image_parent_class = g_type_class_peek_parent (class); - object_class->finalize = gl_label_image_finalize; -} + label_object_class->copy = copy; + label_object_class->set_size = set_size; + label_object_class->draw_object = draw_object; + label_object_class->draw_shadow = draw_shadow; + label_object_class->object_at = object_at; -static void -gl_label_image_init (glLabelImage *limage) -{ - GdkPixbuf *pixbuf; + object_class->finalize = gl_label_image_finalize; - if ( default_pixbuf == NULL ) { - pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)checkerboard_xpm); + if ( default_pixbuf == NULL ) { + pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)checkerboard_xpm); default_pixbuf = gdk_pixbuf_scale_simple (pixbuf, 128, 128, GDK_INTERP_NEAREST); g_object_unref (pixbuf); - } + } +} - limage->priv = g_new0 (glLabelImagePrivate, 1); - limage->priv->filename = g_new0 (glTextNode, 1); +static void +gl_label_image_init (glLabelImage *this) +{ + this->priv = g_new0 (glLabelImagePrivate, 1); + + this->priv->filename = g_new0 (glTextNode, 1); - limage->priv->pixbuf = default_pixbuf; + this->priv->type = FILE_TYPE_NONE; + this->priv->pixbuf = NULL; + this->priv->svg_handle = NULL; } + static void gl_label_image_finalize (GObject *object) { - glLabelObject *lobject = GL_LABEL_OBJECT (object); - glLabelImage *limage = GL_LABEL_IMAGE (object);; - GHashTable *pixbuf_cache; + glLabelObject *lobject = GL_LABEL_OBJECT (object); + glLabelImage *this = GL_LABEL_IMAGE (object); + glLabel *label; + GHashTable *cache; - g_return_if_fail (object && GL_IS_LABEL_IMAGE (object)); + g_return_if_fail (object && GL_IS_LABEL_IMAGE (object)); - if (!limage->priv->filename->field_flag) { - pixbuf_cache = gl_label_get_pixbuf_cache (lobject->parent); - gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, - limage->priv->filename->data); - } - gl_text_node_free (&limage->priv->filename); - g_free (limage->priv); + if (!this->priv->filename->field_flag) { + + label = gl_label_object_get_parent (lobject); + + switch ( this->priv->type ) + { + + case FILE_TYPE_PIXBUF: + cache = gl_label_get_pixbuf_cache (label); + gl_pixbuf_cache_remove_pixbuf (cache, this->priv->filename->data); + break; + + case FILE_TYPE_SVG: + cache = gl_label_get_svg_cache (label); + gl_svg_cache_remove_svg (cache, this->priv->filename->data); + break; + + default: + break; + + } + + } + gl_text_node_free (&this->priv->filename); + g_free (this->priv); - G_OBJECT_CLASS (gl_label_image_parent_class)->finalize (object); + G_OBJECT_CLASS (gl_label_image_parent_class)->finalize (object); } + /*****************************************************************************/ /* NEW label "image" object. */ /*****************************************************************************/ GObject * -gl_label_image_new (glLabel *label) +gl_label_image_new (glLabel *label, + gboolean checkpoint) { - glLabelImage *limage; + glLabelImage *this; + + this = g_object_new (gl_label_image_get_type(), NULL); - limage = g_object_new (gl_label_image_get_type(), NULL); + if (label != NULL) + { + if ( checkpoint ) + { + gl_label_checkpoint (label, _("Create image object")); + } - gl_label_object_set_parent (GL_LABEL_OBJECT(limage), label); + gl_label_add_object (label, GL_LABEL_OBJECT (this)); + gl_label_object_set_parent (GL_LABEL_OBJECT (this), label); + } - return G_OBJECT (limage); + return G_OBJECT (this); } + /*****************************************************************************/ /* Copy object contents. */ /*****************************************************************************/ @@ -154,32 +215,58 @@ static void copy (glLabelObject *dst_object, glLabelObject *src_object) { - glLabelImage *limage = (glLabelImage *)src_object; - glLabelImage *new_limage = (glLabelImage *)dst_object; - glTextNode *filename; - GdkPixbuf *pixbuf; - GHashTable *pixbuf_cache; + glLabelImage *src_limage = (glLabelImage *)src_object; + glLabelImage *new_limage = (glLabelImage *)dst_object; + glTextNode *filename; + GdkPixbuf *pixbuf; + gchar *contents; + glLabel *src_label, *dst_label; + GHashTable *cache; - gl_debug (DEBUG_LABEL, "START"); + gl_debug (DEBUG_LABEL, "START"); - g_return_if_fail (limage && GL_IS_LABEL_IMAGE (limage)); - g_return_if_fail (new_limage && GL_IS_LABEL_IMAGE (new_limage)); + g_return_if_fail (src_limage && GL_IS_LABEL_IMAGE (src_limage)); + g_return_if_fail (new_limage && GL_IS_LABEL_IMAGE (new_limage)); - filename = gl_label_image_get_filename (limage); + filename = gl_label_image_get_filename (src_limage); - /* Make sure destination label has data suitably cached. */ - if ( !filename->field_flag && (filename->data != NULL) ) { - pixbuf = limage->priv->pixbuf; - if ( pixbuf != default_pixbuf ) { - pixbuf_cache = gl_label_get_pixbuf_cache (dst_object->parent); - gl_pixbuf_cache_add_pixbuf (pixbuf_cache, filename->data, pixbuf); - } - } + /* Make sure destination label has data suitably cached. */ + if ( !filename->field_flag && (src_limage->priv->type != FILE_TYPE_NONE) ) + { + src_label = gl_label_object_get_parent (src_object); + dst_label = gl_label_object_get_parent (dst_object); + + switch ( src_limage->priv->type ) + { + + case FILE_TYPE_PIXBUF: + pixbuf = src_limage->priv->pixbuf; + if ( pixbuf != NULL ) { + cache = gl_label_get_pixbuf_cache (dst_label); + gl_pixbuf_cache_add_pixbuf (cache, filename->data, pixbuf); + } + break; + + case FILE_TYPE_SVG: + cache = gl_label_get_svg_cache (src_label); + contents = gl_svg_cache_get_contents (cache, filename->data); + if ( contents != NULL ) { + cache = gl_label_get_svg_cache (dst_label); + gl_svg_cache_add_svg (cache, filename->data, contents); + g_free (contents); + } + break; + + default: + break; + + } + } - gl_label_image_set_filename (new_limage, filename); - gl_text_node_free (&filename); + gl_label_image_set_filename (new_limage, filename, FALSE); + gl_text_node_free (&filename); - gl_debug (DEBUG_LABEL, "END"); + gl_debug (DEBUG_LABEL, "END"); } @@ -188,10 +275,11 @@ copy (glLabelObject *dst_object, /*---------------------------------------------------------------------------*/ static void set_size (glLabelObject *object, - gdouble w, - gdouble h) + gdouble w, + gdouble h, + gboolean checkpoint) { - g_return_if_fail (object && GL_IS_LABEL_OBJECT (object)); + g_return_if_fail (object && GL_IS_LABEL_OBJECT (object)); if (w < MIN_IMAGE_SIZE) { @@ -203,7 +291,7 @@ set_size (glLabelObject *object, h = MIN_IMAGE_SIZE; } - GL_LABEL_OBJECT_CLASS (gl_label_image_parent_class)->set_size (object, w, h); + GL_LABEL_OBJECT_CLASS (gl_label_image_parent_class)->set_size (object, w, h, checkpoint); } @@ -211,114 +299,382 @@ set_size (glLabelObject *object, /* Set object params. */ /*****************************************************************************/ void -gl_label_image_set_filename (glLabelImage *limage, - glTextNode *filename) +gl_label_image_set_filename (glLabelImage *this, + glTextNode *filename, + gboolean checkpoint) { - glTextNode *old_filename; - GHashTable *pixbuf_cache; - GdkPixbuf *pixbuf; - gdouble image_w, image_h, aspect_ratio, w, h; + glTextNode *old_filename; + glLabel *label; + GHashTable *pixbuf_cache; + GHashTable *svg_cache; + GdkPixbuf *pixbuf; + RsvgHandle *svg_handle; + RsvgDimensionData svg_dim; + gdouble image_w, image_h, aspect_ratio, w, h; - gl_debug (DEBUG_LABEL, "START"); + gl_debug (DEBUG_LABEL, "START"); - g_return_if_fail (limage && GL_IS_LABEL_IMAGE (limage)); - g_return_if_fail (filename != NULL); + g_return_if_fail (this && GL_IS_LABEL_IMAGE (this)); + g_return_if_fail (filename != NULL); - old_filename = limage->priv->filename; + old_filename = this->priv->filename; - /* If Unchanged don't do anything */ - if ( gl_text_node_equal (filename, old_filename ) ) { - return; - } + /* If Unchanged don't do anything */ + if ( gl_text_node_equal (filename, old_filename ) ) { + return; + } - pixbuf_cache = gl_label_get_pixbuf_cache (GL_LABEL_OBJECT(limage)->parent); + label = gl_label_object_get_parent (GL_LABEL_OBJECT (this)); + pixbuf_cache = gl_label_get_pixbuf_cache (label); + svg_cache = gl_label_get_svg_cache (label); - /* Remove reference to previous pixbuf from cache, if needed. */ - if ( !old_filename->field_flag && (old_filename->data != NULL) ) { - gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data); - } + if ( checkpoint ) + { + gl_label_checkpoint (label, _("Set image")); + } - /* Set new filename. */ - limage->priv->filename = gl_text_node_dup(filename); - gl_text_node_free (&old_filename); + /* Set new filename. */ + this->priv->filename = gl_text_node_dup(filename); - /* Now set the pixbuf. */ - if ( filename->field_flag || (filename->data == NULL) ) { + /* Remove reference to previous item. */ + switch (this->priv->type) + { - limage->priv->pixbuf = default_pixbuf; + case FILE_TYPE_PIXBUF: + if ( !old_filename->field_flag && (old_filename->data != NULL) ) { + gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data); + } + break; - } else { + case FILE_TYPE_SVG: + if ( !old_filename->field_flag && (old_filename->data != NULL) ) { + gl_svg_cache_remove_svg (svg_cache, old_filename->data); + } + break; - pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, filename->data); + default: + break; - if (pixbuf != NULL) { - limage->priv->pixbuf = pixbuf; - } else { - limage->priv->pixbuf = default_pixbuf; - } - } + } - /* Treat current size as a bounding box, scale image to maintain aspect - * ratio while fitting it in this bounding box. */ - image_w = gdk_pixbuf_get_width (limage->priv->pixbuf); - image_h = gdk_pixbuf_get_height (limage->priv->pixbuf); - aspect_ratio = image_h / image_w; - gl_label_object_get_size (GL_LABEL_OBJECT(limage), &w, &h); - if ( h > w*aspect_ratio ) { - h = w * aspect_ratio; - } else { - w = h / aspect_ratio; - } - gl_label_object_set_size (GL_LABEL_OBJECT(limage), w, h); + gl_text_node_free (&old_filename); + + + /* Now set the new file type and the pixbuf or svg_handle. */ + if ( !filename->field_flag && (filename->data != NULL) ) + { + + if ( gl_file_util_is_extension (filename->data, ".svg") ) + { + svg_handle = gl_svg_cache_get_handle (svg_cache, filename->data); + + if (svg_handle != NULL) + { + this->priv->type = FILE_TYPE_SVG; + this->priv->pixbuf = NULL; + this->priv->svg_handle = svg_handle; + } + else + { + this->priv->type = FILE_TYPE_NONE; + this->priv->pixbuf = NULL; + this->priv->svg_handle = NULL; + } + + } + else + { + + pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, filename->data); + + if (pixbuf != NULL) + { + this->priv->type = FILE_TYPE_PIXBUF; + this->priv->pixbuf = pixbuf; + this->priv->svg_handle = NULL; + } + else + { + this->priv->type = FILE_TYPE_NONE; + this->priv->pixbuf = NULL; + this->priv->svg_handle = NULL; + } + + } + } + else + { + this->priv->type = FILE_TYPE_NONE; + this->priv->pixbuf = NULL; + this->priv->svg_handle = NULL; + } + + + /* Treat current size as a bounding box, scale image to maintain aspect + * ratio while fitting it in this bounding box. */ + switch (this->priv->type) + { + + case FILE_TYPE_PIXBUF: + image_w = gdk_pixbuf_get_width (this->priv->pixbuf); + image_h = gdk_pixbuf_get_height (this->priv->pixbuf); + break; + + case FILE_TYPE_SVG: + rsvg_handle_get_dimensions (this->priv->svg_handle, &svg_dim); + image_w = svg_dim.width; + image_h = svg_dim.height; + break; + + default: + image_w = gdk_pixbuf_get_width (default_pixbuf); + image_h = gdk_pixbuf_get_height (default_pixbuf); + break; + + } + aspect_ratio = image_h / image_w; + gl_label_object_get_size (GL_LABEL_OBJECT(this), &w, &h); + if ( h > w*aspect_ratio ) { + h = w * aspect_ratio; + } else { + w = h / aspect_ratio; + } + gl_label_object_set_size (GL_LABEL_OBJECT(this), w, h, FALSE); + + gl_label_object_emit_changed (GL_LABEL_OBJECT(this)); + + gl_debug (DEBUG_LABEL, "END"); +} + + +void +gl_label_image_set_pixbuf (glLabelImage *this, + GdkPixbuf *pixbuf, + gboolean checkpoint) +{ + glTextNode *old_filename; + glLabel *label; + GHashTable *pixbuf_cache; + GHashTable *svg_cache; + gchar *cs; + gchar *name; + gdouble image_w, image_h; + + gl_debug (DEBUG_LABEL, "START"); + + g_return_if_fail (this && GL_IS_LABEL_IMAGE (this)); + g_return_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf)); + + old_filename = this->priv->filename; + + label = gl_label_object_get_parent (GL_LABEL_OBJECT (this)); + + if ( checkpoint ) + { + gl_label_checkpoint (label, _("Set image")); + } + + pixbuf_cache = gl_label_get_pixbuf_cache (label); + svg_cache = gl_label_get_svg_cache (label); + + /* Remove reference to previous item. */ + switch (this->priv->type) + { + + case FILE_TYPE_PIXBUF: + if ( !old_filename->field_flag && (old_filename->data != NULL) ) { + gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data); + } + break; + + case FILE_TYPE_SVG: + if ( !old_filename->field_flag && (old_filename->data != NULL) ) { + gl_svg_cache_remove_svg (svg_cache, old_filename->data); + } + break; + + default: + break; + + } + + /* Set new filename. */ + cs = g_compute_checksum_for_data (G_CHECKSUM_MD5, + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf)*gdk_pixbuf_get_height (pixbuf)); + name = g_strdup_printf ("%s.bitmap", cs); + this->priv->filename = gl_text_node_new_from_text(name); + gl_text_node_free (&old_filename); - gl_label_object_emit_changed (GL_LABEL_OBJECT(limage)); + this->priv->pixbuf = g_object_ref (pixbuf); + gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf); - gl_debug (DEBUG_LABEL, "END"); + g_free (cs); + g_free (name); + + this->priv->type = FILE_TYPE_PIXBUF; + this->priv->svg_handle = NULL; + + image_w = gdk_pixbuf_get_width (this->priv->pixbuf); + image_h = gdk_pixbuf_get_height (this->priv->pixbuf); + gl_label_object_set_size (GL_LABEL_OBJECT(this), image_w, image_h, FALSE); + + gl_label_object_emit_changed (GL_LABEL_OBJECT(this)); + + gl_debug (DEBUG_LABEL, "END"); } /*****************************************************************************/ /* Get object params. */ /*****************************************************************************/ -glTextNode * -gl_label_image_get_filename (glLabelImage *limage) +GdkPixbuf * +gl_label_image_get_pixbuf (glLabelImage *this, + glMergeRecord *record) { - g_return_val_if_fail (limage && GL_IS_LABEL_IMAGE (limage), NULL); + g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), NULL); + + if ((record != NULL) && this->priv->filename->field_flag) + { + + GdkPixbuf *pixbuf = NULL; + gchar *real_filename; + + /* Indirect filename, re-evaluate for given record. */ + + real_filename = gl_merge_eval_key (record, + this->priv->filename->data); + + if (real_filename != NULL) + { + pixbuf = gdk_pixbuf_new_from_file (real_filename, NULL); + } + return pixbuf; + } - return gl_text_node_dup (limage->priv->filename); + if ( this->priv->type == FILE_TYPE_PIXBUF ) + { + return g_object_ref (this->priv->pixbuf); + } + else + { + return NULL; + } } -const GdkPixbuf * -gl_label_image_get_pixbuf (glLabelImage *limage, - glMergeRecord *record) + +RsvgHandle * +gl_label_image_get_svg_handle (glLabelImage *this, + glMergeRecord *record) { - g_return_val_if_fail (limage && GL_IS_LABEL_IMAGE (limage), NULL); + g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), NULL); - if ((record != NULL) && limage->priv->filename->field_flag) { + if ((record != NULL) && this->priv->filename->field_flag) + { - GdkPixbuf *pixbuf = NULL; + RsvgHandle *svg_handle = NULL; gchar *real_filename; /* Indirect filename, re-evaluate for given record. */ real_filename = gl_merge_eval_key (record, - limage->priv->filename->data); - - if (real_filename != NULL) { - pixbuf = gdk_pixbuf_new_from_file (real_filename, NULL); - } - if ( pixbuf != NULL ) { - return pixbuf; - } else { - return default_pixbuf; + this->priv->filename->data); + + if (real_filename != NULL) + { + if ( gl_file_util_is_extension (real_filename, ".svg") ) + { + svg_handle = rsvg_handle_new_from_file (real_filename, NULL); + } } - + return svg_handle; } - return limage->priv->pixbuf; + if ( this->priv->type == FILE_TYPE_SVG ) + { + return g_object_ref (this->priv->svg_handle); + } + else + { + return NULL; + } +} + + +static FileType +get_type (glLabelImage *this, + glMergeRecord *record) +{ + g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), FALSE); + + if ((record != NULL) && this->priv->filename->field_flag) + { + gchar *real_filename; + + real_filename = gl_merge_eval_key (record, + this->priv->filename->data); + + if ( gl_file_util_is_extension (real_filename, ".svg") ) + { + return FILE_TYPE_SVG; + } + else + { + /* Assume a pixbuf compat file. If not, queries for + pixbufs should return NULL and do the right thing. */ + return FILE_TYPE_PIXBUF; + } + } + else + { + return (this->priv->type); + } +} + + +glTextNode * +gl_label_image_get_filename (glLabelImage *this) +{ + g_return_val_if_fail (this && GL_IS_LABEL_IMAGE (this), NULL); + + return gl_text_node_dup (this->priv->filename); +} + + +void +gl_label_image_get_base_size (glLabelImage *this, + gdouble *w, + gdouble *h) +{ + RsvgDimensionData svg_dim; + + g_return_if_fail (this && GL_IS_LABEL_IMAGE (this)); + g_return_if_fail (w != NULL); + g_return_if_fail (h != NULL); + + switch (this->priv->type) + { + + case FILE_TYPE_PIXBUF: + *w = gdk_pixbuf_get_width (this->priv->pixbuf); + *h = gdk_pixbuf_get_height (this->priv->pixbuf); + break; + + case FILE_TYPE_SVG: + rsvg_handle_get_dimensions (this->priv->svg_handle, &svg_dim); + *w = svg_dim.width; + *h = svg_dim.height; + break; + default: + *w = gdk_pixbuf_get_width (default_pixbuf); + *h = gdk_pixbuf_get_height (default_pixbuf); + break; + + } } + /*****************************************************************************/ /* Draw object method. */ /*****************************************************************************/ @@ -328,32 +684,168 @@ draw_object (glLabelObject *object, gboolean screen_flag, glMergeRecord *record) { - gdouble x0, y0; - gdouble w, h; - const GdkPixbuf *pixbuf; - gint image_w, image_h; + glLabelImage *this = GL_LABEL_IMAGE (object); + gdouble w, h; + gdouble image_w, image_h; + GdkPixbuf *pixbuf; + RsvgHandle *svg_handle; + RsvgDimensionData svg_dim; - gl_debug (DEBUG_LABEL, "START"); + gl_debug (DEBUG_LABEL, "START"); - gl_label_object_get_size (object, &w, &h); - gl_label_object_get_position (object, &x0, &y0); + gl_label_object_get_size (object, &w, &h); - pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE (object), record); - image_w = gdk_pixbuf_get_width (pixbuf); - image_h = gdk_pixbuf_get_height (pixbuf); + cairo_save (cr); - cairo_save (cr); + switch (get_type (this, record)) + { - cairo_rectangle (cr, 0.0, 0.0, w, h); + case FILE_TYPE_PIXBUF: + pixbuf = gl_label_image_get_pixbuf (this, record); + if ( pixbuf ) + { + image_w = gdk_pixbuf_get_width (pixbuf); + image_h = gdk_pixbuf_get_height (pixbuf); + cairo_rectangle (cr, 0.0, 0.0, w, h); + cairo_scale (cr, w/image_w, h/image_h); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_fill (cr); + g_object_unref (pixbuf); + } + break; + + case FILE_TYPE_SVG: + svg_handle = gl_label_image_get_svg_handle (this, record); + if ( svg_handle ) + { + rsvg_handle_get_dimensions (svg_handle, &svg_dim); + cairo_scale (cr, w/svg_dim.width, h/svg_dim.height); + rsvg_handle_render_cairo (svg_handle, cr); + } + break; + + default: + cairo_rectangle (cr, 0.0, 0.0, w, h); + image_w = gdk_pixbuf_get_width (default_pixbuf); + image_h = gdk_pixbuf_get_height (default_pixbuf); + cairo_scale (cr, w/image_w, h/image_h); + gdk_cairo_set_source_pixbuf (cr, default_pixbuf, 0, 0); + cairo_fill (cr); + break; - cairo_scale (cr, w/image_w, h/image_h); - gdk_cairo_set_source_pixbuf (cr, (GdkPixbuf *)pixbuf, 0, 0); - cairo_fill (cr); + } - cairo_restore (cr); + cairo_restore (cr); - gl_debug (DEBUG_LABEL, "END"); + gl_debug (DEBUG_LABEL, "END"); } +/*****************************************************************************/ +/* Draw shadow method. */ +/*****************************************************************************/ +static void +draw_shadow (glLabelObject *object, + cairo_t *cr, + gboolean screen_flag, + glMergeRecord *record) +{ + glLabelImage *this = GL_LABEL_IMAGE (object); + gdouble w, h; + GdkPixbuf *pixbuf; + GdkPixbuf *shadow_pixbuf; + gdouble image_w, image_h; + glColorNode *shadow_color_node; + guint shadow_color; + gdouble shadow_opacity; + + gl_debug (DEBUG_LABEL, "START"); + + gl_label_object_get_size (object, &w, &h); + + shadow_color_node = gl_label_object_get_shadow_color (object); + shadow_color = gl_color_node_expand (shadow_color_node, record); + if (shadow_color_node->field_flag && screen_flag) + { + shadow_color = GL_COLOR_SHADOW_MERGE_DEFAULT; + } + shadow_opacity = gl_label_object_get_shadow_opacity (object); + + cairo_save (cr); + + switch (get_type (this, record)) + { + case FILE_TYPE_PIXBUF: + pixbuf = gl_label_image_get_pixbuf (this, record); + if ( pixbuf ) + { + image_w = gdk_pixbuf_get_width (pixbuf); + image_h = gdk_pixbuf_get_height (pixbuf); + + shadow_pixbuf = gl_pixbuf_util_create_shadow_pixbuf (pixbuf, + shadow_color, shadow_opacity); + cairo_rectangle (cr, 0.0, 0.0, w, h); + cairo_scale (cr, w/image_w, h/image_h); + gdk_cairo_set_source_pixbuf (cr, (GdkPixbuf *)shadow_pixbuf, 0, 0); + cairo_fill (cr); + + g_object_unref (G_OBJECT (shadow_pixbuf)); + g_object_unref (G_OBJECT (pixbuf)); + } + break; + + case FILE_TYPE_SVG: + /* FIXME: no shadow support, yet. */ + break; + + default: + shadow_color = gl_color_set_opacity (shadow_color, shadow_opacity); + + cairo_rectangle (cr, 0.0, 0.0, w, h); + cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (shadow_color)); + cairo_fill (cr); + break; + } + + cairo_restore (cr); + + gl_debug (DEBUG_LABEL, "END"); +} + + +/*****************************************************************************/ +/* Is object at coordinates? */ +/*****************************************************************************/ +static gboolean +object_at (glLabelObject *object, + cairo_t *cr, + gdouble x, + gdouble y) +{ + gdouble w, h; + + gl_label_object_get_size (object, &w, &h); + + cairo_new_path (cr); + cairo_rectangle (cr, 0.0, 0.0, w, h); + + if (cairo_in_fill (cr, x, y)) + { + return TRUE; + } + + return FALSE; +} + + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */