[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