From 0b797d704c718aba64720734377f7b23aa0098f5 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Wed, 4 Oct 2017 16:26:51 +0000 Subject: Fl_SVG_Image class: add support for compressed .svgz image files. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12477 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_SVG_Image.cxx | 69 ++++++++++++++++++++++++++++++++++++++++++++++---- src/fl_images_core.cxx | 13 +++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Fl_SVG_Image.cxx b/src/Fl_SVG_Image.cxx index c30227daa..c5ad1e69f 100644 --- a/src/Fl_SVG_Image.cxx +++ b/src/Fl_SVG_Image.cxx @@ -26,6 +26,9 @@ #include #include #include +#if defined(HAVE_LIBZ) +#include +#endif #if !defined(HAVE_LONG_LONG) static double strtoll(const char *str, char **endptr, int base) { @@ -41,8 +44,8 @@ static double strtoll(const char *str, char **endptr, int base) { #include "../nanosvg/altsvgrast.h" -/** The constructor loads the SVG image from the given .svg filename or in-memory data. - \param filename A full path and name pointing to an SVG file, or NULL. +/** The constructor loads the SVG image from the given .svg/.svgz filename or in-memory data. + \param filename A full path and name pointing to a .svg or .svgz file, or NULL. \param filedata A pointer to the memory location of the SVG image data. This parameter allows to load an SVG image from in-memory data, and is used when \p filename is NULL. \note In-memory SVG data is modified by the object constructor and is no longer used after construction. @@ -73,6 +76,55 @@ float Fl_SVG_Image::svg_scaling_(int W, int H) { return (f1 < f2) ? f1 : f2; } +/** Opens for reading a potentially gzip'ed file identified by a UTF-8 encoded filename. */ +void* Fl_SVG_Image::gzopen(const char *fname) { +#if defined(HAVE_LIBZ) +# ifdef _WIN32 + unsigned wl = fl_utf8towc(fname, strlen(fname), NULL, 0) + 1; + wchar_t *wc = new wchar_t[wl]; + fl_utf8towc(fname, strlen(fname), wc, wl); + gzFile gzf = gzopen_w(wc, "r"); + delete[] wc; + return gzf; +# else + int fd = fl_open(fname, 0); + if (fd < 0) return NULL; + return gzdopen(fd, "r"); +# endif +#else + return NULL; +#endif // HAVE_LIBZ +} + +#if defined(HAVE_LIBZ) + +static char *svg_inflate(const char *fname) { + struct stat b; + fl_stat(fname, &b); + long size = b.st_size; + gzFile gzf = (gzFile)Fl_SVG_Image::gzopen(fname); + int l; + bool direct = gzdirect(gzf); + long out_size = direct ? size + 1 : 3*size + 1; + char *out = (char*)malloc(out_size); + char *p = out; + do { + if ((!direct) && p + size > out + out_size) { + out_size += size; + char *tmp = (char*)realloc(out, out_size + 1); + p = tmp + (p - out); + out = tmp; + } + l = gzread(gzf, p, size); + if (l > 0) { + p += l; *p = 0; + } + } while ((!direct) && l >0); + gzclose(gzf); + if (!direct) out = (char*)realloc(out, (p-out)+1); + return out; +} +#endif void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *copy_source) { if (copy_source) { @@ -88,22 +140,29 @@ void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *cop average_weight_ = 1; proportional = true; if (filename) { +#if defined(HAVE_LIBZ) + filedata = svg_inflate(filename); +#else filedata = NULL; FILE *fp = fl_fopen(filename, "rb"); if (fp) { fseek(fp, 0, SEEK_END); - size_t size = ftell(fp); + long size = ftell(fp); fseek(fp, 0, SEEK_SET); filedata = (char*)malloc(size+1); if (filedata) { - if (fread(filedata, 1, size, fp) == size) filedata[size] = '\0'; + if (fread(filedata, 1, size, fp) == size) { + filedata[size] = '\0'; + } else { free(filedata); filedata = NULL; } } fclose(fp); - } else ld(ERR_FILE_ACCESS); + } +#endif // HAVE_LIBZ + if (!filedata) ld(ERR_FILE_ACCESS); } if (filedata) { counted_svg_image_->svg_image = nsvgParse(filedata, "px", 96); diff --git a/src/fl_images_core.cxx b/src/fl_images_core.cxx index 5af696764..3ed225c8c 100644 --- a/src/fl_images_core.cxx +++ b/src/fl_images_core.cxx @@ -35,7 +35,9 @@ #include #include #include "flstring.h" - +#if defined(HAVE_LIBZ) +#include +#endif // // Define a simple global image registration function that registers @@ -90,6 +92,15 @@ fl_check_images(const char *name, // I - Filename #endif // HAVE_LIBJPEG #ifdef FLTK_USE_NANOSVG +# if defined(HAVE_LIBZ) + if (header[0] == 0x1f && header[1] == 0x8b) { // denotes gzip'ed data + gzFile gzf = (gzFile)Fl_SVG_Image::gzopen(name); + if (gzf) { + gzread(gzf, header, headerlen); + gzclose(gzf); + } + } +# endif // HAVE_LIBZ if ( (headerlen > 5 && memcmp(header, "