-/* -*- 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 <evins@snaught.com>.
*
- * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
+ * 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 <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
+
#include "label-image.h"
-#include <glib/gmem.h>
-#include <glib/gstrfuncs.h>
-#include <glib/gmessages.h>
-#include <gdk/gdkcairo.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <librsvg/rsvg.h>
+#include <librsvg/rsvg-cairo.h>
+#include "pixbuf-util.h"
+#include "file-util.h"
#include "pixmaps/checkerboard.xpm"
#include "debug.h"
/* 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. */
/*========================================================*/
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);
+
-\f
/*****************************************************************************/
/* 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. */
/*****************************************************************************/
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");
}
/*---------------------------------------------------------------------------*/
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)
{
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);
}
/* 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. */
/*****************************************************************************/
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
+ */