diff options
author | Federico Mena Quintero <federico@gnome.org> | 2018-07-30 21:10:41 -0700 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2018-07-30 21:10:41 -0700 |
commit | 340a2635f36f510ad833f6ca34f29f89d21451f3 (patch) | |
tree | 7a1359afbe880e6ad552b3d4744ea71ac91fe412 /librsvg | |
parent | 0133a6964a02eeaf55dba320c8b513890691d0fd (diff) | |
parent | 184c10cbe2c3562152954b7a81399dca2dc834e8 (diff) | |
download | librsvg-340a2635f36f510ad833f6ca34f29f89d21451f3.tar.gz |
Merge branch 'pborelli/librsvg-cleanup'
Diffstat (limited to 'librsvg')
-rw-r--r-- | librsvg/rsvg-base-file-util.c | 129 | ||||
-rw-r--r-- | librsvg/rsvg-base.c | 346 | ||||
-rw-r--r-- | librsvg/rsvg-handle.c | 449 | ||||
-rw-r--r-- | librsvg/rsvg-pixbuf.c (renamed from librsvg/rsvg-file-util.c) | 39 | ||||
-rw-r--r-- | librsvg/rsvg-private.h | 9 |
5 files changed, 448 insertions, 524 deletions
diff --git a/librsvg/rsvg-base-file-util.c b/librsvg/rsvg-base-file-util.c deleted file mode 100644 index 6b2aca14..00000000 --- a/librsvg/rsvg-base-file-util.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: set sw=4 sts=4 expandtab: */ -/* - rsvg-file-util.c: SAX-based renderer for SVG files into a GdkPixbuf. - - Copyright (C) 2000 Eazel, Inc. - Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com> - - 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. - - Author: Raph Levien <raph@artofcode.com> -*/ - -#include "config.h" -#include "rsvg-private.h" -#include "rsvg-io.h" - -static gboolean -rsvg_handle_fill_with_data (RsvgHandle * handle, - const char * data, gsize data_len, GError ** error) -{ - gboolean rv; - - rsvg_return_val_if_fail (data != NULL, FALSE, error); - rsvg_return_val_if_fail (data_len != 0, FALSE, error); - - rv = rsvg_handle_write (handle, (guchar *) data, data_len, error); - - return rsvg_handle_close (handle, rv ? error : NULL) && rv; -} - -/** - * rsvg_handle_new_from_data: - * @data: (array length=data_len): The SVG data - * @data_len: The length of @data, in bytes - * @error: return location for errors - * - * Loads the SVG specified by @data. - * - * Returns: A #RsvgHandle or %NULL if an error occurs. - * Since: 2.14 - */ -RsvgHandle * -rsvg_handle_new_from_data (const guint8 * data, gsize data_len, GError ** error) -{ - RsvgHandle *handle; - - handle = rsvg_handle_new (); - - if (handle) { - if (!rsvg_handle_fill_with_data (handle, (char *) data, data_len, error)) { - g_object_unref (handle); - handle = NULL; - } - } - - return handle; -} - -/** - * rsvg_handle_new_from_file: - * @file_name: The file name to load. If built with gnome-vfs, can be a URI. - * @error: return location for errors - * - * Loads the SVG specified by @file_name. - * - * Returns: A #RsvgHandle or %NULL if an error occurs. - * Since: 2.14 - */ -RsvgHandle * -rsvg_handle_new_from_file (const gchar * file_name, GError ** error) -{ - gchar *base_uri; - char *data; - gsize data_len; - RsvgHandle *handle = NULL; - GFile *file; - char *scheme; - - rsvg_return_val_if_fail (file_name != NULL, NULL, error); - - scheme = g_uri_parse_scheme (file_name); - if (scheme) { - file = g_file_new_for_uri (file_name); - g_free (scheme); - } else { - file = g_file_new_for_path (file_name); - } - - base_uri = g_file_get_uri (file); - if (!base_uri) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Cannot obtain URI from '%s'"), file_name); - g_object_unref (file); - return NULL; - } - - data = _rsvg_io_acquire_data (base_uri, base_uri, NULL, &data_len, NULL, error); - - if (data) { - handle = rsvg_handle_new (); - 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_free (data); - } - - g_free (base_uri); - g_object_unref (file); - - return handle; -} diff --git a/librsvg/rsvg-base.c b/librsvg/rsvg-base.c index 920bc04b..df770c85 100644 --- a/librsvg/rsvg-base.c +++ b/librsvg/rsvg-base.c @@ -31,7 +31,6 @@ #include "rsvg-css.h" #include "rsvg-styles.h" #include "rsvg-io.h" -#include "rsvg-load.h" #include <gio/gio.h> @@ -146,142 +145,6 @@ rsvg_set_default_dpi_x_y (double dpi_x, double dpi_y) } /** - * rsvg_handle_write: - * @handle: an #RsvgHandle - * @buf: (array length=count) (element-type guchar): pointer to svg data - * @count: length of the @buf buffer in bytes - * @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 #RsvgError domain. Errors - * from #GIOErrorEnum are also possible. - * - * 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); - priv = handle->priv; - - rsvg_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START - || priv->hstate == RSVG_HANDLE_STATE_LOADING, - FALSE, - error); - - if (priv->hstate == RSVG_HANDLE_STATE_START) { - priv->hstate = RSVG_HANDLE_STATE_LOADING; - priv->load = rsvg_load_new (handle, (priv->flags & RSVG_HANDLE_FLAG_UNLIMITED) != 0); - } - - g_assert (priv->hstate == RSVG_HANDLE_STATE_LOADING); - - return rsvg_load_write (priv->load, buf, count, error); -} - -static gboolean -finish_load (RsvgHandle *handle, gboolean was_successful) -{ - RsvgNode *treebase = rsvg_load_destroy (handle->priv->load); - handle->priv->load = NULL; - - if (was_successful) { - handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_OK; - handle->priv->treebase = treebase; - } else { - handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_ERROR; - treebase = rsvg_node_unref (treebase); - } - - return was_successful; -} - -/** - * rsvg_handle_close: - * @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 - * freed until @g_object_unref is called. - * - * Returns: %TRUE on success, or %FALSE on error - **/ -gboolean -rsvg_handle_close (RsvgHandle *handle, GError **error) -{ - RsvgHandlePrivate *priv; - gboolean result; - - rsvg_return_val_if_fail (handle, FALSE, error); - priv = handle->priv; - - if (priv->hstate == RSVG_HANDLE_STATE_CLOSED_OK - || priv->hstate == RSVG_HANDLE_STATE_CLOSED_ERROR) { - /* closing is idempotent */ - return TRUE; - } - - result = finish_load (handle, rsvg_load_close (priv->load, error)); - - return result; -} - -/** - * rsvg_handle_read_stream_sync: - * @handle: a #RsvgHandle - * @stream: a #GInputStream - * @cancellable: (allow-none): a #GCancellable, or %NULL - * @error: (allow-none): a location to store a #GError, or %NULL - * - * Reads @stream and writes the data from it to @handle. - * - * If @cancellable is not %NULL, then the operation can be cancelled by - * triggering the cancellable object from another thread. If the - * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be - * returned. - * - * Returns: %TRUE if reading @stream succeeded, or %FALSE otherwise - * with @error filled in - * - * Since: 2.32 - */ -gboolean -rsvg_handle_read_stream_sync (RsvgHandle *handle, - GInputStream *stream, - GCancellable *cancellable, - GError **error) -{ - RsvgHandlePrivate *priv; - gboolean result; - RsvgLoad *saved_load; - - g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE); - g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE); - g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - priv = handle->priv; - - g_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START, FALSE); - - priv->hstate = RSVG_HANDLE_STATE_LOADING; - - saved_load = priv->load; - - priv->load = rsvg_load_new (handle, (priv->flags & RSVG_HANDLE_FLAG_UNLIMITED) != 0); - result = finish_load (handle, rsvg_load_read_stream_sync (priv->load, stream, cancellable, error)); - - priv->load = saved_load; - - return result; -} - -/** * rsvg_init: * * This function does nothing. @@ -321,138 +184,12 @@ rsvg_cleanup (void) xmlCleanupParser (); } -cairo_surface_t * -rsvg_cairo_surface_new_from_href (RsvgHandle *handle, - const char *href, - GError **error) -{ - char *data; - gsize data_len; - char *mime_type = NULL; - GdkPixbufLoader *loader = NULL; - GdkPixbuf *pixbuf = NULL; - cairo_surface_t *surface = NULL; - - data = _rsvg_handle_acquire_data (handle, href, &mime_type, &data_len, error); - if (data == NULL) - return NULL; - - if (mime_type) { - loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, error); - } else { - loader = gdk_pixbuf_loader_new (); - } - - if (loader == NULL) - goto out; - - if (!gdk_pixbuf_loader_write (loader, (guchar *) data, data_len, error)) { - gdk_pixbuf_loader_close (loader, NULL); - goto out; - } - - if (!gdk_pixbuf_loader_close (loader, error)) - goto out; - - pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - - if (!pixbuf) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_FAILED, - _("Failed to load image '%s': reason not known, probably a corrupt image file"), - href); - goto out; - } - - surface = rsvg_cairo_surface_from_pixbuf (pixbuf); - - if (mime_type == NULL) { - /* Try to get the information from the loader */ - GdkPixbufFormat *format; - char **mime_types; - - if ((format = gdk_pixbuf_loader_get_format (loader)) != NULL) { - mime_types = gdk_pixbuf_format_get_mime_types (format); - - if (mime_types != NULL) - mime_type = g_strdup (mime_types[0]); - g_strfreev (mime_types); - } - } - - if ((handle->priv->flags & RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA) != 0 && - mime_type != NULL && - cairo_surface_set_mime_data (surface, mime_type, (guchar *) data, - data_len, g_free, data) == CAIRO_STATUS_SUCCESS) { - data = NULL; /* transferred to the surface */ - } - - out: - if (loader) - g_object_unref (loader); - g_free (mime_type); - g_free (data); - - return surface; -} - void rsvg_return_if_fail_warning (const char *pretty_function, const char *expression, GError ** error) { g_set_error (error, RSVG_ERROR, 0, _("%s: assertion `%s' failed"), pretty_function, expression); } -#ifdef HAVE_PANGOFT2 - -static void -create_font_config_for_testing (RsvgHandle *handle) -{ - const char *font_paths[] = { - "resources/Roboto-Regular.ttf", - "resources/Roboto-Italic.ttf", - "resources/Roboto-Bold.ttf", - "resources/Roboto-BoldItalic.ttf", - }; - - int i; - - if (handle->priv->font_config_for_testing != NULL) - return; - - handle->priv->font_config_for_testing = FcConfigCreate (); - - for (i = 0; i < G_N_ELEMENTS(font_paths); i++) { - char *font_path = g_test_build_filename (G_TEST_DIST, font_paths[i], NULL); - - if (!FcConfigAppFontAddFile (handle->priv->font_config_for_testing, (const FcChar8 *) font_path)) { - g_error ("Could not load font file \"%s\" for tests; aborting", font_path); - } - - g_free (font_path); - } -} - -#endif - -void -rsvg_handle_update_font_map_for_testing (RsvgHandle *handle) -{ -#ifdef HAVE_PANGOFT2 - if (handle->priv->is_testing) { - create_font_config_for_testing (handle); - - if (handle->priv->font_map_for_testing == NULL) { - handle->priv->font_map_for_testing = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT); - pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (handle->priv->font_map_for_testing), - handle->priv->font_config_for_testing); - - pango_cairo_font_map_set_default (PANGO_CAIRO_FONT_MAP (handle->priv->font_map_for_testing)); - } - } -#endif -} - gboolean rsvg_allow_load (GFile *base_gfile, const char *uri, @@ -534,86 +271,3 @@ rsvg_allow_load (GFile *base_gfile, "File may not link to URI \"%s\"", uri); return FALSE; } - -char * -rsvg_handle_resolve_uri (RsvgHandle *handle, - const char *uri) -{ - RsvgHandlePrivate *priv = handle->priv; - char *scheme, *resolved_uri; - GFile *base, *resolved; - - if (uri == NULL) - return NULL; - - scheme = g_uri_parse_scheme (uri); - if (scheme != NULL || - priv->base_gfile == NULL || - (base = g_file_get_parent (priv->base_gfile)) == NULL) { - g_free (scheme); - return g_strdup (uri); - } - - resolved = g_file_resolve_relative_path (base, uri); - resolved_uri = g_file_get_uri (resolved); - - g_free (scheme); - g_object_unref (base); - g_object_unref (resolved); - - return resolved_uri; -} - -char * -_rsvg_handle_acquire_data (RsvgHandle *handle, - const char *url, - char **content_type, - gsize *len, - GError **error) -{ - RsvgHandlePrivate *priv = handle->priv; - char *uri; - char *data; - - uri = rsvg_handle_resolve_uri (handle, url); - - if (rsvg_allow_load (priv->base_gfile, uri, error)) { - data = _rsvg_io_acquire_data (uri, - rsvg_handle_get_base_uri (handle), - content_type, - len, - handle->priv->cancellable, - error); - } else { - data = NULL; - } - - g_free (uri); - return data; -} - -GInputStream * -_rsvg_handle_acquire_stream (RsvgHandle *handle, - const char *url, - char **content_type, - GError **error) -{ - RsvgHandlePrivate *priv = handle->priv; - char *uri; - GInputStream *stream; - - uri = rsvg_handle_resolve_uri (handle, url); - - if (rsvg_allow_load (priv->base_gfile, uri, error)) { - stream = _rsvg_io_acquire_stream (uri, - rsvg_handle_get_base_uri (handle), - content_type, - handle->priv->cancellable, - error); - } else { - stream = NULL; - } - - g_free (uri); - return stream; -} diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c index f2802ac6..01af7762 100644 --- a/librsvg/rsvg-handle.c +++ b/librsvg/rsvg-handle.c @@ -120,6 +120,8 @@ #include "config.h" #include <string.h> +#include "rsvg-io.h" +#include "rsvg-load.h" #include "rsvg-private.h" enum { @@ -425,6 +427,107 @@ rsvg_handle_new (void) return RSVG_HANDLE (g_object_new (RSVG_TYPE_HANDLE, NULL)); } +static gboolean +rsvg_handle_fill_with_data (RsvgHandle *handle, + const char *data, + gsize data_len, + GError ** error) +{ + gboolean rv; + + rsvg_return_val_if_fail (data != NULL, FALSE, error); + rsvg_return_val_if_fail (data_len != 0, FALSE, error); + + rv = rsvg_handle_write (handle, (guchar *) data, data_len, error); + + return rsvg_handle_close (handle, rv ? error : NULL) && rv; +} + +/** + * rsvg_handle_new_from_data: + * @data: (array length=data_len): The SVG data + * @data_len: The length of @data, in bytes + * @error: return location for errors + * + * Loads the SVG specified by @data. + * + * Returns: A #RsvgHandle or %NULL if an error occurs. + * Since: 2.14 + */ +RsvgHandle * +rsvg_handle_new_from_data (const guint8 *data, gsize data_len, GError **error) +{ + RsvgHandle *handle; + + handle = rsvg_handle_new (); + + if (handle) { + if (!rsvg_handle_fill_with_data (handle, (char *) data, data_len, error)) { + g_object_unref (handle); + handle = NULL; + } + } + + return handle; +} + +/** + * rsvg_handle_new_from_file: + * @file_name: The file name to load. If built with gnome-vfs, can be a URI. + * @error: return location for errors + * + * Loads the SVG specified by @file_name. + * + * Returns: A #RsvgHandle or %NULL if an error occurs. + * Since: 2.14 + */ +RsvgHandle * +rsvg_handle_new_from_file (const gchar *file_name, GError **error) +{ + gchar *base_uri; + char *data; + gsize data_len; + RsvgHandle *handle = NULL; + GFile *file; + char *scheme; + + rsvg_return_val_if_fail (file_name != NULL, NULL, error); + + scheme = g_uri_parse_scheme (file_name); + if (scheme) { + file = g_file_new_for_uri (file_name); + g_free (scheme); + } else { + file = g_file_new_for_path (file_name); + } + + base_uri = g_file_get_uri (file); + if (!base_uri) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Cannot obtain URI from '%s'"), file_name); + g_object_unref (file); + return NULL; + } + + data = _rsvg_io_acquire_data (base_uri, base_uri, NULL, &data_len, NULL, error); + + if (data) { + handle = rsvg_handle_new (); + 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_free (data); + } + + g_free (base_uri); + g_object_unref (file); + + return handle; +} /** * rsvg_handle_new_with_flags: @@ -532,6 +635,142 @@ rsvg_handle_new_from_stream_sync (GInputStream *input_stream, return handle; } +/** + * rsvg_handle_write: + * @handle: an #RsvgHandle + * @buf: (array length=count) (element-type guchar): pointer to svg data + * @count: length of the @buf buffer in bytes + * @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 #RsvgError domain. Errors + * from #GIOErrorEnum are also possible. + * + * 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); + priv = handle->priv; + + rsvg_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START + || priv->hstate == RSVG_HANDLE_STATE_LOADING, + FALSE, + error); + + if (priv->hstate == RSVG_HANDLE_STATE_START) { + priv->hstate = RSVG_HANDLE_STATE_LOADING; + priv->load = rsvg_load_new (handle, (priv->flags & RSVG_HANDLE_FLAG_UNLIMITED) != 0); + } + + g_assert (priv->hstate == RSVG_HANDLE_STATE_LOADING); + + return rsvg_load_write (priv->load, buf, count, error); +} + +static gboolean +finish_load (RsvgHandle *handle, gboolean was_successful) +{ + RsvgNode *treebase = rsvg_load_destroy (handle->priv->load); + handle->priv->load = NULL; + + if (was_successful) { + handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_OK; + handle->priv->treebase = treebase; + } else { + handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_ERROR; + treebase = rsvg_node_unref (treebase); + } + + return was_successful; +} + +/** + * rsvg_handle_close: + * @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 + * freed until @g_object_unref is called. + * + * Returns: %TRUE on success, or %FALSE on error + **/ +gboolean +rsvg_handle_close (RsvgHandle *handle, GError **error) +{ + RsvgHandlePrivate *priv; + gboolean result; + + rsvg_return_val_if_fail (handle, FALSE, error); + priv = handle->priv; + + if (priv->hstate == RSVG_HANDLE_STATE_CLOSED_OK + || priv->hstate == RSVG_HANDLE_STATE_CLOSED_ERROR) { + /* closing is idempotent */ + return TRUE; + } + + result = finish_load (handle, rsvg_load_close (priv->load, error)); + + return result; +} + +/** + * rsvg_handle_read_stream_sync: + * @handle: a #RsvgHandle + * @stream: a #GInputStream + * @cancellable: (allow-none): a #GCancellable, or %NULL + * @error: (allow-none): a location to store a #GError, or %NULL + * + * Reads @stream and writes the data from it to @handle. + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the + * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be + * returned. + * + * Returns: %TRUE if reading @stream succeeded, or %FALSE otherwise + * with @error filled in + * + * Since: 2.32 + */ +gboolean +rsvg_handle_read_stream_sync (RsvgHandle *handle, + GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + RsvgHandlePrivate *priv; + gboolean result; + RsvgLoad *saved_load; + + g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE); + g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + priv = handle->priv; + + g_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START, FALSE); + + priv->hstate = RSVG_HANDLE_STATE_LOADING; + + saved_load = priv->load; + + priv->load = rsvg_load_new (handle, (priv->flags & RSVG_HANDLE_FLAG_UNLIMITED) != 0); + result = finish_load (handle, rsvg_load_read_stream_sync (priv->load, stream, cancellable, error)); + + priv->load = saved_load; + + return result; +} + /* http://www.ietf.org/rfc/rfc2396.txt */ static gboolean @@ -771,7 +1010,6 @@ rsvg_handle_create_drawing_ctx(RsvgHandle *handle, handle->priv->dpi_x, handle->priv->dpi_y, handle->priv->defs, handle->priv->is_testing); - } /** @@ -1256,6 +1494,215 @@ rsvg_handle_set_size_callback (RsvgHandle * handle, handle->priv->user_data_destroy = user_data_destroy; } +char * +rsvg_handle_resolve_uri (RsvgHandle *handle, + const char *uri) +{ + RsvgHandlePrivate *priv = handle->priv; + char *scheme, *resolved_uri; + GFile *base, *resolved; + + if (uri == NULL) + return NULL; + + scheme = g_uri_parse_scheme (uri); + if (scheme != NULL || + priv->base_gfile == NULL || + (base = g_file_get_parent (priv->base_gfile)) == NULL) { + g_free (scheme); + return g_strdup (uri); + } + + resolved = g_file_resolve_relative_path (base, uri); + resolved_uri = g_file_get_uri (resolved); + + g_free (scheme); + g_object_unref (base); + g_object_unref (resolved); + + return resolved_uri; +} + +char * +_rsvg_handle_acquire_data (RsvgHandle *handle, + const char *url, + char **content_type, + gsize *len, + GError **error) +{ + RsvgHandlePrivate *priv = handle->priv; + char *uri; + char *data; + + uri = rsvg_handle_resolve_uri (handle, url); + + if (rsvg_allow_load (priv->base_gfile, uri, error)) { + data = _rsvg_io_acquire_data (uri, + rsvg_handle_get_base_uri (handle), + content_type, + len, + handle->priv->cancellable, + error); + } else { + data = NULL; + } + + g_free (uri); + return data; +} + +GInputStream * +_rsvg_handle_acquire_stream (RsvgHandle *handle, + const char *url, + char **content_type, + GError **error) +{ + RsvgHandlePrivate *priv = handle->priv; + char *uri; + GInputStream *stream; + + uri = rsvg_handle_resolve_uri (handle, url); + + if (rsvg_allow_load (priv->base_gfile, uri, error)) { + stream = _rsvg_io_acquire_stream (uri, + rsvg_handle_get_base_uri (handle), + content_type, + handle->priv->cancellable, + error); + } else { + stream = NULL; + } + + g_free (uri); + return stream; +} + +cairo_surface_t * +rsvg_cairo_surface_new_from_href (RsvgHandle *handle, + const char *href, + GError **error) +{ + char *data; + gsize data_len; + char *mime_type = NULL; + GdkPixbufLoader *loader = NULL; + GdkPixbuf *pixbuf = NULL; + cairo_surface_t *surface = NULL; + + data = _rsvg_handle_acquire_data (handle, href, &mime_type, &data_len, error); + if (data == NULL) + return NULL; + + if (mime_type) { + loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, error); + } else { + loader = gdk_pixbuf_loader_new (); + } + + if (loader == NULL) + goto out; + + if (!gdk_pixbuf_loader_write (loader, (guchar *) data, data_len, error)) { + gdk_pixbuf_loader_close (loader, NULL); + goto out; + } + + if (!gdk_pixbuf_loader_close (loader, error)) + goto out; + + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + + if (!pixbuf) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_FAILED, + _("Failed to load image '%s': reason not known, probably a corrupt image file"), + href); + goto out; + } + + surface = rsvg_cairo_surface_from_pixbuf (pixbuf); + + if (mime_type == NULL) { + /* Try to get the information from the loader */ + GdkPixbufFormat *format; + char **mime_types; + + if ((format = gdk_pixbuf_loader_get_format (loader)) != NULL) { + mime_types = gdk_pixbuf_format_get_mime_types (format); + + if (mime_types != NULL) + mime_type = g_strdup (mime_types[0]); + g_strfreev (mime_types); + } + } + + if ((handle->priv->flags & RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA) != 0 && + mime_type != NULL && + cairo_surface_set_mime_data (surface, mime_type, (guchar *) data, + data_len, g_free, data) == CAIRO_STATUS_SUCCESS) { + data = NULL; /* transferred to the surface */ + } + + out: + if (loader) + g_object_unref (loader); + g_free (mime_type); + g_free (data); + + return surface; +} + +#ifdef HAVE_PANGOFT2 + +static void +create_font_config_for_testing (RsvgHandle *handle) +{ + const char *font_paths[] = { + "resources/Roboto-Regular.ttf", + "resources/Roboto-Italic.ttf", + "resources/Roboto-Bold.ttf", + "resources/Roboto-BoldItalic.ttf", + }; + + int i; + + if (handle->priv->font_config_for_testing != NULL) + return; + + handle->priv->font_config_for_testing = FcConfigCreate (); + + for (i = 0; i < G_N_ELEMENTS(font_paths); i++) { + char *font_path = g_test_build_filename (G_TEST_DIST, font_paths[i], NULL); + + if (!FcConfigAppFontAddFile (handle->priv->font_config_for_testing, (const FcChar8 *) font_path)) { + g_error ("Could not load font file \"%s\" for tests; aborting", font_path); + } + + g_free (font_path); + } +} + +#endif + +static void +rsvg_handle_update_font_map_for_testing (RsvgHandle *handle) +{ +#ifdef HAVE_PANGOFT2 + if (handle->priv->is_testing) { + create_font_config_for_testing (handle); + + if (handle->priv->font_map_for_testing == NULL) { + handle->priv->font_map_for_testing = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT); + pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (handle->priv->font_map_for_testing), + handle->priv->font_config_for_testing); + + pango_cairo_font_map_set_default (PANGO_CAIRO_FONT_MAP (handle->priv->font_map_for_testing)); + } + } +#endif +} + /** * _rsvg_handle_internal_set_testing: * @handle: a #RsvgHandle diff --git a/librsvg/rsvg-file-util.c b/librsvg/rsvg-pixbuf.c index 47eeec58..198a5642 100644 --- a/librsvg/rsvg-file-util.c +++ b/librsvg/rsvg-pixbuf.c @@ -42,45 +42,6 @@ #include <stdio.h> #include <stdlib.h> -#define SVG_BUFFER_SIZE (1024 * 8) - -/* private */ -GdkPixbuf * -rsvg_pixbuf_from_data_with_size_data (const guchar * buff, - size_t len, - /* RsvgSizeCallbackData */ gpointer data, - const char *base_uri, GError ** error) -{ - RsvgHandle *handle; - GdkPixbuf *retval; - - handle = rsvg_handle_new (); - - if (!handle) { - g_set_error (error, rsvg_error_quark (), 0, _("Error creating SVG reader")); - return NULL; - } - - rsvg_handle_set_size_callback (handle, _rsvg_size_callback, data, NULL); - rsvg_handle_set_base_uri (handle, base_uri); - - if (!rsvg_handle_write (handle, buff, len, error)) { - (void) rsvg_handle_close (handle, NULL); - g_object_unref (handle); - return NULL; - } - - if (!rsvg_handle_close (handle, error)) { - g_object_unref (handle); - return NULL; - } - - retval = rsvg_handle_get_pixbuf (handle); - g_object_unref (handle); - - return retval; -} - static GdkPixbuf * rsvg_pixbuf_from_stdio_file_with_size_data (const char *data, gsize data_len, diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h index 1d4269e9..c33f69f1 100644 --- a/librsvg/rsvg-private.h +++ b/librsvg/rsvg-private.h @@ -325,12 +325,6 @@ gboolean rsvg_property_bag_iter_next (RsvgPropertyBagIter *iter, G_GNUC_INTERNAL void rsvg_property_bag_iter_end (RsvgPropertyBagIter *iter); -/* for some reason this one's public... */ -GdkPixbuf *rsvg_pixbuf_from_data_with_size_data (const guchar * buff, - size_t len, - gpointer data, - const char *base_uri, GError ** error); - /* Implemented in rust/src/cond.rs */ G_GNUC_INTERNAL gboolean rsvg_cond_check_required_features (const char *value); @@ -418,9 +412,6 @@ RsvgHandle *rsvg_handle_load_extern (RsvgHandle *handle, const char *uri); G_GNUC_INTERNAL -void rsvg_handle_update_font_map_for_testing (RsvgHandle *handle); - -G_GNUC_INTERNAL gboolean rsvg_allow_load (GFile *base_gfile, const char *uri, GError **error); |