diff --git a/crates/typst-layout/src/inline/shaping.rs b/crates/typst-layout/src/inline/shaping.rs index d1e748da8..a8f2bcaba 100644 --- a/crates/typst-layout/src/inline/shaping.rs +++ b/crates/typst-layout/src/inline/shaping.rs @@ -719,6 +719,10 @@ fn glyphs_width(glyphs: &[ShapedGlyph]) -> Abs { struct ShapingContext<'a, 'v> { engine: &'a Engine<'v>, glyphs: Vec, + /// Font families that have been used with unlimited coverage. + /// + /// These font families are considered exhausted and will not be used again, + /// even if they are declared again (e.g., during fallback after normal selection). used: Vec, styles: StyleChain<'a>, size: Abs, @@ -777,7 +781,10 @@ fn shape_segment<'a>( return; }; - ctx.used.push(font.clone()); + // This font has been exhausted and will not be used again. + if covers.is_none() { + ctx.used.push(font.clone()); + } // Fill the buffer with our text. let mut buffer = UnicodeBuffer::new(); diff --git a/tests/ref/text-font-covers-repeat.png b/tests/ref/text-font-covers-repeat.png new file mode 100644 index 000000000..aceb8d007 Binary files /dev/null and b/tests/ref/text-font-covers-repeat.png differ diff --git a/tests/ref/text-font-covers-riffle.png b/tests/ref/text-font-covers-riffle.png new file mode 100644 index 000000000..577e4f23d Binary files /dev/null and b/tests/ref/text-font-covers-riffle.png differ diff --git a/tests/suite/text/font.typ b/tests/suite/text/font.typ index 6e21dfd23..dd61bfc86 100644 --- a/tests/suite/text/font.typ +++ b/tests/suite/text/font.typ @@ -135,6 +135,34 @@ I The number 123. +--- text-font-covers-repeat --- +// Repeatedly use the same font. +#set text(font: ( + (name: "Libertinus Serif", covers: regex("[0-9]")), + "Libertinus Serif" +)) + +The number 123. + +--- text-font-covers-riffle --- +// Repeatedly use two fonts alternately. +#set text(font: ( + (name: "Noto Color Emoji", covers: regex("[🔗⛓‍💥]")), + (name: "Twitter Color Emoji", covers: regex("[^🖥️]")), + "Noto Color Emoji", +)) + +🔗⛓‍💥🖥️🔑 + +// The above should be the same as: +#{ + text(font: "Noto Color Emoji", "🔗⛓‍💥🖥️") + text(font: "Twitter Color Emoji", "🔑") +} + +// but not: +#text(font: "Twitter Color Emoji", "🔗⛓‍💥🖥️🔑") + --- text-font-covers-bad-1 --- // Error: 17-59 coverage regex may only use dot, letters, and character classes // Hint: 17-59 the regex is applied to each letter individually