From d5619bcf6707e1fe737505afb5a38da70ca420a0 Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Wed, 24 Jul 2019 15:45:49 +0900 Subject: [PATCH] Backported missing svg loader from upstream Change-Id: Ie1aff1cc8a597d3ad20502aa914de153e339fab3 --- src/generic/evas/svg/main.c | 236 +++++++++++++++++++++++++++++++++++++++ src/generic/evas/svg/meson.build | 12 ++ 2 files changed, 248 insertions(+) create mode 100644 src/generic/evas/svg/main.c create mode 100644 src/generic/evas/svg/meson.build diff --git a/src/generic/evas/svg/main.c b/src/generic/evas/svg/main.c new file mode 100644 index 0000000..f197330 --- /dev/null +++ b/src/generic/evas/svg/main.c @@ -0,0 +1,236 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "shmfile.h" +#include "timeout.h" + +#include + +#include +#ifndef LIBRSVG_CHECK_VERSION +# include +#endif +#if LIBRSVG_CHECK_VERSION(2,36,2) +#else +# include +#endif + +#define DATA32 unsigned int + +static RsvgHandle *rsvg = NULL; +static int width = 0; +static int height = 0; +static RsvgDimensionData dim; + +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 int +_svg_init(const char *file) +{ +#ifdef HAVE_SVG_2_36 +# if !defined(GLIB_VERSION_2_36) + g_type_init(); +# endif +#else + rsvg_init(); +#endif + + if (!evas_image_load_file_is_svg(file)) return 0; + + rsvg = rsvg_handle_new_from_file(file, NULL); + if (!rsvg) return 0; + + return 1; +} + +static void +_svg_shutdown(void) +{ + if (rsvg) + { + rsvg_handle_close(rsvg, NULL); + g_object_unref(rsvg); + } + // Maybe it's not crashing anymore, let's try it. +#ifndef HAVE_SVG_2_36 + rsvg_term(); +#endif +} + +static int +read_svg_header(int scale_down, double dpi, int size_w, int size_h) +{ + rsvg_handle_set_dpi(rsvg, 75.0); + rsvg_handle_get_dimensions(rsvg, &dim); + width = dim.width; + height = dim.height; + + if ((width < 1) || (height < 1)) return 0; + + if (scale_down > 1) + { + width /= scale_down; + height /= scale_down; + } + else if (dpi > 0.0) + { + width = (width * dpi) / 75; + height = (height * dpi) / 75; + } + else if (size_w > 0 && size_h > 0) + { + int w, h; + + w = size_w; + h = (size_w * height) / width; + if (h > size_h) + { + h = size_h; + w = (size_h * width) / height; + } + width = w; + height = h; + } + if (width < 1) width = 1; + if (height < 1) height = 1; + + return 1; +} + +static int +read_svg_data(void) +{ + cairo_surface_t *surface; + cairo_t *cr; + + shm_alloc(width * height * (sizeof(DATA32))); + if (!shm_addr) return 0; + + memset(shm_addr, 0, width * height * sizeof (DATA32)); + surface = cairo_image_surface_create_for_data((unsigned char *)shm_addr, CAIRO_FORMAT_ARGB32, + width, height, width * sizeof(DATA32));; + if (!surface) return 0; + + cr = cairo_create(surface); + if (!cr) return 0; + + cairo_scale(cr, (double) width / dim.em, (double) height / dim.ex); + rsvg_handle_render_cairo(rsvg, cr); + cairo_surface_destroy(surface); + cairo_destroy(cr); + + return 1; +} + +int main(int argc, char **argv) +{ + char *file; + int i; + int head_only = 0; + int scale_down = 0; + double dpi = 0.0; + int size_w = 0, size_h = 0; + + if (argc < 2) return -1; + file = argv[1]; + + for (i = 2; i < argc; ++i) + { + if (!strcmp(argv[i], "-head")) + head_only = 1; + else if (!strcmp(argv[i], "-key")) + { // not used by svg loader + i++; + // const char *key = argv[i]; + } + else if (!strcmp(argv[i], "-opt-scale-down-by")) + { + i++; + scale_down = atoi(argv[i]); + } + else if (!strcmp(argv[i], "-opt-dpi")) + { + i++; + dpi = ((double)atoi(argv[i])) / 1000.0; + } + else if (!strcmp(argv[i], "-opt-size")) + { + i++; + size_w = atoi(argv[i]); + i++; + size_h = atoi(argv[i]); + } + } + + timeout_init(5); + + if (!_svg_init(file)) return -1; + if (!read_svg_header(scale_down, dpi, size_w, size_h)) return -1; + + if (head_only != 0) + { + printf("size %d %d\n", width, height); + printf("alpha 1\n"); + printf("done\n"); + } + else + { + if (read_svg_data()) + { + printf("size %d %d\n", width, height); + printf("alpha 1\n"); + if (shm_fd >= 0) printf("shmfile %s\n", shmfile); + else + { + printf("data\n"); + if (fwrite(shm_addr, width * height * sizeof(DATA32), 1, stdout) != 1) + { + // nothing much to do, the receiver will simply ignore the + // data as it's too short + //D("fwrite failed (%d bytes): %m\n", width * height * sizeof(DATA32)); + } + } + shm_free(); + } + } + _svg_shutdown(); + fflush(stdout); + return 0; + +} + diff --git a/src/generic/evas/svg/meson.build b/src/generic/evas/svg/meson.build new file mode 100644 index 0000000..4e39e74 --- /dev/null +++ b/src/generic/evas/svg/meson.build @@ -0,0 +1,12 @@ +generic_src = files([ + 'main.c' +]) + +rsvg = dependency('librsvg-2.0') + +if rsvg.version() >= '2.36.0' + config_h.set('HAVE_SVG_2_36', '1') +endif + +generic_deps = [rsvg] +generic_support = ['svgz', 'svg.gz'] -- 2.7.4