Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
use super::{ClassDefinition, Coverage, SequenceLookupRecord};
use crate::parser::{FromSlice, LazyArray16, LazyOffsetArray16, Stream};
/// A [Chained Contextual Lookup Subtable](
/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chseqctxt1).
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum ChainedContextLookup<'a> {
/// Simple glyph contexts.
Format1 {
coverage: Coverage<'a>,
sets: ChainedSequenceRuleSets<'a>,
},
/// Class-based glyph contexts.
Format2 {
coverage: Coverage<'a>,
backtrack_classes: ClassDefinition<'a>,
input_classes: ClassDefinition<'a>,
lookahead_classes: ClassDefinition<'a>,
sets: ChainedSequenceRuleSets<'a>,
},
/// Coverage-based glyph contexts.
Format3 {
coverage: Coverage<'a>,
backtrack_coverages: LazyOffsetArray16<'a, Coverage<'a>>,
input_coverages: LazyOffsetArray16<'a, Coverage<'a>>,
lookahead_coverages: LazyOffsetArray16<'a, Coverage<'a>>,
lookups: LazyArray16<'a, SequenceLookupRecord>,
},
}
impl<'a> ChainedContextLookup<'a> {
pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
match s.read::<u16>()? {
1 => {
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
Some(Self::Format1 {
coverage,
sets: ChainedSequenceRuleSets::new(data, offsets),
})
}
2 => {
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let backtrack_classes = ClassDefinition::parse(s.read_at_offset16(data)?)?;
let input_classes = ClassDefinition::parse(s.read_at_offset16(data)?)?;
let lookahead_classes = ClassDefinition::parse(s.read_at_offset16(data)?)?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
Some(Self::Format2 {
coverage,
backtrack_classes,
input_classes,
lookahead_classes,
sets: LazyOffsetArray16::new(data, offsets),
})
}
3 => {
let backtrack_count = s.read::<u16>()?;
let backtrack_coverages = s.read_array16(backtrack_count)?;
let input_count = s.read::<u16>()?;
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let input_coverages = s.read_array16(input_count.checked_sub(1)?)?;
let lookahead_count = s.read::<u16>()?;
let lookahead_coverages = s.read_array16(lookahead_count)?;
let lookup_count = s.read::<u16>()?;
let lookups = s.read_array16(lookup_count)?;
Some(Self::Format3 {
coverage,
backtrack_coverages: LazyOffsetArray16::new(data, backtrack_coverages),
input_coverages: LazyOffsetArray16::new(data, input_coverages),
lookahead_coverages: LazyOffsetArray16::new(data, lookahead_coverages),
lookups,
})
}
_ => None,
}
}
/// Returns the subtable coverage.
#[inline]
pub fn coverage(&self) -> Coverage<'a> {
match self {
Self::Format1 { coverage, .. } => *coverage,
Self::Format2 { coverage, .. } => *coverage,
Self::Format3 { coverage, .. } => *coverage,
}
}
}
/// A list of [`ChainedSequenceRule`] sets.
pub type ChainedSequenceRuleSets<'a> = LazyOffsetArray16<'a, ChainedSequenceRuleSet<'a>>;
/// A set of [`ChainedSequenceRule`].
pub type ChainedSequenceRuleSet<'a> = LazyOffsetArray16<'a, ChainedSequenceRule<'a>>;
impl<'a> FromSlice<'a> for ChainedSequenceRuleSet<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
Self::parse(data)
}
}
/// A [Chained Sequence Rule](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-1-simple-glyph-contexts).
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct ChainedSequenceRule<'a> {
/// Contains either glyph IDs or glyph Classes.
pub backtrack: LazyArray16<'a, u16>,
pub input: LazyArray16<'a, u16>,
/// Contains either glyph IDs or glyph Classes.
pub lookahead: LazyArray16<'a, u16>,
pub lookups: LazyArray16<'a, SequenceLookupRecord>,
}
impl<'a> FromSlice<'a> for ChainedSequenceRule<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let backtrack_count = s.read::<u16>()?;
let backtrack = s.read_array16(backtrack_count)?;
let input_count = s.read::<u16>()?;
let input = s.read_array16(input_count.checked_sub(1)?)?;
let lookahead_count = s.read::<u16>()?;
let lookahead = s.read_array16(lookahead_count)?;
let lookup_count = s.read::<u16>()?;
let lookups = s.read_array16(lookup_count)?;
Some(Self {
backtrack,
input,
lookahead,
lookups,
})
}
}

129
vendor/ttf-parser/src/ggg/context.rs vendored Normal file
View File

@@ -0,0 +1,129 @@
use super::{ClassDefinition, Coverage, LookupIndex};
use crate::parser::{FromData, FromSlice, LazyArray16, LazyOffsetArray16, Stream};
/// A [Contextual Lookup Subtable](
/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#seqctxt1).
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum ContextLookup<'a> {
/// Simple glyph contexts.
Format1 {
coverage: Coverage<'a>,
sets: SequenceRuleSets<'a>,
},
/// Class-based glyph contexts.
Format2 {
coverage: Coverage<'a>,
classes: ClassDefinition<'a>,
sets: SequenceRuleSets<'a>,
},
/// Coverage-based glyph contexts.
Format3 {
coverage: Coverage<'a>,
coverages: LazyOffsetArray16<'a, Coverage<'a>>,
lookups: LazyArray16<'a, SequenceLookupRecord>,
},
}
impl<'a> ContextLookup<'a> {
pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
match s.read::<u16>()? {
1 => {
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
Some(Self::Format1 {
coverage,
sets: SequenceRuleSets::new(data, offsets),
})
}
2 => {
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let classes = ClassDefinition::parse(s.read_at_offset16(data)?)?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
Some(Self::Format2 {
coverage,
classes,
sets: SequenceRuleSets::new(data, offsets),
})
}
3 => {
let input_count = s.read::<u16>()?;
let lookup_count = s.read::<u16>()?;
let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
let coverages = s.read_array16(input_count.checked_sub(1)?)?;
let lookups = s.read_array16(lookup_count)?;
Some(Self::Format3 {
coverage,
coverages: LazyOffsetArray16::new(data, coverages),
lookups,
})
}
_ => None,
}
}
/// Returns the subtable coverage.
#[inline]
pub fn coverage(&self) -> Coverage<'a> {
match self {
Self::Format1 { coverage, .. } => *coverage,
Self::Format2 { coverage, .. } => *coverage,
Self::Format3 { coverage, .. } => *coverage,
}
}
}
/// A list of [`SequenceRuleSet`]s.
pub type SequenceRuleSets<'a> = LazyOffsetArray16<'a, SequenceRuleSet<'a>>;
impl<'a> FromSlice<'a> for SequenceRuleSet<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
Self::parse(data)
}
}
impl<'a> FromSlice<'a> for SequenceRule<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let input_count = s.read::<u16>()?;
let lookup_count = s.read::<u16>()?;
let input = s.read_array16(input_count.checked_sub(1)?)?;
let lookups = s.read_array16(lookup_count)?;
Some(Self { input, lookups })
}
}
/// A set of [`SequenceRule`]s.
pub type SequenceRuleSet<'a> = LazyOffsetArray16<'a, SequenceRule<'a>>;
/// A sequence rule.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct SequenceRule<'a> {
pub input: LazyArray16<'a, u16>,
pub lookups: LazyArray16<'a, SequenceLookupRecord>,
}
/// A sequence rule record.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct SequenceLookupRecord {
pub sequence_index: u16,
pub lookup_list_index: LookupIndex,
}
impl FromData for SequenceLookupRecord {
const SIZE: usize = 4;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(Self {
sequence_index: s.read::<u16>()?,
lookup_list_index: s.read::<LookupIndex>()?,
})
}
}

View File

@@ -0,0 +1,186 @@
use super::{Feature, FeatureIndex, RecordListItem, VariationIndex};
use crate::parser::{FromData, LazyArray16, LazyArray32};
use crate::parser::{Offset, Offset32, Stream};
use crate::{NormalizedCoordinate, Tag};
/// A [Feature Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table).
#[derive(Clone, Copy, Debug)]
pub struct FeatureVariations<'a> {
data: &'a [u8],
records: LazyArray32<'a, FeatureVariationRecord>,
}
impl<'a> FeatureVariations<'a> {
pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let major_version = s.read::<u16>()?;
s.skip::<u16>(); // minor version
if major_version != 1 {
return None;
}
let count = s.read::<u32>()?;
let records = s.read_array32(count)?;
Some(Self { data, records })
}
/// Returns a [`VariationIndex`] for variation coordinates.
pub fn find_index(&self, coords: &[NormalizedCoordinate]) -> Option<VariationIndex> {
for i in 0..self.records.len() {
let record = self.records.get(i)?;
let offset = record.conditions.to_usize();
let set = ConditionSet::parse(self.data.get(offset..)?)?;
if set.evaluate(coords) {
return Some(i);
}
}
None
}
/// Returns a [`Feature`] at specified indices.
pub fn find_substitute(
&self,
feature_index: FeatureIndex,
variation_index: VariationIndex,
) -> Option<Feature<'a>> {
let offset = self.records.get(variation_index)?.substitutions.to_usize();
let subst = FeatureTableSubstitution::parse(self.data.get(offset..)?)?;
subst.find_substitute(feature_index)
}
}
#[derive(Clone, Copy, Debug)]
struct FeatureVariationRecord {
conditions: Offset32,
substitutions: Offset32,
}
impl FromData for FeatureVariationRecord {
const SIZE: usize = 8;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(Self {
conditions: s.read::<Offset32>()?,
substitutions: s.read::<Offset32>()?,
})
}
}
#[derive(Clone, Copy, Debug)]
struct ConditionSet<'a> {
data: &'a [u8],
conditions: LazyArray16<'a, Offset32>,
}
impl<'a> ConditionSet<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let count = s.read::<u16>()?;
let conditions = s.read_array16(count)?;
Some(Self { data, conditions })
}
fn evaluate(&self, coords: &[NormalizedCoordinate]) -> bool {
self.conditions.into_iter().all(|offset| {
self.data
.get(offset.to_usize()..)
.and_then(Condition::parse)
.map_or(false, |c| c.evaluate(coords))
})
}
}
#[derive(Clone, Copy, Debug)]
enum Condition {
Format1 {
axis_index: u16,
filter_range_min: i16,
filter_range_max: i16,
},
}
impl Condition {
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
let format = s.read::<u16>()?;
match format {
1 => {
let axis_index = s.read::<u16>()?;
let filter_range_min = s.read::<i16>()?;
let filter_range_max = s.read::<i16>()?;
Some(Self::Format1 {
axis_index,
filter_range_min,
filter_range_max,
})
}
_ => None,
}
}
fn evaluate(&self, coords: &[NormalizedCoordinate]) -> bool {
let Self::Format1 {
axis_index,
filter_range_min,
filter_range_max,
} = *self;
let coord = coords
.get(usize::from(axis_index))
.map(|c| c.get())
.unwrap_or(0);
filter_range_min <= coord && coord <= filter_range_max
}
}
#[derive(Clone, Copy, Debug)]
struct FeatureTableSubstitution<'a> {
data: &'a [u8],
records: LazyArray16<'a, FeatureTableSubstitutionRecord>,
}
impl<'a> FeatureTableSubstitution<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let major_version = s.read::<u16>()?;
s.skip::<u16>(); // minor version
if major_version != 1 {
return None;
}
let count = s.read::<u16>()?;
let records = s.read_array16(count)?;
Some(Self { data, records })
}
fn find_substitute(&self, feature_index: FeatureIndex) -> Option<Feature<'a>> {
for record in self.records {
if record.feature_index == feature_index {
let offset = record.feature.to_usize();
// TODO: set tag
return Feature::parse(Tag::from_bytes(b"DFLT"), self.data.get(offset..)?);
}
}
None
}
}
#[derive(Clone, Copy, Debug)]
struct FeatureTableSubstitutionRecord {
feature_index: FeatureIndex,
feature: Offset32,
}
impl FromData for FeatureTableSubstitutionRecord {
const SIZE: usize = 6;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(Self {
feature_index: s.read::<FeatureIndex>()?,
feature: s.read::<Offset32>()?,
})
}
}

View File

@@ -0,0 +1,287 @@
// Suppresses `minor_version` variable warning.
#![allow(unused_variables)]
#[cfg(feature = "variable-fonts")]
use super::FeatureVariations;
use super::LookupList;
#[cfg(feature = "variable-fonts")]
use crate::parser::Offset32;
use crate::parser::{FromData, LazyArray16, Offset, Offset16, Stream};
use crate::Tag;
/// A [Layout Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#table-organization).
#[derive(Clone, Copy, Debug)]
pub struct LayoutTable<'a> {
/// A list of all supported scripts.
pub scripts: ScriptList<'a>,
/// A list of all supported features.
pub features: FeatureList<'a>,
/// A list of all lookups.
pub lookups: LookupList<'a>,
/// Used to substitute an alternate set of lookup tables
/// to use for any given feature under specified conditions.
#[cfg(feature = "variable-fonts")]
pub variations: Option<FeatureVariations<'a>>,
}
impl<'a> LayoutTable<'a> {
pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let major_version = s.read::<u16>()?;
let minor_version = s.read::<u16>()?;
if major_version != 1 {
return None;
}
let scripts = ScriptList::parse(s.read_at_offset16(data)?)?;
let features = FeatureList::parse(s.read_at_offset16(data)?)?;
let lookups = LookupList::parse(s.read_at_offset16(data)?)?;
#[cfg(feature = "variable-fonts")]
{
let mut variations_offset = None;
if minor_version >= 1 {
variations_offset = s.read::<Option<Offset32>>()?;
}
let variations = match variations_offset {
Some(offset) => data
.get(offset.to_usize()..)
.and_then(FeatureVariations::parse),
None => None,
};
Some(Self {
scripts,
features,
lookups,
variations,
})
}
#[cfg(not(feature = "variable-fonts"))]
{
Some(Self {
scripts,
features,
lookups,
})
}
}
}
/// An index in [`ScriptList`].
pub type ScriptIndex = u16;
/// An index in [`LanguageSystemList`].
pub type LanguageIndex = u16;
/// An index in [`FeatureList`].
pub type FeatureIndex = u16;
/// An index in [`LookupList`].
pub type LookupIndex = u16;
/// An index in [`FeatureVariations`].
pub type VariationIndex = u32;
/// A trait to parse item in [`RecordList`].
///
/// Internal use only.
pub trait RecordListItem<'a>: Sized {
/// Parses raw data.
fn parse(tag: Tag, data: &'a [u8]) -> Option<Self>;
}
/// A data storage used by [`ScriptList`], [`LanguageSystemList`] and [`FeatureList`] data types.
#[derive(Clone, Copy, Debug)]
pub struct RecordList<'a, T: RecordListItem<'a>> {
data: &'a [u8],
records: LazyArray16<'a, TagRecord>,
data_type: core::marker::PhantomData<T>,
}
impl<'a, T: RecordListItem<'a>> RecordList<'a, T> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let count = s.read::<u16>()?;
let records = s.read_array16(count)?;
Some(Self {
data,
records,
data_type: core::marker::PhantomData,
})
}
/// Returns a number of items in the RecordList.
pub fn len(&self) -> u16 {
self.records.len()
}
/// Checks that RecordList is empty.
pub fn is_empty(&self) -> bool {
self.records.is_empty()
}
/// Returns RecordList value by index.
pub fn get(&self, index: u16) -> Option<T> {
let record = self.records.get(index)?;
self.data
.get(record.offset.to_usize()..)
.and_then(|data| T::parse(record.tag, data))
}
/// Returns RecordList value by [`Tag`].
pub fn find(&self, tag: Tag) -> Option<T> {
let record = self
.records
.binary_search_by(|record| record.tag.cmp(&tag))
.map(|p| p.1)?;
self.data
.get(record.offset.to_usize()..)
.and_then(|data| T::parse(record.tag, data))
}
/// Returns RecordList value index by [`Tag`].
pub fn index(&self, tag: Tag) -> Option<u16> {
self.records
.binary_search_by(|record| record.tag.cmp(&tag))
.map(|p| p.0)
}
}
impl<'a, T: RecordListItem<'a>> IntoIterator for RecordList<'a, T> {
type Item = T;
type IntoIter = RecordListIter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
RecordListIter {
list: self,
index: 0,
}
}
}
/// An iterator over [`RecordList`] values.
#[allow(missing_debug_implementations)]
pub struct RecordListIter<'a, T: RecordListItem<'a>> {
list: RecordList<'a, T>,
index: u16,
}
impl<'a, T: RecordListItem<'a>> Iterator for RecordListIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.list.len() {
self.index += 1;
self.list.get(self.index - 1)
} else {
None
}
}
}
/// A list of [`Script`] records.
pub type ScriptList<'a> = RecordList<'a, Script<'a>>;
/// A list of [`LanguageSystem`] records.
pub type LanguageSystemList<'a> = RecordList<'a, LanguageSystem<'a>>;
/// A list of [`Feature`] records.
pub type FeatureList<'a> = RecordList<'a, Feature<'a>>;
#[derive(Clone, Copy, Debug)]
struct TagRecord {
tag: Tag,
offset: Offset16,
}
impl FromData for TagRecord {
const SIZE: usize = 6;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(Self {
tag: s.read::<Tag>()?,
offset: s.read::<Offset16>()?,
})
}
}
/// A [Script Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#script-table-and-language-system-record).
#[derive(Clone, Copy, Debug)]
pub struct Script<'a> {
/// Script tag.
pub tag: Tag,
/// Default language.
pub default_language: Option<LanguageSystem<'a>>,
/// List of supported languages, excluding the default one. Listed alphabetically.
pub languages: LanguageSystemList<'a>,
}
impl<'a> RecordListItem<'a> for Script<'a> {
fn parse(tag: Tag, data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let mut default_language = None;
if let Some(offset) = s.read::<Option<Offset16>>()? {
default_language =
LanguageSystem::parse(Tag::from_bytes(b"dflt"), data.get(offset.to_usize()..)?);
}
let mut languages = RecordList::parse(s.tail()?)?;
// Offsets are relative to this table.
languages.data = data;
Some(Self {
tag,
default_language,
languages,
})
}
}
/// A [Language System Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#language-system-table).
#[derive(Clone, Copy, Debug)]
pub struct LanguageSystem<'a> {
/// Language tag.
pub tag: Tag,
/// Index of a feature required for this language system.
pub required_feature: Option<FeatureIndex>,
/// Array of indices into the FeatureList, in arbitrary order.
pub feature_indices: LazyArray16<'a, FeatureIndex>,
}
impl<'a> RecordListItem<'a> for LanguageSystem<'a> {
fn parse(tag: Tag, data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let _lookup_order = s.read::<Offset16>()?; // Unsupported.
let required_feature = match s.read::<FeatureIndex>()? {
0xFFFF => None,
v => Some(v),
};
let count = s.read::<u16>()?;
let feature_indices = s.read_array16(count)?;
Some(Self {
tag,
required_feature,
feature_indices,
})
}
}
/// A [Feature](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table).
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct Feature<'a> {
pub tag: Tag,
pub lookup_indices: LazyArray16<'a, LookupIndex>,
}
impl<'a> RecordListItem<'a> for Feature<'a> {
fn parse(tag: Tag, data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let _params_offset = s.read::<Offset16>()?; // Unsupported.
let count = s.read::<u16>()?;
let lookup_indices = s.read_array16(count)?;
Some(Self {
tag,
lookup_indices,
})
}
}

165
vendor/ttf-parser/src/ggg/lookup.rs vendored Normal file
View File

@@ -0,0 +1,165 @@
use crate::parser::{
FromData, FromSlice, LazyArray16, LazyOffsetArray16, Offset, Offset16, Offset32, Stream,
};
/// A list of [`Lookup`] values.
pub type LookupList<'a> = LazyOffsetArray16<'a, Lookup<'a>>;
/// A [Lookup Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table).
#[derive(Clone, Copy, Debug)]
pub struct Lookup<'a> {
/// Lookup qualifiers.
pub flags: LookupFlags,
/// Available subtables.
pub subtables: LookupSubtables<'a>,
/// Index into GDEF mark glyph sets structure.
pub mark_filtering_set: Option<u16>,
}
impl<'a> FromSlice<'a> for Lookup<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let kind = s.read::<u16>()?;
let flags = s.read::<LookupFlags>()?;
let count = s.read::<u16>()?;
let offsets = s.read_array16(count)?;
let mut mark_filtering_set: Option<u16> = None;
if flags.use_mark_filtering_set() {
mark_filtering_set = Some(s.read::<u16>()?);
}
Some(Self {
flags,
subtables: LookupSubtables {
kind,
data,
offsets,
},
mark_filtering_set,
})
}
}
/// A trait for parsing Lookup subtables.
///
/// Internal use only.
pub trait LookupSubtable<'a>: Sized {
/// Parses raw data.
fn parse(data: &'a [u8], kind: u16) -> Option<Self>;
}
/// A list of lookup subtables.
#[derive(Clone, Copy)]
pub struct LookupSubtables<'a> {
kind: u16,
data: &'a [u8],
offsets: LazyArray16<'a, Offset16>,
}
impl core::fmt::Debug for LookupSubtables<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "LookupSubtables {{ ... }}")
}
}
impl<'a> LookupSubtables<'a> {
/// Returns a number of items in the LookupSubtables.
#[inline]
pub fn len(&self) -> u16 {
self.offsets.len()
}
/// Checks if there are any items.
pub fn is_empty(&self) -> bool {
self.offsets.is_empty()
}
/// Parses a subtable at index.
///
/// Accepts either
/// [`PositioningSubtable`](crate::gpos::PositioningSubtable)
/// or [`SubstitutionSubtable`](crate::gsub::SubstitutionSubtable).
///
/// Technically, we can enforce it at compile time, but it makes code too convoluted.
pub fn get<T: LookupSubtable<'a>>(&self, index: u16) -> Option<T> {
let offset = self.offsets.get(index)?.to_usize();
let data = self.data.get(offset..)?;
T::parse(data, self.kind)
}
/// Creates an iterator over subtables.
///
/// We cannot use `IntoIterator` here, because we have to use user-provided base type.
#[allow(clippy::should_implement_trait)]
pub fn into_iter<T: LookupSubtable<'a>>(self) -> LookupSubtablesIter<'a, T> {
LookupSubtablesIter {
data: self,
index: 0,
data_type: core::marker::PhantomData,
}
}
}
/// An iterator over lookup subtables.
#[allow(missing_debug_implementations)]
pub struct LookupSubtablesIter<'a, T: LookupSubtable<'a>> {
data: LookupSubtables<'a>,
index: u16,
data_type: core::marker::PhantomData<T>,
}
impl<'a, T: LookupSubtable<'a>> Iterator for LookupSubtablesIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.data.len() {
self.index += 1;
self.data.get(self.index - 1)
} else {
None
}
}
}
/// Lookup table flags.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub struct LookupFlags(pub u16);
#[rustfmt::skip]
#[allow(missing_docs)]
impl LookupFlags {
#[inline] pub fn right_to_left(self) -> bool { self.0 & 0x0001 != 0 }
#[inline] pub fn ignore_base_glyphs(self) -> bool { self.0 & 0x0002 != 0 }
#[inline] pub fn ignore_ligatures(self) -> bool { self.0 & 0x0004 != 0 }
#[inline] pub fn ignore_marks(self) -> bool { self.0 & 0x0008 != 0 }
#[inline] pub fn ignore_flags(self) -> bool { self.0 & 0x000E != 0 }
#[inline] pub fn use_mark_filtering_set(self) -> bool { self.0 & 0x0010 != 0 }
#[inline] pub fn mark_attachment_type(self) -> u8 { (self.0 & 0xFF00) as u8 }
}
impl FromData for LookupFlags {
const SIZE: usize = 2;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
u16::parse(data).map(Self)
}
}
pub(crate) fn parse_extension_lookup<'a, T: 'a>(
data: &'a [u8],
parse: impl FnOnce(&'a [u8], u16) -> Option<T>,
) -> Option<T> {
let mut s = Stream::new(data);
let format = s.read::<u16>()?;
match format {
1 => {
let kind = s.read::<u16>()?;
let offset = s.read::<Offset32>()?.to_usize();
parse(data.get(offset..)?, kind)
}
_ => None,
}
}

168
vendor/ttf-parser/src/ggg/mod.rs vendored Normal file
View File

@@ -0,0 +1,168 @@
//! Common data types used by GDEF/GPOS/GSUB tables.
//!
//! <https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2>
// A heavily modified port of https://github.com/RazrFalcon/rustybuzz implementation
// originally written by https://github.com/laurmaedje
use crate::parser::{FromData, FromSlice, LazyArray16, Stream};
use crate::GlyphId;
mod chained_context;
mod context;
#[cfg(feature = "variable-fonts")]
mod feature_variations;
mod layout_table;
mod lookup;
pub use chained_context::*;
pub use context::*;
#[cfg(feature = "variable-fonts")]
pub use feature_variations::*;
pub use layout_table::*;
pub use lookup::*;
/// A record that describes a range of glyph IDs.
#[derive(Clone, Copy, Debug)]
pub struct RangeRecord {
/// First glyph ID in the range
pub start: GlyphId,
/// Last glyph ID in the range
pub end: GlyphId,
/// Coverage Index of first glyph ID in range.
pub value: u16,
}
impl LazyArray16<'_, RangeRecord> {
/// Returns a [`RangeRecord`] for a glyph.
pub fn range(&self, glyph: GlyphId) -> Option<RangeRecord> {
self.binary_search_by(|record| {
if glyph < record.start {
core::cmp::Ordering::Greater
} else if glyph <= record.end {
core::cmp::Ordering::Equal
} else {
core::cmp::Ordering::Less
}
})
.map(|p| p.1)
}
}
impl FromData for RangeRecord {
const SIZE: usize = 6;
#[inline]
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(RangeRecord {
start: s.read::<GlyphId>()?,
end: s.read::<GlyphId>()?,
value: s.read::<u16>()?,
})
}
}
/// A [Coverage Table](
/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-table).
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum Coverage<'a> {
Format1 {
/// Array of glyph IDs. Sorted.
glyphs: LazyArray16<'a, GlyphId>,
},
Format2 {
/// Array of glyph ranges. Ordered by `RangeRecord.start`.
records: LazyArray16<'a, RangeRecord>,
},
}
impl<'a> FromSlice<'a> for Coverage<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
match s.read::<u16>()? {
1 => {
let count = s.read::<u16>()?;
let glyphs = s.read_array16(count)?;
Some(Self::Format1 { glyphs })
}
2 => {
let count = s.read::<u16>()?;
let records = s.read_array16(count)?;
Some(Self::Format2 { records })
}
_ => None,
}
}
}
impl<'a> Coverage<'a> {
/// Checks that glyph is present.
pub fn contains(&self, glyph: GlyphId) -> bool {
self.get(glyph).is_some()
}
/// Returns the coverage index of the glyph or `None` if it is not covered.
pub fn get(&self, glyph: GlyphId) -> Option<u16> {
match self {
Self::Format1 { glyphs } => glyphs.binary_search(&glyph).map(|p| p.0),
Self::Format2 { records } => {
let record = records.range(glyph)?;
let offset = glyph.0 - record.start.0;
record.value.checked_add(offset)
}
}
}
}
/// A value of [Class Definition Table](
/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table).
pub type Class = u16;
/// A [Class Definition Table](
/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table).
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum ClassDefinition<'a> {
Format1 {
start: GlyphId,
classes: LazyArray16<'a, Class>,
},
Format2 {
records: LazyArray16<'a, RangeRecord>,
},
}
impl<'a> ClassDefinition<'a> {
#[inline]
pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
match s.read::<u16>()? {
1 => {
let start = s.read::<GlyphId>()?;
let count = s.read::<u16>()?;
let classes = s.read_array16(count)?;
Some(Self::Format1 { start, classes })
}
2 => {
let count = s.read::<u16>()?;
let records = s.read_array16(count)?;
Some(Self::Format2 { records })
}
_ => None,
}
}
/// Returns the glyph class of the glyph (zero if it is not defined).
pub fn get(&self, glyph: GlyphId) -> Class {
match self {
Self::Format1 { start, classes } => glyph
.0
.checked_sub(start.0)
.and_then(|index| classes.get(index)),
Self::Format2 { records } => records.range(glyph).map(|record| record.value),
}
.unwrap_or(0)
}
}