Use GZlibDecompressor for SVGZ support

On gio >= 2.24, use GZlibDecompressor for SVGZ. Otherwise use libgsf.

Bug #621699.
parent 9aa2584d
......@@ -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
......@@ -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
......
......@@ -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);
}
......
......@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment