67 lines
3.3 KiB
Rust
67 lines
3.3 KiB
Rust
#![forbid(unsafe_code)]
|
|
//! # epiphany-render-svg
|
|
//!
|
|
//! Agent I's **SVG renderer** behind the Epiphany `RenderIR` interface (spec
|
|
//! **Chapter 7** §"RenderIR"): it turns a
|
|
//! [`ResolvedLayoutIR`] into well-formed
|
|
//! **SVG 1.1**, drawing each glyph from **genuine Bravura SMuFL** data: inline
|
|
//! outline `<path>`s by default, or `<text>` set in an `@font-face`-embedded
|
|
//! subset. It is the visible end of the v0 `Score → layout IR` pipeline: from a
|
|
//! resolved layout, produce an image a musician would recognise.
|
|
//!
|
|
//! ## Scope and status
|
|
//!
|
|
//! Per the QUICKSTART development pattern (`spec/PHASE2_QUICKSTART.md`, Agent I),
|
|
//! the renderer was golden-locked against the **stub solver's** output first, then
|
|
//! against the real [`epiphany_engrave`](../epiphany_engrave/index.html) solver
|
|
//! once real notation and re-spacing landed. The renderer consumes any solver's
|
|
//! [`ResolvedLayoutIR`]: it preserves the
|
|
//! resolved geometry, provenance traces, XML validity, deterministic output, and
|
|
//! glyph-mode choice without making engraving-semantic decisions.
|
|
//!
|
|
//! ## What it draws, and the non-overreach rule
|
|
//!
|
|
//! The bundled outlines are extracted from the official OFL `Bravura.otf` in
|
|
//! staff-space, y-up coordinates, by `epiphany-glyphs`'s
|
|
//! `tools/extract_bravura_outlines.py` and redistributed under
|
|
//! `epiphany-glyphs/tools/OFL.txt` (Editor T4-pre W2 moved the bundled table
|
|
//! and its extractor out of this crate into that shared seam; this crate
|
|
//! depends on it but still emits each glyph's *stored* `d` string
|
|
//! byte-for-byte — never a re-serialization of the typed outline — so this
|
|
//! move changed no SVG byte). The renderer makes SVG-encoding choices only
|
|
//! and never engraving-semantic ones; see the private `svg` module for the
|
|
//! coordinate system, the provenance-tracing contract, and the
|
|
//! diagnostic-not-paper-over rule.
|
|
//!
|
|
//! ## Font availability
|
|
//!
|
|
//! Two self-contained modes ([`GlyphMode`]):
|
|
//!
|
|
//! * [`GlyphMode::PathOutline`] (default) inlines genuine Bravura outlines as
|
|
//! `<path>`s — no font dependency, byte-golden-locked, the pixel-verified
|
|
//! reference (QUICKSTART, Agent I, recommendation).
|
|
//! * [`GlyphMode::EmbeddedFont`] references glyphs by SMuFL codepoint via a
|
|
//! `<text>` element and an `@font-face`-embedded Bravura *subset* (the same
|
|
//! SHA-pinned font the outlines come from, base64 in `font_subset_generated`,
|
|
//! regenerated by `epiphany-glyphs/tools/extract_bravura_outlines.py --font-out`,
|
|
//! which stays this crate's own generated file — an embeddable font subset
|
|
//! is a renderer concern, not a shared asset). Still
|
|
//! self-contained — the font travels in the SVG — and text-selectable, at the
|
|
//! cost of a larger file; glyph placement is consistent with the path mode by
|
|
//! construction, while exact rasterisation is the consumer's font renderer's.
|
|
|
|
mod font_subset_generated;
|
|
mod outline;
|
|
mod svg;
|
|
pub mod xml;
|
|
|
|
pub use outline::{bundled_glyph_count, smufl_codepoint};
|
|
pub use svg::{
|
|
render, Diagnostic, GlyphClass, GlyphMode, RenderOptions, RenderOutput, RenderStats,
|
|
};
|
|
pub use xml::{check_well_formed, XmlError};
|
|
|
|
// Re-exported so callers can name the renderer's input without also importing
|
|
// epiphany-layout-ir directly.
|
|
pub use epiphany_layout_ir::{ResolvedLayoutIR, ScaleContext};
|