Skip to content

Rendering

Rodrigo Agurto edited this page May 30, 2026 · 2 revisions

Rendering

SVG (default, no feature)

let svg: String = tk.render_to_svg(page)?;
// Buffer reuse
let mut buf = String::new();
tk.render_to_svg_into(page, &mut buf)?;
// Streaming-shape write into any io::Write
let mut file = std::fs::File::create("page.svg")?;
tk.render_to_svg_writer(page, &mut file)?;

Honest disclaimer: Verovio's C++ side allocates a full std::string per render. The _writer and _into variants save the caller's intermediate allocation but the C++ heap traffic persists. True streaming would need an upstream RenderToSVG(std::ostream&) overload.

Measure-range rendering

Render only a slice of measures (preserves layout for the slice):

let svg = tk.render_svg_measure_range(4, 8, "\n")?;

Internally: sets Verovio's measureFrom / measureTo options, redoes layout, renders the resulting pages, and restores prior options. Use for click-to-zoom UIs that want one bar at a time.

PNG (png feature)

let png: Vec<u8> = tk.render_to_png(page, 2.0)?;     // 2x scale (HiDPI)
let pngs: Vec<Vec<u8>> = tk.render_to_png_all_pages(1.0)?;
// Pure-function form for SVG you already have:
let png = verovio::raster::svg_to_png(&svg, 1.0)?;

PDF (pdf feature)

Per-page:

let pdf: Vec<u8> = tk.render_to_pdf(page)?;

Multi-page (single document with every page sized to its rendered SVG):

let pdf: Vec<u8> = tk.render_to_pdf_all_pages()?;

Implementation: each page's SVG is converted to a Form XObject via svg2pdf::to_chunk, renumbered against a unified ref allocator, and referenced from a Page with the right MediaBox. The result is a single proper PDF document.

// Pure-function form for a slice of SVG strings:
let pdf = verovio::raster::svgs_to_pdf(&svgs)?;

Layout setters

Convenience over set_options(json):

tk.set_font("Leland")?;            // SMuFL font swap
tk.set_zoom(150)?;                 // 150% scale
tk.set_page_size(2100, 2970)?;     // dimensions in Verovio units
tk.set_breaks("smart")?;           // "auto" | "none" | "encoded" | "smart" | "line"
tk.set_landscape(true)?;           // swap page dimensions

Read one option without parsing the whole JSON document:

let scale = tk.option_value("scale").and_then(|v| v.as_u64());

Available SMuFL fonts

for font in verovio_data::AVAILABLE_FONTS {
    println!("{font}");
}
// Bravura, Leipzig, Gootville, Leland, Petaluma

SVG theming

Embed CSS inside the rendered SVG with SvgOptions:

use verovio::SvgOptions;

let css = r#"
    svg { background: #fafaf5; }
    g.note { fill: #14213d; }
    g.note.playing { fill: #fca311; }
    g.measure line { stroke: #999; }
"#;

tk.set_svg_options(&SvgOptions {
    css: css.into(),
    ..Default::default()
})?;

Common CSS targets: note, notehead, stem, chord, rest, measure, staff, layer, beam, tie, slur, clef, keysig, metersig, barline.

For runtime highlighting, toggle a class (e.g. .playing) on the SVG <g> element from JS. The SVG IDs match the MEI IDs returned by Toolkit::timemap / verovio::lookup::sounding_at.

Per-track CSS generators (verovio::styling)

let staff_map = tk.staff_map()?;
let palette = &["#1f77b4", "#ff7f0e", "#2ca02c"];
let css = verovio::styling::stripe_tracks_by_id(&staff_map, palette);
tk.set_svg_options(&verovio::SvgOptions { css, ..Default::default() })?;
// Solo a single track visually by fading everything else:
let keep_ids = /* ids for the soloed track */ Vec::new();
let css = verovio::styling::fade_others(&keep_ids, "#888");

Clone this wiki locally