pub fn shape_with_fallback(
primary: Font,
fallbacks: &[EmbeddedFontId],
size_pt: f32,
text: &str,
) -> Vec<WordSubRun>Expand description
Shape text against primary with per-glyph fallback. Walks each
HarfBuzz cluster in the primary’s shaped output; clusters that
contain any .notdef (GID 0) glyph are re-shaped against each
embedded face in fallbacks in order. The first fallback to produce a
glyph stream with no .notdef wins the whole cluster (cluster-
granular replacement, never partial: partial replacement would
duplicate bases, drop marks, break ligatures).
Returns one WordSubRun per contiguous source span that shares
a face. Each sub-run’s glyphs cluster offsets are rebased to
the sub-run’s local text, so mos-pdf::plan_embedded reads
/ToUnicode clusters with no awareness of the parent word.
Input is normalized through crate::nfc_text before fallback
shaping. Each returned WordSubRun::text is therefore a slice of
the normalized NFC string; decomposed caller input may not be
byte-identical to returned text.
Base14 primary: returns a single sub-run with empty glyphs
(Base14 has no glyph stream to inspect for .notdef; fallback
isn’t meaningful for that path). The advance comes from the AFM
width sum via text_width, same as the legacy shape_text
path.
All-fallback-fails behaviour: if no face in fallbacks covers a
.notdef cluster, the cluster stays in primary with .notdef
glyphs. plan_embedded already skips GID 0 from gid_to_text,
so copy-paste extraction is correct (empty for the un-renderable
span); the PDF reader renders an empty box.
§Examples
use mos_fonts::{Base14Font, Font, shape_with_fallback};
let subruns = shape_with_fallback(Font::Base14(Base14Font::Helvetica), &[], 10.0, "A");
assert_eq!(subruns.len(), 1);
assert_eq!(subruns[0].text, "A");