GTK_REQUIRED=2.20.0
GCONF_REQUIRED=2.28.0
LIBXML_REQUIRED=2.7.0
+LIBRSVG_REQUIRED=2.26.0
dnl Optional dependencies
LIBEBOOK_REQUIRED=2.28.0
gtk+-2.0 >= $GTK_REQUIRED \
gconf-2.0 >= $GCONF_REQUIRED \
libxml-2.0 >= $LIBXML_REQUIRED \
+ librsvg-2.0 > $LIBRSVG_REQUIRED \
])
AC_SUBST(GLABELS_CFLAGS)
src/stock.h
src/str-util.c
src/str-util.h
+src/svg-cache.c
+src/svg-cache.h
src/template-designer.c
src/template-designer.h
src/template-history.c
xml-label-04.h \
pixbuf-cache.c \
pixbuf-cache.h \
+ svg-cache.c \
+ svg-cache.h \
merge.c \
merge.h \
merge-init.c \
xml-label-04.h \
pixbuf-cache.c \
pixbuf-cache.h \
+ svg-cache.c \
+ svg-cache.h \
merge.c \
merge.h \
merge-init.c \
debug_flags |= GLABELS_DEBUG_MINI_PREVIEW;
if (g_getenv ("GLABELS_DEBUG_PIXBUF_CACHE") != NULL)
debug_flags |= GLABELS_DEBUG_PIXBUF_CACHE;
+ if (g_getenv ("GLABELS_DEBUG_SVG_CACHE") != NULL)
+ debug_flags |= GLABELS_DEBUG_SVG_CACHE;
if (g_getenv ("GLABELS_DEBUG_EDITOR") != NULL)
debug_flags |= GLABELS_DEBUG_EDITOR;
if (g_getenv ("GLABELS_DEBUG_WDGT") != NULL)
GLABELS_DEBUG_MEDIA_SELECT = 1 << 16,
GLABELS_DEBUG_MINI_PREVIEW = 1 << 17,
GLABELS_DEBUG_PIXBUF_CACHE = 1 << 18,
- GLABELS_DEBUG_EDITOR = 1 << 19,
- GLABELS_DEBUG_WDGT = 1 << 20,
- GLABELS_DEBUG_PATH = 1 << 21,
- GLABELS_DEBUG_FIELD_BUTTON = 1 << 22,
- GLABELS_DEBUG_BARCODE = 1 << 23,
+ GLABELS_DEBUG_SVG_CACHE = 1 << 19,
+ GLABELS_DEBUG_EDITOR = 1 << 20,
+ GLABELS_DEBUG_WDGT = 1 << 21,
+ GLABELS_DEBUG_PATH = 1 << 22,
+ GLABELS_DEBUG_FIELD_BUTTON = 1 << 23,
+ GLABELS_DEBUG_BARCODE = 1 << 24,
} glDebugSection;
#define DEBUG_MEDIA_SELECT GLABELS_DEBUG_MEDIA_SELECT, __FILE__, __LINE__, __FUNCTION__
#define DEBUG_MINI_PREVIEW GLABELS_DEBUG_MINI_PREVIEW, __FILE__, __LINE__, __FUNCTION__
#define DEBUG_PIXBUF_CACHE GLABELS_DEBUG_PIXBUF_CACHE, __FILE__, __LINE__, __FUNCTION__
+#define DEBUG_SVG_CACHE GLABELS_DEBUG_SVG_CACHE, __FILE__, __LINE__, __FUNCTION__
#define DEBUG_EDITOR GLABELS_DEBUG_EDITOR, __FILE__, __LINE__, __FUNCTION__
#define DEBUG_WDGT GLABELS_DEBUG_WDGT, __FILE__, __LINE__, __FUNCTION__
#define DEBUG_PATH GLABELS_DEBUG_PATH, __FILE__, __LINE__, __FUNCTION__
}
+/****************************************************************************/
+/* Test for given extension. */
+/****************************************************************************/
+gboolean
+gl_file_util_is_extension (const gchar *filename,
+ const gchar *ext_test)
+{
+ gchar *ext;
+
+ ext = strrchr (filename, '.');
+ if ( ext != NULL )
+ {
+ return (g_ascii_strcasecmp (ext, ext_test) == 0);
+ }
+
+ return FALSE;
+}
+
+
/*
* Local Variables: -- emacs
gchar *gl_file_util_make_absolute (const gchar *filename);
+gboolean gl_file_util_is_extension (const gchar *filename,
+ const gchar *ext_test);
+
G_END_DECLS
#endif /* __FILE_UTIL_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 "pixmaps/checkerboard.xpm"
/* 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;
};
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,
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);
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
+ GdkPixbuf *pixbuf;
- gl_label_image_parent_class = g_type_class_peek_parent (class);
+ gl_label_image_parent_class = g_type_class_peek_parent (class);
- label_object_class->copy = copy;
- label_object_class->set_size = set_size;
+ 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;
- object_class->finalize = gl_label_image_finalize;
-}
+ object_class->finalize = gl_label_image_finalize;
-
-static void
-gl_label_image_init (glLabelImage *limage)
-{
- GdkPixbuf *pixbuf;
-
- 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);
+static void
+gl_label_image_init (glLabelImage *this)
+{
+ this->priv = g_new0 (glLabelImagePrivate, 1);
- limage->priv->filename = g_new0 (glTextNode, 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);
+ glLabelObject *lobject = GL_LABEL_OBJECT (object);
+ glLabelImage *this = GL_LABEL_IMAGE (object);
glLabel *label;
- GHashTable *pixbuf_cache;
+ 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) {
+ if (!this->priv->filename->field_flag) {
+
label = gl_label_object_get_parent (lobject);
- pixbuf_cache = gl_label_get_pixbuf_cache (label);
- gl_pixbuf_cache_remove_pixbuf (pixbuf_cache,
- limage->priv->filename->data);
- }
- gl_text_node_free (&limage->priv->filename);
- g_free (limage->priv);
- G_OBJECT_CLASS (gl_label_image_parent_class)->finalize (object);
+ 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);
}
gl_label_image_new (glLabel *label,
gboolean checkpoint)
{
- glLabelImage *limage;
+ glLabelImage *this;
- limage = g_object_new (gl_label_image_get_type(), NULL);
+ this = g_object_new (gl_label_image_get_type(), NULL);
if (label != NULL)
{
gl_label_checkpoint (label, _("Create image object"));
}
- gl_label_add_object (label, GL_LABEL_OBJECT (limage));
- 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 (glLabelObject *dst_object,
glLabelObject *src_object)
{
- glLabelImage *limage = (glLabelImage *)src_object;
- glLabelImage *new_limage = (glLabelImage *)dst_object;
- glTextNode *filename;
- GdkPixbuf *pixbuf;
- glLabel *label;
- GHashTable *pixbuf_cache;
-
- 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));
-
- filename = gl_label_image_get_filename (limage);
-
- /* Make sure destination label has data suitably cached. */
- if ( !filename->field_flag && (filename->data != NULL) ) {
- pixbuf = limage->priv->pixbuf;
- if ( pixbuf != default_pixbuf ) {
- label = gl_label_object_get_parent (dst_object);
- pixbuf_cache = gl_label_get_pixbuf_cache (label);
- gl_pixbuf_cache_add_pixbuf (pixbuf_cache, filename->data, pixbuf);
- }
- }
+ 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_label_image_set_filename (new_limage, filename, FALSE);
- gl_text_node_free (&filename);
+ g_return_if_fail (src_limage && GL_IS_LABEL_IMAGE (src_limage));
+ g_return_if_fail (new_limage && GL_IS_LABEL_IMAGE (new_limage));
- gl_debug (DEBUG_LABEL, "END");
+ filename = gl_label_image_get_filename (src_limage);
+
+ /* 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, FALSE);
+ gl_text_node_free (&filename);
+
+ 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, checkpoint);
+ 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;
- glLabel *label;
- 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;
+ }
- label = gl_label_object_get_parent (GL_LABEL_OBJECT (limage));
+ 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);
if ( checkpoint )
{
gl_label_checkpoint (label, _("Set image"));
}
- pixbuf_cache = gl_label_get_pixbuf_cache (label);
+ /* Set new filename. */
+ this->priv->filename = gl_text_node_dup(filename);
- /* 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);
- }
+ /* Remove reference to previous item. */
+ switch (this->priv->type)
+ {
- /* Set new filename. */
- limage->priv->filename = gl_text_node_dup(filename);
- gl_text_node_free (&old_filename);
+ case FILE_TYPE_PIXBUF:
+ if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
+ gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, old_filename->data);
+ }
+ break;
- /* Now set the pixbuf. */
- if ( filename->field_flag || (filename->data == NULL) ) {
+ case FILE_TYPE_SVG:
+ if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
+ gl_svg_cache_remove_svg (svg_cache, old_filename->data);
+ }
+ break;
- limage->priv->pixbuf = default_pixbuf;
+ default:
+ break;
- } else {
+ }
- pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, filename->data);
+ gl_text_node_free (&old_filename);
- 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, FALSE);
+ /* 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(limage));
+ gl_label_object_emit_changed (GL_LABEL_OBJECT(this));
- gl_debug (DEBUG_LABEL, "END");
+ gl_debug (DEBUG_LABEL, "END");
}
void
-gl_label_image_set_pixbuf (glLabelImage *limage,
+gl_label_image_set_pixbuf (glLabelImage *this,
GdkPixbuf *pixbuf,
gboolean checkpoint)
{
- glTextNode *old_filename;
+ glTextNode *old_filename;
glLabel *label;
- GHashTable *pixbuf_cache;
+ GHashTable *pixbuf_cache;
+ GHashTable *svg_cache;
+ gchar *cs;
gchar *name;
- gdouble image_w, image_h;
+ gdouble image_w, image_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 (pixbuf && GDK_IS_PIXBUF (pixbuf));
+ g_return_if_fail (this && GL_IS_LABEL_IMAGE (this));
+ g_return_if_fail (pixbuf && GDK_IS_PIXBUF (pixbuf));
- old_filename = limage->priv->filename;
+ old_filename = this->priv->filename;
- label = gl_label_object_get_parent (GL_LABEL_OBJECT (limage));
+ 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);
+ pixbuf_cache = gl_label_get_pixbuf_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);
- }
+ /* 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. */
- name = g_compute_checksum_for_data (G_CHECKSUM_MD5,
- gdk_pixbuf_get_pixels (pixbuf),
- gdk_pixbuf_get_rowstride (pixbuf)*gdk_pixbuf_get_height (pixbuf));
- limage->priv->filename = gl_text_node_new_from_text(name);
- gl_text_node_free (&old_filename);
+ /* 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);
- limage->priv->pixbuf = g_object_ref (pixbuf);
+ this->priv->pixbuf = g_object_ref (pixbuf);
gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
+ g_free (cs);
g_free (name);
- image_w = gdk_pixbuf_get_width (limage->priv->pixbuf);
- image_h = gdk_pixbuf_get_height (limage->priv->pixbuf);
- gl_label_object_set_size (GL_LABEL_OBJECT(limage), image_w, image_h, FALSE);
+ 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(limage));
+ gl_label_object_emit_changed (GL_LABEL_OBJECT(this));
- gl_debug (DEBUG_LABEL, "END");
+ 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)
+ {
- return gl_text_node_dup (limage->priv->filename);
+ 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;
+ }
+
+ 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);
+ this->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;
+ 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;
+
+ }
}
gboolean screen_flag,
glMergeRecord *record)
{
- 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_label_object_get_size (object, &w, &h);
- gl_debug (DEBUG_LABEL, "START");
+ cairo_save (cr);
- gl_label_object_get_size (object, &w, &h);
+ switch (get_type (this, record))
+ {
- 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);
+ 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;
- cairo_save (cr);
+ 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;
- cairo_rectangle (cr, 0.0, 0.0, w, h);
+ 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");
}
gboolean screen_flag,
glMergeRecord *record)
{
+ glLabelImage *this = GL_LABEL_IMAGE (object);
gdouble w, h;
- const GdkPixbuf *pixbuf;
+ GdkPixbuf *pixbuf;
GdkPixbuf *shadow_pixbuf;
- gint image_w, image_h;
+ gdouble image_w, image_h;
glColorNode *shadow_color_node;
guint shadow_color;
gdouble shadow_opacity;
}
shadow_opacity = gl_label_object_get_shadow_opacity (object);
- 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);
- shadow_pixbuf = gl_pixbuf_util_create_shadow_pixbuf (pixbuf, shadow_color, shadow_opacity);
-
cairo_save (cr);
- cairo_rectangle (cr, 0.0, 0.0, w, h);
+ 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;
- cairo_scale (cr, w/image_w, h/image_h);
- gdk_cairo_set_source_pixbuf (cr, (GdkPixbuf *)shadow_pixbuf, 0, 0);
- cairo_fill (cr);
+ case FILE_TYPE_SVG:
+ /* FIXME: no shadow support, yet. */
+ break;
- cairo_restore (cr);
+ default:
+ shadow_color = gl_color_set_opacity (shadow_color, shadow_opacity);
- g_object_unref (G_OBJECT (shadow_pixbuf));
+ 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");
}
glLabelObjectClass parent_class;
};
-GType gl_label_image_get_type (void) G_GNUC_CONST;
+GType gl_label_image_get_type (void) G_GNUC_CONST;
-GObject *gl_label_image_new (glLabel *label,
- gboolean checkpoint);
+GObject *gl_label_image_new (glLabel *label,
+ gboolean checkpoint);
-void gl_label_image_set_filename (glLabelImage *limage,
- glTextNode *filename,
- gboolean checkpoint);
+void gl_label_image_set_filename (glLabelImage *limage,
+ glTextNode *filename,
+ gboolean checkpoint);
-void gl_label_image_set_pixbuf (glLabelImage *limage,
- GdkPixbuf *pixbuf,
- gboolean checkpoint);
+void gl_label_image_set_pixbuf (glLabelImage *limage,
+ GdkPixbuf *pixbuf,
+ gboolean checkpoint);
-glTextNode *gl_label_image_get_filename (glLabelImage *limage);
+GdkPixbuf *gl_label_image_get_pixbuf (glLabelImage *limage,
+ glMergeRecord *record);
-const GdkPixbuf *gl_label_image_get_pixbuf (glLabelImage *limage,
- glMergeRecord *record);
+RsvgHandle *gl_label_image_get_svg_handle (glLabelImage *this,
+ glMergeRecord *record);
+
+glTextNode *gl_label_image_get_filename (glLabelImage *limage);
+
+void gl_label_image_get_base_size (glLabelImage *this,
+ gdouble *w,
+ gdouble *h);
G_END_DECLS
glMerge *merge;
GHashTable *pixbuf_cache;
+ GHashTable *svg_cache;
/* Delay changed signals while operating on selections of multiple objects. */
gboolean selection_op_flag;
label->priv->merge = NULL;
label->priv->pixbuf_cache = gl_pixbuf_cache_new ();
+ label->priv->svg_cache = gl_svg_cache_new ();
label->priv->undo_stack = g_queue_new ();
label->priv->redo_stack = g_queue_new ();
g_queue_free (label->priv->redo_stack);
gl_pixbuf_cache_free (label->priv->pixbuf_cache);
+ gl_svg_cache_free (label->priv->svg_cache);
g_free (label->priv);
}
+/****************************************************************************/
+/* Get svg cache. */
+/****************************************************************************/
+GHashTable *
+gl_label_get_svg_cache (glLabel *label)
+{
+ return label->priv->svg_cache;
+}
+
+
/*****************************************************************************/
/* Add object to label. */
/*****************************************************************************/
if ( gl_label_is_selection_atomic (label) &&
GL_IS_LABEL_IMAGE (selection_list->data) )
{
- glLabelImage *image_object = GL_LABEL_IMAGE (selection_list->data);
- const GdkPixbuf *pixbuf = gl_label_image_get_pixbuf (image_object, NULL);
-
- gtk_target_list_add_image_targets (target_list, 2, TRUE);
+ glLabelImage *image_object = GL_LABEL_IMAGE (selection_list->data);
+ GdkPixbuf *pixbuf = gl_label_image_get_pixbuf (image_object, NULL);
- data->pixbuf = g_object_ref (G_OBJECT (pixbuf));
+ if (pixbuf)
+ {
+ gtk_target_list_add_image_targets (target_list, 2, TRUE);
+ data->pixbuf = pixbuf;
+ }
}
#include "merge.h"
#include "color.h"
#include "pixbuf-cache.h"
+#include "svg-cache.h"
G_BEGIN_DECLS
GHashTable *gl_label_get_pixbuf_cache (glLabel *label);
+GHashTable *gl_label_get_svg_cache (glLabel *label);
+
+
void gl_label_add_object (glLabel *label,
glLabelObject *object);
PangoAlignment align;
gdouble text_line_spacing;
gboolean auto_shrink;
- const GdkPixbuf *pixbuf;
gdouble image_w, image_h;
glTextNode *filename;
glTextNode *bc_data;
{
gl_label_object_get_size (object, &w, &h);
- pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object), NULL);
filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
- image_w = gdk_pixbuf_get_width (pixbuf);
- image_h = gdk_pixbuf_get_height (pixbuf);
+ gl_label_image_get_base_size (GL_LABEL_IMAGE(object), &image_w, &image_h);
gl_object_editor_set_size (editor, w, h);
gl_object_editor_set_base_size (editor, image_w, image_h);
gdouble text_line_spacing;
gboolean auto_shrink;
glTextNode *filename;
- const GdkPixbuf *pixbuf;
gdouble w, h;
gdouble image_w, image_h;
gdouble new_w, new_h;
}
/* It may also have a new base size. */
- pixbuf = gl_label_image_get_pixbuf (GL_LABEL_IMAGE(object), NULL);
- image_w = gdk_pixbuf_get_width (pixbuf);
- image_h = gdk_pixbuf_get_height (pixbuf);
+ gl_label_image_get_base_size (GL_LABEL_IMAGE(object), &image_w, &image_h);
gl_object_editor_set_base_size (editor, image_w, image_h);
gl_text_node_free (&filename);
--- /dev/null
+/*
+ * svg-cache.c
+ * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of gLabels.
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 gLabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "svg-cache.h"
+
+#include "debug.h"
+
+
+/*========================================================*/
+/* Private types. */
+/*========================================================*/
+
+typedef struct {
+ gchar *key;
+ guint references;
+ RsvgHandle *svg_handle;
+ gchar *contents;
+} CacheRecord;
+
+
+/*========================================================*/
+/* Private globals. */
+/*========================================================*/
+
+
+/*========================================================*/
+/* Private function prototypes. */
+/*========================================================*/
+
+static void record_destroy (gpointer val);
+
+static void add_name_to_list (gpointer key,
+ gpointer val,
+ gpointer user_data);
+
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Destroy cache record. */
+/*---------------------------------------------------------------------------*/
+static void
+record_destroy (gpointer val)
+{
+ CacheRecord *record = (CacheRecord *)val;
+
+ g_return_if_fail (record);
+
+ g_free (record->key);
+ g_object_unref (record->svg_handle);
+ g_free (record->contents);
+ g_free (record);
+}
+
+
+/*****************************************************************************/
+/* Create a new hash table to keep track of cached svgs. */
+/*****************************************************************************/
+GHashTable *
+gl_svg_cache_new (void)
+{
+ GHashTable *svg_cache;
+
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ svg_cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ NULL,
+ record_destroy);
+
+ gl_debug (DEBUG_SVG_CACHE, "END svg_cache=%p", svg_cache);
+
+ return svg_cache;
+}
+
+
+/*****************************************************************************/
+/* Free up previously allocated hash table and its contents. */
+/*****************************************************************************/
+void
+gl_svg_cache_free (GHashTable *svg_cache)
+{
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ g_hash_table_destroy (svg_cache);
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+}
+
+
+/*****************************************************************************/
+/* Add svg to cache explicitly. */
+/*****************************************************************************/
+void
+gl_svg_cache_add_svg (GHashTable *svg_cache,
+ gchar *name,
+ const gchar *contents)
+{
+ CacheRecord *test_record, *record;
+ RsvgHandle *svg_handle;
+
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ test_record = g_hash_table_lookup (svg_cache, name);
+ if (test_record != NULL) {
+ /* svg is already in the cache. */
+ gl_debug (DEBUG_SVG_CACHE, "END already in cache");
+ return;
+ }
+
+ record = g_new0 (CacheRecord, 1);
+ record->key = g_strdup (name);
+ record->references = 0; /* No references yet. */
+ record->svg_handle = rsvg_handle_new_from_data (contents, strlen(contents), NULL);
+ record->contents = g_strdup (contents);
+
+ g_hash_table_insert (svg_cache, record->key, record);
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+}
+
+
+/*****************************************************************************/
+/* Get svg handle adding a reference. If not in cache, read it and add. */
+/*****************************************************************************/
+RsvgHandle *
+gl_svg_cache_get_handle (GHashTable *svg_cache,
+ gchar *name)
+{
+ CacheRecord *record;
+ RsvgHandle *svg_handle = NULL;
+ gchar *buffer;
+ gsize length;
+ GFile *file;
+
+ gl_debug (DEBUG_SVG_CACHE, "START svg_cache=%p", svg_cache);
+
+ record = g_hash_table_lookup (svg_cache, name);
+
+ if (record != NULL)
+ {
+ record->references++;
+ gl_debug (DEBUG_SVG_CACHE, "references=%d", record->references);
+ gl_debug (DEBUG_SVG_CACHE, "END cached");
+ return record->svg_handle;
+ }
+
+
+ file = g_file_new_for_path (name);
+ if ( g_file_load_contents (file, NULL, &buffer, &length, NULL, NULL) )
+ {
+ svg_handle = rsvg_handle_new_from_data (buffer, length, NULL);
+ if ( svg_handle != NULL) {
+ record = g_new0 (CacheRecord, 1);
+ record->key = g_strdup (name);
+ record->references = 1;
+ record->svg_handle = svg_handle;
+ record->contents = buffer;
+
+ g_hash_table_insert (svg_cache, record->key, record);
+ }
+ }
+ g_object_unref (file);
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+
+ return svg_handle;
+}
+
+
+/*****************************************************************************/
+/* Get contents. Do not add reference. */
+/*****************************************************************************/
+gchar *
+gl_svg_cache_get_contents (GHashTable *svg_cache,
+ gchar *name)
+{
+ CacheRecord *record;
+ RsvgHandle *svg_handle = NULL;
+ GFile *file;
+
+ gl_debug (DEBUG_SVG_CACHE, "START svg_cache=%p", svg_cache);
+
+ record = g_hash_table_lookup (svg_cache, name);
+
+ if (record != NULL)
+ {
+ gl_debug (DEBUG_SVG_CACHE, "references=%d", record->references);
+ gl_debug (DEBUG_SVG_CACHE, "END cached");
+ return g_strdup (record->contents);
+ }
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+
+ return NULL;
+}
+
+
+/*****************************************************************************/
+/* Remove svg, but only if no references left. */
+/*****************************************************************************/
+void
+gl_svg_cache_remove_svg (GHashTable *svg_cache,
+ gchar *name)
+{
+ CacheRecord *record;
+
+ if (name == NULL) return;
+
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ record = g_hash_table_lookup (svg_cache, name);
+ if (record == NULL) {
+ gl_debug (DEBUG_SVG_CACHE, "END not in cache");
+ return;
+ }
+
+ record->references--;
+
+ if ( record->references == 0 ) {
+ g_hash_table_remove (svg_cache, name);
+ }
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Add a name to a GList while iterating over cache. */
+/*---------------------------------------------------------------------------*/
+static void
+add_name_to_list (gpointer key,
+ gpointer val,
+ gpointer user_data)
+{
+ gchar *name = (gchar *)key;
+ GList **name_list = (GList **)user_data;
+
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ gl_debug (DEBUG_SVG_CACHE, "adding name=%s", name);
+
+ *name_list = g_list_append (*name_list, g_strdup(name));
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+}
+
+
+/*****************************************************************************/
+/* Return a list of names for all svgs in the cache. */
+/*****************************************************************************/
+GList *
+gl_svg_cache_get_name_list (GHashTable *svg_cache)
+{
+ GList *name_list = NULL;
+
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ g_hash_table_foreach (svg_cache, add_name_to_list, &name_list);
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+
+ return name_list;
+}
+
+
+/*****************************************************************************/
+/* Free up a list of svg names. */
+/*****************************************************************************/
+void
+gl_svg_cache_free_name_list (GList *name_list)
+{
+ GList *p_name;
+
+ gl_debug (DEBUG_SVG_CACHE, "START");
+
+ for (p_name = name_list; p_name != NULL; p_name = p_name->next) {
+ g_free (p_name->data);
+ p_name->data = NULL;
+ }
+
+ g_list_free (name_list);
+
+ gl_debug (DEBUG_SVG_CACHE, "END");
+}
+
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * svg-cache.h
+ * Copyright (C) 2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of gLabels.
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 gLabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SVG_CACHE_H__
+#define __SVG_CACHE_H__
+
+#include <glib.h>
+#include <librsvg/rsvg.h>
+
+G_BEGIN_DECLS
+
+GHashTable *gl_svg_cache_new (void);
+
+void gl_svg_cache_free (GHashTable *svg_cache);
+
+void gl_svg_cache_add_svg (GHashTable *svg_cache,
+ gchar *name,
+ const gchar *contents);
+
+RsvgHandle *gl_svg_cache_get_handle (GHashTable *svg_cache,
+ gchar *name);
+
+gchar *gl_svg_cache_get_contents (GHashTable *svg_cache,
+ gchar *name);
+
+void gl_svg_cache_remove_svg (GHashTable *svg_cache,
+ gchar *name);
+
+GList *gl_svg_cache_get_name_list (GHashTable *svg_cache);
+
+void gl_svg_cache_free_name_list (GList *name_list);
+
+G_END_DECLS
+
+#endif /*__SVG_CACHE_H__ */
+
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
static void xml_parse_pixdata (xmlNodePtr node,
glLabel *label);
+static void xml_parse_file_node (xmlNodePtr node,
+ glLabel *label);
+
static void xml_parse_toplevel_span (xmlNodePtr node,
glLabelObject *object);
static xmlDocPtr xml_label_to_doc (glLabel *label,
glXMLLabelStatus *status);
-static void xml_create_objects (xmlNodePtr root,
+static void xml_create_objects (xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label);
-static void xml_create_object_text (xmlNodePtr root,
+static void xml_create_object_text (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object);
-static void xml_create_object_box (xmlNodePtr root,
+static void xml_create_object_box (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object);
-static void xml_create_object_line (xmlNodePtr root,
+static void xml_create_object_line (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object);
-static void xml_create_object_ellipse(xmlNodePtr root,
+static void xml_create_object_ellipse(xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object);
-static void xml_create_object_image (xmlNodePtr root,
+static void xml_create_object_image (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object);
-static void xml_create_object_barcode(xmlNodePtr root,
+static void xml_create_object_barcode(xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object);
-static void xml_create_merge_fields (xmlNodePtr root,
+static void xml_create_merge_fields (xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label);
-static void xml_create_data (xmlNodePtr root,
+static void xml_create_data (xmlDocPtr doc,
+ xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label);
-static void xml_create_pixdata (xmlNodePtr root,
+static void xml_create_pixdata (xmlNodePtr parent,
+ xmlNsPtr ns,
+ glLabel *label,
+ gchar *name);
+
+static void xml_create_file_svg (xmlDocPtr doc,
+ xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label,
gchar *name);
if (lgl_xml_is_node (child, "Pixdata")) {
xml_parse_pixdata (child, label);
+ } else if (lgl_xml_is_node (child, "File")) {
+ xml_parse_file_node (child, label);
} else {
if (!xmlNodeIsText (child)) {
g_message (_("bad node in Data node = \"%s\""),
/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML pixbuf data tag. */
+/* PRIVATE. Parse XML embedded Pixdata node. */
/*--------------------------------------------------------------------------*/
static void
xml_parse_pixdata (xmlNodePtr node,
}
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML embedded File node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_file_node (xmlNodePtr node,
+ glLabel *label)
+{
+ gchar *name, *format;
+ gchar *content;
+ GHashTable *svg_cache;
+
+ name = lgl_xml_get_prop_string (node, "name", NULL);
+ format = lgl_xml_get_prop_string (node, "format", NULL);
+
+ if ( format && (lgl_str_utf8_casecmp (format, "SVG") == 0) )
+ {
+ content = lgl_xml_get_node_content (node);
+
+ svg_cache = gl_label_get_svg_cache (label);
+ gl_svg_cache_add_svg (svg_cache, name, content);
+
+ g_free (content);
+ }
+ else
+ {
+ g_message (_("Unknown embedded file format: \"%s\""), format);
+
+ }
+
+ g_free (name);
+ g_free (format);
+}
+
+
/*--------------------------------------------------------------------------*/
/* PRIVATE. Parse top-level Span tag. */
/*--------------------------------------------------------------------------*/
g_object_unref (G_OBJECT(merge));
}
- xml_create_data (doc->xmlRootNode, ns, label);
+ xml_create_data (doc, doc->xmlRootNode, ns, label);
gl_debug (DEBUG_XML, "END");
/* PRIVATE. Add XML Objects Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_objects (xmlNodePtr root,
+xml_create_objects (xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label)
{
rotate_flag = gl_label_get_rotate_flag (label);
object_list = gl_label_get_object_list (label);
- node = xmlNewChild (root, ns, (xmlChar *)"Objects", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Objects", NULL);
lgl_xml_set_prop_string (node, "id", "0");
lgl_xml_set_prop_boolean (node, "rotate", rotate_flag);
/* PRIVATE. Add XML Objects->Object-text Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_object_text (xmlNodePtr root,
+xml_create_object_text (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object)
{
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Object-text", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Object-text", NULL);
/* position attrs */
gl_label_object_get_position (object, &x, &y);
/* PRIVATE. Add XML Objects->Object-box Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_object_box (xmlNodePtr root,
+xml_create_object_box (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object)
{
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Object-box", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Object-box", NULL);
/* position attrs */
gl_label_object_get_position (object, &x, &y);
/* PRIVATE. Add XML Objects->Object-ellipse Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_object_ellipse (xmlNodePtr root,
+xml_create_object_ellipse (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object)
{
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Object-ellipse", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Object-ellipse", NULL);
/* position attrs */
gl_label_object_get_position (object, &x, &y);
/* PRIVATE. Add XML Objects->Object-line Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_object_line (xmlNodePtr root,
+xml_create_object_line (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object)
{
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Object-line", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Object-line", NULL);
/* position attrs */
gl_label_object_get_position (object, &x, &y);
/* PRIVATE. Add XML Objects->Object-image Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_object_image (xmlNodePtr root,
+xml_create_object_image (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object)
{
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Object-image", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Object-image", NULL);
/* position attrs */
gl_label_object_get_position (object, &x, &y);
/* PRIVATE. Add XML Objects->Object-barcode Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_object_barcode (xmlNodePtr root,
+xml_create_object_barcode (xmlNodePtr parent,
xmlNsPtr ns,
glLabelObject *object)
{
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Object-barcode", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Object-barcode", NULL);
/* position attrs */
gl_label_object_get_position (object, &x, &y);
/* PRIVATE. Add XML Label Merge Fields Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_merge_fields (xmlNodePtr root,
+xml_create_merge_fields (xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label)
{
merge = gl_label_get_merge (label);
- node = xmlNewChild (root, ns, (xmlChar *)"Merge", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Merge", NULL);
string = gl_merge_get_name (merge);
lgl_xml_set_prop_string (node, "type", string);
/* PRIVATE. Add XML Label Data Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_data (xmlNodePtr root,
+xml_create_data (xmlDocPtr doc,
+ xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label)
{
xmlNodePtr node;
+ GHashTable *cache;
GList *name_list, *p;
- GHashTable *pixbuf_cache;
gl_debug (DEBUG_XML, "START");
- node = xmlNewChild (root, ns, (xmlChar *)"Data", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Data", NULL);
- pixbuf_cache = gl_label_get_pixbuf_cache (label);
- name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
+ cache = gl_label_get_pixbuf_cache (label);
+ name_list = gl_pixbuf_cache_get_name_list (cache);
for (p = name_list; p != NULL; p=p->next) {
xml_create_pixdata (node, ns, label, p->data);
gl_pixbuf_cache_free_name_list (name_list);
+ cache = gl_label_get_svg_cache (label);
+ name_list = gl_svg_cache_get_name_list (cache);
+
+ for (p = name_list; p != NULL; p=p->next) {
+ xml_create_file_svg (doc, node, ns, label, p->data);
+ }
+
+ gl_pixbuf_cache_free_name_list (name_list);
+
+
gl_debug (DEBUG_XML, "END");
}
/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Label Data Pixbuf Node */
+/* PRIVATE. Add XML Label Data embedded Pixdata Node */
/*--------------------------------------------------------------------------*/
static void
-xml_create_pixdata (xmlNodePtr root,
+xml_create_pixdata (xmlNodePtr parent,
xmlNsPtr ns,
glLabel *label,
gchar *name)
stream = gdk_pixdata_serialize (pixdata, &stream_length);
base64 = g_base64_encode (stream, stream_length);
- node = xmlNewChild (root, ns, (xmlChar *)"Pixdata", (xmlChar *)base64);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Pixdata", (xmlChar *)base64);
lgl_xml_set_prop_string (node, "name", name);
lgl_xml_set_prop_string (node, "encoding", "Base64");
}
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Label Data embedded SVG file Node */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_file_svg (xmlDocPtr doc,
+ xmlNodePtr parent,
+ xmlNsPtr ns,
+ glLabel *label,
+ gchar *name)
+{
+ xmlNodePtr node;
+ xmlNodePtr cdata_section_node;
+ GHashTable *svg_cache;
+ gchar *svg_data;
+
+ gl_debug (DEBUG_XML, "START");
+
+ svg_cache = gl_label_get_svg_cache (label);
+
+ svg_data = gl_svg_cache_get_contents (svg_cache, name);
+ if ( svg_data != NULL ) {
+
+ node = xmlNewChild (parent, ns, (xmlChar *)"File", NULL);
+ lgl_xml_set_prop_string (node, "name", name);
+ lgl_xml_set_prop_string (node, "format", "SVG");
+
+ cdata_section_node = xmlNewCDataBlock (doc, (xmlChar *)svg_data, strlen (svg_data));
+ xmlAddChild (node, cdata_section_node);
+
+ g_free (svg_data);
+ }
+
+
+ gl_debug (DEBUG_XML, "END");
+}
+
+
/*--------------------------------------------------------------------------*/
/* PRIVATE. Create top-level Span node. */
/*--------------------------------------------------------------------------*/
static void
-xml_create_toplevel_span (xmlNodePtr root,
+xml_create_toplevel_span (xmlNodePtr parent,
xmlNsPtr ns,
glLabelText *object_text)
{
glTextNode *text_node;
xmlNodePtr child;
- node = xmlNewChild (root, ns, (xmlChar *)"Span", NULL);
+ node = xmlNewChild (parent, ns, (xmlChar *)"Span", NULL);
/* All span attrs at top level. */
font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
<!-- Data encoding method -->
<!ENTITY % DATA_ENCODING_TYPE "(None | Base64)">
+<!-- Inline file format type -->
+<!ENTITY % FILE_FORMAT_TYPE "(SVG)">
+
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- Top-level glabels paper data base -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- Data Section -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
-<!ENTITY % data_element "Pixdata">
+<!ENTITY % data_element "Pixdata | File">
<!ELEMENT Data (%data_element;)*>
encoding %DATA_ENCODING_TYPE; "Base64"
>
+<!-- Inline File -->
+<!ELEMENT File (#PCDATA)>
+<!ATTLIST File
+ name %STRING_TYPE; #REQUIRED
+ format %FILE_FORMAT_TYPE; "SVG"
+>
+
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- Text elements -->