~ubuntu-branches/ubuntu/trusty/librsvg/trusty-proposed

« back to all changes in this revision

Viewing changes to rsvg-image.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2012-03-27 01:47:52 UTC
  • mfrom: (1.1.32) (34.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20120327014752-c9vmipiww40cnip7
Tags: 2.36.0-1
* New upstream release.
* Update debian/copyright using the machine-readable copyright format 1.0.
* Bump Standards-Version to 3.9.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include <math.h>
35
35
#include <errno.h>
36
36
#include "rsvg-css.h"
37
 
#include <gio/gio.h>
38
 
 
39
 
static GByteArray *
40
 
rsvg_acquire_base64_resource (const char *data, GError ** error)
41
 
{
42
 
    GByteArray *array = NULL;
43
 
    gsize data_len, written_len;
44
 
    int state = 0;
45
 
    guint save = 0;
46
 
 
47
 
    rsvg_return_val_if_fail (data != NULL, NULL, error);
48
 
 
49
 
    while (*data)
50
 
        if (*data++ == ',')
51
 
            break;
52
 
 
53
 
    data_len = strlen (data);
54
 
    array = g_byte_array_sized_new (data_len / 4 * 3);
55
 
    written_len = g_base64_decode_step (data, data_len, array->data,
56
 
                                        &state, &save);
57
 
    g_byte_array_set_size (array, written_len);
58
 
 
59
 
    return array;
60
 
}
61
 
 
62
 
gchar *
63
 
rsvg_get_file_path (const gchar * filename, const gchar * base_uri)
64
 
{
65
 
    gchar *absolute_filename;
66
 
 
67
 
    if (g_file_test (filename, G_FILE_TEST_EXISTS) || g_path_is_absolute (filename)) {
68
 
        absolute_filename = g_strdup (filename);
 
37
#include "rsvg-io.h"
 
38
 
 
39
cairo_surface_t *
 
40
rsvg_cairo_surface_new_from_href (RsvgHandle *handle,
 
41
                                  const char *href,
 
42
                                  GError **error)
 
43
{
 
44
    guint8 *data;
 
45
    gsize data_len;
 
46
    char *mime_type = NULL;
 
47
    GdkPixbufLoader *loader;
 
48
    GdkPixbuf *pixbuf = NULL;
 
49
    int res;
 
50
    cairo_surface_t *surface;
 
51
 
 
52
    data = _rsvg_handle_acquire_data (handle, href, &mime_type, &data_len, error);
 
53
    if (data == NULL)
 
54
        return NULL;
 
55
 
 
56
    if (mime_type) {
 
57
        loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, error);
 
58
        g_free (mime_type);
69
59
    } else {
70
 
        gchar *tmpcdir;
71
 
        gchar *base_filename;
72
 
 
73
 
        if (base_uri) {
74
 
            base_filename = g_filename_from_uri (base_uri, NULL, NULL);
75
 
            if (base_filename != NULL) {
76
 
                tmpcdir = g_path_get_dirname (base_filename);
77
 
                g_free (base_filename);
78
 
            } else 
79
 
                return NULL;
80
 
        } else
81
 
            tmpcdir = g_get_current_dir ();
82
 
 
83
 
        absolute_filename = g_build_filename (tmpcdir, filename, NULL);
84
 
        g_free (tmpcdir);
85
 
    }
86
 
 
87
 
    return absolute_filename;
88
 
}
89
 
 
90
 
static GByteArray *
91
 
rsvg_acquire_file_resource (const char *filename, const char *base_uri, GError ** error)
92
 
{
93
 
    GByteArray *array;
94
 
    gchar *path;
95
 
    gchar *data = NULL;
96
 
    gsize length;
97
 
 
98
 
    rsvg_return_val_if_fail (filename != NULL, NULL, error);
99
 
 
100
 
    path = rsvg_get_file_path (filename, base_uri);
101
 
    if (path == NULL)
102
 
        return NULL;
103
 
 
104
 
    if (!g_file_get_contents (path, &data, &length, error)) {
105
 
        g_free (path);
106
 
        return NULL;
107
 
    }
108
 
 
109
 
    array = g_byte_array_new ();
110
 
 
111
 
    g_byte_array_append (array, (guint8 *)data, length);
 
60
        loader = gdk_pixbuf_loader_new ();
 
61
    }
 
62
 
 
63
    if (loader == NULL) {
 
64
        g_free (data);
 
65
        return NULL;
 
66
    }
 
67
 
 
68
    res = gdk_pixbuf_loader_write (loader, data, data_len, error);
112
69
    g_free (data);
113
 
    g_free (path);
114
 
 
115
 
    return array;
116
 
}
117
 
 
118
 
static GByteArray *
119
 
rsvg_acquire_vfs_resource (const char *filename, const char *base_uri, GError ** error)
120
 
{
121
 
    GByteArray *array;
122
 
 
123
 
    GFile *file;
124
 
    char *data;
125
 
    gsize size;
126
 
    gboolean res = FALSE;
127
 
 
128
 
    rsvg_return_val_if_fail (filename != NULL, NULL, error);
129
 
 
130
 
    file = g_file_new_for_uri (filename);
131
 
 
132
 
    if (!(res = g_file_load_contents (file, NULL, &data, &size, NULL, error))) {
133
 
        if (base_uri != NULL) {
134
 
            GFile *base;
135
 
 
136
 
            g_clear_error (error);
137
 
 
138
 
            g_object_unref (file);
139
 
 
140
 
            base = g_file_new_for_uri (base_uri);
141
 
            file = g_file_resolve_relative_path (base, filename);
142
 
            g_object_unref (base);
143
 
 
144
 
            res = g_file_load_contents (file, NULL, &data, &size, NULL, error);
145
 
        }
146
 
    }
147
 
 
148
 
    g_object_unref (file);
149
 
 
150
 
    if (res) {
151
 
        array = g_byte_array_new ();
152
 
 
153
 
        g_byte_array_append (array, (guint8 *)data, size);
154
 
        g_free (data);
155
 
    } else {
156
 
        return NULL;
157
 
    }
158
 
 
159
 
    return array;
160
 
}
161
 
 
162
 
GByteArray *
163
 
_rsvg_acquire_xlink_href_resource (const char *href, const char *base_uri, GError ** err)
164
 
{
165
 
    GByteArray *arr = NULL;
166
 
 
167
 
    if (!(href && *href))
168
 
        return NULL;
169
 
 
170
 
    if (!strncmp (href, "data:", 5))
171
 
        arr = rsvg_acquire_base64_resource (href, NULL);
172
 
 
173
 
    if (!arr)
174
 
        arr = rsvg_acquire_file_resource (href, base_uri, NULL);
175
 
 
176
 
    if (!arr)
177
 
        arr = rsvg_acquire_vfs_resource (href, base_uri, NULL);
178
 
 
179
 
    return arr;
180
 
}
181
 
 
182
 
GdkPixbuf *
183
 
rsvg_pixbuf_new_from_href (const char *href, const char *base_uri, GError ** error)
184
 
{
185
 
    GByteArray *arr;
186
 
 
187
 
    arr = _rsvg_acquire_xlink_href_resource (href, base_uri, error);
188
 
    if (arr) {
189
 
        GdkPixbufLoader *loader;
190
 
        GdkPixbuf *pixbuf = NULL;
191
 
        int res;
192
 
 
193
 
        loader = gdk_pixbuf_loader_new ();
194
 
 
195
 
        res = gdk_pixbuf_loader_write (loader, arr->data, arr->len, error);
196
 
        g_byte_array_free (arr, TRUE);
197
 
 
198
 
        if (!res) {
199
 
            gdk_pixbuf_loader_close (loader, NULL);
200
 
            g_object_unref (loader);
201
 
            return NULL;
202
 
        }
203
 
 
204
 
        if (!gdk_pixbuf_loader_close (loader, error)) {
205
 
            g_object_unref (loader);
206
 
            return NULL;
207
 
        }
208
 
 
209
 
        pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
210
 
 
211
 
        if (!pixbuf) {
212
 
            g_object_unref (loader);
213
 
            g_set_error (error,
214
 
                         GDK_PIXBUF_ERROR,
215
 
                         GDK_PIXBUF_ERROR_FAILED,
216
 
                         _
217
 
                         ("Failed to load image '%s': reason not known, probably a corrupt image file"),
218
 
                         href);
219
 
            return NULL;
220
 
        }
221
 
 
222
 
        g_object_ref (pixbuf);
223
 
 
224
 
        g_object_unref (loader);
225
 
 
226
 
        return pixbuf;
227
 
    }
228
 
 
229
 
    return NULL;
 
70
 
 
71
    if (!res) {
 
72
        gdk_pixbuf_loader_close (loader, NULL);
 
73
        g_object_unref (loader);
 
74
        return NULL;
 
75
    }
 
76
 
 
77
    if (!gdk_pixbuf_loader_close (loader, error)) {
 
78
        g_object_unref (loader);
 
79
        return NULL;
 
80
    }
 
81
 
 
82
    pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
 
83
 
 
84
    if (!pixbuf) {
 
85
        g_object_unref (loader);
 
86
        g_set_error (error,
 
87
                     GDK_PIXBUF_ERROR,
 
88
                     GDK_PIXBUF_ERROR_FAILED,
 
89
                      _("Failed to load image '%s': reason not known, probably a corrupt image file"),
 
90
                      href);
 
91
        return NULL;
 
92
    }
 
93
 
 
94
    surface = rsvg_cairo_surface_from_pixbuf (pixbuf);
 
95
 
 
96
    g_object_unref (loader);
 
97
 
 
98
    return surface;
230
99
}
231
100
 
232
101
void
275
144
    rsvg_state_finalize (z->super.state);
276
145
    g_free (z->super.state);
277
146
    z->super.state = NULL;
278
 
    if (z->img)
279
 
        g_object_unref (z->img);
 
147
    if (z->surface)
 
148
        cairo_surface_destroy (z->surface);
280
149
    _rsvg_node_free(self);
281
150
}
282
151
 
285
154
{
286
155
    RsvgNodeImage *z = (RsvgNodeImage *) self;
287
156
    unsigned int aspect_ratio = z->preserve_aspect_ratio;
288
 
    GdkPixbuf *img = z->img;
289
157
    gdouble x, y, w, h;
 
158
    cairo_surface_t *surface = z->surface;
290
159
 
291
 
    if (img == NULL)
 
160
    if (surface == NULL)
292
161
        return;
293
162
 
294
163
    x = _rsvg_css_normalize_length (&z->x, ctx, 'h');
304
173
        rsvg_add_clipping_rect (ctx, x, y, w, h);
305
174
    }
306
175
 
307
 
    rsvg_preserve_aspect_ratio (aspect_ratio, (double) gdk_pixbuf_get_width (img),
308
 
                                (double) gdk_pixbuf_get_height (img), &w, &h, &x, &y);
 
176
    rsvg_preserve_aspect_ratio (aspect_ratio, 
 
177
                                (double) cairo_image_surface_get_width (surface),
 
178
                                (double) cairo_image_surface_get_height (surface), 
 
179
                                &w, &h, &x, &y);
309
180
 
310
 
    rsvg_render_image (ctx, img, x, y, w, h);
 
181
    rsvg_render_surface (ctx, surface, x, y, w, h);
311
182
 
312
183
    rsvg_pop_discrete_layer (ctx);
313
184
}
330
201
        /* path is used by some older adobe illustrator versions */
331
202
        if ((value = rsvg_property_bag_lookup (atts, "path"))
332
203
            || (value = rsvg_property_bag_lookup (atts, "xlink:href"))) {
333
 
            image->img = rsvg_pixbuf_new_from_href (value, rsvg_handle_get_base_uri (ctx), NULL);
 
204
            image->surface = rsvg_cairo_surface_new_from_href (ctx,
 
205
                                                               value, 
 
206
                                                               NULL);
334
207
 
335
 
            if (!image->img) {
 
208
            if (!image->surface) {
336
209
#ifdef G_ENABLE_DEBUG
337
 
                g_warning (_("Couldn't load image: %s\n"), value);
 
210
                g_warning ("Couldn't load image: %s\n", value);
338
211
#endif
339
212
            }
340
213
        }
358
231
    image = g_new (RsvgNodeImage, 1);
359
232
    _rsvg_node_init (&image->super, RSVG_NODE_TYPE_IMAGE);
360
233
    g_assert (image->super.state);
361
 
    image->img = NULL;
 
234
    image->surface = NULL;
362
235
    image->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
363
236
    image->x = image->y = image->w = image->h = _rsvg_css_parse_length ("0");
364
237
    image->super.free = rsvg_node_image_free;