From 61656c2ecce7b5dc6a3a365bff0130be0e54e897 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Wed, 16 May 2012 21:28:36 +0000 Subject: [PATCH] Evas: use Esvg for svg rendering. If Esvg is not found, librsvg is used (if found) See README to see how to installe Esvg SVN revision: 71180 --- legacy/evas/README | 25 +- legacy/evas/m4/evas_check_loader.m4 | 20 +- .../evas/src/modules/loaders/svg/Makefile.am | 12 +- .../loaders/svg/evas_image_load_esvg.c | 301 ++++++++++++++++++ ...mage_load_svg.c => evas_image_load_rsvg.c} | 0 5 files changed, 344 insertions(+), 14 deletions(-) create mode 100644 legacy/evas/src/modules/loaders/svg/evas_image_load_esvg.c rename legacy/evas/src/modules/loaders/svg/{evas_image_load_svg.c => evas_image_load_rsvg.c} (100%) diff --git a/legacy/evas/README b/legacy/evas/README index 78c068b2b3..f7b076340f 100644 --- a/legacy/evas/README +++ b/legacy/evas/README @@ -27,7 +27,7 @@ Recommended: liblinebreak Optional: - XCB SDL OpenGL librsvg libtiff libgif edb DirectFB evas_generic_loaders + XCB SDL OpenGL esvg/librsvg libtiff libgif edb DirectFB evas_generic_loaders Evas is a clean display canvas API for several target display systems that can draw anti-aliased text, smooth super and sub-sampled scaled @@ -506,11 +506,24 @@ bitmap data in binary or ascii format --enable-image-loader-svg[=static] -this loader can load svg files via librsvg (thus it is a dependency). -this loader supports load options to set the dpi to decode the svg at -etc. which can then be used to create scalable images that scale to -any size without becoming blocky or blurry, if the source is an svg -file. +this loader can load svg files via esvg or librsvg (thus it is a +dependency). This loader supports load options to set the dpi to +decode the svg at etc. which can then be used to create scalable +images that scale to any size without becoming blocky or blurry, if +the source is an svg file. + +Esvg can be found here: + +http://code.google.com/p/enesim/ + +Install (in that order): + +enesim +emage +etex +ender +etch +egueb --enable-image-loader-tiff[=static] diff --git a/legacy/evas/m4/evas_check_loader.m4 b/legacy/evas/m4/evas_check_loader.m4 index a26509403c..ea5015701f 100644 --- a/legacy/evas/m4/evas_check_loader.m4 +++ b/legacy/evas/m4/evas_check_loader.m4 @@ -228,15 +228,21 @@ AC_DEFUN([EVAS_CHECK_LOADER_DEP_SVG], [ requirement="" -have_dep="no" +have_esvg="no" evas_image_loader_[]$1[]_cflags="" evas_image_loader_[]$1[]_libs="" -PKG_CHECK_MODULES([SVG], [librsvg-2.0 >= 2.14.0 - cairo >= 1.0.0], - [have_dep="yes" requirement="librsvg-2.0 cairo"], - [have_svg="no"] -) +PKG_CHECK_MODULES([SVG], + [esvg >= 0.0.16], + [have_dep="yes" have_esvg="yes" requirement="esvg"], + [have_dep="no"]) + +if test "x${have_dep}" = "xno" ; then + PKG_CHECK_MODULES([SVG], + [librsvg-2.0 >= 2.14.0 cairo >= 1.0.0], + [have_dep="yes" requirement="librsvg-2.0 cairo"], + [have_dep="no"]) +fi if test "x${have_dep}" = "xyes" ; then evas_image_loader_[]$1[]_cflags="${SVG_CFLAGS}" @@ -250,6 +256,8 @@ if test "x$2" = "xstatic" ; then requirement_evas="${requirement} ${requirement_evas}" fi +AM_CONDITIONAL(BUILD_LOADER_SVG_ESVG, [test "x${have_esvg}" = "xyes"]) + if test "x${have_dep}" = "xyes" ; then m4_default([$3], [:]) else diff --git a/legacy/evas/src/modules/loaders/svg/Makefile.am b/legacy/evas/src/modules/loaders/svg/Makefile.am index 39cb1b0054..2b47de327b 100644 --- a/legacy/evas/src/modules/loaders/svg/Makefile.am +++ b/legacy/evas/src/modules/loaders/svg/Makefile.am @@ -17,7 +17,11 @@ if !EVAS_STATIC_BUILD_SVG pkgdir = $(libdir)/evas/modules/loaders/svg/$(MODULE_ARCH) pkg_LTLIBRARIES = module.la -module_la_SOURCES = evas_image_load_svg.c +if BUILD_LOADER_SVG_ESVG +module_la_SOURCES = evas_image_load_esvg.c +else +module_la_SOURCES = evas_image_load_rsvg.c +endif module_la_LIBADD = @EINA_LIBS@ @evas_image_loader_svg_libs@ $(top_builddir)/src/lib/libevas.la module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version @@ -26,7 +30,11 @@ module_la_LIBTOOLFLAGS = --tag=disable-static else noinst_LTLIBRARIES = libevas_loader_svg.la -libevas_loader_svg_la_SOURCES = evas_image_load_svg.c +if BUILD_LOADER_SVG_ESVG +libevas_loader_svg_la_SOURCES = evas_image_load_esvg.c +else +libevas_loader_svg_la_SOURCES = evas_image_load_rsvg.c +endif libevas_loader_svg_la_LIBADD = @evas_image_loader_svg_libs@ endif diff --git a/legacy/evas/src/modules/loaders/svg/evas_image_load_esvg.c b/legacy/evas/src/modules/loaders/svg/evas_image_load_esvg.c new file mode 100644 index 0000000000..92100f6ed1 --- /dev/null +++ b/legacy/evas/src/modules/loaders/svg/evas_image_load_esvg.c @@ -0,0 +1,301 @@ +#include + +#include "evas_common.h" +#include "evas_private.h" + +#include + +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 Eina_Bool esvg_initialized = EINA_FALSE; + + +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) +{ + Ender_Element *e; + int w, h; + double sw, sh; + + /* 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; + } + + e = esvg_parser_load(file, NULL, NULL); + if (!e) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + esvg_renderable_x_dpi_set(e, 75.0); + esvg_renderable_y_dpi_set(e, 75.0); + esvg_svg_actual_width_get(e, &sw); + esvg_svg_actual_height_get(e, &sh); + esvg_element_setup(e, NULL); + w = (int)ceil(sw); + h = (int)ceil(sh); + if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || + IMG_TOO_BIG(w, h)) + { + ender_element_delete(e); + 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; + + ender_element_delete(e); + + *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; + Ender_Element *e; + Enesim_Error *err = NULL; + Enesim_Surface *s; + void *data; + size_t stride; + int w, h; + double sw, sh; + + if (!evas_image_load_file_is_svg(file)) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE; + } + + e = esvg_parser_load(file, NULL, NULL); + if (!e) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + esvg_renderable_x_dpi_set(e, 75.0); + esvg_renderable_y_dpi_set(e, 75.0); + esvg_svg_actual_width_get(e, &sw); + esvg_svg_actual_height_get(e, &sh); + w = (int)ceil(sw); + h = (int)ceil(sh); + if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE)) + { + ender_element_delete(e); + if (IMG_TOO_BIG(w, h)) + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + else + *error = EVAS_LOAD_ERROR_GENERIC; + goto unref_renderer; + } + 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 unref_renderer; + } + 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 unref_renderer; + } + + memset(pixels, 0, w * h * sizeof(DATA32)); + + s = enesim_surface_new(ENESIM_FORMAT_ARGB8888, w, h); + if (!s) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto unref_renderer; + } + + esvg_element_setup(e, NULL); + + if (!esvg_renderable_draw(e, s, NULL, 0, 0, &err)) + { + *error = EVAS_LOAD_ERROR_GENERIC; + enesim_error_dump(err); + goto unref_surface; + } + + if (!enesim_surface_data_get(s, &data, &stride)) + { + *error = EVAS_LOAD_ERROR_GENERIC; + goto unref_surface; + } + +/* printf("test : %d %d\n", w * h * sizeof(int), h * stride); */ +/* if ((w * h * sizeof(int)) != (h * stride)) */ +/* { */ +/* *error = EVAS_LOAD_ERROR_GENERIC; */ +/* goto unref_surface; */ +/* } */ + + /* FIXME: scale to (double)ie->w / dim.em, (double)ie->h / dim.ex */ + + memcpy (pixels, data, h * stride); + + enesim_surface_unref(s); + ender_element_delete(e); + + evas_common_image_set_alpha_sparse(ie); + + return EINA_TRUE; + + unref_surface: + enesim_surface_unref(s); + unref_renderer: + ender_element_delete(e); + + return EINA_FALSE; +} + +static int +module_open(Evas_Module *em) +{ + if (!em) return 0; + em->functions = (void *)(&evas_image_load_svg_func); + if (!esvg_initialized) esvg_init(); + esvg_initialized = EINA_TRUE; + return 1; +} + +static void +module_close(Evas_Module *em __UNUSED__) +{ + if (!esvg_initialized) return; + esvg_shutdown(); + esvg_initialized = EINA_FALSE; +} + +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 diff --git a/legacy/evas/src/modules/loaders/svg/evas_image_load_svg.c b/legacy/evas/src/modules/loaders/svg/evas_image_load_rsvg.c similarity index 100% rename from legacy/evas/src/modules/loaders/svg/evas_image_load_svg.c rename to legacy/evas/src/modules/loaders/svg/evas_image_load_rsvg.c