diff options
| author | damaxwell <damaxwell@alaska.edu> | 2023-06-26 03:51:27 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-26 13:51:27 +0200 |
| commit | 9eb350d7deadd59efba50b0e33acfd0967b8d0a6 (patch) | |
| tree | d3a96e090bca97fb207c583ea4991ed26e939de3 /library/src/math | |
| parent | 1861ceb1792d2a42979dff2fa721246ada922a42 (diff) | |
support optical sizes for script/scriptscript when available (#1580)
Diffstat (limited to 'library/src/math')
| -rw-r--r-- | library/src/math/ctx.rs | 50 | ||||
| -rw-r--r-- | library/src/math/fragment.rs | 30 |
2 files changed, 72 insertions, 8 deletions
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs index a6487476..a1dc6cf4 100644 --- a/library/src/math/ctx.rs +++ b/library/src/math/ctx.rs @@ -31,6 +31,7 @@ pub struct MathContext<'a, 'b, 'v> { pub ttf: &'a ttf_parser::Face<'a>, pub table: ttf_parser::math::Table<'a>, pub constants: ttf_parser::math::Constants<'a>, + pub ssty_table: Option<ttf_parser::gsub::AlternateSubstitution<'a>>, pub space_width: Em, pub fragments: Vec<MathFragment>, pub local: Styles, @@ -50,6 +51,27 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> { ) -> Self { let table = font.ttf().tables().math.unwrap(); let constants = table.constants.unwrap(); + + let ssty_table = font + .ttf() + .tables() + .gsub + .and_then(|gsub| { + gsub.features + .find(ttf_parser::Tag::from_bytes(b"ssty")) + .and_then(|feature| feature.lookup_indices.get(0)) + .and_then(|index| gsub.lookups.get(index)) + }) + .and_then(|ssty| { + ssty.subtables.get::<ttf_parser::gsub::SubstitutionSubtable>(0) + }) + .and_then(|ssty| match ssty { + ttf_parser::gsub::SubstitutionSubtable::Alternate(alt_glyphs) => { + Some(alt_glyphs) + } + _ => None, + }); + let size = TextElem::size_in(styles); let ttf = font.ttf(); let space_width = ttf @@ -66,6 +88,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> { ttf: font.ttf(), table, constants, + ssty_table, space_width, fragments: vec![], local: Styles::new(), @@ -129,20 +152,31 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> { let text = elem.text(); let span = elem.span(); let mut chars = text.chars(); - let fragment = if let Some(glyph) = chars + let fragment = if let Some(mut glyph) = chars .next() .filter(|_| chars.next().is_none()) .map(|c| self.style.styled_char(c)) .and_then(|c| GlyphFragment::try_new(self, c, span)) { // A single letter that is available in the math font. - if self.style.size == MathSize::Display - && glyph.class == Some(MathClass::Large) - { - let height = scaled!(self, display_operator_min_height); - glyph.stretch_vertical(self, height, Abs::zero()).into() - } else { - glyph.into() + match self.style.size { + MathSize::Display => { + if glyph.class == Some(MathClass::Large) { + let height = scaled!(self, display_operator_min_height); + glyph.stretch_vertical(self, height, Abs::zero()).into() + } else { + glyph.into() + } + } + MathSize::Script => { + glyph.make_scriptsize(self); + glyph.into() + } + MathSize::ScriptScript => { + glyph.make_scriptscriptsize(self); + glyph.into() + } + _ => glyph.into(), } } else if text.chars().all(|c| c.is_ascii_digit()) { // Numbers aren't that difficult. diff --git a/library/src/math/fragment.rs b/library/src/math/fragment.rs index b70a3f7d..139ce07b 100644 --- a/library/src/math/fragment.rs +++ b/library/src/math/fragment.rs @@ -1,4 +1,5 @@ use super::*; +use ttf_parser::gsub::AlternateSet; #[derive(Debug, Clone)] pub enum MathFragment { @@ -272,6 +273,25 @@ impl GlyphFragment { frame.meta_iter(self.meta); frame } + + pub fn make_scriptsize(&mut self, ctx: &MathContext) { + let alt_id = + script_alternatives(ctx, self.id).and_then(|alts| alts.alternates.get(0)); + + if let Some(alt_id) = alt_id { + self.set_id(ctx, alt_id); + } + } + + pub fn make_scriptscriptsize(&mut self, ctx: &MathContext) { + let alts = script_alternatives(ctx, self.id); + let alt_id = alts + .and_then(|alts| alts.alternates.get(1).or_else(|| alts.alternates.get(0))); + + if let Some(alt_id) = alt_id { + self.set_id(ctx, alt_id); + } + } } impl Debug for GlyphFragment { @@ -347,6 +367,16 @@ fn italics_correction(ctx: &MathContext, id: GlyphId) -> Option<Abs> { Some(ctx.table.glyph_info?.italic_corrections?.get(id)?.scaled(ctx)) } +/// Look up the script/scriptscript alternates for a glyph +fn script_alternatives<'a>( + ctx: &MathContext<'a, '_, '_>, + id: GlyphId, +) -> Option<AlternateSet<'a>> { + ctx.ssty_table.and_then(|ssty| { + ssty.coverage.get(id).and_then(|index| ssty.alternate_sets.get(index)) + }) +} + /// Look up the italics correction for a glyph. fn is_extended_shape(ctx: &MathContext, id: GlyphId) -> bool { ctx.table |
