From f93bac061c59a6efab309b43eb893bf041c93ee1 Mon Sep 17 00:00:00 2001 From: Peter Williams Date: Sun, 30 Jan 2022 11:12:58 -0500 Subject: [PATCH] Start implementing the MATH table --- src/font.rs | 6 ++ src/lib.rs | 1 + src/math.rs | 155 ++++++++++++++++++++++++++++++++++++++++++++++ src/otl/shared.rs | 2 +- 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 src/math.rs diff --git a/src/font.rs b/src/font.rs index aeb17b5..762ff71 100644 --- a/src/font.rs +++ b/src/font.rs @@ -13,6 +13,7 @@ use super::{ hhea::*, hmtx::*, hvar::*, + math::*, maxp::*, name::*, os2::*, @@ -329,6 +330,11 @@ pub trait TableProvider<'a> { fn gpos(&self) -> Option> { Some(Gpos::new(self.table_data(GPOS)?, self.gdef())) } + + /// Returns the mathemetical typesetting table. + fn math(&self) -> Option> { + Some(Math::new(self.table_data(MATH)?)) + } } impl<'a> TableProvider<'a> for FontRef<'a> { diff --git a/src/lib.rs b/src/lib.rs index 8203630..d5e473d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ pub mod head; pub mod hhea; pub mod hmtx; pub mod hvar; +pub mod math; pub mod maxp; pub mod name; pub mod os2; diff --git a/src/math.rs b/src/math.rs new file mode 100644 index 0000000..10a5ec6 --- /dev/null +++ b/src/math.rs @@ -0,0 +1,155 @@ +//! Mathematical typesetting table. + +use super::otl::Coverage; +use super::parse_prelude::*; + +/// Tag for the `math` table. +pub const MATH: Tag = Tag::new(b"MATH"); + +/// Mathematical typesetting table. +/// +/// +/// +/// The math constants and math glyph information subtables are not (yet) +/// implemented. +#[derive(Copy, Clone)] +pub struct Math<'a>(Buffer<'a>); + +impl<'a> Math<'a> { + /// Creates a new math table from a byte slice containing the table data. + pub fn new(data: &'a [u8]) -> Self { + Self(Buffer::new(data)) + } + + /// Returns the major version. + pub fn major_version(&self) -> u16 { + self.0.read(0).unwrap_or(0) + } + + /// Returns the minor version. + pub fn minor_version(&self) -> u16 { + self.0.read(2).unwrap_or(0) + } + + /// Returns the MathVariants subtable. + pub fn variants(&self) -> Option { + let offset = self.0.read_offset16(8, 0)?; + Some(MathVariants { math: self, offset }) + } +} + +/// Mathematical variants subtable. +/// +/// +#[derive(Copy, Clone)] +pub struct MathVariants<'a> { + math: &'a Math<'a>, + offset: u32, +} + +impl<'a> MathVariants<'a> { + /// Returns the minimum overlap of connecting glyphs during glyph + /// construction. + pub fn min_connector_overlap(&self) -> UfWord { + self.math.0.read(self.offset as usize).unwrap_or(0) + } + + /// Returns the number of glyphs for which information is provided for + /// vertically growing variants. + pub fn vert_glyph_count(&self) -> u16 { + self.math.0.read(self.offset as usize + 6).unwrap_or(0) + } + + /// Returns the number of glyphs for which information is provided for + /// horizontally growing variants. + pub fn horiz_glyph_count(&self) -> u16 { + self.math.0.read(self.offset as usize + 8).unwrap_or(0) + } + + /// Returns the coverage table associated with vertically growing glyphs. + pub fn vert_glyph_coverage(&self) -> Option { + let offset = self + .math + .0 + .read_offset16(self.offset as usize + 2, self.offset)?; + Some(Coverage::new(self.math.0, offset)) + } + + /// Returns the coverage table associated with horizontally growing glyphs. + pub fn horiz_glyph_coverage(&self) -> Option { + let offset = self + .math + .0 + .read_offset16(self.offset as usize + 4, self.offset)?; + Some(Coverage::new(self.math.0, offset)) + } + + /// Returns information about how to a construct vertically growing glyph, + /// based on its coverage index. + pub fn vert_glyph_construction(&self, coverage_index: u16) -> Option { + let offset = self.offset as usize + 10 + 2 * coverage_index as usize; + let offset = self.math.0.read_offset16(offset, self.offset)?; + Some(MathGlyphConstruction { + math: self.math, + offset: offset, + }) + } + + /// Returns information about how to a construct horizontally growing glyph, + /// based on its coverage index. + pub fn horiz_glyph_construction(&self, coverage_index: u16) -> Option { + let offset = self.offset as usize + + 10 + + 2 * self.vert_glyph_count() as usize + + 2 * coverage_index as usize; + let offset = self.math.0.read_offset16(offset, self.offset)?; + Some(MathGlyphConstruction { + math: self.math, + offset: offset, + }) + } +} + +/// Mathematical glyph construction subtable. +/// +/// +/// +/// The "glyph assembly" subtable is not (yet) implemented. +#[derive(Copy, Clone)] +pub struct MathGlyphConstruction<'a> { + math: &'a Math<'a>, + offset: u32, +} + +impl<'a> MathGlyphConstruction<'a> { + /// Returns the number of growing variants for this glyph. + pub fn variant_count(&self) -> u16 { + self.math.0.read(self.offset as usize + 2).unwrap_or(0) + } + + /// Return the growing variants associated with this glyph. + pub fn variants(&self) -> Option> { + self.math + .0 + .read_slice(self.offset as usize + 4, self.variant_count() as usize) + } +} + +/// Information about a math glyph variant. +#[derive(Copy, Clone, Debug)] +pub struct MathGlyphVariantRecord { + /// The variant glyph + pub variant_glyph: GlyphId, + /// The advance width/height of the variant, in the direction of this + /// record's associated table. + pub advance_measurement: UfWord, +} + +impl ReadData for MathGlyphVariantRecord { + unsafe fn read_data_unchecked(buf: &[u8], offset: usize) -> Self { + Self { + variant_glyph: GlyphId::read_data_unchecked(buf, offset), + advance_measurement: UfWord::read_data_unchecked(buf, offset + 2), + } + } +} diff --git a/src/otl/shared.rs b/src/otl/shared.rs index 24f0f1d..f1a00fb 100644 --- a/src/otl/shared.rs +++ b/src/otl/shared.rs @@ -13,7 +13,7 @@ pub struct Coverage<'a> { } impl<'a> Coverage<'a> { - pub(super) fn new(data: Buffer<'a>, offset: u32) -> Self { + pub(crate) fn new(data: Buffer<'a>, offset: u32) -> Self { Self { data, offset } }