For drawing custom graphics, azul has a high-performance 2D vector API. It alsoallows you to load and draw SVG files (with the exceptions of gradients: gradientsin SVG files are not yet supported). But azul itself does not know about SVG shapesat all - so how the SVG widget implemented?

The solution is to draw the SVG to an OpenGL texture and hand that to azul. Thisway, the SVG drawing component could even be implemented in an external crate, ifyou really wanted to. This mechanism also allows for completely custom drawing(let's say: a game, a 3D viewer, etc.) to be drawn.

Necessary features

SVG rendering has a number of dependencies that are not enabled by default, to saveon compile time in simple cases (i.e. by default the SVG module is disabled, sothat a Hello-World doesn't need to compile those unnecessary dependencies):

  1. [dependencies.azul]
  2. git = "https://github.com/maps4print/azul"
  3. rev = "..."
  4. features = ["svg", "svg_parsing"]

You only need to enable the svg_parsing feature if you want to parse SVG files.For building the documentation, you'll likely want to run cargo doc —all-features.You can import the SVG module using use azul::widgets::svg::*;.

Getting started

The SVG component currently uses the resvg parser, usvg simplification and thelyon triangulation libraries). Of course you can also add custom shapes(bezier curves, circles, lines, whatever) programmatically, without going throughthe SVG parser:

  1. use azul::prelude::*;
  2. use azul::widgets::svg::*;
  3.  
  4. const TEST_SVG: &str = include_str!("tiger.svg");
  5.  
  6. impl Layout for Model {
  7. fn layout(&self, _info: LayoutInfo<Self>) -> Dom<Self> {
  8. if let Some((svg_cache, svg_layers)) = self.svg {
  9. Svg::with_layers(svg_layers).dom(&info.window, &svg_cache)
  10. } else {
  11. Button::labeled("Load SVG file").dom()
  12. .with_callback(load_svg)
  13. }
  14. }
  15. }
  16.  
  17. fn load_svg(app_state: &mut AppState<MyAppData>, _: &mut CallbackInfo<MyAppData>) -> UpdateScreen {
  18. let mut svg_cache = SvgCache::empty();
  19. let svg_layers = svg_cache.add_svg(TEST_SVG).unwrap();
  20. app_state.data.modify(|data| data.svg = Some((svg_cache, svg_layers)));
  21. Redraw
  22. }

This is one of the few exceptions where azul allows persistent data across framessince it wouldn't be performant enough otherwise. Ideally you'd have to load, triangulateand draw the SVG file on every frame, but this isn't performant. You might havenoticed that the .dom() function takes in an extra parameter: The svg_cacheand the info.window. This way, the svg_cache handles everything necessary tocache vertex buffers / the triangulated layers and shapes, only the drawing itselfis done on every frame.

Additionally, you can also register callbacks on any item inside the SVG using theSvgCallbacks, i.e. when someone clicks on or hovers over a certain shape. In orderto draw your own vector data (for example in order to make a vector graphics editor),you can build the "SVG layers" yourself (ex. from the SVG data). Each layer isbatch-rendered, so you can draw many lines or polygons in one draw call, as long asthey share the same SvgStyle.