[aisleriot] Support compressed SVG files
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aisleriot] Support compressed SVG files
- Date: Tue, 26 Apr 2011 20:36:43 +0000 (UTC)
commit 1de6550ead1837c63e8980197c0e3169229bf8d1
Author: Christian Persch <chpe gnome org>
Date: Tue Apr 26 21:50:06 2011 +0200
Support compressed SVG files
Make ArSvg inherit RsvgHandle, implement GInitable, and support
SVGZ files.
src/lib/Makefile.am | 1 -
src/lib/ar-card-theme-kde.c | 28 +++---
src/lib/ar-card-theme-preimage.c | 4 +-
src/lib/ar-card-theme-svg.c | 1 -
src/lib/ar-svg-private.h | 32 ------
src/lib/ar-svg.c | 198 ++++++++++++++++++++++++++++----------
src/lib/ar-svg.h | 35 ++++---
7 files changed, 184 insertions(+), 115 deletions(-)
---
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index f6529e4..dfdea2e 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -50,7 +50,6 @@ if HAVE_RSVG
libaisleriot_la_SOURCES += \
ar-svg.c \
ar-svg.h \
- ar-svg-private.h \
ar-card-theme-preimage.c \
$(NULL)
diff --git a/src/lib/ar-card-theme-kde.c b/src/lib/ar-card-theme-kde.c
index 7abf22a..38bff97 100644
--- a/src/lib/ar-card-theme-kde.c
+++ b/src/lib/ar-card-theme-kde.c
@@ -29,7 +29,6 @@
#include "ar-debug.h"
#include "ar-profile.h"
#include "ar-svg.h"
-#include "ar-svg-private.h"
#include "ar-runtime.h"
#include "ar-string-utils.h"
@@ -205,7 +204,7 @@ ar_card_theme_kde_get_card_extents (ArCardThemeKDE *theme,
surface = cairo_recording_surface_create (CAIRO_CONTENT_ALPHA, NULL);
cr = cairo_create (surface);
ar_profilestart ("getting ink extents for node %s", node);
- rsvg_handle_render_cairo_sub (svg->rsvg_handle, cr, node);
+ rsvg_handle_render_cairo_sub (RSVG_HANDLE (svg), cr, node);
ar_profileend ("getting ink extents for node %s", node);
cairo_destroy (cr);
@@ -242,6 +241,7 @@ ar_card_theme_kde_load (ArCardTheme *card_theme,
};
ArCardThemeKDE *theme = (ArCardThemeKDE *) card_theme;
ArSvg *svg;
+ RsvgHandle *rsvg_handle;
char node[32];
guint i;
gboolean has_red_joker, has_black_joker, has_joker;
@@ -250,24 +250,25 @@ ar_card_theme_kde_load (ArCardTheme *card_theme,
return FALSE;
svg = ((ArCardThemePreimage *) theme)->cards_svg;
+ rsvg_handle = RSVG_HANDLE (svg);
/* Check available backs */
g_assert (theme->n_backs == 0);
ar_card_get_node_by_id_snprintf (node, sizeof (node), AR_CARD_BACK);
- if (rsvg_handle_has_sub (svg->rsvg_handle, node)) {
+ if (rsvg_handle_has_sub (rsvg_handle, node)) {
theme->backs[theme->n_backs++] = g_strdup (node);
}
for (i = 0; i < G_N_ELEMENTS (extra_backs); ++i) {
- if (rsvg_handle_has_sub (svg->rsvg_handle, extra_backs[i])) {
+ if (rsvg_handle_has_sub (rsvg_handle, extra_backs[i])) {
theme->backs[theme->n_backs++] = g_strdup (extra_backs[i]);
}
}
for (i = 1; i < 10; ++i) {
g_snprintf (node, sizeof (node), "#back_c%d", i);
- if (rsvg_handle_has_sub (svg->rsvg_handle, node)) {
+ if (rsvg_handle_has_sub (rsvg_handle, node)) {
theme->backs[theme->n_backs++] = g_strdup (node);
}
}
@@ -281,11 +282,11 @@ ar_card_theme_kde_load (ArCardTheme *card_theme,
/* Look for the jokers */
ar_card_get_node_by_id_snprintf (node, sizeof (node), AR_CARD_BLACK_JOKER);
- has_black_joker = rsvg_handle_has_sub (svg->rsvg_handle, node);
+ has_black_joker = rsvg_handle_has_sub (rsvg_handle, node);
ar_card_get_node_by_id_snprintf (node, sizeof (node), AR_CARD_RED_JOKER);
- has_red_joker = rsvg_handle_has_sub (svg->rsvg_handle, node);
+ has_red_joker = rsvg_handle_has_sub (rsvg_handle, node);
- has_joker = rsvg_handle_has_sub (svg->rsvg_handle, "#joker");
+ has_joker = rsvg_handle_has_sub (rsvg_handle, "#joker");
theme->has_2_jokers = has_red_joker && has_black_joker;
theme->has_joker = has_joker;
@@ -323,6 +324,7 @@ ar_card_theme_kde_paint_card (ArCardTheme *card_theme,
char node[32];
cairo_rectangle_t *card_extents;
cairo_matrix_t matrix;
+ cairo_font_options_t *font_options;
if (G_UNLIKELY (card_id == AR_CARD_SLOT)) {
ar_svg_render_cairo (preimage_card_theme->slot_preimage,
@@ -340,10 +342,10 @@ ar_card_theme_kde_paint_card (ArCardTheme *card_theme,
cairo_save (cr);
- if (svg->font_options) {
- cairo_set_antialias (cr, cairo_font_options_get_antialias (svg->font_options));
-
- cairo_set_font_options (cr, svg->font_options);
+ font_options = ar_svg_get_font_options (svg);
+ if (font_options) {
+ cairo_set_antialias (cr, cairo_font_options_get_antialias (font_options));
+ cairo_set_font_options (cr, font_options);
}
cairo_matrix_init_identity (&matrix);
@@ -354,7 +356,7 @@ ar_card_theme_kde_paint_card (ArCardTheme *card_theme,
cairo_set_matrix (cr, &matrix);
- rsvg_handle_render_cairo_sub (svg->rsvg_handle, cr, node);
+ rsvg_handle_render_cairo_sub (RSVG_HANDLE (svg), cr, node);
cairo_restore (cr);
}
diff --git a/src/lib/ar-card-theme-preimage.c b/src/lib/ar-card-theme-preimage.c
index 279b77d..8056706 100644
--- a/src/lib/ar-card-theme-preimage.c
+++ b/src/lib/ar-card-theme-preimage.c
@@ -68,7 +68,7 @@ ar_card_theme_preimage_load (ArCardTheme *card_theme,
/* FIXMEchpe: use uninstalled data dir for rendering the card theme! */
slot_dir = ar_runtime_get_directory (AR_RUNTIME_PIXMAP_DIRECTORY);
path = g_build_filename (slot_dir, "slot.svg", NULL);
- theme->slot_preimage = ar_svg_new_from_file (path, error);
+ theme->slot_preimage = ar_svg_new_from_filename_sync (path, NULL, error);
g_free (path);
if (!theme->slot_preimage)
return FALSE;
@@ -76,7 +76,7 @@ ar_card_theme_preimage_load (ArCardTheme *card_theme,
/* Now the main course */
path = g_build_filename (theme_info->path, theme_info->filename, NULL);
- theme->cards_svg = ar_svg_new_from_file (path, error);
+ theme->cards_svg = ar_svg_new_from_filename_sync (path, NULL, error);
g_free (path);
if (!theme->cards_svg)
return FALSE;
diff --git a/src/lib/ar-card-theme-svg.c b/src/lib/ar-card-theme-svg.c
index 5aaebf0..b7ad3f6 100644
--- a/src/lib/ar-card-theme-svg.c
+++ b/src/lib/ar-card-theme-svg.c
@@ -26,7 +26,6 @@
#include <gtk/gtk.h>
#include "ar-svg.h"
-#include "ar-svg-private.h"
#include "ar-runtime.h"
#include "ar-string-utils.h"
diff --git a/src/lib/ar-svg.c b/src/lib/ar-svg.c
index 4fff3fc..0a6748b 100644
--- a/src/lib/ar-svg.c
+++ b/src/lib/ar-svg.c
@@ -1,6 +1,6 @@
/*
Copyright © 2004 Richard Hoelscher
- Copyright © 2007 Christian Persch
+ Copyright © 2007, 2011 Christian Persch
This library is free software; you can redistribute it and'or modify
it under the terms of the GNU Library General Public License as published
@@ -37,16 +37,29 @@
#include "ar-profile.h"
#include "ar-svg.h"
-#include "ar-svg-private.h"
+
+struct _ArSvgClass {
+ RsvgHandleClass parent_class;
+};
+
+struct _ArSvg {
+ RsvgHandle parent_instance;
+
+ cairo_font_options_t *font_options;
+ GFile *file;
+
+ gint width;
+ gint height;
+};
enum {
PROP_0,
- PROP_FILENAME
+ PROP_FILE
};
static void ar_svg_initable_iface_init (GInitableIface *iface);
-G_DEFINE_TYPE_WITH_CODE (ArSvg, ar_svg, G_TYPE_OBJECT,
+G_DEFINE_TYPE_WITH_CODE (ArSvg, ar_svg, RSVG_TYPE_HANDLE,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, ar_svg_initable_iface_init))
static void
@@ -62,21 +75,56 @@ ar_svg_initable_init (GInitable *initable,
GError **error)
{
ArSvg *svg = AR_SVG (initable);
+ RsvgHandle *handle = RSVG_HANDLE (initable);
+ GFileInfo *info;
+ const char *type;
+ char *gz_type;
+ GInputStream *stream;
RsvgDimensionData data;
+ gboolean is_gzip;
gboolean retval = FALSE;
- ar_profilestart ("creating ArSvg from %s", svg->filename);
+// ar_profilestart ("creating ArSvg from %s", svg->filename);
- svg->rsvg_handle = rsvg_handle_new_from_file (svg->filename, error);
- if (svg->rsvg_handle == NULL)
+ if (!(info = g_file_query_info (svg->file,
+ G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ error)))
goto out;
- rsvg_handle_get_dimensions (svg->rsvg_handle, &data);
+ type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
+ gz_type = g_content_type_from_mime_type ("application/x-gzip");
+ is_gzip = (type != NULL && g_content_type_is_a (type, gz_type));
+ g_free (gz_type);
+ g_object_unref (info);
+
+ if (!(stream = G_INPUT_STREAM (g_file_read (svg->file, cancellable, error))))
+ goto out;
+ if (is_gzip) {
+ GZlibDecompressor *decompressor;
+ GInputStream *converter_stream;
+
+ decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
+ converter_stream = g_converter_input_stream_new (stream,
+ G_CONVERTER (decompressor));
+ g_object_unref (stream);
+ stream = converter_stream;
+ }
+
+ if (!rsvg_handle_read_stream_sync (handle, stream, cancellable, error)) {
+ g_object_unref (stream);
+ goto out;
+ }
+ g_object_unref (stream);
+
+ rsvg_handle_get_dimensions (handle, &data);
if (data.width == 0 || data.height == 0) {
- g_set_error (error,
- GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_FAILED, "Image has zero extent");
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ "Image has zero extent");
goto out;
}
@@ -86,7 +134,8 @@ ar_svg_initable_init (GInitable *initable,
retval = TRUE;
out:
- ar_profileend ("creating ArSvg from %s", svg->filename);
+
+// ar_profileend ("creating ArSvg from %s", svg->filename);
return retval;
}
@@ -95,9 +144,8 @@ ar_svg_finalize (GObject * object)
{
ArSvg *svg = AR_SVG (object);
- if (svg->rsvg_handle != NULL) {
- g_object_unref (svg->rsvg_handle);
- }
+ if (svg->file)
+ g_object_unref (svg->file);
if (svg->font_options) {
cairo_font_options_destroy (svg->font_options);
}
@@ -114,8 +162,10 @@ ar_svg_set_property (GObject *object,
ArSvg *svg = AR_SVG (object);
switch (property_id) {
- case PROP_FILENAME:
- svg->filename = g_value_dup_string (value);
+ case PROP_FILE:
+ svg->file = g_value_dup_object (value);
+ if (svg->file)
+ rsvg_handle_set_base_gfile (RSVG_HANDLE (svg), svg->file);
break;
default:
@@ -133,9 +183,9 @@ ar_svg_class_init (ArSvgClass * klass)
g_object_class_install_property
(object_class,
- PROP_FILENAME,
- g_param_spec_string ("filename", NULL, NULL,
- NULL,
+ PROP_FILE,
+ g_param_spec_object ("file", NULL, NULL,
+ G_TYPE_FILE,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
@@ -151,13 +201,12 @@ ar_svg_initable_iface_init (GInitableIface *iface)
/**
* ar_svg_render_cairo:
- * @preimage:
- * @cr:
+ * @svg: a #ArSvg
+ * @cr: a #cairo_t
* @width: the desired width
* @height: the desired height
*
- * Renders from @preimage's image at the specified
- * @width and @height to @cr.
+ * Paints the SVG at the specified @width and @height to @cr.
**/
void
ar_svg_render_cairo (ArSvg *svg,
@@ -181,9 +230,9 @@ ar_svg_render_cairo (ArSvg *svg,
/**
* ar_svg_render_cairo_sub:
- * @preimage:
- * @cr:
- * @node: a SVG node ID (starting with "#"), or %NULL
+ * @svg: a #ArSvg
+ * @cr: a #cairo_t
+ * @node: (allow-none): a SVG node ID (starting with "#"), or %NULL
* @width: the width of the clip region
* @height: the height of the clip region
* @xoffset: the x offset of the clip region
@@ -191,14 +240,10 @@ ar_svg_render_cairo (ArSvg *svg,
* @xzoom: the x zoom factor
* @yzoom: the y zoom factor
*
- * Creates a #GdkPixbuf with the dimensions @width by @height,
- * and renders the subimage of @preimage specified by @node to it,
- * transformed by @xzoom, @yzoom and offset by @xoffset and @yoffset,
- * clipped to @width and @height.
- * If @node is NULL, the whole image is rendered into tha clip region.
+ * Paints the SVG element @node to @cr, transformed by @xzoom, @yzoom
+ * and offset by @xoffset and @yoffset, clipped to @width and @height.
*
- * Returns: %TRUE, of %FALSE if there was an error or @preimage
- * isn't a scalable SVG image
+ * If @node is NULL, the whole image is rendered into tha clip region.
**/
void
ar_svg_render_cairo_sub (ArSvg *svg,
@@ -227,37 +272,88 @@ ar_svg_render_cairo_sub (ArSvg *svg,
cairo_set_matrix (cr, &matrix);
- rsvg_handle_render_cairo_sub (svg->rsvg_handle, cr, node);
+ rsvg_handle_render_cairo_sub (RSVG_HANDLE (svg), cr, node);
}
/**
- * ar_svg_new_from_file:
- * @filename:
- * @error: a location for a #GError
+ * ar_svg_new_from_gfile_sync:
+ * @file: a #GFile
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a location to store a #GError, or %NULL
*
- * Creates a new #ArSvg from the image in @filename.
+ * Creates a new #ArSvg and synchronously loads its contents from @file.
*
- * Returns: (allow-none): a new #ArSvg, or %NULL if there was an error
+ * Returns: (allow-none): a new #ArSvg, or %NULL on error with @error
+ * filled in
*/
ArSvg *
-ar_svg_new_from_file (const gchar * filename, GError ** error)
+ar_svg_new_from_gfile_sync (GFile *file,
+ GCancellable *cancellable,
+ GError ** error)
{
- g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
return g_initable_new (AR_TYPE_SVG,
- NULL,
+ cancellable,
error,
- "filename", filename,
+ "file", file,
NULL);
}
/**
+ * ar_svg_new_from_filename:
+ * @filename: the path to the SVG file
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a location to store a #GError, or %NULL
+ *
+ * Creates a new #ArSvg and synchronously loads its contents from @filename.
+ *
+ * Returns: (allow-none): a new #ArSvg, or %NULL on error with @error
+ * filled in
+ */
+ArSvg *
+ar_svg_new_from_filename_sync (const char *filename,
+ GCancellable *cancellable,
+ GError ** error)
+{
+ GFile *file;
+ ArSvg *svg;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ file = g_file_new_for_path (filename);
+ svg = ar_svg_new_from_gfile_sync (file, cancellable, error);
+ g_object_unref (file);
+
+ return svg;
+}
+
+/**
+ * ar_svg_get_font_options:
+ * @svg: a #ArSvg
+ *
+ * Returns the font options set in @svg.
+ *
+ * Retursn: (transfer none): a #cairo_font_options_t, or %NULL
+ */
+cairo_font_options_t *
+ar_svg_get_font_options (ArSvg *svg)
+{
+ g_return_val_if_fail (AR_IS_SVG (svg), NULL);
+
+ return svg->font_options;
+}
+
+/**
* ar_svg_set_font_options:
- * @preimage: a #ArSvg
- * @font_options: the font options
+ * @svg: a #ArSvg
+ * @font_options: (allow-none): a #cairo_font_options_t, or %NULL
*
- * Turns on antialising of @preimage, if it contains an SVG image.
+ * Sets font options to use when painting to cairo using
+ * ar_svg_render_cairo_sub(). Use %NULL to unset previously set
+ * font options.
*/
void
ar_svg_set_font_options (ArSvg *svg,
@@ -278,9 +374,9 @@ ar_svg_set_font_options (ArSvg *svg,
/**
* ar_svg_get_width:
- * @preimage:
+ * @svg: a #ArSvg
*
- * Returns: the natural width of the image in @preimage
+ * Returns: the natural width of the image in @svg
*/
gint
ar_svg_get_width (ArSvg *svg)
@@ -292,9 +388,9 @@ ar_svg_get_width (ArSvg *svg)
/**
* ar_svg_get_height:
- * @preimage:
+ * @svg: a #ArSvg
*
- * Returns: the natural height of the image in @preimage
+ * Returns: the natural height of the image in @svg
*/
gint
ar_svg_get_height (ArSvg *svg)
diff --git a/src/lib/ar-svg.h b/src/lib/ar-svg.h
index 562b473..90c1bac 100644
--- a/src/lib/ar-svg.h
+++ b/src/lib/ar-svg.h
@@ -1,5 +1,6 @@
/*
Copyright © 2004 Richard Hoelscher
+ Copyright © 2011 Christian Persch
This library is free software; you can redistribute it and'or modify
it under the terms of the GNU Library General Public License as published
@@ -22,9 +23,9 @@
#ifndef AR_SVG_H
#define AR_SVG_H
-#include <glib.h>
+#include <gio/gio.h>
#include <cairo.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <librsvg/rsvg.h>
G_BEGIN_DECLS
@@ -35,28 +36,32 @@ G_BEGIN_DECLS
#define AR_IS_SVG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AR_TYPE_SVG))
#define AR_GET_SVG_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AR_TYPE_SVG, ArSvgClass))
-typedef struct _ArSvg ArSvg;
-
-typedef struct {
- GObjectClass parent_class;
-} ArSvgClass;
+typedef struct _ArSvg ArSvg;
+typedef struct _ArSvgClass ArSvgClass;
GType ar_svg_get_type (void);
ArSvg *ar_svg_new (void);
-ArSvg *ar_svg_new_from_file (const gchar * filename,
- GError ** error);
+ArSvg *ar_svg_new_from_gfile_sync (GFile *file,
+ GCancellable *cancellable,
+ GError ** error);
+
+ArSvg *ar_svg_new_from_filename_sync (const gchar * filename,
+ GCancellable *cancellable,
+ GError ** error);
+
+cairo_font_options_t *ar_svg_get_font_options (ArSvg *svg);
-void ar_svg_set_font_options (ArSvg * preimage,
- const cairo_font_options_t *font_options);
+void ar_svg_set_font_options (ArSvg *svg,
+ const cairo_font_options_t *font_options);
-void ar_svg_render_cairo (ArSvg * preimage,
+void ar_svg_render_cairo (ArSvg *svg,
cairo_t *cr,
gint width,
gint height);
-void ar_svg_render_cairo_sub (ArSvg * preimage,
+void ar_svg_render_cairo_sub (ArSvg *svg,
cairo_t *cr,
const char *node,
int width,
@@ -66,9 +71,9 @@ void ar_svg_render_cairo_sub (ArSvg * preimage,
double xzoom,
double yzoom);
-gint ar_svg_get_width (ArSvg * preimage);
+gint ar_svg_get_width (ArSvg *svg);
-gint ar_svg_get_height (ArSvg * preimage);
+gint ar_svg_get_height (ArSvg *svg);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]