+++ /dev/null
-#include "evas_common.h"
-#include "evas_private.h"
-
-#include <librsvg/rsvg.h>
-#include <librsvg/rsvg-cairo.h>
-
-static inline Eina_Bool evas_image_load_file_is_svg(const char *file) EINA_ARG_NONNULL(1) EINA_PURE;
-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);
-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);
-
-Evas_Image_Load_Func evas_image_load_svg_func =
-{
- EINA_FALSE,
- evas_image_load_file_head_svg,
- evas_image_load_file_data_svg,
- NULL,
- EINA_FALSE
-};
-
-static int rsvg_initialized = 0;
-
-
-static inline Eina_Bool evas_image_load_file_is_svg(const char *file)
-{
- int i, len = strlen(file);
- Eina_Bool is_gz = EINA_FALSE;
-
- for (i = len - 1; i > 0; i--)
- {
- if (file[i] == '.')
- {
- if (is_gz)
- break;
- else if (strcasecmp(file + i + 1, "gz") == 0)
- is_gz = EINA_TRUE;
- else
- break;
- }
- }
-
- if (i < 1) return EINA_FALSE;
- i++;
- if (i >= len) return EINA_FALSE;
- if (strncasecmp(file + i, "svg", 3) != 0) return EINA_FALSE;
- i += 3;
- if (is_gz)
- {
- if (file[i] == '.') return EINA_TRUE;
- else return EINA_FALSE;
- }
- else
- {
- if (file[i] == '\0') return EINA_TRUE;
- else if (((file[i] == 'z') || (file[i] == 'Z')) && (!file[i + 1])) return EINA_TRUE;
- else return EINA_FALSE;
- }
-}
-
-static Eina_Bool
-evas_image_load_file_head_svg(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
-{
- RsvgHandle *rsvg;
- RsvgDimensionData dim;
- int w, h;
-
- /* ignore all files not called .svg or .svg.gz - because rsvg has a leak
- * where closing the handle doesn't free mem */
- if (!evas_image_load_file_is_svg(file))
- {
- *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
- return EINA_FALSE;
- }
-
- rsvg = rsvg_handle_new_from_file(file, NULL);
- if (!rsvg)
- {
- *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
- return EINA_FALSE;
- }
-
- rsvg_handle_set_dpi(rsvg, 75.0);
- rsvg_handle_get_dimensions(rsvg, &dim);
- w = dim.width;
- h = dim.height;
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
- IMG_TOO_BIG(w, h))
- {
- rsvg_handle_close(rsvg, NULL);
- g_object_unref(rsvg);
- if (IMG_TOO_BIG(w, h))
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- else
- *error = EVAS_LOAD_ERROR_GENERIC;
- return EINA_FALSE;
- }
- if (ie->load_opts.scale_down_by > 1)
- {
- w /= ie->load_opts.scale_down_by;
- h /= ie->load_opts.scale_down_by;
- }
- else if (ie->load_opts.dpi > 0.0)
- {
- w = (w * ie->load_opts.dpi) / 75.0;
- h = (h * ie->load_opts.dpi) / 75.0;
- }
- else if ((ie->load_opts.w > 0) &&
- (ie->load_opts.h > 0))
- {
- unsigned int w2, h2;
-
- w2 = ie->load_opts.w;
- h2 = (ie->load_opts.w * h) / w;
- if (h2 > ie->load_opts.h)
- {
- h2 = ie->load_opts.h;
- w2 = (ie->load_opts.h * w) / h;
- }
- w = w2;
- h = h2;
- }
- if (w < 1) w = 1;
- if (h < 1) h = 1;
- ie->w = w;
- ie->h = h;
- ie->flags.alpha = 1;
- rsvg_handle_close(rsvg, NULL);
- g_object_unref(rsvg);
-
- *error = EVAS_LOAD_ERROR_NONE;
- return EINA_TRUE;
-}
-
-/** FIXME: All evas loaders need to be tightened up **/
-static Eina_Bool
-evas_image_load_file_data_svg(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
-{
- DATA32 *pixels;
- RsvgHandle *rsvg;
- RsvgDimensionData dim;
- int w, h;
- cairo_surface_t *surface;
- cairo_t *cr;
-
- /* ignore all files not called .svg or .svg.gz - because rsvg has a leak
- * where closing the handle doesn't free mem */
- if (!evas_image_load_file_is_svg(file))
- {
- *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
- return EINA_FALSE;
- }
-
- rsvg = rsvg_handle_new_from_file(file, NULL);
- if (!rsvg)
- {
- *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
- return EINA_FALSE;
- }
-
- rsvg_handle_set_dpi(rsvg, 75.0);
- rsvg_handle_get_dimensions(rsvg, &dim);
- w = dim.width;
- h = dim.height;
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
- {
- rsvg_handle_close(rsvg, NULL);
- g_object_unref(rsvg);
- if (IMG_TOO_BIG(w, h))
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- else
- *error = EVAS_LOAD_ERROR_GENERIC;
- return EINA_FALSE;
- }
- if (ie->load_opts.scale_down_by > 1)
- {
- w /= ie->load_opts.scale_down_by;
- h /= ie->load_opts.scale_down_by;
- }
- else if (ie->load_opts.dpi > 0.0)
- {
- w = (w * ie->load_opts.dpi) / 75.0;
- h = (h * ie->load_opts.dpi) / 75.0;
- }
- else if ((ie->load_opts.w > 0) &&
- (ie->load_opts.h > 0))
- {
- unsigned int w2, h2;
-
- w2 = ie->load_opts.w;
- h2 = (ie->load_opts.w * h) / w;
- if (h2 > ie->load_opts.h)
- {
- h2 = ie->load_opts.h;
- w2 = (ie->load_opts.h * w) / h;
- }
- w = w2;
- h = h2;
- }
- if (w < 1) w = 1;
- if (h < 1) h = 1;
- if ((w != (int)ie->w) || (h != (int)ie->h))
- {
- *error = EVAS_LOAD_ERROR_GENERIC;
- goto error;
- }
- ie->flags.alpha = 1;
- evas_cache_image_surface_alloc(ie, w, h);
- pixels = evas_cache_image_pixels(ie);
- if (!pixels)
- {
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto error;
- }
-
- memset(pixels, 0, w * h * sizeof(DATA32));
- surface = cairo_image_surface_create_for_data((unsigned char *)pixels, CAIRO_FORMAT_ARGB32,
- w, h, w * sizeof(DATA32));
- if (!surface)
- {
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto error;
- }
- cr = cairo_create(surface);
- if (!cr)
- {
- cairo_surface_destroy(surface);
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto error;
- }
-
- cairo_scale(cr,
- (double)ie->w / dim.em,
- (double)ie->h / dim.ex);
- rsvg_handle_render_cairo(rsvg, cr);
- cairo_surface_destroy(surface);
- /* need to check if this is required... */
- cairo_destroy(cr);
- rsvg_handle_close(rsvg, NULL);
- g_object_unref(rsvg);
- evas_common_image_set_alpha_sparse(ie);
- return EINA_TRUE;
-
- error:
- rsvg_handle_close(rsvg, NULL);
- g_object_unref(rsvg);
- return EINA_FALSE;
-}
-
-static int
-module_open(Evas_Module *em)
-{
- if (!em) return 0;
- em->functions = (void *)(&evas_image_load_svg_func);
- if (!rsvg_initialized) rsvg_init();
- rsvg_initialized = 1;
- return 1;
-}
-
-static void
-module_close(Evas_Module *em __UNUSED__)
-{
- if (!rsvg_initialized) return;
- //rsvg_term();
- //rsvg_initialized = 0;
-}
-
-static Evas_Module_Api evas_modapi =
-{
- EVAS_MODULE_API_VERSION,
- "svg",
- "none",
- {
- module_open,
- module_close
- }
-};
-
-EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, svg);
-
-#ifndef EVAS_STATIC_BUILD_SVG
-EVAS_EINA_MODULE_DEFINE(image_loader, svg);
-#endif