1 /* libsvg - Library for parsing/rendering SVG documents
2
3 Copyright � 2002 USC/Information Sciences Institute
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20 Author: Carl Worth <cworth@isi.edu>
21 */
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <libgen.h>
28 #include <zlib.h>
29 #include <sys/param.h>
30
31 #include "svgint.h"
32
33 static svg_status_t
34 _svg_init (svg_t *svg);
35
36 svg_status_t
svg_create(svg_t ** svg)37 svg_create (svg_t **svg)
38 {
39 *svg = malloc (sizeof (svg_t));
40 if (*svg == NULL) {
41 return SVG_STATUS_NO_MEMORY;
42 }
43
44 return _svg_init (*svg);
45 }
46
47 static svg_status_t
_svg_init(svg_t * svg)48 _svg_init (svg_t *svg)
49 {
50 svg->dpi = 100;
51
52 svg->dir_name = strdup (".");
53
54 svg->group_element = NULL;
55
56 _svg_parser_init (&svg->parser, svg);
57
58 svg->engine = NULL;
59
60 svg->element_ids = _svg_xml_hash_create (100);
61
62 return SVG_STATUS_SUCCESS;
63 }
64
65 static svg_status_t
_svg_deinit(svg_t * svg)66 _svg_deinit (svg_t *svg)
67 {
68 free (svg->dir_name);
69 svg->dir_name = NULL;
70
71 if (svg->group_element)
72 _svg_element_destroy (svg->group_element);
73
74 _svg_parser_deinit (&svg->parser);
75
76 svg->engine = NULL;
77
78 _svg_xml_hash_free (svg->element_ids);
79
80 return SVG_STATUS_SUCCESS;
81 }
82
83 svg_status_t
svg_destroy(svg_t * svg)84 svg_destroy (svg_t *svg)
85 {
86 svg_status_t status;
87 status = _svg_deinit (svg);
88 free (svg);
89
90 return status;
91 }
92
93 #define SVG_PARSE_BUFFER_SIZE (8 * 1024)
94
95 svg_status_t
svg_parse_file(svg_t * svg,FILE * file)96 svg_parse_file (svg_t *svg, FILE *file)
97 {
98 svg_status_t status = SVG_STATUS_SUCCESS;
99 gzFile zfile;
100 char buf[SVG_PARSE_BUFFER_SIZE];
101 int read;
102
103 zfile = gzdopen (dup(fileno(file)), "r");
104 if (zfile == NULL) {
105 switch (errno) {
106 case ENOMEM:
107 return SVG_STATUS_NO_MEMORY;
108 case ENOENT:
109 return SVG_STATUS_FILE_NOT_FOUND;
110 default:
111 return SVG_STATUS_IO_ERROR;
112 }
113 }
114
115 status = svg_parse_chunk_begin (svg);
116 if (status)
117 goto CLEANUP;
118
119 while (! gzeof (zfile)) {
120 read = gzread (zfile, buf, SVG_PARSE_BUFFER_SIZE);
121 if (read > -1) {
122 status = svg_parse_chunk (svg, buf, read);
123 if (status)
124 goto CLEANUP;
125 } else {
126 status = SVG_STATUS_IO_ERROR;
127 goto CLEANUP;
128 }
129 }
130
131 status = svg_parse_chunk_end (svg);
132
133 CLEANUP:
134 gzclose (zfile);
135 return status;
136 }
137
138 svg_status_t
svg_parse(svg_t * svg,const char * filename)139 svg_parse (svg_t *svg, const char *filename)
140 {
141 svg_status_t status = SVG_STATUS_SUCCESS;
142 FILE *file;
143 char *tmp;
144
145 free (svg->dir_name);
146 /* awful dirname semantics require some hoops */
147 tmp = strdup (filename);
148 svg->dir_name = strdup (dirname (tmp));
149 free (tmp);
150
151 file = fopen (filename, "r");
152 if (file == NULL) {
153 switch (errno) {
154 case ENOMEM:
155 return SVG_STATUS_NO_MEMORY;
156 case ENOENT:
157 return SVG_STATUS_FILE_NOT_FOUND;
158 default:
159 return SVG_STATUS_IO_ERROR;
160 }
161 }
162 status = svg_parse_file (svg, file);
163 fclose (file);
164 return status;
165 }
166
167 svg_status_t
svg_parse_buffer(svg_t * svg,const char * buf,size_t count)168 svg_parse_buffer (svg_t *svg, const char *buf, size_t count)
169 {
170 svg_status_t status;
171
172 status = svg_parse_chunk_begin (svg);
173 if (status)
174 return status;
175
176 status = svg_parse_chunk (svg, buf, count);
177 if (status)
178 return status;
179
180 status = svg_parse_chunk_end (svg);
181
182 return status;
183 }
184
185 svg_status_t
svg_parse_chunk_begin(svg_t * svg)186 svg_parse_chunk_begin (svg_t *svg)
187 {
188 return _svg_parser_begin (&svg->parser);
189 }
190
191 svg_status_t
svg_parse_chunk(svg_t * svg,const char * buf,size_t count)192 svg_parse_chunk (svg_t *svg, const char *buf, size_t count)
193 {
194 return _svg_parser_parse_chunk (&svg->parser, buf, count);
195 }
196
197 svg_status_t
svg_parse_chunk_end(svg_t * svg)198 svg_parse_chunk_end (svg_t *svg)
199 {
200 return _svg_parser_end (&svg->parser);
201 }
202
203 svg_status_t
svg_render(svg_t * svg,svg_render_engine_t * engine,void * closure)204 svg_render (svg_t *svg,
205 svg_render_engine_t *engine,
206 void *closure)
207 {
208 svg_status_t status;
209 char orig_dir[MAXPATHLEN];
210
211 if (svg->group_element == NULL)
212 return SVG_STATUS_SUCCESS;
213
214 /* XXX: Currently, the SVG parser doesn't resolve relative URLs
215 properly, so I'll just cheese things in by changing the current
216 directory -- at least I'll be nice about it and restore it
217 afterwards. */
218
219 getcwd (orig_dir, MAXPATHLEN);
220 chdir (svg->dir_name);
221
222 status = svg_element_render (svg->group_element, engine, closure);
223
224 chdir (orig_dir);
225
226 return status;
227 }
228
229 svg_status_t
_svg_store_element_by_id(svg_t * svg,svg_element_t * element)230 _svg_store_element_by_id (svg_t *svg, svg_element_t *element)
231 {
232 _svg_xml_hash_add_entry (svg->element_ids,
233 (unsigned char *)element->id,
234 element);
235
236 return SVG_STATUS_SUCCESS;
237 }
238
239 svg_status_t
_svg_fetch_element_by_id(svg_t * svg,const char * id,svg_element_t ** element_ret)240 _svg_fetch_element_by_id (svg_t *svg, const char *id, svg_element_t **element_ret)
241 {
242 *element_ret = _svg_xml_hash_lookup (svg->element_ids, (unsigned char *)id);
243
244 return SVG_STATUS_SUCCESS;
245 }
246
247 void
svg_get_size(svg_t * svg,svg_length_t * width,svg_length_t * height)248 svg_get_size (svg_t *svg, svg_length_t *width, svg_length_t *height)
249 {
250 if (svg->group_element) {
251 _svg_group_get_size (&svg->group_element->e.group, width, height);
252 } else {
253 _svg_length_init (width, 0.0);
254 _svg_length_init (height, 0.0);
255 }
256 }
257