aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/loaders/svg/evas_image_load_svg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/loaders/svg/evas_image_load_svg.c')
-rw-r--r--libraries/evas/src/modules/loaders/svg/evas_image_load_svg.c281
1 files changed, 0 insertions, 281 deletions
diff --git a/libraries/evas/src/modules/loaders/svg/evas_image_load_svg.c b/libraries/evas/src/modules/loaders/svg/evas_image_load_svg.c
deleted file mode 100644
index dc0fc8d..0000000
--- a/libraries/evas/src/modules/loaders/svg/evas_image_load_svg.c
+++ /dev/null
@@ -1,281 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4#include <librsvg/rsvg.h>
5#include <librsvg/rsvg-cairo.h>
6
7static inline Eina_Bool evas_image_load_file_is_svg(const char *file) EINA_ARG_NONNULL(1) EINA_PURE;
8static Eina_Bool evas_image_load_file_head_svg(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
9static Eina_Bool evas_image_load_file_data_svg(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
10
11Evas_Image_Load_Func evas_image_load_svg_func =
12{
13 EINA_FALSE,
14 evas_image_load_file_head_svg,
15 evas_image_load_file_data_svg,
16 NULL,
17 EINA_FALSE
18};
19
20static int rsvg_initialized = 0;
21
22
23static inline Eina_Bool evas_image_load_file_is_svg(const char *file)
24{
25 int i, len = strlen(file);
26 Eina_Bool is_gz = EINA_FALSE;
27
28 for (i = len - 1; i > 0; i--)
29 {
30 if (file[i] == '.')
31 {
32 if (is_gz)
33 break;
34 else if (strcasecmp(file + i + 1, "gz") == 0)
35 is_gz = EINA_TRUE;
36 else
37 break;
38 }
39 }
40
41 if (i < 1) return EINA_FALSE;
42 i++;
43 if (i >= len) return EINA_FALSE;
44 if (strncasecmp(file + i, "svg", 3) != 0) return EINA_FALSE;
45 i += 3;
46 if (is_gz)
47 {
48 if (file[i] == '.') return EINA_TRUE;
49 else return EINA_FALSE;
50 }
51 else
52 {
53 if (file[i] == '\0') return EINA_TRUE;
54 else if (((file[i] == 'z') || (file[i] == 'Z')) && (!file[i + 1])) return EINA_TRUE;
55 else return EINA_FALSE;
56 }
57}
58
59static Eina_Bool
60evas_image_load_file_head_svg(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
61{
62 RsvgHandle *rsvg;
63 RsvgDimensionData dim;
64 int w, h;
65
66 /* ignore all files not called .svg or .svg.gz - because rsvg has a leak
67 * where closing the handle doesn't free mem */
68 if (!evas_image_load_file_is_svg(file))
69 {
70 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
71 return EINA_FALSE;
72 }
73
74 rsvg = rsvg_handle_new_from_file(file, NULL);
75 if (!rsvg)
76 {
77 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
78 return EINA_FALSE;
79 }
80
81 rsvg_handle_set_dpi(rsvg, 75.0);
82 rsvg_handle_get_dimensions(rsvg, &dim);
83 w = dim.width;
84 h = dim.height;
85 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
86 IMG_TOO_BIG(w, h))
87 {
88 rsvg_handle_close(rsvg, NULL);
89 g_object_unref(rsvg);
90 if (IMG_TOO_BIG(w, h))
91 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
92 else
93 *error = EVAS_LOAD_ERROR_GENERIC;
94 return EINA_FALSE;
95 }
96 if (ie->load_opts.scale_down_by > 1)
97 {
98 w /= ie->load_opts.scale_down_by;
99 h /= ie->load_opts.scale_down_by;
100 }
101 else if (ie->load_opts.dpi > 0.0)
102 {
103 w = (w * ie->load_opts.dpi) / 75.0;
104 h = (h * ie->load_opts.dpi) / 75.0;
105 }
106 else if ((ie->load_opts.w > 0) &&
107 (ie->load_opts.h > 0))
108 {
109 unsigned int w2, h2;
110
111 w2 = ie->load_opts.w;
112 h2 = (ie->load_opts.w * h) / w;
113 if (h2 > ie->load_opts.h)
114 {
115 h2 = ie->load_opts.h;
116 w2 = (ie->load_opts.h * w) / h;
117 }
118 w = w2;
119 h = h2;
120 }
121 if (w < 1) w = 1;
122 if (h < 1) h = 1;
123 ie->w = w;
124 ie->h = h;
125 ie->flags.alpha = 1;
126 rsvg_handle_close(rsvg, NULL);
127 g_object_unref(rsvg);
128
129 *error = EVAS_LOAD_ERROR_NONE;
130 return EINA_TRUE;
131}
132
133/** FIXME: All evas loaders need to be tightened up **/
134static Eina_Bool
135evas_image_load_file_data_svg(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
136{
137 DATA32 *pixels;
138 RsvgHandle *rsvg;
139 RsvgDimensionData dim;
140 int w, h;
141 cairo_surface_t *surface;
142 cairo_t *cr;
143
144 /* ignore all files not called .svg or .svg.gz - because rsvg has a leak
145 * where closing the handle doesn't free mem */
146 if (!evas_image_load_file_is_svg(file))
147 {
148 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
149 return EINA_FALSE;
150 }
151
152 rsvg = rsvg_handle_new_from_file(file, NULL);
153 if (!rsvg)
154 {
155 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
156 return EINA_FALSE;
157 }
158
159 rsvg_handle_set_dpi(rsvg, 75.0);
160 rsvg_handle_get_dimensions(rsvg, &dim);
161 w = dim.width;
162 h = dim.height;
163 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
164 {
165 rsvg_handle_close(rsvg, NULL);
166 g_object_unref(rsvg);
167 if (IMG_TOO_BIG(w, h))
168 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
169 else
170 *error = EVAS_LOAD_ERROR_GENERIC;
171 return EINA_FALSE;
172 }
173 if (ie->load_opts.scale_down_by > 1)
174 {
175 w /= ie->load_opts.scale_down_by;
176 h /= ie->load_opts.scale_down_by;
177 }
178 else if (ie->load_opts.dpi > 0.0)
179 {
180 w = (w * ie->load_opts.dpi) / 75.0;
181 h = (h * ie->load_opts.dpi) / 75.0;
182 }
183 else if ((ie->load_opts.w > 0) &&
184 (ie->load_opts.h > 0))
185 {
186 unsigned int w2, h2;
187
188 w2 = ie->load_opts.w;
189 h2 = (ie->load_opts.w * h) / w;
190 if (h2 > ie->load_opts.h)
191 {
192 h2 = ie->load_opts.h;
193 w2 = (ie->load_opts.h * w) / h;
194 }
195 w = w2;
196 h = h2;
197 }
198 if (w < 1) w = 1;
199 if (h < 1) h = 1;
200 if ((w != (int)ie->w) || (h != (int)ie->h))
201 {
202 *error = EVAS_LOAD_ERROR_GENERIC;
203 goto error;
204 }
205 ie->flags.alpha = 1;
206 evas_cache_image_surface_alloc(ie, w, h);
207 pixels = evas_cache_image_pixels(ie);
208 if (!pixels)
209 {
210 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
211 goto error;
212 }
213
214 memset(pixels, 0, w * h * sizeof(DATA32));
215 surface = cairo_image_surface_create_for_data((unsigned char *)pixels, CAIRO_FORMAT_ARGB32,
216 w, h, w * sizeof(DATA32));
217 if (!surface)
218 {
219 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
220 goto error;
221 }
222 cr = cairo_create(surface);
223 if (!cr)
224 {
225 cairo_surface_destroy(surface);
226 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
227 goto error;
228 }
229
230 cairo_scale(cr,
231 (double)ie->w / dim.em,
232 (double)ie->h / dim.ex);
233 rsvg_handle_render_cairo(rsvg, cr);
234 cairo_surface_destroy(surface);
235 /* need to check if this is required... */
236 cairo_destroy(cr);
237 rsvg_handle_close(rsvg, NULL);
238 g_object_unref(rsvg);
239 evas_common_image_set_alpha_sparse(ie);
240 return EINA_TRUE;
241
242 error:
243 rsvg_handle_close(rsvg, NULL);
244 g_object_unref(rsvg);
245 return EINA_FALSE;
246}
247
248static int
249module_open(Evas_Module *em)
250{
251 if (!em) return 0;
252 em->functions = (void *)(&evas_image_load_svg_func);
253 if (!rsvg_initialized) rsvg_init();
254 rsvg_initialized = 1;
255 return 1;
256}
257
258static void
259module_close(Evas_Module *em __UNUSED__)
260{
261 if (!rsvg_initialized) return;
262 //rsvg_term();
263 //rsvg_initialized = 0;
264}
265
266static Evas_Module_Api evas_modapi =
267{
268 EVAS_MODULE_API_VERSION,
269 "svg",
270 "none",
271 {
272 module_open,
273 module_close
274 }
275};
276
277EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, svg);
278
279#ifndef EVAS_STATIC_BUILD_SVG
280EVAS_EINA_MODULE_DEFINE(image_loader, svg);
281#endif