[OpenFontFormat] Clean up OpenFont.py
This commit is contained in:
parent
6a33053dfc
commit
33e9714d34
@ -3,8 +3,8 @@ from datetime import datetime, timedelta, timezone
|
||||
from enum import Enum, EnumMeta
|
||||
from io import BytesIO
|
||||
from math import floor, log2
|
||||
from typing import Callable, Generic, List, Optional, Tuple, TypeVar, BinaryIO
|
||||
from typing_extensions import Self
|
||||
from types import TracebackType
|
||||
from typing import Callable, Generic, List, Optional, Tuple, Type, TypeVar, BinaryIO, Self
|
||||
|
||||
from abcde import ABD, ABE
|
||||
from read_utils import read_ascii, read_fixed_point, read_i16, read_i32, read_i8, read_int, read_pascal_string, read_u16, read_u24, read_u32, read_u64, read_u8
|
||||
@ -28,7 +28,7 @@ def read_long_datetime(f: BinaryIO) -> datetime:
|
||||
Tag_ = TypeVar('Tag_')
|
||||
SomeTag = Callable[[str], Tag_] # If SomeTag is not an EnumMeta, it should throw a ValueError to indicate an invalid tag
|
||||
|
||||
def parse_tag_with_conditions(f: BinaryIO, *conditions: Tuple[Callable[[str], bool], SomeTag[Tag_]], umbrellaTagCls: type | SomeTag[Tag_], strict:bool=True) -> Tag_:
|
||||
def read_tag_with_conditions(f: BinaryIO, *conditions: Tuple[Callable[[str], bool], SomeTag[Tag_]], umbrellaTagCls: type | SomeTag[Tag_], strict:bool=True) -> Tag_:
|
||||
tag = read_ascii(f, 4)
|
||||
assert not strict or all([0x20 <= ord(c) <= 0x7e for c in tag]), f"Invalid tag: {[f.seek(-4, 1), f.read(4)][1]}"
|
||||
for (condition, tagCls) in conditions:
|
||||
@ -38,14 +38,14 @@ def parse_tag_with_conditions(f: BinaryIO, *conditions: Tuple[Callable[[str], bo
|
||||
else:
|
||||
assert False, f"Invalid {umbrellaTagCls.__name__}: '{tag}'"
|
||||
|
||||
def parse_tag_cascading(f: BinaryIO, *tagClss: SomeTag[Tag_], umbrellaTagCls: type | SomeTag[Tag_], strict:bool=True) -> Tag_:
|
||||
def read_tag_from_tags(f: BinaryIO, *tagClss: SomeTag[Tag_], umbrellaTagCls: type | SomeTag[Tag_], strict:bool=True) -> Tag_:
|
||||
"""
|
||||
This is meant to be used for when some instances of an Enum are just CC01, CC02, CC03, ...
|
||||
"""
|
||||
return parse_tag_with_conditions(f, *[(lambda _: True, tagCls) for tagCls in tagClss], umbrellaTagCls=umbrellaTagCls, strict=strict)
|
||||
return read_tag_with_conditions(f, *[(lambda _: True, tagCls) for tagCls in tagClss], umbrellaTagCls=umbrellaTagCls, strict=strict)
|
||||
|
||||
def parse_tag(f: BinaryIO, tagCls: SomeTag[Tag_], *, strict:bool=True) -> Tag_:
|
||||
return parse_tag_cascading(f, tagCls, umbrellaTagCls=tagCls, strict=strict)
|
||||
def read_tag(f: BinaryIO, tagCls: SomeTag[Tag_], *, strict:bool=True) -> Tag_:
|
||||
return read_tag_from_tags(f, tagCls, umbrellaTagCls=tagCls, strict=strict)
|
||||
|
||||
ID_ = TypeVar('ID_')
|
||||
SomeID = Callable[[int], ID_]
|
||||
@ -53,7 +53,7 @@ SomeID = Callable[[int], ID_]
|
||||
T = TypeVar('T')
|
||||
Parser = Callable[[BinaryIO], T]
|
||||
|
||||
def parse_id_ranges(f: BinaryIO, *ranges: Tuple[Optional[int], SomeID[ID_]], umbrellaIdCls: SomeID[ID_], reader: Parser[int]=read_u16) -> ID_: # must be in ascending order
|
||||
def read_id_from_ranges(f: BinaryIO, *ranges: Tuple[Optional[int], SomeID[ID_]], umbrellaIdCls: SomeID[ID_], reader: Parser[int]=read_u16) -> ID_: # must be in ascending order
|
||||
assert len(ranges) > 0, f"Must have at least one range"
|
||||
id = reader(f)
|
||||
for (num, idCls) in ranges:
|
||||
@ -62,18 +62,18 @@ def parse_id_ranges(f: BinaryIO, *ranges: Tuple[Optional[int], SomeID[ID_]], umb
|
||||
except ValueError: pass
|
||||
assert False, f"Invalid {umbrellaIdCls.__name__}: {id}"
|
||||
|
||||
def parse_id(f: BinaryIO, idCls: SomeID[ID_], *, reader: Parser[int]=read_u16) -> ID_:
|
||||
return parse_id_ranges(f, (None, idCls), umbrellaIdCls=idCls, reader=reader)
|
||||
def read_id(f: BinaryIO, idCls: SomeID[ID_], *, reader: Parser[int]=read_u16) -> ID_:
|
||||
return read_id_from_ranges(f, (None, idCls), umbrellaIdCls=idCls, reader=reader)
|
||||
|
||||
class SaveTell:
|
||||
def __init__(self, f: BinaryIO):
|
||||
self.f = f
|
||||
|
||||
def __enter__(self):
|
||||
def __enter__(self) -> int:
|
||||
self.tell = self.f.tell()
|
||||
return self.tell
|
||||
|
||||
def __exit__(self, exc_type, exc_value, exc_tb):
|
||||
def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], exc_tb: Optional[TracebackType]) -> None:
|
||||
self.f.seek(self.tell)
|
||||
|
||||
# The following `parse_at_...` functions all move the BinaryIO away from wherever it was, so use `with SaveTell(f): ...` to save the tell
|
||||
@ -128,8 +128,8 @@ SomeTable = TypeVar('SomeTable', bound=Table)
|
||||
|
||||
@dataclass
|
||||
class SetTable(Table, Generic[SomeTable]):
|
||||
count: int
|
||||
elements: List[SomeTable]
|
||||
tableCount: int
|
||||
tables: List[SomeTable]
|
||||
|
||||
def parse_set_table(f: BinaryIO, parser: Parser[SomeTable], *, offset_reader: Parser[int]=read_u16) -> SetTable[SomeTable]:
|
||||
start_tell = f.tell()
|
||||
@ -237,6 +237,9 @@ class TableTag(Enum):
|
||||
|
||||
def __str__(self) -> str: return self._value_
|
||||
|
||||
def parse_table_tag(f: BinaryIO) -> TableTag:
|
||||
return read_tag(f, TableTag)
|
||||
|
||||
@dataclass
|
||||
class TableDirectoryEntry:
|
||||
tableTag: TableTag
|
||||
@ -245,7 +248,7 @@ class TableDirectoryEntry:
|
||||
length: int
|
||||
|
||||
def parse_table_directory_entry(f: BinaryIO) -> TableDirectoryEntry:
|
||||
tableTag = parse_tag(f, TableTag)
|
||||
tableTag = parse_table_tag(f)
|
||||
checkSum = read_u32(f)
|
||||
offset = read_u32(f)
|
||||
length = read_u32(f)
|
||||
@ -435,12 +438,12 @@ class CmapSubtable_Format_12(CmapSubtable):
|
||||
groups: List[SequentialMapGroup]
|
||||
|
||||
@dataclass
|
||||
class UnicodeRangeRecord:
|
||||
class UnicodeRangeRecord(Record):
|
||||
startUnicodeValue: int
|
||||
additionalCount: int
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"U+{hex(self.startUnicodeValue)[2:]:0>4}" + (f"-U+{hex(self.startUnicodeValue+self.additionalCount)[2:]:0>4}" if self.additionalCount > 0 else '')
|
||||
return f"<U+{hex(self.startUnicodeValue)[2:]:0>4}" + (f"-U+{hex(self.startUnicodeValue+self.additionalCount)[2:]:0>4}" if self.additionalCount > 0 else '')+">"
|
||||
|
||||
def parse_unicode_range_record(f: BinaryIO) -> UnicodeRangeRecord:
|
||||
startUnicodeValue = read_u24(f)
|
||||
@ -461,7 +464,7 @@ def parse_default_UVS_table(f: BinaryIO) -> DefaultUVSTable:
|
||||
return DefaultUVSTable(numUnicodeValueRanges, ranges)
|
||||
|
||||
@dataclass
|
||||
class UVSMappingRecord:
|
||||
class UVSMappingRecord(Record):
|
||||
unicodeValue: int
|
||||
glyphID: int
|
||||
|
||||
@ -483,7 +486,7 @@ def parse_non_default_UVS_table(f: BinaryIO) -> NonDefaultUVSTable:
|
||||
return NonDefaultUVSTable(numUVSMappings, uvsMappings)
|
||||
|
||||
@dataclass
|
||||
class VariationSelectorRecord:
|
||||
class VariationSelectorRecord(Record):
|
||||
varSelector: int
|
||||
defaultUVS: Optional[DefaultUVSTable]
|
||||
nonDefaultUVS: Optional[NonDefaultUVSTable]
|
||||
@ -637,8 +640,8 @@ def encoding_ID_cls_from_platform_ID(platformID: PlatformID) -> Callable[[int],
|
||||
|
||||
assert False, platformID
|
||||
|
||||
def parse_encoding_ID(f: BinaryIO, platformID: PlatformID):
|
||||
return parse_id(f, encoding_ID_cls_from_platform_ID(platformID))
|
||||
def parse_encoding_ID(f: BinaryIO, platformID: PlatformID) -> EncodingID:
|
||||
return read_id(f, encoding_ID_cls_from_platform_ID(platformID))
|
||||
|
||||
def parse_string_with_encoding_ID(f: BinaryIO, length: int, encodingID: EncodingID) -> str:
|
||||
bytes = f.read(length)
|
||||
@ -653,13 +656,13 @@ def parse_string_with_encoding_ID(f: BinaryIO, length: int, encodingID: Encoding
|
||||
assert False, encodingID
|
||||
|
||||
@dataclass
|
||||
class EncodingRecord:
|
||||
class EncodingRecord(Record):
|
||||
platformID: PlatformID
|
||||
encodingID: EncodingID
|
||||
subtable: CmapSubtable
|
||||
|
||||
def parse_encoding_record(f: BinaryIO, start_tell:int) -> EncodingRecord:
|
||||
platformID = parse_id(f, PlatformID)
|
||||
platformID = read_id(f, PlatformID)
|
||||
encodingID = parse_encoding_ID(f, platformID)
|
||||
subtableOffset = read_u32(f)
|
||||
with SaveTell(f):
|
||||
@ -1086,7 +1089,7 @@ def languageID_cls_from_platform_ID(platformID: PlatformID) -> Callable[[int], L
|
||||
assert False, platformID
|
||||
|
||||
def parse_language_ID(f: BinaryIO, platformID: PlatformID) -> LanguageID:
|
||||
return parse_id(f, languageID_cls_from_platform_ID(platformID))
|
||||
return read_id(f, languageID_cls_from_platform_ID(platformID))
|
||||
|
||||
class NameID(ABE): pass
|
||||
|
||||
@ -1123,7 +1126,7 @@ class FontSpecificNameID(NameID):
|
||||
nameID: int
|
||||
|
||||
def parse_name_ID(f: BinaryIO) -> NameID:
|
||||
return parse_id_ranges(f, (255, PredefinedNameID), (32767, FontSpecificNameID), umbrellaIdCls=NameID)
|
||||
return read_id_from_ranges(f, (255, PredefinedNameID), (32767, FontSpecificNameID), umbrellaIdCls=NameID)
|
||||
|
||||
@dataclass
|
||||
class NameRecord:
|
||||
@ -1135,7 +1138,7 @@ class NameRecord:
|
||||
string: str
|
||||
|
||||
def parse_name_record(f: BinaryIO, stringBytes: BinaryIO) -> NameRecord:
|
||||
platformID = parse_id(f, PlatformID)
|
||||
platformID = read_id(f, PlatformID)
|
||||
encodingID = parse_encoding_ID(f, platformID)
|
||||
languageID = parse_language_ID(f, platformID)
|
||||
nameID = parse_name_ID(f)
|
||||
@ -1178,6 +1181,9 @@ def parse_name_table(f: BinaryIO, length: int) -> NameTable:
|
||||
class VendorTag:
|
||||
achVendID: str
|
||||
|
||||
def parse_vendor_tag(f: BinaryIO) -> VendorTag:
|
||||
return read_tag(f, VendorTag, strict=False)
|
||||
|
||||
@dataclass
|
||||
class OS2Table(Table, ABD):
|
||||
version: int
|
||||
@ -1251,7 +1257,7 @@ def parse_OS2_table(f: BinaryIO) -> OS2Table:
|
||||
panose0, panose1, panose2, panose3, panose4, panose5, panose6, panose7, panose8, panose9 = [read_u8(f) for _ in range(10)]
|
||||
panose = (panose0, panose1, panose2, panose3, panose4, panose5, panose6, panose7, panose8, panose9)
|
||||
ulUnicodeRange1, ulUnicodeRange2, ulUnicodeRange3, ulUnicodeRange4 = [read_u32(f) for _ in range(4)]
|
||||
achVendID = parse_tag(f, VendorTag, strict=False)
|
||||
achVendID = parse_vendor_tag(f)
|
||||
fsSelection = read_u16(f)
|
||||
usFirstCharIndex, usLastCharIndex = read_u16(f), read_u16(f)
|
||||
sTypoAscender, sTypoDescender, sTypoLineGap = read_i16(f), read_i16(f), read_i16(f)
|
||||
@ -2470,7 +2476,7 @@ class ValidLangSysTag(LangSysTag, Enum):
|
||||
def __str__(self) -> str: return self._name_
|
||||
|
||||
def parse_lang_sys_tag(f: BinaryIO) -> LangSysTag:
|
||||
return parse_tag_cascading(f, ValidLangSysTag, MS_VOLT_Tag, umbrellaTagCls=LangSysTag)
|
||||
return read_tag_from_tags(f, ValidLangSysTag, MS_VOLT_Tag, umbrellaTagCls=LangSysTag)
|
||||
|
||||
@dataclass
|
||||
class LangSysRecord:
|
||||
@ -2508,7 +2514,7 @@ class ScriptRecord:
|
||||
script: ScriptTable
|
||||
|
||||
def parse_script_record(f: BinaryIO, start_tell:int) -> ScriptRecord:
|
||||
tag = parse_tag(f, ScriptTag)
|
||||
tag = read_tag(f, ScriptTag)
|
||||
scriptOffset = read_u16(f)
|
||||
with SaveTell(f):
|
||||
script = parse_at_offset(f, start_tell, scriptOffset, parse_script_table)
|
||||
@ -2677,7 +2683,7 @@ class MS_VOLT_Tag(CCXXTag, LangSysTag, FeatureTag):
|
||||
__range__ = (0, 99) # I don't know if zz00 is valid or not, but I am letting it be, so that it can be caught, because zzXX is not a valid tag for anything
|
||||
|
||||
def parse_feature_tag(f: BinaryIO) -> FeatureTag:
|
||||
return parse_tag_cascading(f, SimpleFeatureTag, CvXXFeatureTag, SsXXFeatureTag, MS_VOLT_Tag, umbrellaTagCls=FeatureTag)
|
||||
return read_tag_from_tags(f, SimpleFeatureTag, CvXXFeatureTag, SsXXFeatureTag, MS_VOLT_Tag, umbrellaTagCls=FeatureTag)
|
||||
|
||||
@dataclass
|
||||
class FeatureParamsTable(Table, ABD): pass
|
||||
@ -2711,7 +2717,7 @@ class SizeFeatureParamsTable(FeatureParamsTable):
|
||||
subfamily_nameID: Optional[int]
|
||||
recommended_usage_range: Optional[Tuple[int, int]]
|
||||
|
||||
def parse_feature_params_table(f: BinaryIO, featureTag: FeatureTag):
|
||||
def parse_feature_params_table(f: BinaryIO, featureTag: FeatureTag) -> FeatureParamsTable:
|
||||
match featureTag:
|
||||
case CvXXFeatureTag(num=_):
|
||||
format = read_u16(f)
|
||||
@ -2840,7 +2846,7 @@ def parse_lookup_table(f: BinaryIO, _lookupType: Callable[[int], LookupType], lo
|
||||
|
||||
start_tell = f.tell()
|
||||
|
||||
lookupType = parse_id(f, _lookupType)
|
||||
lookupType = read_id(f, _lookupType)
|
||||
lookupFlag = parse_lookup_flag(f)
|
||||
subTableCount = read_u16(f)
|
||||
subTableOffsets = [read_u16(f) for _ in range(subTableCount)]
|
||||
@ -2893,20 +2899,18 @@ def parse_condition_table(f: BinaryIO) -> ConditionTable:
|
||||
|
||||
assert False, format
|
||||
|
||||
@dataclass
|
||||
class ConditionSetTable(Table):
|
||||
conditionCount: int
|
||||
conditions: List[ConditionTable]
|
||||
ConditionSetTable = SetTable[ConditionTable]
|
||||
|
||||
def parse_condition_set_table(f: BinaryIO) -> ConditionSetTable:
|
||||
start_tell = f.tell()
|
||||
return parse_set_table(f, parse_condition_table, offset_reader=read_u32)
|
||||
# start_tell = f.tell()
|
||||
|
||||
conditionCount = read_u16(f)
|
||||
conditionOffsets = [read_u32(f) for _ in range(conditionCount)]
|
||||
with SaveTell(f):
|
||||
conditions = parse_at_offsets(f, start_tell, conditionOffsets, parse_condition_table)
|
||||
# conditionCount = read_u16(f)
|
||||
# conditionOffsets = [read_u32(f) for _ in range(conditionCount)]
|
||||
# with SaveTell(f):
|
||||
# conditions = parse_at_offsets(f, start_tell, conditionOffsets, parse_condition_table)
|
||||
|
||||
return ConditionSetTable(conditionCount, conditions)
|
||||
# return ConditionSetTable(conditionCount, conditions)
|
||||
|
||||
@dataclass
|
||||
class FeatureTableSubstitutionRecord:
|
||||
@ -2949,14 +2953,14 @@ def parse_feature_table_substitution_table(f: BinaryIO, featureList: FeatureList
|
||||
|
||||
@dataclass
|
||||
class FeatureVariationRecord:
|
||||
conditionSet: SetTable[ConditionTable]
|
||||
conditionSet: ConditionSetTable
|
||||
featureTableSubstitution: FeatureTableSubstitutionTable
|
||||
|
||||
def parse_feature_variation_record(f: BinaryIO, start_tell: int, featureList: FeatureListTable) -> FeatureVariationRecord:
|
||||
conditionSetOffset = read_u32(f)
|
||||
featureTableSubstitutionOffset = read_u32(f)
|
||||
with SaveTell(f):
|
||||
conditionSet = parse_at_offset(f, start_tell, conditionSetOffset, lambda f: parse_set_table(f, parse_condition_table, offset_reader=read_u32))
|
||||
conditionSet = parse_at_offset(f, start_tell, conditionSetOffset, parse_condition_set_table)
|
||||
featureTableSubstitution = parse_at_offset(f, start_tell, featureTableSubstitutionOffset, lambda f: parse_feature_table_substitution_table(f, featureList))
|
||||
|
||||
return FeatureVariationRecord(conditionSet, featureTableSubstitution)
|
||||
@ -2997,7 +3001,7 @@ class CoverageTable_Format_1(CoverageTable):
|
||||
glyphArray: List[int]
|
||||
|
||||
@dataclass
|
||||
class RangeRecord:
|
||||
class RangeRecord(Record):
|
||||
startGlyphID: int
|
||||
endGlyphID: int
|
||||
startCoverageIndex: int
|
||||
@ -3045,7 +3049,7 @@ class ClassRangeRecord:
|
||||
endGlyphID: int
|
||||
classValue: int
|
||||
|
||||
def parse_class_range_record(f) -> ClassRangeRecord:
|
||||
def parse_class_range_record(f: BinaryIO) -> ClassRangeRecord:
|
||||
startGlyphID = read_u16(f)
|
||||
endGlyphID = read_u16(f)
|
||||
classValue = read_u16(f)
|
||||
@ -3087,7 +3091,7 @@ class ValueFormatFlags:
|
||||
def x_advance_device(self) -> bool: return (self.bytes & 0x0040)!=0
|
||||
def y_advance_device(self) -> bool: return (self.bytes & 0x0080)!=0
|
||||
|
||||
def parse_value_format(f) -> ValueFormatFlags:
|
||||
def parse_value_format(f: BinaryIO) -> ValueFormatFlags:
|
||||
valueFormat = read_u16(f)
|
||||
assert valueFormat & 0xFF00 == 0, "Reserved"
|
||||
|
||||
@ -3142,7 +3146,7 @@ class BaseTagListTable(Table):
|
||||
|
||||
def parse_base_tag_list_table(f: BinaryIO) -> BaseTagListTable:
|
||||
baseTagCount = read_u16(f)
|
||||
baselineTags = [parse_tag(f, BaselineTag) for _ in range(baseTagCount)]
|
||||
baselineTags = [read_tag(f, BaselineTag) for _ in range(baseTagCount)]
|
||||
|
||||
return BaseTagListTable(baseTagCount, baselineTags)
|
||||
|
||||
@ -3225,7 +3229,7 @@ class BaseScriptRecord:
|
||||
baseScript: BaseScriptTable
|
||||
|
||||
def parse_base_script_record(f: BinaryIO, start_tell: int) -> BaseScriptRecord:
|
||||
baseScriptTag = parse_tag(f, ScriptTag)
|
||||
baseScriptTag = read_tag(f, ScriptTag)
|
||||
baseScriptOffset = read_u16(f)
|
||||
with SaveTell(f):
|
||||
baseScript = parse_at_offset(f, start_tell, baseScriptOffset, parse_base_script_table)
|
||||
@ -3879,11 +3883,16 @@ def parse_chain_pos_rule_table(f: BinaryIO) -> ChainPosRuleTable:
|
||||
|
||||
return ChainPosRuleTable(backtrackGlyphCount, backtrackSequence, inputGlyphCount, inputSequence, lookaheadGlyphCount, lookAheadSequence, posCount, posLookupRecords)
|
||||
|
||||
ChainPosRuleSetTable = SetTable[ChainPosRuleTable]
|
||||
|
||||
def parse_chain_pos_rule_set_table(f: BinaryIO) -> ChainPosRuleSetTable:
|
||||
return parse_set_table(f, parse_chain_pos_rule_table)
|
||||
|
||||
@dataclass
|
||||
class ChainContextPosSubtable_Format_1(ChainContextPosSubtable):
|
||||
coverage: CoverageTable
|
||||
chainPosRuleSetCount: int
|
||||
chainPosRuleSets: List[SetTable[ChainPosRuleTable]]
|
||||
chainPosRuleSets: List[ChainPosRuleSetTable]
|
||||
|
||||
@dataclass
|
||||
class ChainPosClassRuleTable(Table):
|
||||
@ -3908,6 +3917,11 @@ def parse_chain_pos_class_rule_table(f: BinaryIO) -> ChainPosClassRuleTable:
|
||||
|
||||
return ChainPosClassRuleTable(backtrackGlyphCount, backtrackSequence, inputGlyphCount, inputSequence, lookaheadGlyphCount, lookAheadSequence, posCount, posLookupRecords)
|
||||
|
||||
ChainPosClassRuleSetTable = SetTable[ChainPosClassRuleTable]
|
||||
|
||||
def parse_chain_pos_class_rule_set_table(f: BinaryIO) -> ChainPosClassRuleSetTable:
|
||||
return parse_set_table(f, parse_chain_pos_class_rule_table)
|
||||
|
||||
@dataclass
|
||||
class ChainContextPosSubtable_Format_2(ChainContextPosSubtable):
|
||||
coverage: CoverageTable
|
||||
@ -3915,7 +3929,7 @@ class ChainContextPosSubtable_Format_2(ChainContextPosSubtable):
|
||||
inputClassDef: ClassDefTable
|
||||
lookaheadClassDef: ClassDefTable
|
||||
chainPosClassSetCount: int
|
||||
chainPosClassSets: List[Optional[SetTable[ChainPosClassRuleTable]]]
|
||||
chainPosClassSets: List[Optional[ChainPosClassRuleSetTable]]
|
||||
|
||||
@dataclass
|
||||
class ChainContextPosSubtable_Format_3(ChainContextPosSubtable):
|
||||
@ -4112,7 +4126,7 @@ def parse_GPOS_lookup_subtable(f: BinaryIO, lookupType: GPOSLookupType) -> GPOSL
|
||||
chainPosRuleSetOffsets = [read_u16(f) for _ in range(chainPosRuleSetCount)]
|
||||
with SaveTell(f):
|
||||
coverage = parse_at_offset(f, start_tell, coverageOffset, parse_coverage_table)
|
||||
chainPosRuleSets = parse_at_offsets(f, start_tell, chainPosRuleSetOffsets, lambda f: parse_set_table(f, parse_chain_pos_rule_table))
|
||||
chainPosRuleSets = parse_at_offsets(f, start_tell, chainPosRuleSetOffsets, parse_chain_pos_rule_set_table)
|
||||
|
||||
return ChainContextPosSubtable_Format_1(posFormat, coverage, chainPosRuleSetCount, chainPosRuleSets)
|
||||
case 2:
|
||||
@ -4127,7 +4141,7 @@ def parse_GPOS_lookup_subtable(f: BinaryIO, lookupType: GPOSLookupType) -> GPOSL
|
||||
backtrackClassDef = parse_at_offset(f, start_tell, backtrackClassDefOffset, parse_class_def_table)
|
||||
inputClassDef = parse_at_offset(f, start_tell, inputClassDefOffset, parse_class_def_table)
|
||||
lookaheadClassDef = parse_at_offset(f, start_tell, lookaheadClassDefOffset, parse_class_def_table)
|
||||
chainPosClassSets = parse_at_optional_offsets(f, start_tell, chainPosClassSetOffsets, lambda f: parse_set_table(f, parse_chain_pos_class_rule_table))
|
||||
chainPosClassSets = parse_at_optional_offsets(f, start_tell, chainPosClassSetOffsets, parse_chain_pos_class_rule_set_table)
|
||||
|
||||
return ChainContextPosSubtable_Format_2(posFormat, coverage, backtrackClassDef, inputClassDef, lookaheadClassDef, chainPosClassSetCount, chainPosClassSets)
|
||||
case 3:
|
||||
@ -4156,7 +4170,7 @@ def parse_GPOS_lookup_subtable(f: BinaryIO, lookupType: GPOSLookupType) -> GPOSL
|
||||
|
||||
match posFormat:
|
||||
case 1:
|
||||
extensionLookupType = parse_id(f, GPOSLookupType)
|
||||
extensionLookupType = read_id(f, GPOSLookupType)
|
||||
assert extensionLookupType != GPOSLookupType.ExtensionPos, f"ExtensionPos subtable cannot reference another ExtensionPos subtable"
|
||||
extensionOffset = read_u32(f)
|
||||
with SaveTell(f):
|
||||
@ -4323,11 +4337,16 @@ def parse_ligature_table(f: BinaryIO) -> LigatureTable:
|
||||
|
||||
return LigatureTable(ligatureGlyph, componentCount, componentGlyphIDs)
|
||||
|
||||
LigatureSetTable = SetTable[LigatureTable]
|
||||
|
||||
def parse_ligature_set_table(f: BinaryIO) -> LigatureSetTable:
|
||||
return parse_set_table(f, parse_ligature_table)
|
||||
|
||||
@dataclass
|
||||
class LigatureSubstSubtable_Format_1(LigatureSubstSubtable):
|
||||
coverage: CoverageTable
|
||||
ligatureSetCount: int
|
||||
ligatureSets: List[SetTable[LigatureTable]]
|
||||
ligatureSets: List[LigatureSetTable]
|
||||
|
||||
# 5
|
||||
|
||||
@ -4350,11 +4369,16 @@ def parse_sub_rule_table(f: BinaryIO) -> SubRuleTable:
|
||||
|
||||
return SubRuleTable(glyphCount, substitutionCount, inputSequence, substLookupRecords)
|
||||
|
||||
SubRuleSetTable = SetTable[SubRuleTable]
|
||||
|
||||
def parse_sub_rule_set_table(f: BinaryIO) -> SubRuleSetTable:
|
||||
return parse_set_table(f, parse_sub_rule_table)
|
||||
|
||||
@dataclass
|
||||
class ContextSubstSubtable_Format_1(ContextSubstSubtable):
|
||||
coverage: CoverageTable
|
||||
subRuleSetCount: int
|
||||
subRuleSets: List[SetTable[SubRuleTable]]
|
||||
subRuleSets: List[SubRuleSetTable]
|
||||
|
||||
@dataclass
|
||||
class SubClassRuleTable(Table):
|
||||
@ -4371,12 +4395,17 @@ def parse_sub_class_rule_table(f: BinaryIO) -> SubClassRuleTable:
|
||||
|
||||
return SubClassRuleTable(glyphCount, substitutionCount, inputSequence, substLookupRecords)
|
||||
|
||||
SubClassRuleSetTable = SetTable[SubClassRuleTable]
|
||||
|
||||
def parse_sub_class_rule_set_table(f: BinaryIO) -> SubClassRuleSetTable:
|
||||
return parse_set_table(f, parse_sub_class_rule_table)
|
||||
|
||||
@dataclass
|
||||
class ContextSubstSubtable_Format_2(ContextSubstSubtable):
|
||||
coverage: CoverageTable
|
||||
classDef: ClassDefTable
|
||||
subClassSetCount: int
|
||||
subClassSets: List[Optional[SetTable[SubClassRuleTable]]]
|
||||
subClassSets: List[Optional[SubClassRuleSetTable]]
|
||||
|
||||
@dataclass
|
||||
class ContextSubstSubtable_Format_3(ContextSubstSubtable):
|
||||
@ -4417,11 +4446,16 @@ def parse_chain_sub_rule_table(f: BinaryIO) -> ChainSubRuleTable:
|
||||
|
||||
return ChainSubRuleTable(backtrackGlyphCount, backtrackSequence, inputGlyphCount, inputSequence, lookaheadGlyphCount, lookAheadSequence, substitutionCount, substLookupRecords)
|
||||
|
||||
ChainSubRuleSetTable = SetTable[ChainSubRuleTable]
|
||||
|
||||
def parse_chain_sub_rule_set_table(f: BinaryIO) -> ChainSubRuleSetTable:
|
||||
return parse_set_table(f, parse_chain_sub_rule_table)
|
||||
|
||||
@dataclass
|
||||
class ChainContextSubstSubtable_Format_1(ChainContextSubstSubtable):
|
||||
coverage: CoverageTable
|
||||
chainSubRuleSetCount: int
|
||||
chainSubRuleSets: List[SetTable[ChainSubRuleTable]]
|
||||
chainSubRuleSets: List[ChainSubRuleSetTable]
|
||||
|
||||
@dataclass
|
||||
class ChainSubClassRuleTable(Table):
|
||||
@ -4449,6 +4483,11 @@ def parse_chain_sub_class_rule_table(f: BinaryIO) -> ChainSubClassRuleTable:
|
||||
|
||||
return ChainSubClassRuleTable(backtrackGlyphCount, backtrackSequence, inputGlyphCount, inputSequence, lookaheadGlyphCount, lookAheadSequence, substitutionCount, substLookupRecords)
|
||||
|
||||
ChainSubClassRuleSetTable = SetTable[ChainSubClassRuleTable]
|
||||
|
||||
def parse_chain_sub_class_rule_set_table(f: BinaryIO) -> ChainSubClassRuleSetTable:
|
||||
return parse_set_table(f, parse_chain_sub_class_rule_table)
|
||||
|
||||
@dataclass
|
||||
class ChainContextSubstSubtable_Format_2(ChainContextSubstSubtable):
|
||||
coverage: CoverageTable
|
||||
@ -4456,7 +4495,7 @@ class ChainContextSubstSubtable_Format_2(ChainContextSubstSubtable):
|
||||
inputClassDef: ClassDefTable
|
||||
lookaheadClassDef: ClassDefTable
|
||||
chainSubClassSetCount: int
|
||||
chainSubClassSets: List[Optional[SetTable[ChainSubClassRuleTable]]]
|
||||
chainSubClassSets: List[Optional[ChainSubClassRuleSetTable]]
|
||||
|
||||
@dataclass
|
||||
class ChainContextSubstSubtable_Format_3(ChainContextSubstSubtable):
|
||||
@ -4597,7 +4636,7 @@ def parse_GSUB_lookup_subtable(f: BinaryIO, lookupType: GSUBLookupType) -> GSUBL
|
||||
subRuleSetOffsets = [read_u16(f) for _ in range(subRuleSetCount)]
|
||||
with SaveTell(f):
|
||||
coverage = parse_at_offset(f, start_tell, coverageOffset, parse_coverage_table)
|
||||
subRuleSets = parse_at_offsets(f, start_tell, subRuleSetOffsets, lambda f: parse_set_table(f, parse_sub_rule_table))
|
||||
subRuleSets = parse_at_offsets(f, start_tell, subRuleSetOffsets, parse_sub_rule_set_table)
|
||||
|
||||
return ContextSubstSubtable_Format_1(substFormat, coverage, subRuleSetCount, subRuleSets)
|
||||
case 2:
|
||||
@ -4608,7 +4647,7 @@ def parse_GSUB_lookup_subtable(f: BinaryIO, lookupType: GSUBLookupType) -> GSUBL
|
||||
with SaveTell(f):
|
||||
coverage = parse_at_offset(f, start_tell, coverageOffset, parse_coverage_table)
|
||||
classDef = parse_at_offset(f, start_tell, classDefOffset, parse_class_def_table)
|
||||
subClassSets = parse_at_optional_offsets(f, start_tell, subClassSetOffsets, lambda f: parse_set_table(f, parse_sub_class_rule_table))
|
||||
subClassSets = parse_at_optional_offsets(f, start_tell, subClassSetOffsets, parse_sub_class_rule_set_table)
|
||||
|
||||
return ContextSubstSubtable_Format_2(substFormat, coverage, classDef, subClassSetCount, subClassSets)
|
||||
case 3:
|
||||
@ -4636,7 +4675,7 @@ def parse_GSUB_lookup_subtable(f: BinaryIO, lookupType: GSUBLookupType) -> GSUBL
|
||||
chainSubRuleSetOffsets = [read_u16(f) for _ in range(chainSubRuleSetCount)]
|
||||
with SaveTell(f):
|
||||
coverage = parse_at_offset(f, start_tell, coverageOffset, parse_coverage_table)
|
||||
chainSubRuleSets = parse_at_offsets(f, start_tell, chainSubRuleSetOffsets, lambda f: parse_set_table(f, parse_chain_sub_rule_table))
|
||||
chainSubRuleSets = parse_at_offsets(f, start_tell, chainSubRuleSetOffsets, parse_chain_sub_rule_set_table)
|
||||
|
||||
return ChainContextSubstSubtable_Format_1(substFormat, coverage, chainSubRuleSetCount, chainSubRuleSets)
|
||||
case 2:
|
||||
@ -4651,7 +4690,7 @@ def parse_GSUB_lookup_subtable(f: BinaryIO, lookupType: GSUBLookupType) -> GSUBL
|
||||
backtrackClassDef = parse_at_offset(f, start_tell, backtrackClassDefOffset, parse_class_def_table)
|
||||
inputClassDef = parse_at_offset(f, start_tell, inputClassDefOffset, parse_class_def_table)
|
||||
lookaheadClassDef = parse_at_offset(f, start_tell, lookaheadClassDefOffset, parse_class_def_table)
|
||||
chainSubClassSets = parse_at_optional_offsets(f, start_tell, chainSubClassSetOffsets, lambda f: parse_set_table(f, parse_chain_sub_class_rule_table))
|
||||
chainSubClassSets = parse_at_optional_offsets(f, start_tell, chainSubClassSetOffsets, parse_chain_sub_class_rule_set_table)
|
||||
|
||||
return ChainContextSubstSubtable_Format_2(substFormat, coverage, backtrackClassDef, inputClassDef, lookaheadClassDef, chainSubClassSetCount, chainSubClassSets)
|
||||
case 3:
|
||||
@ -4685,7 +4724,7 @@ def parse_GSUB_lookup_subtable(f: BinaryIO, lookupType: GSUBLookupType) -> GSUBL
|
||||
|
||||
match substFormat:
|
||||
case 1:
|
||||
extensionLookupType = parse_id(f, GSUBLookupType)
|
||||
extensionLookupType = read_id(f, GSUBLookupType)
|
||||
extensionOffset = read_u32(f)
|
||||
with SaveTell(f):
|
||||
extension = parse_at_offset(f, start_tell, extensionOffset, lambda f: parse_GSUB_lookup_subtable(f, extensionLookupType))
|
||||
@ -5370,7 +5409,7 @@ def is_valid_possible_foundry_defined_axis_tag(tag: str) -> bool:
|
||||
return len(tag) == 4 and is_upper(tag[0]) and all(map(lambda s: is_upper(s) or is_digit(s), tag[1:]))
|
||||
|
||||
def parse_axis_tag(f: BinaryIO) -> AxisTag:
|
||||
return parse_tag_with_conditions(f, (is_valid_possible_registed_axis_tag, RegisteredAxisTag), (is_valid_possible_foundry_defined_axis_tag, FoundryDefinedAxisTag), umbrellaTagCls=AxisTag)
|
||||
return read_tag_with_conditions(f, (is_valid_possible_registed_axis_tag, RegisteredAxisTag), (is_valid_possible_foundry_defined_axis_tag, FoundryDefinedAxisTag), umbrellaTagCls=AxisTag)
|
||||
|
||||
@dataclass
|
||||
class AxisValueMapRecord:
|
||||
|
Loading…
Reference in New Issue
Block a user