Lands the renderer-against-stub slice of Agent I's visible engraving work (spec/PHASE2_QUICKSTART.md). Two new crates; prerequisites (G Pass 11, H spelling/decomposition) are in place. Real engraving + Minimal-tier solver follow next phase. epiphany-render-svg (the deliverable this phase): - Renders a ResolvedLayoutIR to well-formed SVG 1.1, drawing each glyph as a GENUINE Bravura SMuFL outline <path>. Outlines are extracted reproducibly from the official OFL Bravura.otf by a committed generator (tools/extract_bravura_outlines.py, OFL.txt); the font is not vendored, only the generated Rust (src/outlines_generated.rs). Staff-space/y-up coords with one global y-flip wrapper; viewBox in staff spaces, px scale on the root. - Non-overreach: every element traces to a ResolvedGlyph (data-prov) or a declared wrapper; a glyph lacking an outline is surfaced as a diagnostic and drawn as a fallback rect, never silently dropped. - Hand-rolled xml::check_well_formed (no XML dep); acceptance tests cross-check with system xmllint when present. - examples/render_fixture.rs demo (fixture name -> SVG stdout, --solver=stub|real). - Golden-locked machine acceptance snapshot + full-SVG golden for ten_measure_single_staff and valid_score_rich; deterministic output. epiphany-engrave (honest scaffold): - Engraver: a deterministic horizontal-spacing pass (first axis of the planned two-pass spring layout). Reports SolverTier::Stub — NOT Minimal — until it evaluates the declared hard constraints, guarded by a regression test. The demo's --solver=real exercises it end to end. Honesty notes (recorded as Pass-12 candidates P12-I1..I3 in spec/PASS12_BATCH.md and the crates' DECISIONS.md): the v0 to_logical/to_constrained pipeline is a structural placeholder (arbitrary glyph per object, y=0), so stub output is not yet recognizable notation and the QUICKSTART human visual gate is a next-phase gate; MUSCLOID layout-id derivation stays unwired; bundled BRAVURA_METRICS are approximations that disagree with the real outlines. Gates: cargo fmt + clippy -D warnings clean; cargo test --workspace 504 passed, 0 failed, 0 ignored (criterion 6 layout round-trip still green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| examples | ||
| src | ||
| tests | ||
| tools | ||
| Cargo.toml | ||
| DECISIONS.md | ||
| README.md | ||
README.md
epiphany-render-svg
Agent I's SVG renderer behind the Epiphany RenderIR interface (spec
Chapter 7): turns a ResolvedLayoutIR into well-formed SVG 1.1, drawing each
glyph as a genuine Bravura SMuFL outline <path>. It is the visible end of
the v0 Score → layout IR pipeline.
Status: renderer against the stub solver
This phase builds and golden-locks the renderer against the stub solver's
output (the QUICKSTART development pattern), before the real engraving solver and
the score→real-notation engraving pass land. The stub returns the IR geometry
verbatim — a structural projection (each object becomes one arbitrary glyph in a
row), not yet recognizable notation — so what is proven here is renderer
correctness and faithfulness: real outlines, provenance preserved, output
XML-valid and deterministic. The renderer consumes any solver's output, so the
picture improves with no renderer change once epiphany-engrave lands.
Demo
# Render a fixture to SVG (stub solver by default):
cargo run -p epiphany-render-svg --example render_fixture -- \
ten_measure_single_staff > out.svg
# Drive Agent I's engrave solver instead, to bisect renderer-vs-solver:
cargo run -p epiphany-render-svg --example render_fixture -- \
ten_measure_single_staff --solver=real > out.svg
Fixtures: ten_measure_single_staff, valid_score_rich, valid_score. Stats and
diagnostics go to stderr; the SVG goes to stdout.
Library
use epiphany_render_svg::{render, RenderOptions};
let out = render(&resolved_layout_ir, &RenderOptions::default());
assert!(out.is_well_formed());
println!("{}", out.svg);
render is pure and deterministic. RenderOptions controls SVG-encoding choices
only (display scale, margin, provenance attributes) — nothing that changes
engraving.
Bundled outlines
The glyph outlines in src/outlines_generated.rs are extracted from the official
OFL Bravura.otf by tools/extract_bravura_outlines.py. The font is not
vendored; only the generated Rust is committed. Bravura is © Steinberg Media
Technologies GmbH under the SIL Open Font License 1.1 (tools/OFL.txt); the
extracted outlines are redistributed under the same license. To regenerate:
cd crates/epiphany-render-svg/tools
python3 -m venv .venv && . .venv/bin/activate && pip install fonttools
python3 extract_bravura_outlines.py > ../src/outlines_generated.rs