]> git.sur5r.net Git - glabels/commitdiff
Add native support for SVG images.
authorJim Evins <evins@snaught.com>
Sat, 3 Jul 2010 03:12:32 +0000 (23:12 -0400)
committerJim Evins <evins@snaught.com>
Sat, 3 Jul 2010 03:15:29 +0000 (23:15 -0400)
Rather than just rasterizing SVG files into GdkPixbufs, use RSVG to handle
SVG files directly -- preserving the original file as inline data.

16 files changed:
configure.ac
po/POTFILES.in
src/Makefile.am
src/debug.c
src/debug.h
src/file-util.c
src/file-util.h
src/label-image.c
src/label-image.h
src/label.c
src/label.h
src/object-editor.c
src/svg-cache.c [new file with mode: 0644]
src/svg-cache.h [new file with mode: 0644]
src/xml-label.c
templates/glabels-2.3.dtd

index 4942de82bece010ab529cabd547af011fab918cf..d3ee342c4baba167ddd1a1130375cea10999cbbd 100644 (file)
@@ -74,6 +74,7 @@ GLIB_REQUIRED=2.24.0
 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
@@ -102,6 +103,7 @@ PKG_CHECK_MODULES(GLABELS, [\
        gtk+-2.0 >= $GTK_REQUIRED \
        gconf-2.0 >= $GCONF_REQUIRED \
        libxml-2.0 >= $LIBXML_REQUIRED \
+       librsvg-2.0 > $LIBRSVG_REQUIRED \
 ])
 
 AC_SUBST(GLABELS_CFLAGS)
index 9dd1ad9fba9fea919b71493ec8256fc8461813c5..c19d0095ad59d180f1582ca0ac88f4bd2f162b09 100644 (file)
@@ -141,6 +141,8 @@ src/stock.c
 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
index 72f8e05b9e51349f447f09097530d6841425e709..4ebd3a1c4dfb4185f41e7e288d38435faef57d5a 100644 (file)
@@ -155,6 +155,8 @@ glabels_3_SOURCES =                         \
        xml-label-04.h                  \
        pixbuf-cache.c                  \
        pixbuf-cache.h                  \
+       svg-cache.c                     \
+       svg-cache.h                     \
        merge.c                         \
        merge.h                         \
        merge-init.c                    \
@@ -280,6 +282,8 @@ glabels_3_batch_SOURCES =           \
        xml-label-04.h                  \
        pixbuf-cache.c                  \
        pixbuf-cache.h                  \
+       svg-cache.c                     \
+       svg-cache.h                     \
        merge.c                         \
        merge.h                         \
        merge-init.c                    \
index 23432d9e9a4ecb6c8f87f94cf6f9367c72115c54..d29d6246ea851a8e60f0201bd048c55905827e91 100644 (file)
@@ -85,6 +85,8 @@ gl_debug_init (void)
                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)
index 59a862b8c01a11685c1d1196c57855178d6ba523..25825a818583fd0bed41750c30fefaac33f9c937 100644 (file)
@@ -59,11 +59,12 @@ typedef enum {
        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;
 
 
@@ -90,6 +91,7 @@ typedef enum {
 #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__
index ace188bdf1380aaa96a70c0bf55ca49885046643..66d8ebf0f2525bc57e6776c2f56a1abba47fdebb 100644 (file)
@@ -90,6 +90,25 @@ gl_file_util_make_absolute (const gchar *filename)
 }
 
 
+/****************************************************************************/
+/* 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
index 50c447c12d843110ed75fb87b351d59019e3228b..f4e94f3890ac16f72bdd98f32d09dfe2cf545778 100644 (file)
@@ -30,6 +30,9 @@ gchar              *gl_file_util_remove_extension      (const gchar       *orig_
 
 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__ */
index 7b7181ea5787d936dad4655ea837c6ef592135aa..46fc49f6e6e4afe9facfe9a13ab97caa77bea9cf 100644 (file)
@@ -25,6 +25,8 @@
 #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;
 };
 
 
@@ -59,7 +73,7 @@ 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,
@@ -91,61 +105,79 @@ 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);
+        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);
 }
 
 
@@ -156,9 +188,9 @@ GObject *
 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)
         {
@@ -167,11 +199,11 @@ gl_label_image_new (glLabel *label,
                         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);
 }
 
 
@@ -182,34 +214,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;
-        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");
 }
 
 
@@ -218,11 +274,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)
         {
@@ -234,7 +290,7 @@ set_size (glLabelObject *object,
                 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);
 }
 
 
@@ -242,176 +298,378 @@ 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;
-        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;
+
+        }
 }
 
 
@@ -424,29 +682,60 @@ draw_object (glLabelObject *object,
              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");
 }
 
 
@@ -459,10 +748,11 @@ draw_shadow (glLabelObject *object,
              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;
@@ -479,22 +769,44 @@ draw_shadow (glLabelObject *object,
         }
         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");
 }
index 218a2e75222c6a272831907ae941c1372b94a9d1..98abc46366b37e6d0d528cb299591b9930f00914 100644 (file)
@@ -50,23 +50,30 @@ struct _glLabelImageClass {
        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
 
index 84fc098e2546598e8caa1aa0dec9868fa6d160cb..37e0c6cf7d8e283983f39a4c61b19f94ad422a80 100644 (file)
@@ -62,6 +62,7 @@ struct _glLabelPrivate {
        glMerge     *merge;
 
        GHashTable  *pixbuf_cache;
+       GHashTable  *svg_cache;
 
         /* Delay changed signals while operating on selections of multiple objects. */
         gboolean     selection_op_flag;
@@ -275,6 +276,7 @@ gl_label_init (glLabel *label)
 
        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 ();
@@ -328,6 +330,7 @@ gl_label_finalize (GObject *object)
         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);
 
@@ -741,6 +744,16 @@ gl_label_get_pixbuf_cache (glLabel       *label)
 }
 
 
+/****************************************************************************/
+/* Get svg cache.                                                           */
+/****************************************************************************/
+GHashTable *
+gl_label_get_svg_cache (glLabel       *label)
+{
+       return label->priv->svg_cache;
+}
+
+
 /*****************************************************************************/
 /* Add object to label.                                                      */
 /*****************************************************************************/
@@ -2392,12 +2405,14 @@ gl_label_copy_selection (glLabel       *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;
+                        }
                 }
 
 
index aa183369b10264f1f4883deee87f9003795b8d96..eccd6088825c7fd569b54ccc82576ab58ef2fb6f 100644 (file)
@@ -28,6 +28,7 @@
 #include "merge.h"
 #include "color.h"
 #include "pixbuf-cache.h"
+#include "svg-cache.h"
 
 G_BEGIN_DECLS
 
@@ -133,6 +134,9 @@ glMerge      *gl_label_get_merge               (glLabel       *label);
 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);
 
index d544c55f83d39327f0c404ccbaf7ba149ac3a5ef..8640371225a728b2623f52611e918c835eb10bf2 100644 (file)
@@ -742,7 +742,6 @@ object_changed_cb (glLabelObject  *object,
         PangoAlignment   align;
         gdouble          text_line_spacing;
         gboolean         auto_shrink;
-        const GdkPixbuf *pixbuf;
         gdouble          image_w, image_h;
         glTextNode      *filename;
         glTextNode      *bc_data;
@@ -804,11 +803,9 @@ object_changed_cb (glLabelObject  *object,
         {
 
                 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);
@@ -902,7 +899,6 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         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;
@@ -968,9 +964,7 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
                 }
 
                 /* 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);
diff --git a/src/svg-cache.c b/src/svg-cache.c
new file mode 100644 (file)
index 0000000..f1161bd
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *  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
+ */
diff --git a/src/svg-cache.h b/src/svg-cache.h
new file mode 100644 (file)
index 0000000..b2f406f
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  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
+ */
index 001e33ae8bf0acdf2b3f87cec504f5a2ece3ba5f..09930a4e9bea73d3bd10da78bde0689d76abc973 100644 (file)
@@ -104,6 +104,9 @@ static void           xml_parse_data           (xmlNodePtr        node,
 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);
 
@@ -116,43 +119,50 @@ static void           xml_parse_shadow_attrs   (xmlNodePtr        node,
 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);
@@ -851,6 +861,8 @@ xml_parse_data (xmlNodePtr  node,
 
                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\""),
@@ -864,7 +876,7 @@ xml_parse_data (xmlNodePtr  node,
 
 
 /*--------------------------------------------------------------------------*/
-/* PRIVATE.  Parse XML pixbuf data tag.                                     */
+/* PRIVATE.  Parse XML embedded Pixdata node.                               */
 /*--------------------------------------------------------------------------*/
 static void
 xml_parse_pixdata (xmlNodePtr  node,
@@ -904,6 +916,40 @@ 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.                                      */
 /*--------------------------------------------------------------------------*/
@@ -1181,7 +1227,7 @@ xml_label_to_doc (glLabel          *label,
                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");
 
@@ -1194,7 +1240,7 @@ xml_label_to_doc (glLabel          *label,
 /* PRIVATE.  Add XML Objects Node                                           */
 /*--------------------------------------------------------------------------*/
 static void
-xml_create_objects (xmlNodePtr  root,
+xml_create_objects (xmlNodePtr  parent,
                    xmlNsPtr    ns,
                    glLabel    *label)
 {
@@ -1209,7 +1255,7 @@ xml_create_objects (xmlNodePtr  root,
         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);
 
@@ -1243,7 +1289,7 @@ xml_create_objects (xmlNodePtr  root,
 /* 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)
 {
@@ -1255,7 +1301,7 @@ xml_create_object_text (xmlNodePtr     root,
 
        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);
@@ -1292,7 +1338,7 @@ xml_create_object_text (xmlNodePtr     root,
 /* 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)
 {
@@ -1305,7 +1351,7 @@ xml_create_object_box (xmlNodePtr     root,
 
        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);
@@ -1358,7 +1404,7 @@ xml_create_object_box (xmlNodePtr     root,
 /* 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)
 {
@@ -1371,7 +1417,7 @@ xml_create_object_ellipse (xmlNodePtr     root,
 
        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);
@@ -1425,7 +1471,7 @@ xml_create_object_ellipse (xmlNodePtr     root,
 /* 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)
 {
@@ -1437,7 +1483,7 @@ xml_create_object_line (xmlNodePtr     root,
 
        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);
@@ -1479,7 +1525,7 @@ xml_create_object_line (xmlNodePtr     root,
 /* 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)
 {
@@ -1490,7 +1536,7 @@ xml_create_object_image (xmlNodePtr     root,
 
        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);
@@ -1525,7 +1571,7 @@ xml_create_object_image (xmlNodePtr     root,
 /* 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)
 {
@@ -1541,7 +1587,7 @@ xml_create_object_barcode (xmlNodePtr     root,
 
        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);
@@ -1598,7 +1644,7 @@ xml_create_object_barcode (xmlNodePtr     root,
 /* 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)
 {
@@ -1610,7 +1656,7 @@ xml_create_merge_fields (xmlNodePtr  root,
 
        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);
@@ -1630,20 +1676,21 @@ xml_create_merge_fields (xmlNodePtr  root,
 /* 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);
@@ -1652,15 +1699,25 @@ xml_create_data (xmlNodePtr  root,
        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)
@@ -1685,7 +1742,7 @@ xml_create_pixdata (xmlNodePtr  root,
                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");
 
@@ -1701,11 +1758,48 @@ xml_create_pixdata (xmlNodePtr  root,
 }
 
 
+/*--------------------------------------------------------------------------*/
+/* 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)
 {
@@ -1721,7 +1815,7 @@ xml_create_toplevel_span (xmlNodePtr        root,
        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));
index 316891434b538f27e81181d01d3f3e9f4048c5ae..1e276c363f2c72ef8be07895a7c9cca9bc6a6eea 100644 (file)
@@ -81,6 +81,9 @@
 <!-- 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                                                        -->