rsvg-file-util.c 9.52 KB
Newer Older
1 2
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
   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>
*/

Christian Persch's avatar
Christian Persch committed
27 28 29 30 31 32 33 34 35
/**
 * SECTION: rsvg-pixbuf
 * @short_description: How to render SVGs into GdkPixbufs, for easy use in GTK+
 *  applications
 *
 * GdkPixbuf is a library for image loading and manipulation. It is part of the
 * cross-platform GTK+ widget toolkit.
 */

36
#include "config.h"
37
#include "rsvg-private.h"
38
#include "rsvg-io.h"
39
#include "rsvg-size-callback.h"
40

41 42 43 44 45 46 47 48 49
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#define SVG_BUFFER_SIZE (1024 * 8)

/* private */
GdkPixbuf *
rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
50
                                      size_t len,
51
                                      /* RsvgSizeCallbackData */ gpointer data,
52
                                      const char *base_uri, GError ** error)
53
{
54 55
    RsvgHandle *handle;
    GdkPixbuf *retval;
56

57
    handle = rsvg_handle_new ();
58

59 60 61 62
    if (!handle) {
        g_set_error (error, rsvg_error_quark (), 0, _("Error creating SVG reader"));
        return NULL;
    }
63

64 65
    rsvg_handle_set_size_callback (handle, _rsvg_size_callback, data, NULL);
    rsvg_handle_set_base_uri (handle, base_uri);
66

67
    if (!rsvg_handle_write (handle, buff, len, error)) {
68
        (void) rsvg_handle_close (handle, NULL);
69
        g_object_unref (handle);
70 71
        return NULL;
    }
72

73
    if (!rsvg_handle_close (handle, error)) {
74
        g_object_unref (handle);
75 76
        return NULL;
    }
77

78
    retval = rsvg_handle_get_pixbuf (handle);
79
    g_object_unref (handle);
80

81
    return retval;
82 83 84
}

static GdkPixbuf *
85
rsvg_pixbuf_from_stdio_file_with_size_data (const char *data,
86 87 88 89
                                            gsize data_len,
                                            struct RsvgSizeCallbackData *cb_data,
                                            gchar * base_uri, 
                                            GError ** error)
90
{
91 92
    RsvgHandle *handle;
    GdkPixbuf *retval;
93

94
    handle = rsvg_handle_new ();
95

96 97 98 99
    if (!handle) {
        g_set_error (error, rsvg_error_quark (), 0, _("Error creating SVG reader"));
        return NULL;
    }
100

101
    rsvg_handle_set_size_callback (handle, _rsvg_size_callback, cb_data, NULL);
102
    rsvg_handle_set_base_uri (handle, base_uri);
103

104
    if (!rsvg_handle_write (handle, (guchar *) data, data_len, error)) {
105
        (void) rsvg_handle_close (handle, NULL);
106
        g_object_unref (handle);
107 108
        return NULL;
    }
109

110
    if (!rsvg_handle_close (handle, error)) {
111
        g_object_unref (handle);
112 113
        return NULL;
    }
114

115
    retval = rsvg_handle_get_pixbuf (handle);
116
    g_object_unref (handle);
117

118
    return retval;
119 120
}

121 122
static GdkPixbuf *
rsvg_pixbuf_from_file_with_size_data (const gchar * file_name,
123 124
                                      struct RsvgSizeCallbackData *cb_data, 
                                      GError ** error)
125
{
126
    GdkPixbuf *pixbuf;
127
    char *data;
128
    gsize data_len;
129 130
    GString *base_uri = g_string_new (file_name);

131
    data = _rsvg_io_acquire_data (file_name, base_uri->str, NULL, &data_len, NULL, error);
132

133 134 135 136
    if (data) {
        pixbuf = rsvg_pixbuf_from_stdio_file_with_size_data (data, data_len,
                                                             cb_data, base_uri->str, error);
        g_free (data);
137 138 139 140 141 142 143
    } else {
        pixbuf = NULL;
    }

    g_string_free (base_uri, TRUE);

    return pixbuf;
144 145 146 147 148 149 150 151 152 153 154 155
}

/**
 * rsvg_pixbuf_from_file:
 * @file_name: A file name
 * @error: return location for errors
 * 
 * Loads a new #GdkPixbuf from @file_name and returns it.  The caller must
 * assume the reference to the reurned pixbuf. If an error occurred, @error is
 * set and %NULL is returned.
 * 
 * Return value: A newly allocated #GdkPixbuf, or %NULL
156
 * Deprecated: Set up a cairo matrix and use rsvg_handle_new_from_file() + rsvg_handle_render_cairo() instead.
157 158
 **/
GdkPixbuf *
159
rsvg_pixbuf_from_file (const gchar * file_name, GError ** error)
160
{
161
    return rsvg_pixbuf_from_file_at_size (file_name, -1, -1, error);
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
}

/**
 * rsvg_pixbuf_from_file_at_zoom:
 * @file_name: A file name
 * @x_zoom: The horizontal zoom factor
 * @y_zoom: The vertical zoom factor
 * @error: return location for errors
 * 
 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is scaled
 * from the size indicated by the file by a factor of @x_zoom and @y_zoom.  The
 * caller must assume the reference to the returned pixbuf. If an error
 * occurred, @error is set and %NULL is returned.
 * 
 * Return value: A newly allocated #GdkPixbuf, or %NULL
177
 * Deprecated: Set up a cairo matrix and use rsvg_handle_new_from_file() + rsvg_handle_render_cairo() instead.
178 179
 **/
GdkPixbuf *
180 181
rsvg_pixbuf_from_file_at_zoom (const gchar * file_name,
                               double x_zoom, double y_zoom, GError ** error)
182
{
183 184 185 186 187 188 189 190 191 192 193
    struct RsvgSizeCallbackData data;

    g_return_val_if_fail (file_name != NULL, NULL);
    g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);

    data.type = RSVG_SIZE_ZOOM;
    data.x_zoom = x_zoom;
    data.y_zoom = y_zoom;
    data.keep_aspect_ratio = FALSE;

    return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
}

/**
 * rsvg_pixbuf_from_file_at_zoom_with_max:
 * @file_name: A file name
 * @x_zoom: The horizontal zoom factor
 * @y_zoom: The vertical zoom factor
 * @max_width: The requested max width
 * @max_height: The requested max heigh
 * @error: return location for errors
 * 
 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is scaled
 * from the size indicated by the file by a factor of @x_zoom and @y_zoom. If the
 * resulting pixbuf would be larger than max_width/max_heigh it is uniformly scaled
 * down to fit in that rectangle. The caller must assume the reference to the
 * returned pixbuf. If an error occurred, @error is set and %NULL is returned.
 * 
 * Return value: A newly allocated #GdkPixbuf, or %NULL
212
 * Deprecated: Set up a cairo matrix and use rsvg_handle_new_from_file() + rsvg_handle_render_cairo() instead.
213
 **/
214 215 216 217 218
GdkPixbuf *
rsvg_pixbuf_from_file_at_zoom_with_max (const gchar * file_name,
                                        double x_zoom,
                                        double y_zoom,
                                        gint max_width, gint max_height, GError ** error)
219
{
220 221 222 223 224 225 226 227 228 229 230 231 232
    struct RsvgSizeCallbackData data;

    g_return_val_if_fail (file_name != NULL, NULL);
    g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);

    data.type = RSVG_SIZE_ZOOM_MAX;
    data.x_zoom = x_zoom;
    data.y_zoom = y_zoom;
    data.width = max_width;
    data.height = max_height;
    data.keep_aspect_ratio = FALSE;

    return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
}

/**
 * rsvg_pixbuf_from_file_at_size:
 * @file_name: A file name
 * @width: The new width, or -1
 * @height: The new height, or -1
 * @error: return location for errors
 * 
 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is scaled
 * from the size indicated to the new size indicated by @width and @height.  If
 * either of these are -1, then the default size of the image being loaded is
 * used.  The caller must assume the reference to the returned pixbuf. If an
 * error occurred, @error is set and %NULL is returned.
 * 
 * Return value: A newly allocated #GdkPixbuf, or %NULL
249
 * Deprecated: Set up a cairo matrix and use rsvg_handle_new_from_file() + rsvg_handle_render_cairo() instead.
250 251
 **/
GdkPixbuf *
252
rsvg_pixbuf_from_file_at_size (const gchar * file_name, gint width, gint height, GError ** error)
253
{
254 255 256 257 258 259 260 261
    struct RsvgSizeCallbackData data;

    data.type = RSVG_SIZE_WH;
    data.width = width;
    data.height = height;
    data.keep_aspect_ratio = FALSE;

    return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}

/**
 * rsvg_pixbuf_from_file_at_max_size:
 * @file_name: A file name
 * @max_width: The requested max width
 * @max_height: The requested max heigh
 * @error: return location for errors
 * 
 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is uniformly
 * scaled so that the it fits into a rectangle of size max_width * max_height. The
 * caller must assume the reference to the returned pixbuf. If an error occurred,
 * @error is set and %NULL is returned.
 * 
 * Return value: A newly allocated #GdkPixbuf, or %NULL
277
 * Deprecated: Set up a cairo matrix and use rsvg_handle_new_from_file() + rsvg_handle_render_cairo() instead.
278
 **/
279 280 281
GdkPixbuf *
rsvg_pixbuf_from_file_at_max_size (const gchar * file_name,
                                   gint max_width, gint max_height, GError ** error)
282
{
283 284 285 286 287 288 289 290
    struct RsvgSizeCallbackData data;

    data.type = RSVG_SIZE_WH_MAX;
    data.width = max_width;
    data.height = max_height;
    data.keep_aspect_ratio = FALSE;

    return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
291
}