1 #include "evas_common.h"
2 #include "evas_private.h"
4 #include <librsvg/rsvg.h>
5 #include <librsvg/rsvg-cairo.h>
7 int evas_image_load_file_head_svg(Image_Entry *ie, const char *file, const char *key);
8 int evas_image_load_file_data_svg(Image_Entry *ie, const char *file, const char *key);
10 Evas_Image_Load_Func evas_image_load_svg_func =
12 evas_image_load_file_head_svg,
13 evas_image_load_file_data_svg
16 static int rsvg_initialized = 0;
17 static void svg_loader_unpremul_data(DATA32 *data, unsigned int len);
20 svg_loader_unpremul_data(DATA32 *data, unsigned int len)
22 DATA32 *de = data + len;
26 DATA32 a = A_VAL(data);
30 R_VAL(data) = (R_VAL(data) * 255) / a;
31 G_VAL(data) = (G_VAL(data) * 255) / a;
32 B_VAL(data) = (B_VAL(data) * 255) / a;
39 evas_image_load_file_head_svg(Image_Entry *ie, const char *file, const char *key)
41 char cwd[PATH_MAX], pcwd[PATH_MAX], *p;
44 RsvgDimensionData dim;
50 /* ignore all files not called .svg or .svg.gz - because rsvg has a leak
51 * where closing the handle doesn't free mem */
52 ext = strrchr(file, '.');
54 if (!strcasecmp(ext, ".gz"))
59 while ((*p != '.') && (p > file))
63 if (p <= file) return 0;
64 if (strcasecmp(p, ".svg.gz")) return 0;
69 else if (strcasecmp(ext, ".svg")) return 0;
71 getcwd(pcwd, sizeof(pcwd));
72 strncpy(cwd, file, sizeof(cwd) - 1);
73 cwd[sizeof(cwd) - 1] = 0;
74 p = strrchr(cwd, '/');
78 rsvg = rsvg_handle_new_from_file(file, NULL);
85 rsvg_handle_get_dimensions(rsvg, &dim);
88 if ((w < 1) || (h < 1) || (w > 8192) || (h > 8192))
90 // rsvg_handle_close(rsvg, NULL);
92 // rsvg_handle_free(rsvg);
96 if (ie->load_opts.scale_down_by > 1)
98 w /= ie->load_opts.scale_down_by;
99 h /= ie->load_opts.scale_down_by;
101 else if (ie->load_opts.dpi > 0.0)
103 w = (w * ie->load_opts.dpi) / 90.0;
104 h = (h * ie->load_opts.dpi) / 90.0;
106 else if ((ie->load_opts.w > 0) &&
107 (ie->load_opts.h > 0))
111 w2 = ie->load_opts.w;
112 h2 = (ie->load_opts.w * h) / w;
113 if (h2 > ie->load_opts.h)
115 h2 = ie->load_opts.h;
116 w2 = (ie->load_opts.h * w) / h;
126 // rsvg_handle_close(rsvg, NULL);
127 g_object_unref(rsvg);
128 // rsvg_handle_free(rsvg);
133 /** FIXME: All evas loaders need to be tightened up **/
135 evas_image_load_file_data_svg(Image_Entry *ie, const char *file, const char *key)
138 char cwd[PATH_MAX], pcwd[PATH_MAX], *p;
140 RsvgDimensionData dim;
142 cairo_surface_t *surface;
148 /* ignore all files not called .svg or .svg.gz - because rsvg has a leak
149 * where closing the handle doesn't free mem */
150 ext = strrchr(file, '.');
152 if (!strcasecmp(ext, ".gz"))
157 while ((*p != '.') && (p > file))
161 if (p <= file) return 0;
162 if (strcasecmp(p, ".svg.gz")) return 0;
167 else if (strcasecmp(ext, ".svg")) return 0;
169 getcwd(pcwd, sizeof(pcwd));
170 strncpy(cwd, file, sizeof(cwd) - 1);
171 cwd[sizeof(cwd) - 1] = 0;
172 p = strrchr(cwd, '/');
176 rsvg = rsvg_handle_new_from_file(file, NULL);
183 rsvg_handle_get_dimensions(rsvg, &dim);
186 if ((w < 1) || (h < 1) || (w > 8192) || (h > 8192))
188 // rsvg_handle_close(rsvg, NULL);
189 g_object_unref(rsvg);
190 // rsvg_handle_free(rsvg);
194 if (ie->load_opts.scale_down_by > 1)
196 w /= ie->load_opts.scale_down_by;
197 h /= ie->load_opts.scale_down_by;
199 else if (ie->load_opts.dpi > 0.0)
201 w = (w * ie->load_opts.dpi) / 90.0;
202 h = (h * ie->load_opts.dpi) / 90.0;
204 else if ((ie->load_opts.w > 0) &&
205 (ie->load_opts.h > 0))
209 w2 = ie->load_opts.w;
210 h2 = (ie->load_opts.w * h) / w;
211 if (h2 > ie->load_opts.h)
213 h2 = ie->load_opts.h;
214 w2 = (ie->load_opts.h * w) / h;
222 evas_cache_image_surface_alloc(ie, w, h);
223 pixels = evas_cache_image_pixels(ie);
226 // rsvg_handle_close(rsvg, NULL);
227 g_object_unref(rsvg);
228 // rsvg_handle_free(rsvg);
233 memset(pixels, 0, w * h * sizeof(DATA32));
235 surface = cairo_image_surface_create_for_data((unsigned char *)pixels, CAIRO_FORMAT_ARGB32,
236 w, h, w * sizeof(DATA32));
239 // rsvg_handle_close(rsvg, NULL);
240 g_object_unref(rsvg);
241 // rsvg_handle_free(rsvg);
245 cr = cairo_create(surface);
248 cairo_surface_destroy(surface);
249 // rsvg_handle_close(rsvg, NULL);
250 g_object_unref(rsvg);
251 // rsvg_handle_free(rsvg);
257 (double)ie->w / dim.em,
258 (double)ie->h / dim.ex);
259 rsvg_handle_render_cairo(rsvg, cr);
260 cairo_surface_destroy(surface);
261 /* need to check if this is required... */
263 // rsvg_handle_close(rsvg, NULL);
264 g_object_unref(rsvg);
265 // rsvg_handle_free(rsvg);
267 evas_common_image_set_alpha_sparse(ie);
272 module_open(Evas_Module *em)
275 em->functions = (void *)(&evas_image_load_svg_func);
276 if (!rsvg_initialized) rsvg_init();
277 rsvg_initialized = 1;
284 if (!rsvg_initialized) return;
286 rsvg_initialized = 0;
289 EAPI Evas_Module_Api evas_modapi =
291 EVAS_MODULE_API_VERSION,
292 EVAS_MODULE_TYPE_IMAGE_LOADER,