diff options
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.c | 281 |
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 | |||
7 | static inline Eina_Bool evas_image_load_file_is_svg(const char *file) EINA_ARG_NONNULL(1) EINA_PURE; | ||
8 | static 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); | ||
9 | static 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 | |||
11 | Evas_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 | |||
20 | static int rsvg_initialized = 0; | ||
21 | |||
22 | |||
23 | static 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 | |||
59 | static Eina_Bool | ||
60 | evas_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 **/ | ||
134 | static Eina_Bool | ||
135 | evas_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 | |||
248 | static int | ||
249 | module_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 | |||
258 | static void | ||
259 | module_close(Evas_Module *em __UNUSED__) | ||
260 | { | ||
261 | if (!rsvg_initialized) return; | ||
262 | //rsvg_term(); | ||
263 | //rsvg_initialized = 0; | ||
264 | } | ||
265 | |||
266 | static 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 | |||
277 | EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, svg); | ||
278 | |||
279 | #ifndef EVAS_STATIC_BUILD_SVG | ||
280 | EVAS_EINA_MODULE_DEFINE(image_loader, svg); | ||
281 | #endif | ||