// // SVG Image header file for the Fast Light Tool Kit (FLTK). // // Copyright 2017-2022 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: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_SVG_IMAGE_H #define FL_SVG_IMAGE_H #include struct NSVGimage; /** The Fl_SVG_Image class supports loading, caching and drawing of scalable vector graphics (SVG) images. The FLTK library performs parsing and rasterization of SVG data using a modified version of the \c nanosvg software (https://github.com/memononen/nanosvg). The software modification allows the option to change the image ratio while performing rasterization. Use Fl_Image::fail() to check if the Fl_SVG_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, and ERR_FORMAT if the SVG format could not be decoded. If the image has loaded correctly, w(), h(), and d() should return values greater than zero. Rasterization is not done until the image is first drawn or resize() or normalize() is called. Therefore, \ref array is NULL until then. The delayed rasterization ensures an Fl_SVG_Image is always rasterized to the exact screen resolution at which it is drawn. The Fl_SVG_Image class draws images computed by \c nanosvg with the following known limitations - text between \c and marks, - \c image elements, and - statements are not rendered. The FLTK library can optionally be built without SVG support; in that case, class Fl_SVG_Image is unavailable. Example of displaying a hard-coded svg file: \code #include #include #include #include // A black rotated rectangle const char *svg_data = "\n" " \n"; int main(int argc, char **argv) { Fl_SVG_Image *svg = new Fl_SVG_Image(0, svg_data); // create SVG object Fl_Window *win = new Fl_Window(720, 486, "svg test"); Fl_Box *box = new Fl_Box(0, 0, win->w(), win->h()); box->image(svg); // assign svg object to Fl_Box win->end(); win->show(argc,argv); return(Fl::run()); } \endcode Example of displaying an svg image from a file: \code #include // errno #include // strerror #include #include #include #include #include int main(int argc, char **argv) { Fl_Window *win = new Fl_Window(720, 486, "svg test"); Fl_Box *box = new Fl_Box(0, 0, win->w(), win->h()); // Load svg image from disk, assign to a box const char *svgpath = "/var/tmp/simple.svg"; Fl_SVG_Image *svg = new Fl_SVG_Image(svgpath); // load SVG object from disk switch (svg->fail()) { case Fl_Image::ERR_FILE_ACCESS: // File couldn't load? show path + os error to user fl_alert("%s: %s", svgpath, strerror(errno)); return 1; case Fl_Image::ERR_FORMAT: // Parsing error fl_alert("%s: couldn't decode image", svgpath); return 1; } box->image(svg); // assign svg object to box win->end(); win->show(argc,argv); return(Fl::run()); } \endcode Example of fitting an svg image to a resizable Fl_Box: \code #include #include #include class resizable_box : public Fl_Box { public: resizable_box(int w, int h) : Fl_Box(0, 0, w, h, NULL) {} virtual void resize(int x, int y, int w, int h) { image()->scale(w, h, 1, 1); // p3 = proportional, p4 = can_expand Fl_Box::resize(x, y, w, h); } }; int main(int argc, char **argv) { Fl_Window *win = new Fl_Window(130, 130); resizable_box *box = new resizable_box(win->w(), win->h()); Fl_SVG_Image *svg = new Fl_SVG_Image("/path/to/image.svg"); box->image(svg); svg->scale(box->w(), box->h()); win->end(); win->resizable(win); win->show(argc, argv); return Fl::run(); } \endcode */ class FL_EXPORT Fl_SVG_Image : public Fl_RGB_Image { private: typedef struct { NSVGimage* svg_image; int ref_count; } counted_NSVGimage; counted_NSVGimage* counted_svg_image_; bool rasterized_; int raster_w_, raster_h_; bool to_desaturate_; Fl_Color average_color_; float average_weight_; float svg_scaling_(int W, int H); void rasterize_(int W, int H); virtual void cache_size_(int &width, int &height); void init_(const char *filename, const unsigned char *filedata, const Fl_SVG_Image *copy_source, size_t length); Fl_SVG_Image(const Fl_SVG_Image *source); public: /** Set this to \c false to allow image re-scaling that alters the image aspect ratio. Upon object creation, proportional is set to \c true, and the aspect ratio is kept constant.*/ bool proportional; Fl_SVG_Image(const char *filename, const char *svg_data = NULL, size_t length = 0); virtual ~Fl_SVG_Image(); virtual Fl_Image *copy(int W, int H) const; Fl_Image *copy() const { return Fl_Image::copy(); } void resize(int width, int height); virtual void desaturate(); virtual void color_average(Fl_Color c, float i); virtual void draw(int X, int Y, int W, int H, int cx = 0, int cy = 0); void draw(int X, int Y) { draw(X, Y, w(), h(), 0, 0); } virtual Fl_SVG_Image *as_svg_image() { return this; } virtual void normalize(); }; #endif // FL_SVG_IMAGE_H