Expand/Shrink

librsvg

DRAFT - Experimental / Windows-only (mainly due to use of ".dll")

The file builtins\librsvg.e (not an autoinclude) contains a basic wrapper of the librsvg library.

The librsvg library contains several routines useful for manipulating svg files, in particular converting them to png files so they can be displayed in pGUI applications.
The basic idea is that you can create an svg file (see the example below) using standard Phix code, or download one, and then use it on both the desktop and a webpage - don’t get too excited by the mention of the latter; this is just one possible part of a potential solution to such things.

NB There is as yet no officially-supported Phix-friendly way to install librsvg itself.
I read some post on’t’internet, found some dlls from a past attempt to get gtk/whatever working, and used them. All I know is:
My C:\gtkX\bin contains a working set of 32-bit dlls and the file gtk+-bundle_3.6.4-20130921_win32.README.txt. Note however several files appear to link back to C:\gtk\bin, which does not work....
In C:\Users\Pete\.julia\packages\WinRPM\Y9QdZ\deps\usr, the \sys-root\mingw\bin subdirectories of both \i686-w64-mingw32 and \x86_64-w64-mingw32 also work fine, on 32 and 64 bit respectively.
(Cannot quite remember exactly, but some combination of running import Pkg; Pkg.add("Gtk"); Pkg.add("Graphics"); in the julia repl, failing, and then dowloading/extracting gtk+-bundle_3.6.4-20130513_win32/64 manually.)
The contents of pygi-aio-3.4.2rev11.7z, a file I downloaded in 2015, who knows why or where from, also work fine.
You will most certainly need librsvg-2-2.dll, libglib-2.0-0.dll, libgdk_pixbuf-2.0-0.dll, and libgobject-2.0-0.dll, plus (at least) another 9. I will upload something to PCAN when it is good and ready, but not before.
I specifically wrote set_librsvg_dir() to make switching between various directories as easy as possible.

Sadly the version info in librsvg is implemented as C macros, so as yet I have no way to check whether a .dll (/.so) is a recent enough version. I guess I need to go on a proper version-hunt.

Unfortunately "develop on desktop" has a somewhat heavy footprint: 13 dlls at ˜15MB, just to support SVG display (via librsvg).
Note: some ".svg" files are pure-defs, no actual svg at all, eg fontawesome-webfont.svg (in case, like me, testing them confuses you..)
One thing I have spotted is that librsvg does not like eg <font .. /> at all, but "prefers" <font ..></font>, I can live with that.

The library signals errors by throwing exceptions, which are best fixed by only providing valid inputs: <rant> the worst possible "fix" being to use try/catch to silently ignore them, and in that way absolutely guarantee to maximise head-butting anger and frustration. By all means feel free to use try/catch, but [please] at least display/log errors. Far too many programmers assume that when their users say "it displays error 8000437, which is meaningless to me" they would somehow be happy if pressing the button just quietly did precisely nothing, when of course the only way to make them happy is to make the button actually work. Sometimes that might mean they have to relay some gobbledegook so that you can actually help them, or better yet display messages the average joe can comprehend, for example instead of just "error 8000437", append a helpful hint: "error 8000437 (please relay to a member of the support team, they should know what that means)", or better yet "illegal stroke-width: 'lime' (ditto)", or maybe a help/FAQ link. </rant>

None of these routines are supported by pwa/p2js.

Example:

Creates test.png, as per wikipedia (as noted there, the final image excludes the grid and labels).

include librsvg.e

constant test_text = """
<svg width="391" height="391" viewBox="-70.5 -70.5 391 391" xmlns="http://www.w3.org/2000/svg">
    <rect x="25" y="25" width="200" height="200" fill="lime" stroke-width="4" stroke="pink" />
    <circle cx="125" cy="125" r="75" fill="orange" />
    <polyline points="50,150 50,200 200,200 200,100" stroke="red" stroke-width="4" fill="none" />
    <line x1="50" y1="50" x2="200" y2="200" stroke="blue" stroke-width="4" />
</svg>
"""

rasterize_svg_text(test_text, "test.png")
See demo\rosetta\SierpinskyPentagon.exw for a complete runnable program, including display direct to screen (press 'S').

set_librsvg_dir(string d) - (optional) specify the directory where librsvg-2-2.dll etc can be found.
If the directory does not exist the call is quietly ignored.
If the libraries are in the current directory, or in the path (as they usually are on linux), no such call is required.
atom pGdkPixbuf = 
rasterize_svg_pixbuf(string text) - converts a text svg to a GdkPixbuf.
You can locate the raw data within a GdkPixbuf for passing to IupImageRGBA() using gdk_pixbuf_get_pixels(), see below.
Note that theoretically some svg might create raw data incompatible with IupImageRGBA(), however I have not yet found any such.
At some point you must release resources by invoking g_object_unref(pGdkPixbuf).
integer width = 
gdk_pixbuf_get_width(atom pGdkPixbuf) - obtain the width in pixels.
It may be wise to check that gdk_pixbuf_get_rowstride() yields the same value, times 1/3/4[??], to ensure there is no padding between rows.
integer height = 
gdk_pixbuf_get_height(atom pGdkPixbuf) - obtain the height in pixels.
bool res = 
gdk_pixbuf_get_has_alpha(atom pGdkPixbuf) - check whether the image has an alpha channel.
integer res = 
gdk_pixbuf_get_colorspace(atom pGdkPixbuf) - obtain the colourspace.
Currently the only supported value is apparently GDK_COLORSPACE_RGB(=0).
integer res = 
gdk_pixbuf_get_n_channels(atom pGdkPixbuf) - obtain the number of channels.
integer res = 
gdk_pixbuf_get_bits_per_sample(atom pGdkPixbuf) - obtain the number of bits per sample.
atom pData = 
gdk_pixbuf_get_pixels(atom pGdkPixbuf) - obtain a raw pointer to the pixel data.
Later versions of librsvg apparently implement gdk_pixbuf_read_pixels() and avoid making copies of read-only data.
However I have not located a late-enough version, yet, nor do I have any idea if/when/how pData might need releasing.
g_object_unref(atom pGdkPixbuf) - release resources when no longer needed.
rasterize_svg_text(string text, outputfilename) - creates say test.png from a text svg.
Note that unlike rasterize_svg_file() below, outputfilename must always be provided.
string outputfilename = 
rasterize_svg_file(string inputfilename, outputfilename="") - converts say test.svg to test.png.
If outputfilename is left blank, it replaces ".svg" in the input with ".png" and uses/returns that.
If a non-empty outputfilename is supplied it gets returned unaltered.