A render mode that references each glyph by its SMuFL codepoint via `<text>`,
drawn from an `@font-face`-embedded Bravura subset, alongside the default inline
`<path>` outlines. The SVG stays self-contained (the font travels in it) and the
text is selectable, at a larger file size.
- GlyphMode::EmbeddedFont: the SVG declares the font once via
<defs><style>@font-face{...}</style></defs>, then emits one
<text transform="translate(x y) scale(1 -1)" font-size="4" ...>&#xNNNN;</text>
per glyph. Geometry is consistent with PathOutline by construction: same
origin, a per-glyph counter-flip cancels the outer y-flip, and the SMuFL em is
four staff spaces. A new `text_count` stat; unbundled glyphs still fall through
to the visible bbox rect + diagnostic. The metadata comment declares which mode
produced the SVG (and, on the empty canvas too, via a shared `glyph_note`).
Path mode stays the byte-golden-locked, pixel-verified reference; the embedded
mode is structurally tested (well-formed XML — also under `xmllint`; one
@font-face; one <text>/codepoint per glyph; provenance preserved; determinism).
- The subset is a GENERATED artifact, not a vendored binary: a deterministic
base64 OTF emitted into src/font_subset_generated.rs by
`tools/extract_bravura_outlines.py --font-out` (the same SHA-pinned 1.392 font
the outlines come from). `recalcTimestamp=False` keeps the source font's fixed
head.modified so the bytes are reproducible across runs, not just within one.
- OFL compliance: the subset is a Modified Version, so its PRIMARY font name is
renamed off the Reserved Font Name "Bravura" to "EpiphanyBravuraSubset" in BOTH
naming structures an OTF carries — the SFNT `name` table AND the CFF (Name INDEX
+ top-dict FullName/FamilyName). The copyright/trademark/license records, which
name Bravura as attribution, are kept; the renderer references the renamed
family in @font-face and <text>. The generator reparses the saved bytes and
fails if the reserved name leaks into a primary record, and validates the cmap
covers every glyph.
- Machine-locked payload: the generator emits the decoded length and a BLAKE3-256
(the workspace's sole hash) of the font bytes; a render-svg test base64-decodes
the payload (no new runtime dep) and asserts the length, the OTTO signature, the
BLAKE3, and — parsing the SFNT name table and CFF Name INDEX — that neither
primary name is the reserved name. Adds an epiphany-determinism dev-dep.
The demo example gains `--glyph-mode=path|embedded`; lib/README/DECISIONS document
the two modes, the subset's OFL rename, and the regeneration command (--font-out +
the blake3 dependency). PathOutline goldens are byte-unchanged; the outlines stay
byte-identical. Full gate green: build, fmt, clippy, 585 tests, conformance scale 1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>