diff options
| author | Manolo Gouy <Manolo> | 2017-09-03 13:14:25 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2017-09-03 13:14:25 +0000 |
| commit | 1a28d85dc3f8f062401002bebc8e8a59805cce9b (patch) | |
| tree | 4fd0412732046d526e44476ea22eab343c36673c /src/Fl_SVG_Image.cxx | |
| parent | da31ff4569a252e314ab91b3ea9cc11aafec2a24 (diff) | |
Add new Fl_SVG_Image class to support scalable vector graphics images using the (modified) nanosvg software.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12413 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_SVG_Image.cxx')
| -rw-r--r-- | src/Fl_SVG_Image.cxx | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/Fl_SVG_Image.cxx b/src/Fl_SVG_Image.cxx new file mode 100644 index 000000000..0e04f8201 --- /dev/null +++ b/src/Fl_SVG_Image.cxx @@ -0,0 +1,206 @@ +// +// "$Id: Fl_SVG_Image.cxx 12239 2017-05-17 11:54:18Z manolo $" +// +// SVG image code for the Fast Light Tool Kit (FLTK). +// +// Copyright 2017 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <config.h> + +#if defined(FLTK_USE_NANOSVG) || defined(FL_DOXYGEN) + +#include <FL/Fl_SVG_Image.H> +#include <stdio.h> + +#define NANOSVG_ALL_COLOR_KEYWORDS // Include full list of color keywords. +#define NANOSVG_IMPLEMENTATION // Expands implementation +#include "../nanosvg/nanosvg.h" + +#define NANOSVGRAST_IMPLEMENTATION // Expands implementation +#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. + \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 requires that \p filename is NULL. + \note In-memory SVG data is modified by the object constructor and is no longer used after construction. + */ +Fl_SVG_Image::Fl_SVG_Image(const char *filename, char *filedata) : Fl_RGB_Image(NULL, 0, 0, 4) { + init_(filename, filedata, NULL); +} + + +// private constructor +Fl_SVG_Image::Fl_SVG_Image(Fl_SVG_Image *source) : Fl_RGB_Image(NULL, 0, 0, 4) { + init_(NULL, NULL, source); +} + + +/** The destructor frees all memory and server resources that are used by the SVG image. */ +Fl_SVG_Image::~Fl_SVG_Image() { + if ( --counted_svg_image_->ref_count <= 0) { + nsvgDelete(counted_svg_image_->svg_image); + delete counted_svg_image_; + } +} + + +float Fl_SVG_Image::svg_scaling_(int W, int H) { + float f1 = float(W) / int(counted_svg_image_->svg_image->width+0.5); + float f2 = float(H) / int(counted_svg_image_->svg_image->height+0.5); + return (f1 < f2) ? f1 : f2; +} + + +void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *copy_source) { + if (copy_source) { + filename = filedata = NULL; + counted_svg_image_ = copy_source->counted_svg_image_; + counted_svg_image_->ref_count++; + } else { + counted_svg_image_ = new counted_NSVGimage; + counted_svg_image_->svg_image = NULL; + counted_svg_image_->ref_count = 1; + } + to_desaturate_ = false; + average_weight_ = 1; + proportional = true; + if (filename) { + filedata = NULL; + FILE *fp = fopen(filename, "rb"); + if (fp) { + fseek(fp, 0, SEEK_END); + size_t 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'; + else { + free(filedata); + filedata = NULL; + } + } + fclose(fp); + } else ld(ERR_FILE_ACCESS); + } + if (filedata) { + counted_svg_image_->svg_image = nsvgParse(filedata, "px", 96); + if (filename) free(filedata); + if (counted_svg_image_->svg_image->width == 0 || counted_svg_image_->svg_image->height == 0) { + d(-1); + ld(ERR_FORMAT); + } else { + w(counted_svg_image_->svg_image->width + 0.5); + h(counted_svg_image_->svg_image->height + 0.5); + } + } else if (copy_source) { + w(copy_source->w()); + h(copy_source->h()); + } + rasterized_ = false; +} + + +void Fl_SVG_Image::rasterize_(int W, int H) { + static NSVGrasterizer *rasterizer = nsvgCreateRasterizer(); + double fx, fy; + if (proportional) { + fx = svg_scaling_(W, H); + fy = fx; + } else { + fx = (double)W / counted_svg_image_->svg_image->width; + fy = (double)H / counted_svg_image_->svg_image->height; + } + array = new uchar[W*H*4]; + nsvgAltRasterize(rasterizer, counted_svg_image_->svg_image, 0, 0, fx, fy, (uchar* )array, W, H, W*4); + alloc_array = 1; + data((const char * const *)&array, 1); + d(4); + if (to_desaturate_) Fl_RGB_Image::desaturate(); + if (average_weight_ < 1) Fl_RGB_Image::color_average(average_color_, average_weight_); + rasterized_ = true; + raster_w_ = W; + raster_h_ = H; +} + + +Fl_Image *Fl_SVG_Image::copy(int W, int H) { + Fl_SVG_Image *svg2 = new Fl_SVG_Image(this); + svg2->to_desaturate_ = to_desaturate_; + svg2->average_weight_ = average_weight_; + svg2->average_color_ = average_color_; + svg2->w(W); svg2->h(H); + return svg2; +} + + +/** Have the svg data (re-)rasterized using the given width and height values. + By default, the resulting image width and height will preserve the width/height ratio + of the SVG data. + If \ref proportional was set to false, the image is rasterized to the given \c width + and \v height values.*/ +void Fl_SVG_Image::resize(int width, int height) { + if (ld() < 0) { + return; + } + int w1 = width, h1 = height; + if (proportional) { + float f = svg_scaling_(width, height); + w1 = int( int(counted_svg_image_->svg_image->width+0.5)*f + 0.5 ); + h1 = int( int(counted_svg_image_->svg_image->height+0.5)*f + 0.5 ); + } + w(w1); h(h1); + if (rasterized_ && w1 == raster_w_ && h1 == raster_h_) return; + if (array) { + delete[] array; + array = NULL; + } + uncache(); + rasterize_(w1, h1); +} + + +void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) { + resize(w(), h()); + Fl_RGB_Image::draw(X, Y, W, H, cx, cy); +} + + +void Fl_SVG_Image::desaturate() { + to_desaturate_ = true; + Fl_RGB_Image::desaturate(); +} + + +void Fl_SVG_Image::color_average(Fl_Color c, float i) { + average_color_ = c; + average_weight_ = i; + Fl_RGB_Image::color_average(c, i); +} + + +int Fl_SVG_Image::draw_scaled_(int X, int Y, int W, int H) { + w(W); + h(H); + draw(X, Y, W, H, 0, 0); + return 1; +} + +#endif // FLTK_USE_NANOSVG + + +// +// End of "$Id: Fl_SVG_Image.cxx 12239 2017-05-17 11:54:18Z manolo $". +// |
