[librsvg] Split IO handling to rsvg-io.[ch]



commit 1291ebc3a5cb8addfa97aa56365f15e2427beb22
Author: Christian Persch <chpe gnome org>
Date:   Thu Jan 12 22:13:02 2012 +0100

    Split IO handling to rsvg-io.[ch]
    
    Add rsvg-io.[ch], move the code there, clean it up, and adapt the callers.

 Makefile.am           |    2 +
 rsvg-base-file-util.c |   20 ++--
 rsvg-base.c           |  155 ++++++++++++++++++++--------------
 rsvg-defs.c           |   12 ++-
 rsvg-file-util.c      |   28 ++++---
 rsvg-image.c          |  156 ++--------------------------------
 rsvg-io.c             |  225 +++++++++++++++++++++++++++++++++++++++++++++++++
 rsvg-io.h             |   38 ++++++++
 rsvg-private.h        |    3 -
 rsvg-styles.c         |   33 ++++----
 rsvg-styles.h         |    1 -
 11 files changed, 417 insertions(+), 256 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index e53d569..7c69839 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,8 @@ librsvg_ RSVG_API_MAJOR_VERSION@_la_SOURCES = \
 	rsvg-defs.h 		\
 	rsvg-image.c		\
 	rsvg-image.h		\
+	rsvg-io.c		\
+	rsvg-io.h		\
 	rsvg-paint-server.c 	\
 	rsvg-paint-server.h 	\
 	rsvg-path.c 		\
diff --git a/rsvg-base-file-util.c b/rsvg-base-file-util.c
index 902c436..2c9eae1 100644
--- a/rsvg-base-file-util.c
+++ b/rsvg-base-file-util.c
@@ -26,6 +26,7 @@
 
 #include "config.h"
 #include "rsvg.h"
+#include "rsvg-io.h"
 #include "rsvg-private.h"
 
 static gboolean
@@ -85,24 +86,23 @@ RsvgHandle *
 rsvg_handle_new_from_file (const gchar * file_name, GError ** error)
 {
     gchar *base_uri;
-    GByteArray *f;
+    guint8 *data;
+    gsize data_len;
     RsvgHandle *handle = NULL;
 
     rsvg_return_val_if_fail (file_name != NULL, NULL, error);
 
     base_uri = rsvg_get_base_uri_from_filename (file_name);
-    f = _rsvg_acquire_xlink_href_resource (file_name, base_uri, error);
+    data = _rsvg_io_acquire_data (file_name, base_uri, &data_len, error);
 
-    if (f) {
+    if (data) {
         handle = rsvg_handle_new ();
-        if (handle) {
-            rsvg_handle_set_base_uri (handle, base_uri);
-            if (!rsvg_handle_fill_with_data (handle, f->data, f->len, error)) {
-                g_object_unref (handle);
-                handle = NULL;
-            }
+        rsvg_handle_set_base_uri (handle, base_uri);
+        if (!rsvg_handle_fill_with_data (handle, data, data_len, error)) {
+            g_object_unref (handle);
+            handle = NULL;
         }
-        g_byte_array_free (f, TRUE);
+        g_free (data);
     }
 
     g_free (base_uri);
diff --git a/rsvg-base.c b/rsvg-base.c
index 3dce61c..1b2c20b 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -33,6 +33,7 @@
 #include "rsvg-shapes.h"
 #include "rsvg-structure.h"
 #include "rsvg-image.h"
+#include "rsvg-io.h"
 #include "rsvg-text.h"
 #include "rsvg-filter.h"
 #include "rsvg-mask.h"
@@ -524,57 +525,81 @@ static void
 rsvg_start_xinclude (RsvgHandle * ctx, RsvgPropertyBag * atts)
 {
     RsvgSaxHandlerXinclude *handler;
-    GByteArray *data;
-    const char *href;
+    const char *href, *parse;
     gboolean success = FALSE;
 
     href = rsvg_property_bag_lookup (atts, "href");
-    if (href) {
-        data = _rsvg_acquire_xlink_href_resource (href, rsvg_handle_get_base_uri (ctx), NULL);
-        if (data) {
-            const char *parse;
-
-            parse = rsvg_property_bag_lookup (atts, "parse");
-            if (parse && !strcmp (parse, "text")) {
-                const char *encoding;
-                char *text_data;
-                gsize text_data_len;
-                gboolean text_data_needs_free = FALSE;
-
-                encoding = rsvg_property_bag_lookup (atts, "encoding");
-                if (encoding) {
-                    text_data =
-                        g_convert ((const char *) data->data, data->len, "utf-8", encoding, NULL,
+    if (href == NULL)
+        goto fallback;
+
+    parse = rsvg_property_bag_lookup (atts, "parse");
+    if (parse && !strcmp (parse, "text")) {
+        guint8 *data;
+        gsize data_len;
+        const char *encoding;
+
+        data = _rsvg_io_acquire_data (href, rsvg_handle_get_base_uri (ctx), &data_len, NULL);
+        if (data == NULL)
+            goto fallback;
+
+        encoding = rsvg_property_bag_lookup (atts, "encoding");
+        if (encoding && g_ascii_strcasecmp (encoding, "UTF-8") != 0) {
+            char *text_data;
+            gsize text_data_len;
+
+            text_data = g_convert (data, data_len, "utf-8", encoding, NULL,
                                    &text_data_len, NULL);
-                    text_data_needs_free = TRUE;
-                } else {
-                    text_data = (char *) data->data;
-                    text_data_len = data->len;
-                }
+            g_free (data);
 
-                rsvg_characters_impl (ctx, (const xmlChar *) text_data, text_data_len);
+            data = text_data;
+            data_len = text_data_len;
+        }
 
-                if (text_data_needs_free)
-                    g_free (text_data);
-            } else {
-                /* xml */
-                xmlDocPtr xml_doc;
-                xmlParserCtxtPtr xml_parser;
+        rsvg_characters_impl (ctx, (const xmlChar *) data, data_len);
 
-                xml_parser = xmlCreatePushParserCtxt (&rsvgSAXHandlerStruct, ctx, NULL, 0, NULL);
-                (void) xmlParseChunk (xml_parser, (char *) data->data, data->len, 0);
-                (void) xmlParseChunk (xml_parser, "", 0, TRUE);
+        g_free (data);
+    } else {
+        /* xml */
+        GInputStream *stream;
+        GError *err = NULL;
+        xmlDocPtr xml_doc;
+        xmlParserCtxtPtr xml_parser;
+        xmlParserInputBufferPtr buffer;
+        xmlParserInputPtr input;
+        int result;
 
-                xml_doc = xml_parser->myDoc;
-                xmlFreeParserCtxt (xml_parser);
-                xmlFreeDoc (xml_doc);
-            }
+        stream = _rsvg_io_acquire_stream (href, rsvg_handle_get_base_uri (ctx), NULL);
+        if (stream == NULL)
+            goto fallback;
 
-            g_byte_array_free (data, TRUE);
-            success = TRUE;
+        xml_parser = xmlCreatePushParserCtxt (&rsvgSAXHandlerStruct, ctx, NULL, 0, NULL);
+
+        buffer = _rsvg_xml_input_buffer_new_from_stream (stream, NULL /* cancellable */, XML_CHAR_ENCODING_NONE, &err);
+        g_object_unref (stream);
+
+        input = xmlNewIOInputStream (xml_parser, buffer /* adopts */, XML_CHAR_ENCODING_NONE);
+
+        if (xmlPushInput (xml_parser, input) < 0) {
+            g_clear_error (&err);
+            xmlFreeInputStream (input);
+            xmlFreeParserCtxt (xml_parser);
+            goto fallback;
         }
+
+        (void) xmlParseDocument (xml_parser);
+
+        xml_doc = xml_parser->myDoc;
+        xmlFreeParserCtxt (xml_parser);
+        if (xml_doc)
+            xmlFreeDoc (xml_doc);
+
+        g_clear_error (&err);
     }
 
+    success = TRUE;
+
+  fallback:
+
     /* needed to handle xi:fallback */
     handler = g_new0 (RsvgSaxHandlerXinclude, 1);
 
@@ -776,20 +801,25 @@ rsvg_entity_decl (void *data, const xmlChar * name, int type,
         resolvedPublicId = xmlBuildRelativeURI (publicId, (xmlChar*) rsvg_handle_get_base_uri (ctx));
 
     if (type == XML_EXTERNAL_PARAMETER_ENTITY && !content) {
-      GByteArray *arr = NULL;
-
-      if (systemId)
-        arr = _rsvg_acquire_xlink_href_resource ((const char *) systemId,
-                                                 rsvg_handle_get_base_uri (ctx), NULL);
-      else if (publicId)
-        arr = _rsvg_acquire_xlink_href_resource ((const char *) publicId,
-                                                 rsvg_handle_get_base_uri (ctx), NULL);
-      if (arr) {
-        content = xmlCharStrndup ((const char*)arr->data, arr->len);
-        g_byte_array_free(arr, TRUE);
-      }
+        guint8 *entity_data;
+        gsize entity_data_len;
+
+        if (systemId)
+            entity_data = _rsvg_io_acquire_data ((const char *) systemId,
+                                                 rsvg_handle_get_base_uri (ctx),
+                                                 &entity_data_len,
+                                                 NULL);
+        else if (publicId)
+            entity_data = _rsvg_io_acquire_data ((const char *) publicId,
+                                                 rsvg_handle_get_base_uri (ctx),
+                                                 &entity_data_len,
+                                                 NULL);
+        if (entity_data) {
+            content = xmlCharStrndup (entity_data, entity_data_len);
+            g_free (entity_data);
+        }
     }
-      
+
     entity = xmlNewEntity(NULL, name, type, resolvedPublicId, resolvedSystemId, content);
 
     xmlFree(resolvedPublicId);
@@ -852,15 +882,16 @@ rsvg_processing_instruction (void *ctx, const xmlChar * target, const xmlChar *
                 if (value && strcmp (value, "text/css") == 0) {
                     value = rsvg_property_bag_lookup (atts, "href");
                     if (value && value[0]) {
-                        GByteArray *style;
-
-                        style =
-                            _rsvg_acquire_xlink_href_resource (value,
-                                                               rsvg_handle_get_base_uri (handle),
-                                                               NULL);
-                        if (style) {
-                            rsvg_parse_cssbuffer (handle, (char *) style->data, style->len);
-                            g_byte_array_free (style, TRUE);
+                        guint8 *style_data;
+                        gsize style_data_len;
+
+                        style_data = _rsvg_io_acquire_data (value,
+                                                            rsvg_handle_get_base_uri (handle),
+                                                            &style_data_len,
+                                                            NULL);
+                        if (style_data) {
+                            rsvg_parse_cssbuffer (handle, (char *) style_data, style_data_len);
+                            g_free (style_data);
                         }
                     }
                 }
diff --git a/rsvg-defs.c b/rsvg-defs.c
index 18176f9..0c3df9f 100644
--- a/rsvg-defs.c
+++ b/rsvg-defs.c
@@ -28,6 +28,7 @@
 #include "rsvg-defs.h"
 #include "rsvg-styles.h"
 #include "rsvg-image.h"
+#include "rsvg-io.h"
 
 #include <glib.h>
 
@@ -72,25 +73,26 @@ rsvg_defs_load_extern (const RsvgDefs * defs, const char *name)
 {
     RsvgHandle *handle;
     gchar *filename, *base_uri;
-    GByteArray *chars;
+    guint8 *data;
+    gsize data_len;
 
     filename = rsvg_get_file_path (name, defs->base_uri);
 
-    chars = _rsvg_acquire_xlink_href_resource (name, defs->base_uri, NULL);
+    data = _rsvg_io_acquire_data (name, defs->base_uri, &data_len, NULL);
 
-    if (chars) {
+    if (data) {
         handle = rsvg_handle_new ();
 
         base_uri = rsvg_get_base_uri_from_filename (filename);
         rsvg_handle_set_base_uri (handle, base_uri);
         g_free (base_uri);
 
-        if (rsvg_handle_write (handle, chars->data, chars->len, NULL) &&
+        if (rsvg_handle_write (handle, data, data_len, NULL) &&
             rsvg_handle_close (handle, NULL)) {
             g_hash_table_insert (defs->externs, g_strdup (name), handle);
         }
 
-        g_byte_array_free (chars, TRUE);
+        g_free (data);
     }
 
     g_free (filename);
diff --git a/rsvg-file-util.c b/rsvg-file-util.c
index a1b67b6..39cfe2b 100644
--- a/rsvg-file-util.c
+++ b/rsvg-file-util.c
@@ -36,6 +36,7 @@
 #include "config.h"
 #include "rsvg.h"
 #include "rsvg-private.h"
+#include "rsvg-io.h"
 
 #include <errno.h>
 #include <stdio.h>
@@ -157,9 +158,11 @@ rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
 }
 
 static GdkPixbuf *
-rsvg_pixbuf_from_stdio_file_with_size_data (GByteArray * f,
-                                            struct RsvgSizeCallbackData *data,
-                                            gchar * base_uri, GError ** error)
+rsvg_pixbuf_from_stdio_file_with_size_data (guint8 *data,
+                                            gsize data_len,
+                                            struct RsvgSizeCallbackData *cb_data,
+                                            gchar * base_uri, 
+                                            GError ** error)
 {
     RsvgHandle *handle;
     GdkPixbuf *retval;
@@ -171,10 +174,10 @@ rsvg_pixbuf_from_stdio_file_with_size_data (GByteArray * f,
         return NULL;
     }
 
-    rsvg_handle_set_size_callback (handle, _rsvg_size_callback, data, NULL);
+    rsvg_handle_set_size_callback (handle, _rsvg_size_callback, cb_data, NULL);
     rsvg_handle_set_base_uri (handle, base_uri);
 
-    if (!rsvg_handle_write (handle, f->data, f->len, error)) {
+    if (!rsvg_handle_write (handle, data, data_len, error)) {
         g_object_unref (handle);
         return NULL;
     }
@@ -192,17 +195,20 @@ rsvg_pixbuf_from_stdio_file_with_size_data (GByteArray * f,
 
 static GdkPixbuf *
 rsvg_pixbuf_from_file_with_size_data (const gchar * file_name,
-                                      struct RsvgSizeCallbackData *data, GError ** error)
+                                      struct RsvgSizeCallbackData *cb_data, 
+                                      GError ** error)
 {
     GdkPixbuf *pixbuf;
-    GByteArray *f;
+    guint8 *data;
+    gsize data_len;
     GString *base_uri = g_string_new (file_name);
 
-    f = _rsvg_acquire_xlink_href_resource (file_name, base_uri->str, error);
+    data = _rsvg_io_acquire_data (file_name, base_uri->str, &data_len, error);
 
-    if (f) {
-        pixbuf = rsvg_pixbuf_from_stdio_file_with_size_data (f, data, base_uri->str, error);
-        g_byte_array_free (f, TRUE);
+    if (data) {
+        pixbuf = rsvg_pixbuf_from_stdio_file_with_size_data (data, data_len,
+                                                             cb_data, base_uri->str, error);
+        g_free (data);
     } else {
         pixbuf = NULL;
     }
diff --git a/rsvg-image.c b/rsvg-image.c
index 0ccc7f6..9c4a3f9 100644
--- a/rsvg-image.c
+++ b/rsvg-image.c
@@ -34,170 +34,28 @@
 #include <math.h>
 #include <errno.h>
 #include "rsvg-css.h"
-#include <gio/gio.h>
-
-static GByteArray *
-rsvg_acquire_base64_resource (const char *data, GError ** error)
-{
-    GByteArray *array = NULL;
-    gsize data_len, written_len;
-    int state = 0;
-    guint save = 0;
-
-    rsvg_return_val_if_fail (data != NULL, NULL, error);
-
-    while (*data)
-        if (*data++ == ',')
-            break;
-
-    data_len = strlen (data);
-    array = g_byte_array_sized_new (data_len / 4 * 3);
-    written_len = g_base64_decode_step (data, data_len, array->data,
-                                        &state, &save);
-    g_byte_array_set_size (array, written_len);
-
-    return array;
-}
-
-gchar *
-rsvg_get_file_path (const gchar * filename, const gchar * base_uri)
-{
-    gchar *absolute_filename;
-
-    if (g_file_test (filename, G_FILE_TEST_EXISTS) || g_path_is_absolute (filename)) {
-        absolute_filename = g_strdup (filename);
-    } else {
-        gchar *tmpcdir;
-        gchar *base_filename;
-
-        if (base_uri) {
-            base_filename = g_filename_from_uri (base_uri, NULL, NULL);
-            if (base_filename != NULL) {
-                tmpcdir = g_path_get_dirname (base_filename);
-                g_free (base_filename);
-            } else 
-                return NULL;
-        } else
-            tmpcdir = g_get_current_dir ();
-
-        absolute_filename = g_build_filename (tmpcdir, filename, NULL);
-        g_free (tmpcdir);
-    }
-
-    return absolute_filename;
-}
-
-static GByteArray *
-rsvg_acquire_file_resource (const char *filename, const char *base_uri, GError ** error)
-{
-    GByteArray *array;
-    gchar *path;
-    gchar *data = NULL;
-    gsize length;
-
-    rsvg_return_val_if_fail (filename != NULL, NULL, error);
-
-    path = rsvg_get_file_path (filename, base_uri);
-    if (path == NULL)
-        return NULL;
-
-    if (!g_file_get_contents (path, &data, &length, error)) {
-        g_free (path);
-        return NULL;
-    }
-
-    array = g_byte_array_new ();
-
-    g_byte_array_append (array, (guint8 *)data, length);
-    g_free (data);
-    g_free (path);
-
-    return array;
-}
-
-static GByteArray *
-rsvg_acquire_vfs_resource (const char *filename, const char *base_uri, GError ** error)
-{
-    GByteArray *array;
-
-    GFile *file;
-    char *data;
-    gsize size;
-    gboolean res = FALSE;
-
-    rsvg_return_val_if_fail (filename != NULL, NULL, error);
-
-    file = g_file_new_for_uri (filename);
-
-    if (!(res = g_file_load_contents (file, NULL, &data, &size, NULL, error))) {
-        if (base_uri != NULL) {
-            GFile *base;
-
-            g_clear_error (error);
-
-            g_object_unref (file);
-
-            base = g_file_new_for_uri (base_uri);
-            file = g_file_resolve_relative_path (base, filename);
-            g_object_unref (base);
-
-            res = g_file_load_contents (file, NULL, &data, &size, NULL, error);
-        }
-    }
-
-    g_object_unref (file);
-
-    if (res) {
-        array = g_byte_array_new ();
-
-        g_byte_array_append (array, (guint8 *)data, size);
-        g_free (data);
-    } else {
-        return NULL;
-    }
-
-    return array;
-}
-
-GByteArray *
-_rsvg_acquire_xlink_href_resource (const char *href, const char *base_uri, GError ** err)
-{
-    GByteArray *arr = NULL;
-
-    if (!(href && *href))
-        return NULL;
-
-    if (!strncmp (href, "data:", 5))
-        arr = rsvg_acquire_base64_resource (href, NULL);
-
-    if (!arr)
-        arr = rsvg_acquire_file_resource (href, base_uri, NULL);
-
-    if (!arr)
-        arr = rsvg_acquire_vfs_resource (href, base_uri, NULL);
-
-    return arr;
-}
+#include "rsvg-io.h"
 
 cairo_surface_t *
 rsvg_cairo_surface_new_from_href (const char *href, 
                                   const char *base_uri, 
                                   GError **error)
 {
-    GByteArray *arr;
+    guint8 *data;
+    gsize data_len;
     GdkPixbufLoader *loader;
     GdkPixbuf *pixbuf = NULL;
     int res;
     cairo_surface_t *surface;
 
-    arr = _rsvg_acquire_xlink_href_resource (href, base_uri, error);
-    if (arr == NULL)
+    data = _rsvg_io_acquire_data (href, base_uri, &data_len, error);
+    if (data == NULL)
         return NULL;
 
     loader = gdk_pixbuf_loader_new ();
 
-    res = gdk_pixbuf_loader_write (loader, arr->data, arr->len, error);
-    g_byte_array_free (arr, TRUE);
+    res = gdk_pixbuf_loader_write (loader, data, data_len, error);
+    g_free (data);
 
     if (!res) {
         gdk_pixbuf_loader_close (loader, NULL);
diff --git a/rsvg-io.c b/rsvg-io.c
new file mode 100644
index 0000000..921d113
--- /dev/null
+++ b/rsvg-io.c
@@ -0,0 +1,225 @@
+/*
+   Copyright (C) 2000 Eazel, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Dom Lachowicz <cinamod hotmail com>
+   Copyright (C) 2003, 2004, 2005 Caleb Moore <c moore student unsw edu au>
+   Copyright  2011, 2012 Christian Persch
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#include "config.h"
+
+#include "rsvg-io.h"
+#include "rsvg-private.h"
+
+#include <string.h>
+
+static guint8 *
+rsvg_acquire_base64_data (const char *data, 
+                          const char *base_uri, 
+                          gsize *len,
+                          GError **error)
+{
+    guint8 *bytes;
+    gsize data_len, written_len;
+    int state = 0;
+    guint save = 0;
+
+    /* FIXME: be more correct! Check that is indeed a base64 data: URI */
+    while (*data)
+        if (*data++ == ',')
+            break;
+
+    data_len = strlen (data);
+    bytes = g_try_malloc (data_len / 4 * 3);
+    if (bytes == NULL)
+        return NULL;
+
+    written_len = g_base64_decode_step (data, data_len, bytes, &state, &save);
+
+    *len = written_len;
+
+    return bytes;
+}
+
+gchar *
+rsvg_get_file_path (const gchar * filename, const gchar * base_uri)
+{
+    gchar *absolute_filename;
+
+    if (g_file_test (filename, G_FILE_TEST_EXISTS) || g_path_is_absolute (filename)) {
+        absolute_filename = g_strdup (filename);
+    } else {
+        gchar *tmpcdir;
+        gchar *base_filename;
+
+        if (base_uri) {
+            base_filename = g_filename_from_uri (base_uri, NULL, NULL);
+            if (base_filename != NULL) {
+                tmpcdir = g_path_get_dirname (base_filename);
+                g_free (base_filename);
+            } else 
+                return NULL;
+        } else
+            tmpcdir = g_get_current_dir ();
+
+        absolute_filename = g_build_filename (tmpcdir, filename, NULL);
+        g_free (tmpcdir);
+    }
+
+    return absolute_filename;
+}
+
+static guint8 *
+rsvg_acquire_file_data (const char *filename,
+                        const char *base_uri,
+                        gsize *len,
+                        GError **error)
+{
+    GFile *file;
+    gchar *path, *data;
+    GInputStream *stream;
+
+    rsvg_return_val_if_fail (filename != NULL, NULL, error);
+
+    path = rsvg_get_file_path (filename, base_uri);
+    if (path == NULL)
+        return NULL;
+
+    if (!g_file_get_contents (path, &data, len, error))
+        return NULL;
+
+    return data;
+}
+
+static GInputStream *
+rsvg_acquire_gvfs_stream (const char *uri, 
+                          const char *base_uri, 
+                          GError **error)
+{
+    GFile *base, *file;
+    GInputStream *stream;
+    GError *err = NULL;
+    gchar *data;
+
+    file = g_file_new_for_uri (uri);
+
+    stream = (GInputStream *) g_file_read (file, NULL /* cancellable */, &err);
+    g_object_unref (file);
+
+    if (stream == NULL &&
+        g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+        g_clear_error (&err);
+
+        base = g_file_new_for_uri (base_uri);
+        file = g_file_resolve_relative_path (base, uri);
+        g_object_unref (base);
+
+        stream = (GInputStream *) g_file_read (file, NULL /* cancellable */, &err);
+        g_object_unref (file);
+    }
+
+    if (stream == NULL)
+        g_propagate_error (error, err);
+
+    return stream;
+}
+
+static guint8 *
+rsvg_acquire_gvfs_data (const char *uri, 
+                        const char *base_uri, 
+                        gsize *len,
+                        GError **error)
+{
+    GFile *base, *file;
+    GInputStream *stream;
+    GError *err;
+    gchar *data;
+    gboolean res;
+
+    file = g_file_new_for_uri (uri);
+
+    err = NULL;
+    data = NULL;
+    if (!(res = g_file_load_contents (file, NULL, &data, len, NULL, &err)) &&
+        g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
+        base_uri != NULL) {
+        g_clear_error (&err);
+
+        base = g_file_new_for_uri (base_uri);
+        file = g_file_resolve_relative_path (base, uri);
+        g_object_unref (base);
+
+        res = g_file_load_contents (file, NULL, &data, len, NULL, &err);
+    }
+
+    g_object_unref (file);
+
+    if (err == NULL)
+        return data;
+
+    g_propagate_error (error, err);
+    return NULL;
+}
+
+guint8 *
+_rsvg_io_acquire_data (const char *href, 
+                       const char *base_uri, 
+                       gsize *len,
+                       GError **error)
+{
+    guint8 *data;
+
+    if (!(href && *href))
+        return NULL;
+
+    if (strncmp (href, "data:", 5) == 0 &&
+        (data = rsvg_acquire_base64_data (href, NULL, len, error)))
+      return data;
+
+    if ((data = rsvg_acquire_file_data (href, base_uri, len, error)))
+      return data;
+
+    if ((data = rsvg_acquire_gvfs_data (href, base_uri, len, error)))
+      return data;
+
+    return NULL;
+}
+
+GInputStream *
+_rsvg_io_acquire_stream (const char *href, 
+                         const char *base_uri, 
+                         GError **error)
+{
+    GInputStream *stream;
+    guint8 *data;
+    gsize len;
+
+    if (!(href && *href))
+        return NULL;
+
+    if (strncmp (href, "data:", 5) == 0 &&
+        (data = rsvg_acquire_base64_data (href, NULL, &len, error)))
+      return g_memory_input_stream_new_from_data (data, len, (GDestroyNotify) g_free);
+
+    if ((data = rsvg_acquire_file_data (href, base_uri, &len, error)))
+      return g_memory_input_stream_new_from_data (data, len, (GDestroyNotify) g_free);
+
+    if ((stream = rsvg_acquire_gvfs_stream (href, base_uri, error)))
+      return stream;
+
+    return NULL;
+}
diff --git a/rsvg-io.h b/rsvg-io.h
new file mode 100644
index 0000000..be3db8c
--- /dev/null
+++ b/rsvg-io.h
@@ -0,0 +1,38 @@
+/*
+   Copyright (C) 2000 Eazel, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Dom Lachowicz <cinamod hotmail com>
+   Copyright (C) 2003, 2004, 2005 Caleb Moore <c moore student unsw edu au>
+   Copyright  2011, 2012 Christian Persch
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#ifndef RSVG_IO_H
+#define RSVG_IO_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+guint8* _rsvg_io_acquire_data (const char *uri,
+                               const char *base_uri,
+                               gsize *len,
+                               GError **error);
+
+GInputStream *_rsvg_io_acquire_stream (const char *uri,
+                                       const char *base_uri,
+                                       GError **error);
+
+#endif /* RSVG_IO_H */
diff --git a/rsvg-private.h b/rsvg-private.h
index 4e7fc73..eaaae2d 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -361,9 +361,6 @@ GdkPixbuf *rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
 gboolean     rsvg_eval_switch_attributes	(RsvgPropertyBag * atts, gboolean * p_has_cond);
 
 gchar       *rsvg_get_base_uri_from_filename    (const gchar * file_name);
-GByteArray  *_rsvg_acquire_xlink_href_resource  (const char *href,
-                                                 const char *base_uri, GError ** err);
-
 void rsvg_pop_discrete_layer    (RsvgDrawingCtx * ctx);
 void rsvg_push_discrete_layer   (RsvgDrawingCtx * ctx);
 void rsvg_render_path           (RsvgDrawingCtx * ctx, const cairo_path_t *path);
diff --git a/rsvg-styles.c b/rsvg-styles.c
index dead491..eed23e8 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -32,6 +32,7 @@
 #include "rsvg-private.h"
 #include "rsvg-filter.h"
 #include "rsvg-css.h"
+#include "rsvg-io.h"
 #include "rsvg-styles.h"
 #include "rsvg-shapes.h"
 #include "rsvg-mask.h"
@@ -1161,21 +1162,23 @@ ccss_import_style (CRDocHandler * a_this,
                    GList * a_media_list,
                    CRString * a_uri, CRString * a_uri_default_ns, CRParsingLocation * a_location)
 {
-    if (a_uri) {
-        GByteArray *stylesheet_data;
-        CSSUserData *user_data;
-
-        user_data = (CSSUserData *) a_this->app_data;
-
-        stylesheet_data =
-            _rsvg_acquire_xlink_href_resource ((gchar *) cr_string_peek_raw_str (a_uri),
-                                               rsvg_handle_get_base_uri (user_data->ctx), NULL);
-        if (stylesheet_data) {
-            rsvg_parse_cssbuffer (user_data->ctx, (const char *) stylesheet_data->data,
-                                  (size_t) stylesheet_data->len);
-            g_byte_array_free (stylesheet_data, TRUE);
-        }
-    }
+    CSSUserData *user_data = (CSSUserData *) a_this->app_data;
+    guint8 *stylesheet_data;
+    gsize stylesheet_data_len;
+
+    if (a_uri == NULL)
+        return;
+
+    stylesheet_data = _rsvg_io_acquire_data ((gchar *) cr_string_peek_raw_str (a_uri),
+                                             rsvg_handle_get_base_uri (user_data->ctx), 
+                                             &stylesheet_data_len,
+                                             NULL);
+    if (stylesheet_data == NULL)
+        return;
+
+    rsvg_parse_cssbuffer (user_data->ctx, (const char *) stylesheet_data,
+                          stylesheet_data_len);
+    g_free (stylesheet_data);
 }
 
 /* Parse an SVG transform string into an affine matrix. Reference: SVG
diff --git a/rsvg-styles.h b/rsvg-styles.h
index 87c36eb..22053f0 100644
--- a/rsvg-styles.h
+++ b/rsvg-styles.h
@@ -201,7 +201,6 @@ void rsvg_state_free_all    (RsvgState * state);
 void rsvg_parse_style_pairs (RsvgHandle * ctx, RsvgState * state, RsvgPropertyBag * atts);
 void rsvg_parse_style	    (RsvgHandle * ctx, RsvgState * state, const char *str);
 void rsvg_parse_cssbuffer   (RsvgHandle * ctx, const char *buff, size_t buflen);
-
 void rsvg_parse_style_attrs (RsvgHandle * ctx, RsvgState * state, const char *tag,
                              const char *klazz, const char *id, RsvgPropertyBag * atts);
 



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