FLTK logo

STR #3345

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]

Return to Bugs & Features | SVN ⇄ GIT ]

STR #3345

Application:FLTK Library
Status:1 - Closed w/Resolution
Priority:1 - Request for Enhancement, e.g. asking for a feature
Scope:3 - Applies to all machines and operating systems
Subsystem:Image Support
Summary:SVG image support
Created By:AlbrechtS
Assigned To:AlbrechtS
Fix Version:1.4.0 (SVN: v12413)
Update Notification:

Receive EMails Don't Receive EMails

Trouble Report Files:

Name/Time/Date Filename/Size  
#1 AlbrechtS
16:25 Oct 19, 2016
#2 AlbrechtS
16:31 Oct 19, 2016
#3 AlbrechtS
16:32 Oct 19, 2016
#4 AlbrechtS
07:36 Oct 21, 2016
#5 AlbrechtS
08:03 Oct 21, 2016
#6 AlbrechtS
08:24 Oct 24, 2016
#7 AlbrechtS
09:21 Oct 24, 2016
#8 manolo
00:38 Oct 30, 2016
#9 manolo
05:22 Nov 01, 2016
#10 manolo
09:22 Aug 30, 2017
#11 manolo
04:15 Aug 31, 2017
#12 AlbrechtS
07:36 Aug 31, 2017
#13 AlbrechtS
07:46 Aug 31, 2017
#14 manolo
07:23 Sep 01, 2017

Trouble Report Comments:

Name/Time/Date Text  
#1 AlbrechtS
16:25 Oct 19, 2016
Inspired by the discussion on STR #3341 I could not resist to test if and how FLTK might get support for SVG images, thanks to Chris (OP of STR #3341).
See comment #9.

I wrote a short test program to display an SVG image in FLTK with the mentioned nanosvg library.

The usage is simple: include two header files (together ~115 KB) in a C file to get the entire library implementation like this:

$ cat nanosvg.c
#include <stdio.h>
#include <string.h>
#include <math.h>

#define NANOSVG_ALL_COLOR_KEYWORDS      // Include full list of color keywords.
#define NANOSVG_IMPLEMENTATION          // Expands implementation
#include "nanosvg.h"

#define NANOSVGRAST_IMPLEMENTATION      // Expands implementation
#include "nanosvgrast.h"

That's all for the nanosvg library.

The demo program uses "nanosvg.h" to read the svg image file and "nanosvgrast.h" to rasterize the svg data into a memory buffer suitable for Fl_RGB_Image. It's really that simple.

Full source code attached, see svg.cxx.
#2 AlbrechtS
16:31 Oct 19, 2016
Attached screenshot fltk_svg_image.png shows the program in action.
Image file tiger.svg will also be uploaded shortly.

Note: reading the "docs" and writing the demo program took less than 90 minutes, but I did just the minimum to _use_ the nanosvg library. Image scaling and error handling was done to fit the task to create a demo.

I also didn't thoroughly check the license (of the library as well as the attached "Ghostscript tiger" svg image), so we'd need to check if the nanosvg library could be used and bundled with FLTK.

Have fun!
#3 AlbrechtS
17:00 Oct 19, 2016
Here is the link to the original image on Wikimedia:

Direct link to image:
#4 greg.ercolano
14:55 Oct 20, 2016
Sounds good, though I wonder if we can assume the svg files
in /usr/share/icons stay within the subset of commands nanosvg

I was unable to get nanosvg on my Sci Linux system because:

    1) There's no yum for it
    2) I 'git cloned' it, but it needs premake4 (never heard of it)
    3) There's no yum for premake or premake4
    4) Gave up for now (it's a work day)

Would be interesting to bring it into fltk if we can.. or at least
provide it as an external option.

The other SVG libraries I've seen need cairo (or similar) to render
correctly, as vector art only really draws well with the presence of
antialiased lines, which I don't think FLTK supports unless one links
with cairo.

If nanosvg has its own renderer, I'm curious Albrecht: do you have a
screenshot of what it looks like rendered in FLTK? I'm curious if it
uses antialiased lines.. if so, might be a cheap way to get antialiased
line drawing into FLTK..! ;)
#5 greg.ercolano
14:57 Oct 20, 2016
Oh, I see you included fltk_svg_image.png

Yeah, that looks pretty good..! The lines look kinda antialiased.
#6 AlbrechtS
07:36 Oct 21, 2016
Hi Greg and others,

if you can clone the github repo you're done. Just grab the two header files from the src folder:

 - src/nanosvg.h
 - src/nanosvgrast.h

and put them into the same folder as the test program.

I'm now uploading svg_v2.cxx which has direct download links included and is a standalone FLTK program that just needs the two headers mentioned above in the same folder. Rename to 'svg.cxx' and build with:

$ fltk-config --compile svg.cxx

#7 AlbrechtS
08:03 Oct 21, 2016
Regarding examples and subset the "svg language" nanosvg supports:

I downloaded several test files and also tried lots (maybe 200-300) of the icons included with Ubuntu (there are thousands of them!). I found that very few of the icons didn't render well, but OTOH 'eog' (image display tool) didn't render some of them as well. Most simple icon-type images worked pretty well and fast, but color gradients seemed to be slow when zoomed to 900x900 (default in the demo program).

I also found that some really "complicated" images were displayed well, i.e. w/o visible artefacts/bugs, but I also found an example that didn't render completely correct. Here are the links:


However, the (much smaller) reverse side renders well:

Note: the missing part on the right side of the first image (the eagle's wing and foot) seems to be something that is mirrored from the left side which could be the cause. But there is at least one more missing part (below the red and white stripes).

Uploading screenshot: Great_Seal_with_nanosvg.png
#8 AlbrechtS
08:14 Oct 21, 2016
Regarding potential inclusion in FLTK:

I used both the image parsing (nsvgParseFromFile() in nanosvg.h) and the image rasterization (nsvgRasterize() in nanosvgrast.h) that converts the parsed svg image data to RGBA image data. The latter is used to build an Fl_RGB_Image.

Since FLTK is a graphics (GUI) library I could imagine to do the second part directly in FLTK, i.e. direct rendering of the parsed svg image data in FLTK (in Fl_SVG_Image::draw()). But for my demo program it seemed much easier to use the rasterizer supplied by nanosvg.

BTW: sizes of other bundled libs compared to nanosvg:

$ du -h fltk/jpeg/ fltk/png fltk/zlib nanosvg/src
1.7M    fltk/jpeg/
2.1M    fltk/png
664K    fltk/zlib
120K    nanosvg/src
#10 AlbrechtS
09:07 Oct 21, 2016
Fix broken links in comment #7:

#11 manolo
06:33 Oct 24, 2016
Nanosvg is really impressive.
But it seems to ignore any text content in svg files.
#12 AlbrechtS
08:24 Oct 24, 2016
@Manolo: thanks for taking a look at it.

I think I didn't experience missing text yet. What I saw was white text on a transparent background in some icons, and since the background in svg_v2.cxx was white nothing seemed to be visible, like an empty image.

svg_v3.cxx (uploaded with this post) changes the background to light gray and displays the image file name and dimensions in the title bar. Tested on Linux and Windows so far.

If you still experience missing text, can you please post a simple/small example svg file that exhibits the issue? And - if it's not in the image file's meta data - can you tell us how it was created (if you know it)?
#13 AlbrechtS
09:21 Oct 24, 2016
Indeed, I constructed a simple svg file with a 'text' element, and the text is not rendered by nanosvg. :-(
#14 AlbrechtS
09:27 Oct 24, 2016
See uploaded file text_00.svg.

Anyway, nanosvg is open source, and the author writes on his Github page:

"NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!"
#15 manolo
00:41 Oct 30, 2016
See attached svg_v4.cxx for an essentially complete
implementation of a new class :
  Fl_SVG_Image : public Fl_RGB_Image

This allows full integration of SVG images in fltk
with no platform-specific code anywhere and no
SVG-specific code at user level.
#16 AlbrechtS
04:27 Oct 30, 2016
Manolo, thanks for this great contribution. My goal was to have an Fl_SVG_Image class and to be able to use SVG images as Fl_Shared_Image's once we decide to have SVG image support (with nanosvg or another library) in FLTK. This is a great step forward to this goal.  
#17 AlbrechtS
04:40 Oct 30, 2016
Regarding text rendering (comments #11-14):

I took a deeper look at the nanosvg code, and it is clear now that 'text' elements are completely ignored by the svg parser. Even if the parser would not ignore the 'text' elements I wouldn't know how to rasterize the text w/o implementing a full text (font) rendering engine in the rasterizer.

The rasterizer implementation appears to be sophisticated (maybe derived from a font rasterizer engine?) and seems to do a good job at anti-aliasing lines, curves, filled areas, and color gradients (linear as well as radial). We can't simply use FLTK's font rendering on top of that, AFAICT, because 'text' elements would need to be fully integrated (they could be occluded by later, maybe partially transparent elements etc.).

OTOH it seems that icons and other svg images may have pre-rendered text included in many (most?) cases anyway. If that was true (comments, anybody?), then we could try w/o 'text' rendering and include nanosvg anyway as an (incomplete) improvement.

That's just a thought so far...
#18 AlbrechtS
04:54 Oct 30, 2016
Regarding missing graphics elements in complex images (comment #7 et al.):

FWIW, so far I found out that some of the issues are really caused by the "mirrored" image elements. They are implemented by a 'use' element that refers to a very large image element (the left wing and leg of the eagle).

The original element (left side, id="g6288") starts at line #735 and ends at line #949.

The "used" element (right side) is at line #950:

  <use transform="matrix(-1,0,0,1,608.4247,0)" id="use6503" x="0" y="0" width="467.94525" height="573.34161" xlink:href="#g6288"/>

I don't know yet why this doesn't work, but I succeeded to render the right wing and leg by _copying_ the code instead of 'use'ing it (with an additional transformation).

Needs more investigation and maybe a correction in nanosvg...
#19 manolo
05:24 Nov 01, 2016
Attached file svg_v5.cxx improves the Fl_SVG_Image
class by using less memory for each image.
It also allows to tile svg images.
#20 ianmacarthur
09:53 Mar 22, 2017
For what it's worth, I've been using an old version of nanosvg (circa 2014 or so I think) to render button faces for a particular task, and it certainly works well for simple things like that.

Regarding comment #17, I have never missed the text support, I just use the svg to render the "face" then draw the button label on top anyway. Works for me, but I accept it's not ideal...

It is small enough a library, and the licensing seems OK, so maybe we can bundle it in?

Initially I thought not, since it is easy enough to use anyway as an external lib, but having a specific FLTK svg capability, I can see that being useful.

We probably would want to include a warning in the docs saying it is not a full svg renderer I think, just to cover the trickier edge cases!

One specific change though: I hacked the rasterizer to allow me to set different scales for x and y. This was to allow me to draw the faces on a range of differently sized buttons from a single svg.
Probably not ideal, but very handy in this case.
That *might* be a facility we'd like to keep in, even though it is somewhat odd. And the way I did it is less than ideal (though looks fine in practice!)
#21 djcj
07:04 Aug 27, 2017
What about optionally enabling support for librsvg2 as an external library? Or maybe trying to dlopen() it and fall back to nanosvg otherwise.  
#22 ianmacarthur
11:39 Aug 28, 2017
Adding librsvg2 support is possibly feasible, though it is an additional dependency we (ideally) would not want.

If folks really need better SVG support, then it's not that hard to use it as an external lib themselves, much like nay other support lib.

As for dlopening it as a fallback option, that might be trickier to actually hook together; nanosvg is a compile time option only (there is no lib, it's all in the header files) so making that "congruent" with dlopening a "real" external lib might take a bit of fiddling... and nanosvg would always have to be built into fltk in that case anyway, just in case librsvg2 wasn't found, I guess.

Hmm, don't know.
#23 manolo
09:25 Aug 30, 2017
Attached file #10 svg.patch is a complete implementation
of SVG image reading and drawing as a new Fl_SVG_Image class
derived from Fl_RGB_Image. It could be part of libfltk_images.
#24 manolo
04:18 Aug 31, 2017
Attached file svg2.patch adds:
- a missing FL_EXPORT
- more complete documentation of the new Fl_SVG_Image class
- configure/CMake options to build without nanosvg
#25 AlbrechtS
07:46 Aug 31, 2017
Uploaded files altsvgrast.h (full version) and altsvgrast.diff contain Ian's patch as posted to fltk.general, upgraded to the current nanosvg version (as of Aug 31, 2017). Manolo's proposal is already based on the current nanosvg version, so I just merged Ian's patch.

WRT line width and unproportional scaling: the uploaded files include one modification WRT Ian's patch: I calculated the average scaling factor sw = (sx + sy) / 2; and applied this to the scaling of line widths (instead of sx, as in Ian's code) and to the *new* dash length. This may be changed in the future.

Note: the average scaling factor can be 0 if one of the scaling factors is negative. This needs to be reflected, but I don't think that negative scaling factors are sensible values.

I tested Ian's buttons code and it worked well this his patch.
#26 AlbrechtS
08:00 Aug 31, 2017
Should read: "... worked well with his patch."
And to be precise: with the upgraded patch version.

I don't know if unproportional x- and y-scaling is of any use in the current proposal of Fl_SVG_Image, but since I changed and tested Ian's proposal I thought it's worth posting it here.
#27 AlbrechtS
08:04 Aug 31, 2017
WRT nanosvg files: I suggest to put nanosvg.h and nanosvgrast.h in a separate directory (nanosvg) as we did with the bundled zlib, png, and jpeg libs. Although this is not strictly necessary it would make maintenance (upgrade of image libraries) more explicit.

If we used Ian's patch I would also propose to add a diff file in the nanosvg folder so we can later upgrade the bundled files easier (unless we find a way to push the patch upstream).
#28 manolo
07:24 Sep 01, 2017
Attached svg3.patch completes the class documentation about
the fact that text is not rendered.
#29 manolo
06:42 Sep 03, 2017
The new class Fl_SVG_Image added with commit r.12413
adds SVG image support to FLTK.
#30 djcj
03:55 Sep 07, 2017
I made my own little implementation of Fl_SVG_Image: https://git.io/v5wKH

It may not be as good as yours, but it supports gzip compressed SVG files: https://git.io/v5w62
#31 manolo
09:36 Oct 04, 2017
@djcj: please see the current state of class Fl_SVG_Image
(after r.12477) which should support .svgz compressed SVG files,
and report if something does not run well.
#32 AlbrechtS
07:34 Jan 01, 2019
Fixed in Git repository.

This STR has been fixed a long time ago. Time to close it.

Return to Bugs & Features ]


Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.