Closed IanTrudel closed 8 years ago
Shoes::SVG should allow reading data from a string rather than a file and render its content on screen. It would still be possible to load a file in any event, such as in the example below. Or, perhaps, it should check whether a file or a string is passed and load data accordingly.
Shoes.app {
svg(File.read("bunny.svg"))
}
What does svg(File.read("bunny.svg")) return? A bit map image like png and jpg or a new Shoes widget class with svg specific methods and event handling to be written in C and Objective C?
This is something to think about. Ultimately it should become Shoes::SVG but we could implement the features incrementally for which the svg is rendered as a Shoes::Image, can be displayed, responds to normal image related methods. This should be easy to implement. The additional features can come as time goes.
For now I only need to be able to render svg on screen anyway. This would avoid me a whole lot of troubles converting files for different configurations using external tools. This enhancement will allow me to simplify and streamline the production of commercial software based on Shoes. My very next project will use it. So it's not wishlist as in wishful thinking...
The following will be required to add SVG support to Shoes: librsvg, libxml2, libcroco. These can be found on http://www.gtk.org/download/win32.php for Windows related libraries. The binaries should do fine and the PC files can be obtained from the source files.
Shoes.svg method could have the following styles:
Equivalent methods may be considered for manipulating the svg at runtime.
REFERENCES https://developer.gnome.org/rsvg/2.40/rsvg-Using-RSVG-with-cairo.html http://cairographics.org/manual/cairo-SVG-Surfaces.html https://developer.gnome.org/rsvg/2.40/RsvgHandle.html librsvg source code contains examples in tests directory.
I've got a minor concern over libxml2. We already include an XML dll. Is there a choice of parsers when building libsvg from source?
Expat XML (libexpat) is an overly outdated, slow and complicate library. Might not be alive anymore as the last update is in 2012. Is libexpat used anywhere in Shoes? It is mostly included in GTK+ Bundle to ride along and compatibility. So librsvg does not support libexpat.
A good simple example how to use librsvg in Cairo: http://blog.mathieu-leplatre.info/static-build-of-cairo-and-librsvg.html
I believe libexpat is used by our old friend, fontconfig to parse the font.conf file.
The good news is that fontconfig can be configured to use libxml2 using ./configure --enable-libxml2
.
An interesting experiment on Windows: removed libexpat-1.dll and ran cshoes.exe, checked manual and cobbler — working.
There is no libexpat-1 on MacOS X and probably not on Linux. Recommended to remove this unused library on Windows. It would be a good idea to list and compare libraries on all platforms.
@BackOrder - since I'm redoing the dependencies for OSX , now would be the time to add librsvg to Shoes 3.3. Glancing at the API https://developer.gnome.org/rsvg/2.37/ it seems like a Shoes API is reasonable - make a class out of rsvghandle with some property getters and setter and init with a filename. Add a few methods for the GIO and Cairo calls and ??. Would that be sufficient for your needs?
One other note. libexpat is included in OSX 10.6 and 10.9 in /usr/lib/ and it is used by Shoes - attempts to build libxml w/o homebrew have failed so far.
It sounds reasonable to me. Loading and displaying images, basic manipulations would be a great start.
There is an existing rsvg gem (part of ruby-gnome project). I have no idea what it's api but it depends on Gtk so it should be understandable code.
rvsg2 seems to have a decent implementation with frequent and recent contributions. I don't know how it would integrate with Shoes. My understanding is that it would be best to roll up our own to fully integrate to Shoes. What are your thoughts?
https://github.com/ruby-gnome2/ruby-gnome2/tree/master/rsvg2
There is a problem. From 10.9, attempt to configure:
configure: error: Package requirements ( gdk-pixbuf-2.0 >= 1.3.7
glib-2.0 >= 2.12.0 gio-2.0 >= 2.24.0 libxml-2.0 >= 2.7.0 pangocai
ro >= 1.32.6 cairo >= 1.2.0 cairo-png >= 1.2.0
libcroco-0.6 >= 0.6.1) were not met:
No package 'gdk-pixbuf-2.0' found
No package 'libxml-2.0' found
No package 'libcroco-0.6' found
gdk-pixbuf is a show stopper if it can't be configured away. libxml can be done if one is very careful in osx. That's for the older librsvg-2.39.0. The Changelog for the very recent 2.40 says it won't work with gtk2 and ours Shoes/Windows version of Gtk3 isn't high enough. I haven't looked at libcroco yet. Just a warning that this may be hard to do or even impossible.
Of course, for all I know, cocoa has the svg handling inside it and we really just need to create a native widget (for gtk and cocoa) that can handle what ever the Shoes API is. Quick google says cocoa/Shoes would need an svg/xml to core graphics importer & exporter. If true that's a lot of code to write and test so I would need some major help (aka some one else writes the code).
There is a cocoa project https://github.com/SVGKit/SVGKit that is active although they say it might be broken for OSX. It's also huge. If I was doing this, I'd look into getting librsvg working w/o a gtk requirement. Shoes really can't handle a completely different imaging model (vector vs pixel) in a general purpose way. We can already create and svg from an image but loading an svg into image seems very unlikely. Loading into a new widget might be possible but its going to be a lot of work and I'm not inclined to do it.
Loading into a new widget might be possible but its going to be a lot of work and I'm not inclined to do it.
It would just need some kind of wrapper class in Shoes C-level code with basic functionalities. We can extend it as time goes, as need goes. As a side note, it would be great to have some kind of wiki article on how to extend Shoes with new features, what a new class requires to be fully accessible in Shoes, etc.
Yes, a better description is needed in the wiki if only to help me remember how and where (app.h, app.h, ruby.h, ruby.c, plus a few others)
I've almost got librsvg built on 10.9 but I am running into a problem with gobject-introspection versions building (some) but not working with librsvg. It turns out you can build gdk-pixbuf with out Gtk.
Update: librsvg is built on 10.9 and gem install rsvg2 also installs (along with pkg-config.gem, cairo.gem, and glib2.gem). So the dependencies are good enough for now. I'll do the windows build next - I've peeked at the extconf.rb of rsvg and it's impressive (and possibility cross compile problem but the gem comes with prebuilt mingw binaries so maybe not.
Windows is being a problem. Gobject-introspection won't cross compile because it tries to run linux python and there is confusion about which include files to use. That's during the configuration phase - a nasty place in autoconf to be mucking about. Of course I don't have python-dev on my Win7 system.
The rsvg2 gem does install on Windows (prebuilt .so's) and it does use libsrvg inside so it can be built, somehow. The link above to prebuilt Windows dlls doesn't work as given but http://sourceforge.net/projects/ezwinports/files/ does have librsvg-2.40.1-2-w32-bin.zip which includes the dlls and headers but may create some version number mis-match for Shoes. A good place to start, though because the README.txt is very useful.
Eventually I found --disable-introspection
for configuring librsvg, We now have cross compiled rsvg (and dependencies) for mingw and osx. Time to create an API (and put it in Shoes)
This is an amazing news!
Thinking out loud, again ;^). Assume we have loaded an SVG in shoes and have a shoes/ruby object that mirrors the RsvgHandle. Now we want to display it which done with rsvg_handle_render_cairo() which writes to a cairo_t* which we could get where ever Shoes stashes returns from calls to shoes_cairo_create but that requires in input arg shoes_canvas* If I remember correctly there are a lot of those calls in Shoes. Rather than re-inventing canvas can we just add a new method to canvas something like 'render_svg(rsrvghandle)' That might the way to get started but may not be sufficient. I don't know.
Ideally the SVG would be more like a Shoes Art element (Shoes::Shapes) or maybe an Image?. I'm confused. I think I'll create that svghandle object just to have something that works the rakefiles and allows some testing. (and the wiki article)
Ideally the SVG would be more like a Shoes Art element (Shoes::Shapes) or maybe an Image?. I'm confused. I think I'll create that svghandle object just to have something that works the rakefiles and allows some testing. (and the wiki article)
Ultimately, it should support both but it may be challenging to implement Shapes. My suggestion is that we remain pragmatic and focus on Image for now. Rescaling may be necessary when the image is resized to avoid resampling.
Let's make it easy first and later add features. What do you say?
I am starting small. Hopefully, in a day or two I can get svrghandle.new(:file => path) and svghandle.new(string) and svrghandle.close() defined in C and the rakefiles setup for all platforms to build the no-ops. Documenting that effort https://github.com/Shoes3/shoes3/wiki/Creating-a-Class-for-Shoes-in-C as I go does slow me down - probably a good thing.
The wiki article is mostly accurate and although the code is incomplete the framework is there.
I've managed to get an svg loaded into Shoes but getting it to draw is down the cairo maze and I have no idea what I'm missing. @passenger94 would you like to take a look and tell me what I'm missing? The code only builds on a Loose Shoes Linux (x86_64) - apt-get install rsvg2-dev.
Good news of a sort. Actually, it does draw but like all Shoes things you have to wait for the screen to setup. Since it's not connected to the refresh chain - it disappears easily. That is fixable I think so the current arrangement is more like an alternate way to draw things on a canvas. I would expect confusion if one also wanted to put Shoes art on top of it because someone has to draw first. I'm not enamored how it's set up now.
Shoes Images are completely pixel oriented - (remember all those transforms) Loading an svg in and rendering to a pixel buffer would prevent any further svg operations. Might as well convert to it to png. Images do not redraw by calling cairo. That doesn't seem particularly useful to me unless we add svg only methods to image but they will all have to render to image pixels when finishing because the next script line could manipulate the pixels. That feels hacky and could be very slow for complex svgs.
Creating a new Graphical widget has lots of svg appeal since you could add Shoes methods that deal with svg things and handle resize events in an svg friendly manner. However it would also be part of user initiated layout events and you probably couldn't mix current Shoes art or transforms with it. Nor you could you add to the svg contents with Shoes para (textblock).
Trade off's every where you look. From a different perspective, what do you want to save after loading and manipulating SVG? Vectors or Pixels? Remember Cairo/pango doesn't draw image buffers.
The current experiment, canvas.svghandle requires changes to canvas to render an svg if there is one attached to the canvas when events happen. An ugly hack and damn hard to document in the manual but it might be the better solution. What you see on screen may not be be save-able in .svg
Its been many man-days to get this far and a boat load more man days ahead even for the easies hacky methodt. W/o feedback and engagement @BackOrder it's going to stall here.
@ccoupe i'm busy right now and a bit out of sync, i can have a look maybe this weekend or next week
Without looking at code !!! if i remember correctly snapshot is just a block which is building a svg or ps image, so the tools are just there, isn't it possible (easier ?) to build something from there, an entity like a class for a clean api, build atop of the return of snapshot method ?? again, without looking at code, might be just plain silly! One problem i can see if you want to integrate an svg factory into the shoes chain of events : drawing, refreshing, etc ... at some point you have to decide/choose the dimensions of your image, and rendering the svg into pixels, objects are going twice through shoes_place_decide method which is a hell of a method that does everything, but like you said, this is pixels area only ! I guess you dive deeply into how cairo is handling svgs, i don't expect mixing svg and shoes stuff, that way, to be trivial !!!, but maybe there is a solution hidden in the maze :-)
if a simple hack or two for repainting a canvas doesn't work then the task becomes very large indeed. Currently the svg renders into the existing canvas [cairo matrix] so sizing is controlled by the existing code for a canvas.
When it works (repaint is still a mystery) it looks like this: You can see several problems with the current hack. It's more like a background image - it has no respect for para or button positions or stack/flow layouts. I happen to not like that but maybe it's desired @BackOrder ? If you create a smaller window (not shown), as @passenger94 warned, it does not fit in the window (it's clipped instead). I was wrong when I said it would auto scale to the canvas boundaries.
I think SVG has to be a separate widget (a leaf in the widgets tree) with unique methods on the svg widget and some odd trips in and back from native land. If you have dreams of a graphical svg editor written in Shoes I don't see that happening.
It occurred to me I might learn a lot about how to implement an svg widget by looking at the implementation of the mostly unknown shoes.widget - - basically it's just a nested canvas. Well, what about that old VLC widget? What was it really doing layout wise? Eventually, you find SHOES_SURFACE_REF and shoes_native_surface_new() and friends - which don't appear to be called anymore by 3.2/3.3 and eventually you'll read https://developer.gnome.org/gtk3/stable/GtkDrawingArea.html Yes! That is the correct way to create a new native svg widget! Most of my svghandle code won't work and the corresponding wiki article needs rewriting but that's OK. I learned from the experiment and learning is good.
Of course there's a lot of work to do, particularly if you want mouse and keyboard events in the svg widget (and some way to convert co-ordinates of mouse x,y to svg position). I vaguely remember OSX deprecated or complains about the CGrafPtr equivalent of GtkDrawingArea of so that needs investigation before I go much deeper.
You are correct in assuming that SVG images should be able to live in Shoes visual ecosystem. It has to be able to be positioned and respect other widgets. Behaviour similar to any other component really. Don't forget to take notes on the wiki about it in order to encourage other developers to create new components.
Notes? Like https://github.com/Shoes3/shoes3/wiki/Create-a-native-widget-for-Shoes
We all know the number of people willing and able to write C and Cocoa for Shoes.
Some progress on the widget.
Constrained to a 200px X 200px window although many layout issues exist. Obviously, it does not scale the svg to its widget window . This approach seems promising There is a lot of work needed.
A downsize transform doesn't appear to be something librsvg can do. So I decide to scale the widget to the size of the svg. (samples/good-svg-view.rb) There is still a boat load of work to do but Is that close to what @BackOrder wants?
It has to be resizable as any other widgets. SVG are by nature not fixed in size, they may be in their definition but it is merely as reference for scaling. The output above is cropping the actual SVG as you may well be aware.
Where is samples/good-svg-view.rb? Could you link the file directly here?
Script is here https://github.com/Shoes3/shoes3/blob/svg/samples/good-svgview.rb
I think Cairo has to do the shrinking of the svg to fit the windows. I'm a long ways from getting there. (and then some one will ask for a zoom method ;^). It's still not a well behaved widget yet. I can also see some of the problems experienced when the video widget existed .
So far, so cool !
I think I almost know what to do. In order to call cairo_scale() in you need scale factors w & h which can't be computed without both the widget size and the svg size. I have the svg internal size. What I don't have yet is the parsing of the :width and :height args when the widget is created (styles parsing probably)
The API for svg is coming together so please comment. Creating the widget in Shoes would be svg(hash) where 'hash' has :width, :height:, file:, from_string.With defaults and error raising. Once you have that object in Shoes the scriptwriter can invoke svg.render() or svg.render(svgtag) if they wish to change the contents that is displayed. I'll implement a few methods from Image widget but there is no inheritance in C so I'm only going to implement the methods that will be used (used- not wished for).
It's a huge amount of work that I'm not qualified to do and I have much 'refactoring' ahead just to get that lame API.
This shows a scaled svg in Windows. I'm learning!
Yes, there is a Windows download at the beta site.http:// walkabout.mvmanila.com/public/shoes/shoes-3.3.0-gtk3-32.exe - it's console chatty as is good-svgviewer.rb script (use the load button on Windows).
It's enough progress that I need to switch to working on OSX/Obj-C before I do something it can't do.
This is great work once again. It feels good to be able to count on you.
Unfortunately, I could not successfully test the beta version.
The the upload was incomplete . I've put up another - same address. It will be easy for you to break the widget it's still very incomplete.
It does work here but there are two noticeable problems. First, there is no way to keep aspect ratio at this time. Second, it core dumps (see below) in this particular scenario:
(Shoes::Types::Svg)
[:draw, :render, :full_width, :full_height, :nil?, :===, :=~, :!~, :eql?, :hash,
:<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :unt
rust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :single
ton_methods, :protected_methods, :private_methods, :public_methods, :instance_va
riables, :instance_variable_get, :instance_variable_set, :instance_variable_defi
ned?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :warn,
:send, :public_send, :respond_to?, :extend, :display, :exit, :method, :public_me
thod, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_f
or, :rgb, :gray, :gradient, :pattern, :quit, :debug, :info, :error, :alert, :ask
, :confirm, :ask_color, :ask_open_file, :ask_save_file, :ask_open_folder, :ask_s
ave_folder, :font, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__sen
d__, :__id__]
button t: 43
panel t: 43
svg_draw
svg_draw
draw handle
-e: [BUG] Segmentation fault
ruby 2.1.6p336 (2015-04-13) [i386-mingw32]
-- Control frame information -----------------------------------------------
c:0003 p:---- s:0007 e:000005 CFUNC :remove
c:0002 p:---- s:0004 e:000003 CFUNC :remove
c:0001 p:0000 s:0002 E:001074 TOP [FINISH]
-e:0:in `remove'
-e:0:in `remove'
-- C level backtrace information -------------------------------------------
C:\WINDOWS\SYSTEM32\ntdll.dll(ZwWaitForSingleObject+0xc) [0x779BC4BC]
C:\WINDOWS\SYSTEM32\KERNELBASE.dll(WaitForSingleObject+0x12) [0x770D2C02]
C:\Users\Ian\Desktop\SvgShoes\msvcrt-ruby210.dll(rb_print_backtrace+0x4b) [0x6D3
63828]
C:\Users\Ian\Desktop\SvgShoes\msvcrt-ruby210.dll(rb_vm_bugreport+0x78) [0x6D3638
A5]
C:\Users\Ian\Desktop\SvgShoes\msvcrt-ruby210.dll(rb_bug_reporter_add+0x182) [0x6
D238D56]
C:\Users\Ian\Desktop\SvgShoes\msvcrt-ruby210.dll(rb_bug+0x53) [0x6D238E0A]
C:\Users\Ian\Desktop\SvgShoes\msvcrt-ruby210.dll(rb_get_next_signal+0x130) [0x6D
2F0BBA]
C:\Users\Ian\Desktop\SvgShoes\cshoes.exe(WinMain+0x436) [0x00401996]
C:\WINDOWS\SYSTEM32\KERNELBASE.dll(UnhandledExceptionFilter+0x165) [0x7718F6E5]
C:\WINDOWS\SYSTEM32\ntdll.dll(LdrSetAppCompatDllRedirectionCallback+0x13267) [0x
77A2F0A7]
-- Other runtime information -----------------------------------------------
* Loaded script: -e
* Loaded features:
0 enumerator.so
1 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/enc/encdb.so
2 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/enc/iso_8859_1.s
o
3 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/enc/trans/transd
b.so
4 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/rbconfig.rb
5 thread.rb
6 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/thread.so
7 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/compatibil
ity.rb
8 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/defaults.r
b
9 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/rubygems/deprecate.rb
10 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/errors.rb
11 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/version.rb
12 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/requiremen
t.rb
13 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/platform.r
b
14 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/basic_spec
ification.rb
15 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/stub_speci
fication.rb
16 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/rubygems/util/stringio.rb
17 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/specificat
ion.rb
18 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/exceptions
.rb
19 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/dependency
.rb
20 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/k
ernel_gem.rb
21 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/monitor.rb
22 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/k
ernel_require.rb
23 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/site_ruby/2.1.0/rubygems.rb
24 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/etc.so
25 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/fileutils.rb
26 C:/Users/Ian/Desktop/SvgShoes/lib/shoes/download.rb
27 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/tmpdir.rb
28 C:/Users/Ian/Desktop/SvgShoes/lib/shoes/cache.rb
29 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/common.rb
30 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/generic.rb
31 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/ftp.rb
32 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/http.rb
33 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/https.rb
34 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/ldap.rb
35 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/ldaps.rb
36 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri/mailto.rb
37 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/uri.rb
38 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/stringio.so
39 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/date_core.so
40 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/date/format.rb
41 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/date.rb
42 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/time.rb
43 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/open-uri.rb
44 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/optparse.rb
45 C:/Users/Ian/Desktop/SvgShoes/lib/shoes/inspect.rb
46 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/digest.so
47 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/digest.rb
48 C:/Users/Ian/Desktop/SvgShoes/lib/ruby/2.1.0/i386-mingw32/digest/sha1.so
49 C:/Users/Ian/Desktop/SvgShoes/lib/shoes/image.rb
50 C:/Users/Ian/Desktop/SvgShoes/lib/shoes.rb
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
A friendly reminder about desired features: https://github.com/Shoes3/shoes3/issues/54#issuecomment-74544863
Additionally, SVG may have multiple objects in a single file distinguished by group ids. Being able to display by group id would be a huge bonus.
I knew you'd break it! Yes, the default button doesn't work in windows because it's hardcoded to the an svg path on my system. I suspect the crash is from my garbage collection - my implementation could easily be wrong. There will be a render method() with an argument for the subid. - only of the easier things to do. Styles is on the list of things to do but a OSX ( a partial implementation) is the priority to ensure what we thinking about can be done on OSX.
For the record, I did change the path to an actual SVG file. Tried few of them and they all displayed properly. The exit method worked fine while using quit button, just not the X button.
I'd like to change :from_string to something shorter. What would you think about :content ?
Cairo supports SVG rendering through libRSVG.
https://wiki.gnome.org/action/show/Projects/LibRsvg?action=show&redirect=LibRsvg
From http://cairographics.org/examples/