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