Evas: use Esvg for svg rendering.
authorcaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 16 May 2012 21:28:36 +0000 (21:28 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 16 May 2012 21:28:36 +0000 (21:28 +0000)
If Esvg is not found, librsvg is used (if found)

See README to see how to installe Esvg

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@71180 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

README
m4/evas_check_loader.m4
src/modules/loaders/svg/Makefile.am
src/modules/loaders/svg/evas_image_load_esvg.c [new file with mode: 0644]
src/modules/loaders/svg/evas_image_load_rsvg.c [moved from src/modules/loaders/svg/evas_image_load_svg.c with 100% similarity]

diff --git a/README b/README
index 78c068b..f7b0763 100644 (file)
--- a/README
+++ b/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]
index a265094..ea50157 100644 (file)
@@ -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
index 39cb1b0..2b47de3 100644 (file)
@@ -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/src/modules/loaders/svg/evas_image_load_esvg.c b/src/modules/loaders/svg/evas_image_load_esvg.c
new file mode 100644 (file)
index 0000000..92100f6
--- /dev/null
@@ -0,0 +1,301 @@
+#include <math.h>
+
+#include "evas_common.h"
+#include "evas_private.h"
+
+#include <Esvg.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 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