source: trunk/third/librsvg/rsvg-file-util.c @ 18609

Revision 18609, 8.5 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18608, which included commits to RCS files with non-trunk default branches.
Line 
1/* vim: set sw=4: -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/*
3   rsvg-file-util.c: SAX-based renderer for SVG files into a GdkPixbuf.
4
5   Copyright (C) 2000 Eazel, Inc.
6   Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Library General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   Library General Public License for more details.
17
18   You should have received a copy of the GNU Library General Public
19   License along with this program; if not, write to the
20   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21   Boston, MA 02111-1307, USA.
22
23   Author: Raph Levien <raph@artofcode.com>
24*/
25
26#include "config.h"
27#include "rsvg.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <math.h>
32
33#if ENABLE_GNOME_VFS
34#include <libgnomevfs/gnome-vfs.h>
35#endif
36
37#define SVG_BUFFER_SIZE (1024 * 8)
38
39typedef enum {
40        RSVG_SIZE_ZOOM,
41        RSVG_SIZE_WH,
42        RSVG_SIZE_WH_MAX,
43        RSVG_SIZE_ZOOM_MAX
44} RsvgSizeType;
45
46struct RsvgSizeCallbackData
47{
48        RsvgSizeType type;
49        double x_zoom;
50        double y_zoom;
51        gint width;
52        gint height;
53};
54
55static void
56rsvg_size_callback (int *width,
57                                        int *height,
58                                        gpointer  data)
59{
60        struct RsvgSizeCallbackData *real_data = (struct RsvgSizeCallbackData *) data;
61        double zoomx, zoomy, zoom;
62       
63        switch (real_data->type) {
64        case RSVG_SIZE_ZOOM:
65                if (*width < 0 || *height < 0)
66                        return;
67               
68                *width = floor (real_data->x_zoom * *width + 0.5);
69                *height = floor (real_data->y_zoom * *height + 0.5);
70                return;
71               
72        case RSVG_SIZE_ZOOM_MAX:
73                if (*width < 0 || *height < 0)
74                        return;
75               
76                *width = floor (real_data->x_zoom * *width + 0.5);
77                *height = floor (real_data->y_zoom * *height + 0.5);
78               
79                if (*width > real_data->width || *height > real_data->height)
80                        {
81                                zoomx = (double) real_data->width / *width;
82                                zoomy = (double) real_data->height / *height;
83                                zoom = MIN (zoomx, zoomy);
84                               
85                                *width = floor (zoom * *width + 0.5);
86                                *height = floor (zoom * *height + 0.5);
87                        }
88                return;
89               
90        case RSVG_SIZE_WH_MAX:
91                if (*width < 0 || *height < 0)
92                        return;
93               
94                zoomx = (double) real_data->width / *width;
95                zoomy = (double) real_data->height / *height;
96                zoom = MIN (zoomx, zoomy);
97               
98                *width = floor (zoom * *width + 0.5);
99                *height = floor (zoom * *height + 0.5);
100                return;
101               
102        case RSVG_SIZE_WH:
103               
104                if (real_data->width != -1)
105                        *width = real_data->width;
106                if (real_data->height != -1)
107                        *height = real_data->height;
108                return;
109        }
110       
111        g_assert_not_reached ();
112}
113
114static GdkPixbuf *
115rsvg_pixbuf_from_file_with_size_data (const gchar * file_name,
116                                                                          struct RsvgSizeCallbackData * data,
117                                                                          GError ** error)
118{
119        char chars[SVG_BUFFER_SIZE];
120        gint result;
121        GdkPixbuf *retval;
122        RsvgHandle *handle;
123       
124#if ENABLE_GNOME_VFS
125        GnomeVFSHandle * f = NULL;
126        if (GNOME_VFS_OK != gnome_vfs_open (&handle, file_name, GNOME_VFS_OPEN_READ))
127                {
128                        /* FIXME: Set up error. */
129                        return NULL;
130                }
131#else
132        FILE *f = fopen (file_name, "r");
133        if (!f)
134                {
135                        /* FIXME: Set up error. */
136                        return NULL;
137                }
138#endif
139       
140        handle = rsvg_handle_new ();
141       
142        rsvg_handle_set_size_callback (handle, rsvg_size_callback, data, NULL);
143
144#if ENABLE_GNOME_VFS
145        while (GNOME_VFS_OK == gnome_vfs_read (f,chars, SVG_BUFFER_SIZE, &result))
146                rsvg_handle_write (handle, chars, result, error);
147#else
148        while ((result = fread (chars, 1, SVG_BUFFER_SIZE, f)) > 0)
149                rsvg_handle_write (handle, chars, result, error);
150#endif
151       
152        rsvg_handle_close (handle, error);
153        retval = rsvg_handle_get_pixbuf (handle);
154       
155#if ENABLE_GNOME_VFS
156        gnome_vfs_close (f);
157#else
158        fclose (f);
159#endif
160       
161        rsvg_handle_free (handle);
162       
163        return retval;
164}
165
166/**
167 * rsvg_pixbuf_from_file:
168 * @file_name: A file name
169 * @error: return location for errors
170 *
171 * Loads a new #GdkPixbuf from @file_name and returns it.  The caller must
172 * assume the reference to the reurned pixbuf. If an error occurred, @error is
173 * set and %NULL is returned.
174 *
175 * Return value: A newly allocated #GdkPixbuf, or %NULL
176 **/
177GdkPixbuf *
178rsvg_pixbuf_from_file (const gchar *file_name,
179                                           GError     **error)
180{
181        return rsvg_pixbuf_from_file_at_size (file_name, -1, -1, error);
182}
183
184/**
185 * rsvg_pixbuf_from_file_at_zoom:
186 * @file_name: A file name
187 * @x_zoom: The horizontal zoom factor
188 * @y_zoom: The vertical zoom factor
189 * @error: return location for errors
190 *
191 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is scaled
192 * from the size indicated by the file by a factor of @x_zoom and @y_zoom.  The
193 * caller must assume the reference to the returned pixbuf. If an error
194 * occurred, @error is set and %NULL is returned.
195 *
196 * Return value: A newly allocated #GdkPixbuf, or %NULL
197 **/
198GdkPixbuf *
199rsvg_pixbuf_from_file_at_zoom (const gchar *file_name,
200                                                           double       x_zoom,
201                                                           double       y_zoom,
202                                                           GError     **error)
203{
204        struct RsvgSizeCallbackData data;
205       
206        g_return_val_if_fail (file_name != NULL, NULL);
207        g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);
208       
209        data.type = RSVG_SIZE_ZOOM;
210        data.x_zoom = x_zoom;
211        data.y_zoom = y_zoom;
212       
213        return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
214}
215
216/**
217 * rsvg_pixbuf_from_file_at_zoom_with_max:
218 * @file_name: A file name
219 * @x_zoom: The horizontal zoom factor
220 * @y_zoom: The vertical zoom factor
221 * @max_width: The requested max width
222 * @max_height: The requested max heigh
223 * @error: return location for errors
224 *
225 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is scaled
226 * from the size indicated by the file by a factor of @x_zoom and @y_zoom. If the
227 * resulting pixbuf would be larger than max_width/max_heigh it is uniformly scaled
228 * down to fit in that rectangle. The caller must assume the reference to the
229 * returned pixbuf. If an error occurred, @error is set and %NULL is returned.
230 *
231 * Return value: A newly allocated #GdkPixbuf, or %NULL
232 **/
233GdkPixbuf  *
234rsvg_pixbuf_from_file_at_zoom_with_max (const gchar  *file_name,
235                                                                                double        x_zoom,
236                                                                                double        y_zoom,
237                                                                                gint          max_width,
238                                                                                gint          max_height,
239                                                                                GError      **error)
240{
241        struct RsvgSizeCallbackData data;
242       
243        g_return_val_if_fail (file_name != NULL, NULL);
244        g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);
245       
246        data.type = RSVG_SIZE_ZOOM_MAX;
247        data.x_zoom = x_zoom;
248        data.y_zoom = y_zoom;
249        data.width = max_width;
250        data.height = max_height;
251       
252        return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
253}
254
255/**
256 * rsvg_pixbuf_from_file_at_size:
257 * @file_name: A file name
258 * @width: The new width, or -1
259 * @height: The new height, or -1
260 * @error: return location for errors
261 *
262 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is scaled
263 * from the size indicated to the new size indicated by @width and @height.  If
264 * either of these are -1, then the default size of the image being loaded is
265 * used.  The caller must assume the reference to the returned pixbuf. If an
266 * error occurred, @error is set and %NULL is returned.
267 *
268 * Return value: A newly allocated #GdkPixbuf, or %NULL
269 **/
270GdkPixbuf *
271rsvg_pixbuf_from_file_at_size (const gchar *file_name,
272                                                           gint         width,
273                                                           gint         height,
274                                                           GError     **error)
275{
276        struct RsvgSizeCallbackData data;
277       
278        data.type = RSVG_SIZE_WH;
279        data.width = width;
280        data.height = height;
281       
282        return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
283}
284
285/**
286 * rsvg_pixbuf_from_file_at_max_size:
287 * @file_name: A file name
288 * @max_width: The requested max width
289 * @max_height: The requested max heigh
290 * @error: return location for errors
291 *
292 * Loads a new #GdkPixbuf from @file_name and returns it.  This pixbuf is uniformly
293 * scaled so that the it fits into a rectangle of size max_width * max_height. The
294 * caller must assume the reference to the returned pixbuf. If an error occurred,
295 * @error is set and %NULL is returned.
296 *
297 * Return value: A newly allocated #GdkPixbuf, or %NULL
298 **/
299GdkPixbuf  *
300rsvg_pixbuf_from_file_at_max_size (const gchar     *file_name,
301                                                                   gint             max_width,
302                                                                   gint             max_height,
303                                                                   GError         **error)
304{
305        struct RsvgSizeCallbackData data;
306       
307        data.type = RSVG_SIZE_WH_MAX;
308        data.width = max_width;
309        data.height = max_height;
310       
311        return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
312}
Note: See TracBrowser for help on using the repository browser.