[librsvg] Use GZlibDecompressor for SVGZ support



commit af8dc1feb3e38e06be5865d93ee6d266514c16af
Author: Christian Persch <chpe gnome org>
Date:   Tue Jun 22 17:54:50 2010 +0200

    Use GZlibDecompressor for SVGZ support
    
    On gio >= 2.24, use GZlibDecompressor for SVGZ. Otherwise use libgsf.
    
    Bug #621699.

 configure.in   |   76 +++++++++++++++++++++++---------------
 rsvg-base.c    |  112 ++++++++++++++++++++++++++++++++++++--------------------
 rsvg-gobject.c |   19 +++++++--
 rsvg-private.h |    8 +++-
 4 files changed, 138 insertions(+), 77 deletions(-)
---
diff --git a/configure.in b/configure.in
index 8e7a377..e2d063f 100644
--- a/configure.in
+++ b/configure.in
@@ -133,38 +133,54 @@ PKG_CHECK_MODULES(LIBRSVG, \
 
 dnl ===========================================================================
 
-LIBGSF_CFLAGS=""
-LIBGSF_LIBS=""
+# Using GIO 2.24 we support reading .svg.gz data
 
-LIBGSFPKG=""
-test_gsf=true
-AC_ARG_WITH(svgz,[  --with-svgz  Use libgsf for run-time decompression],[
-	if test "x$withval" = "xno"; then
-		test_gsf=false
-	fi
-])
-if test "x$test_gsf" = "xtrue"; then
-	PKG_CHECK_MODULES(LIBGSF,[libgsf-1 >= 1.6.0], test_gsf=true, test_gsf=false)
-fi
+svgz_warning=
 
-if test "x$test_gsf" = "xtrue"; then
-        svgz_define=1
-	LIBGSF_CFLAGS="$LIBGSF_CFLAGS -DHAVE_SVGZ=1"
-	LIBGSFPKG="libgsf-1"
-else
-        svgz_define=0
-	AC_MSG_WARN([SVGZ support disabled, as requested (Use --with-svgz to enable)])
-	gsf_warning="
-	You are building without libgsf support. LibRSVG will not be able to handle GZipped SVGs, as is required per the SVG specification. If you are a library vendor or distributor, you are doing the world a disservice and should strongly consider shipping libgsf."
-fi
-AM_CONDITIONAL(WITH_LIBGSF,[test "$LIBGSFPKG" != ""])
+AC_MSG_CHECKING([whether gio 2.24 is available])
+PKG_CHECK_EXISTS([gio-2.0 >= 2.24.0],[have_gio_2_24=yes],[have_gio_2_24=no])
+AC_MSG_RESULT([$have_gio_2_24])
 
-AC_SUBST(LIBGSFPKG)
+AC_SUBST([HAVE_GIO_2_24],[$have_gio_2_24])
 
-AC_SUBST(LIBGSF_CFLAGS)
-AC_SUBST(LIBGSF_LIBS)
+if test "$have_gio_2_24" = "yes"; then
+  svgz_define=1
+  test_svgz=true
+else
+  LIBGSF_CFLAGS=""
+  LIBGSF_LIBS=""
+
+  LIBGSFPKG=""
+  test_svgz=true
+  AC_ARG_WITH(svgz,[  --with-svgz  Use libgsf for run-time decompression],[
+          if test "x$withval" = "xno"; then
+                  test_svgz=false
+          fi
+  ])
+  if test "x$test_svgz" = "xtrue"; then
+          PKG_CHECK_MODULES(LIBGSF,[libgsf-1 >= 1.6.0], test_svgz=true, test_svgz=false)
+  fi
+
+  if test "x$test_svgz" = "xtrue"; then
+          svgz_define=1
+          AC_DEFINE([HAVE_GSF],[1],[Define if using libgsf])
+          LIBGSFPKG="libgsf-1"
+  else
+          svgz_define=0
+          AC_MSG_WARN([SVGZ support disabled, as requested (Use --with-svgz to enable)])
+  fi
+
+  AC_SUBST(LIBGSFPKG)
+
+  AC_SUBST(LIBGSF_CFLAGS)
+  AC_SUBST(LIBGSF_LIBS)
+fi # have_gio_2_24
+
+if test "$test_svgz" != "true"; then
+  svgz_warning="You are building without libgsf support. LibRSVG will not be able to handle GZipped SVGs, as is required per the SVG specification. If you are a library vendor or distributor, you are doing the world a disservice and should strongly consider shipping libgsf."
+fi
 
-AC_SUBST([SVGZ_SUPPORTED],[$test_gsf])
+AC_SUBST([SVGZ_SUPPORTED],[$test_svgz])
 AC_SUBST([LIBRSVG_HAVE_SVGZ],[$svgz_define])
 
 dnl ===========================================================================
@@ -376,7 +392,7 @@ librsvg-$VERSION for gtk+-$GTK_API_VERSION
 	Build GdkPixbuf loader:         ${enable_pixbuf_loader}
 	Build theme engine:             ${enable_gtk_theme}
 	Build miscellaenous tools:      ${build_misc_tools}
-	Handle svgz files:              ${test_gsf}
+	Handle svgz files:              ${test_svgz}
 	Use libcroco for css parsing:   ${test_croco}
 "
 
@@ -384,6 +400,6 @@ if test "x$croco_warning" != "x"; then
    AC_MSG_RESULT([$croco_warning]);
 fi
 
-if test "x$gsf_warning" != "x"; then
-   AC_MSG_RESULT([$gsf_warning]);
+if test "x$svgz_warning" != "x"; then
+   AC_MSG_NOTICE([$svgz_warning]);
 fi
diff --git a/rsvg-base.c b/rsvg-base.c
index 85ce8e5..b60261d 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -26,13 +26,6 @@
 
 #include "config.h"
 
-#ifdef HAVE_SVGZ
-#include <gsf/gsf-input-gzip.h>
-#include <gsf/gsf-input-memory.h>
-#include <gsf/gsf-output-memory.h>
-#include <gsf/gsf-utils.h>
-#endif
-
 #include "rsvg.h"
 #include "rsvg-private.h"
 #include "rsvg-css.h"
@@ -54,6 +47,13 @@
 #include <string.h>
 #include <stdarg.h>
 
+#ifdef HAVE_GSF
+#include <gsf/gsf-input-gzip.h>
+#include <gsf/gsf-input-memory.h>
+#include <gsf/gsf-output-memory.h>
+#include <gsf/gsf-utils.h>
+#endif
+
 #include "rsvg-bpath-util.h"
 #include "rsvg-path.h"
 #include "rsvg-paint-server.h"
@@ -1682,79 +1682,109 @@ rsvg_handle_set_size_callback (RsvgHandle * handle,
 
 /**
  * rsvg_handle_write:
- * @handle: An #RsvgHandle
- * @buf: Pointer to svg data
+ * @handle: an #RsvgHandle
+ * @buf: (array length=count) (element-type uint8): pointer to svg data
  * @count: length of the @buf buffer in bytes
- * @error: return location for errors
+ * @error: (allow-none): a location to store a #GError, or %NULL
  *
  * Loads the next @count bytes of the image.  This will return #TRUE if the data
  * was loaded successful, and #FALSE if an error occurred.  In the latter case,
  * the loader will be closed, and will not accept further writes. If FALSE is
- * returned, @error will be set to an error from the #RSVG_ERROR domain.
+ * returned, @error will be set to an error from the #RsvgError domain. Errors
+ * from #GIOErrorEnum are also possible.
  *
- * Returns: #TRUE if the write was successful, or #FALSE if there was an
- * error.
+ * Returns: %TRUE on success, or %FALSE on error
  **/
 gboolean
 rsvg_handle_write (RsvgHandle * handle, const guchar * buf, gsize count, GError ** error)
 {
+    RsvgHandlePrivate *priv;
+
     rsvg_return_val_if_fail (handle, FALSE, error);
-    rsvg_return_val_if_fail (!handle->priv->is_closed, FALSE, error);
+    priv = handle->priv;
 
-    if (handle->priv->first_write) {
-        handle->priv->first_write = FALSE;
+    rsvg_return_val_if_fail (!priv->is_closed, FALSE, error);
+
+    if (priv->first_write) {
+        priv->first_write = FALSE;
 
         /* test for GZ marker. todo: store the first 2 bytes in the odd circumstance that someone calls
          * write() in 1 byte increments */
         if ((count >= 2) && (buf[0] == (guchar) 0x1f) && (buf[1] == (guchar) 0x8b)) {
-            handle->priv->is_gzipped = TRUE;
-
-#ifdef HAVE_SVGZ
-            handle->priv->gzipped_data = GSF_OUTPUT (gsf_output_memory_new ());
+#if GLIB_CHECK_VERSION (2, 24, 0)
+            priv->data_input_stream = g_memory_input_stream_new ();
+#elif defined (HAVE_GSF)
+            priv->gzipped_data = GSF_OUTPUT (gsf_output_memory_new ());
+#else
+            g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                                 "GZip compressed SVG not supported");
+            return FALSE;
 #endif
         }
     }
 
-    if (handle->priv->is_gzipped) {
-#ifdef HAVE_SVGZ
+#if GLIB_CHECK_VERSION (2, 24, 0)
+    if (priv->data_input_stream) {
+        g_memory_input_stream_add_data ((GMemoryInputStream *) priv->data_input_stream,
+                                        g_memdup (buf, count), count, (GDestroyNotify) g_free);
+        return TRUE;
+    }
+#elif defined (HAVE_GSF)
+    if (priv->gzipped_data)
         return gsf_output_write (handle->priv->gzipped_data, count, buf);
-#else
-        return FALSE;
 #endif
-    }
 
     return rsvg_handle_write_impl (handle, buf, count, error);
 }
 
 /**
  * rsvg_handle_close:
- * @handle: A #RsvgHandle
- * @error: A #GError
+ * @handle: a #RsvgHandle
+ * @error: (allow-none): a location to store a #GError, or %NULL
  *
  * Closes @handle, to indicate that loading the image is complete.  This will
- * return #TRUE if the loader closed successfully.  Note that @handle isn't
+ * return %TRUE if the loader closed successfully.  Note that @handle isn't
  * freed until @g_object_unref is called.
  *
- * Returns: #TRUE if the loader closed successfully, or #FALSE if there was
- * an error.
+ * Returns: %TRUE on success, or %FALSE on error
  **/
 gboolean
 rsvg_handle_close (RsvgHandle * handle, GError ** error)
 {
+    RsvgHandlePrivate *priv;
+    gboolean ret;
+
     rsvg_return_val_if_fail (handle, FALSE, error);
+    priv = handle->priv;
+
+    if (priv->is_closed)
+          return TRUE;
 
-	if (handle->priv->is_closed)
-		return TRUE;
+#if GLIB_CHECK_VERSION (2, 24, 0)
+    if (priv->data_input_stream) {
+        GConverter *converter;
+        GInputStream *stream;
 
-#if HAVE_SVGZ
-    if (handle->priv->is_gzipped) {
+        converter = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
+        stream = g_converter_input_stream_new (priv->data_input_stream, converter);
+        g_object_unref (converter);
+        g_object_unref (priv->data_input_stream);
+        priv->data_input_stream = NULL;
+
+        ret = rsvg_handle_read_stream_sync (handle, stream, NULL, error);
+        g_object_unref (stream);
+
+        return ret;
+    }
+#elif defined(HAVE_GSF)
+    if (priv->gzipped_data) {
         GsfInput *gzip;
         const guchar *bytes;
         gsize size;
         gsize remaining;
 
-        bytes = gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (handle->priv->gzipped_data));
-        size = gsf_output_size (handle->priv->gzipped_data);
+        bytes = gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (priv->gzipped_data));
+        size = gsf_output_size (priv->gzipped_data);
 
         gzip =
             GSF_INPUT (gsf_input_gzip_new
@@ -1784,9 +1814,11 @@ rsvg_handle_close (RsvgHandle * handle, GError ** error)
         g_object_unref (gzip);
 
         /* close parent */
-        gsf_output_close (handle->priv->gzipped_data);
+        gsf_output_close (priv->gzipped_data);
+        g_object_unref (priv->gzipped_data);
+        priv->gzipped_data = NULL;
     }
-#endif
+#endif /* GIO >= 2.24.0 */
 
     return rsvg_handle_close_impl (handle, error);
 }
@@ -1978,7 +2010,7 @@ rsvg_init (void)
 {
     g_type_init ();
 
-#ifdef HAVE_SVGZ
+#ifdef HAVE_GSF
     gsf_init ();
 #endif
 
@@ -1994,7 +2026,7 @@ rsvg_init (void)
 void
 rsvg_term (void)
 {
-#ifdef HAVE_SVGZ
+#ifdef HAVE_GSF
     gsf_shutdown ();
 #endif
 
diff --git a/rsvg-gobject.c b/rsvg-gobject.c
index 358f690..37bbde2 100644
--- a/rsvg-gobject.c
+++ b/rsvg-gobject.c
@@ -21,6 +21,8 @@
    Boston, MA 02111-1307, USA.
 */
 
+#include "config.h"
+
 #include "rsvg-private.h"
 #include "rsvg-defs.h"
 
@@ -64,6 +66,11 @@ instance_init (RsvgHandle * self)
     self->priv->treebase = NULL;
 
     self->priv->finished = 0;
+#if GLIB_CHECK_VERSION (2, 24, 0)
+    self->priv->data_input_stream = NULL;
+#elif defined(HAVE_GSF)
+    self->priv->gzipped_data = NULL;
+#endif
     self->priv->first_write = TRUE;
 
     self->priv->is_disposed = FALSE;
@@ -96,11 +103,6 @@ instance_dispose (GObject * instance)
 
     self->priv->is_disposed = TRUE;
 
-#if HAVE_SVGZ
-    if (self->priv->is_gzipped)
-        g_object_unref (self->priv->gzipped_data);
-#endif
-
     g_hash_table_foreach (self->priv->entities, rsvg_ctx_free_helper, NULL);
     g_hash_table_destroy (self->priv->entities);
     rsvg_defs_free (self->priv->defs);
@@ -120,10 +122,17 @@ instance_dispose (GObject * instance)
 
     g_free (self->priv);
 
+#if GLIB_CHECK_VERSION (2, 24, 0)
     if (self->priv->base_gfile) {
         g_object_unref (self->priv->base_gfile);
         self->priv->base_gfile = NULL;
     }
+#elif defined(HAVE_GSF)
+    if (self->priv->gzipped_data) {
+        g_object_unref (self->priv->gzipped_data);
+        self->priv->gzipped_data = NULL;
+    }
+#endif
 
     rsvg_parent_class->dispose (instance);
 }
diff --git a/rsvg-private.h b/rsvg-private.h
index d18b922..85bd7ac 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -166,10 +166,14 @@ struct RsvgHandlePrivate {
 
     gboolean finished;
 
+    gboolean in_loop;		/* see get_dimension() */
+
     gboolean first_write;
-    gboolean is_gzipped;
+#if GLIB_CHECK_VERSION (2, 24, 0)
+    GInputStream *data_input_stream; /* for rsvg_handle_write of svgz data */
+#elif defined(HAVE_GSF)
     void *gzipped_data;         /* really a GsfOutput */
-    gboolean in_loop;		/* see get_dimension() */
+#endif
 };
 
 typedef struct {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]