1 | /* vim: set sw=4: -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ |
---|
2 | /* |
---|
3 | rsvg-gz.c: SAX-based renderer for SVGZ files into a GdkPixbuf. |
---|
4 | |
---|
5 | Copyright (C) 2003 Dom Lachowicz <cinamod@hotmail.com> |
---|
6 | |
---|
7 | This program is free software; you can redistribute it and/or |
---|
8 | modify it under the terms of the GNU Library General Public License as |
---|
9 | published by the Free Software Foundation; either version 2 of the |
---|
10 | License, or (at your option) any later version. |
---|
11 | |
---|
12 | This program is distributed in the hope that it will be useful, |
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
15 | Library General Public License for more details. |
---|
16 | |
---|
17 | You should have received a copy of the GNU Library General Public |
---|
18 | License along with this program; if not, write to the |
---|
19 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
20 | Boston, MA 02111-1307, USA. |
---|
21 | */ |
---|
22 | |
---|
23 | #include "config.h" |
---|
24 | #include "rsvg-gz.h" |
---|
25 | #include "rsvg-private.h" |
---|
26 | |
---|
27 | #ifdef HAVE_SVGZ |
---|
28 | |
---|
29 | #include <gsf/gsf-input-gzip.h> |
---|
30 | #include <gsf/gsf-input-memory.h> |
---|
31 | #include <gsf/gsf-output-memory.h> |
---|
32 | |
---|
33 | /* TODO: this could probably be done about a billion times better */ |
---|
34 | |
---|
35 | struct RsvgHandleGz |
---|
36 | { |
---|
37 | RsvgHandle super; |
---|
38 | GsfOutput * mem; |
---|
39 | }; |
---|
40 | |
---|
41 | typedef struct RsvgHandleGz RsvgHandleGz; |
---|
42 | |
---|
43 | static gboolean |
---|
44 | rsvg_handle_gz_write_impl (RsvgHandle *handle, |
---|
45 | const guchar *buf, |
---|
46 | gsize num_bytes, |
---|
47 | GError **error) |
---|
48 | { |
---|
49 | RsvgHandleGz * me = (RsvgHandleGz*)handle; |
---|
50 | return gsf_output_write (me->mem, num_bytes, buf); |
---|
51 | } |
---|
52 | |
---|
53 | static gboolean |
---|
54 | rsvg_handle_gz_close_impl (RsvgHandle *handle, |
---|
55 | GError **error) |
---|
56 | { |
---|
57 | RsvgHandleGz * me = (RsvgHandleGz*)handle; |
---|
58 | GsfInput * gzip; |
---|
59 | const guchar * bytes; |
---|
60 | gsize size; |
---|
61 | gsize remaining; |
---|
62 | |
---|
63 | bytes = gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (me->mem)); |
---|
64 | size = gsf_output_size (me->mem); |
---|
65 | |
---|
66 | gzip = GSF_INPUT (gsf_input_gzip_new (GSF_INPUT (gsf_input_memory_new (bytes, size, FALSE)), error)); |
---|
67 | remaining = gsf_input_remaining (gzip); |
---|
68 | while ((size = MIN (remaining, 1024)) > 0) { |
---|
69 | guint8 const *buf; |
---|
70 | |
---|
71 | /* write to parent */ |
---|
72 | buf = gsf_input_read (gzip, size, NULL); |
---|
73 | if (!buf) |
---|
74 | { |
---|
75 | /* an error occured, so bail */ |
---|
76 | g_warning ("rsvg_gz_handle_close_impl: gsf_input_read returned NULL"); |
---|
77 | break; |
---|
78 | } |
---|
79 | |
---|
80 | rsvg_handle_write_impl (&(me->super), |
---|
81 | buf, |
---|
82 | size, error); |
---|
83 | /* if we didn't manage to lower remaining number of bytes, |
---|
84 | * something is wrong, and we should avoid an endless loop */ |
---|
85 | if (remaining == gsf_input_remaining (gzip)) |
---|
86 | { |
---|
87 | g_warning ("rsvg_gz_handle_close_impl: write_impl didn't lower the input_remaining count"); |
---|
88 | break; |
---|
89 | } |
---|
90 | remaining = gsf_input_remaining (gzip); |
---|
91 | } |
---|
92 | g_object_unref (G_OBJECT (gzip)); |
---|
93 | |
---|
94 | /* close parent */ |
---|
95 | gsf_output_close (me->mem); |
---|
96 | return rsvg_handle_close_impl (handle, error); |
---|
97 | } |
---|
98 | |
---|
99 | static void |
---|
100 | rsvg_handle_gz_free_impl (RsvgHandle *handle) |
---|
101 | { |
---|
102 | RsvgHandleGz * me = (RsvgHandleGz*)handle; |
---|
103 | g_object_unref (G_OBJECT (me->mem)); |
---|
104 | |
---|
105 | /* free parent */ |
---|
106 | rsvg_handle_free_impl (handle); |
---|
107 | } |
---|
108 | |
---|
109 | static RsvgHandle * |
---|
110 | rsvg_handle_new_gz_impl (void) |
---|
111 | { |
---|
112 | RsvgHandleGz * me = g_new0 (RsvgHandleGz, 1); |
---|
113 | |
---|
114 | /* init parent */ |
---|
115 | rsvg_handle_init (&me->super); |
---|
116 | me->mem = GSF_OUTPUT (gsf_output_memory_new ()); |
---|
117 | |
---|
118 | me->super.write = rsvg_handle_gz_write_impl; |
---|
119 | me->super.close = rsvg_handle_gz_close_impl; |
---|
120 | me->super.free = rsvg_handle_gz_free_impl; |
---|
121 | |
---|
122 | return (RsvgHandle*)me; |
---|
123 | } |
---|
124 | |
---|
125 | #else |
---|
126 | |
---|
127 | static RsvgHandle * |
---|
128 | rsvg_handle_new_gz_impl (void) |
---|
129 | { |
---|
130 | g_warning ("Doesn't support GZipped SVG files"); |
---|
131 | return NULL; |
---|
132 | } |
---|
133 | |
---|
134 | #endif |
---|
135 | |
---|
136 | /** |
---|
137 | * rsvg_handle_new_gz |
---|
138 | * |
---|
139 | * See rsvg_handle_new, except that this will handle GZipped SVGs (svgz) |
---|
140 | * Use the returned handle identically to how you use a handle returned |
---|
141 | * from rsvg_handle_new() |
---|
142 | * |
---|
143 | * Returns: a new SVGZ handle or null if it isn't supported |
---|
144 | */ |
---|
145 | RsvgHandle * |
---|
146 | rsvg_handle_new_gz (void) |
---|
147 | { |
---|
148 | return rsvg_handle_new_gz_impl (); |
---|
149 | } |
---|