Add /OpenFontFormat
This commit is contained in:
		
							parent
							
								
									38987a04c6
								
							
						
					
					
						commit
						9b509e6306
					
				
							
								
								
									
										2
									
								
								OpenFontFormat/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								OpenFontFormat/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
examples
 | 
			
		||||
mypy.ini
 | 
			
		||||
							
								
								
									
										5960
									
								
								OpenFontFormat/OpenFont.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5960
									
								
								OpenFontFormat/OpenFont.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										21
									
								
								OpenFontFormat/abcde.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								OpenFontFormat/abcde.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
class ABD:
 | 
			
		||||
	"""
 | 
			
		||||
	#### Abstract Base Dataclass
 | 
			
		||||
 | 
			
		||||
	This will only work on dataclasses
 | 
			
		||||
	"""
 | 
			
		||||
	def __post_init__(self, *args, **kwargs):
 | 
			
		||||
		if ABD in self.__class__.__bases__ or ABD == self.__class__:
 | 
			
		||||
			msg = f"Cannot instantiate an Abstract Base Dataclass: {self.__class__.__name__}"
 | 
			
		||||
			raise TypeError(msg)
 | 
			
		||||
 | 
			
		||||
class ABE:
 | 
			
		||||
	"""
 | 
			
		||||
	#### Abstract Base Enum
 | 
			
		||||
	
 | 
			
		||||
	This is for classes that will have an Enum subclass them
 | 
			
		||||
	"""
 | 
			
		||||
	def __init__(self, *args, **kwargs):
 | 
			
		||||
		if ABE in self.__class__.__bases__ or ABE == self:
 | 
			
		||||
			msg = f"Cannot instantiate an Abstract Base Enum: {self.__class__.__name__}"
 | 
			
		||||
			raise TypeError(msg)
 | 
			
		||||
							
								
								
									
										49
									
								
								OpenFontFormat/name.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								OpenFontFormat/name.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from OpenFont import FontSpecificNameID, NameID, NameTable_Format_0, OpenFont, PredefinedNameID, TrueTypeOutlines, parse_file
 | 
			
		||||
 | 
			
		||||
def search_names(font: OpenFont, nameID: NameID) -> str:
 | 
			
		||||
	assert isinstance(font.naming_table, NameTable_Format_0)
 | 
			
		||||
 | 
			
		||||
	for nameRecord in font.naming_table.nameRecord:
 | 
			
		||||
		if nameRecord.nameID == nameID:
 | 
			
		||||
			return nameRecord.string
 | 
			
		||||
	
 | 
			
		||||
	assert False, f"Name not found: {nameID}"
 | 
			
		||||
 | 
			
		||||
def print_font(font: OpenFont):
 | 
			
		||||
	assert isinstance(font.naming_table, NameTable_Format_0)
 | 
			
		||||
	assert isinstance(font.outlines, TrueTypeOutlines)
 | 
			
		||||
 | 
			
		||||
	name = search_names(font, PredefinedNameID.FULL_NAME)
 | 
			
		||||
 | 
			
		||||
	print(name, f"({font.maximum_profile.numGlyphs} glyphs, {font.naming_table.count} names)")
 | 
			
		||||
	if font.font_variations:
 | 
			
		||||
		axis_names = [search_names(font, FontSpecificNameID(axis.axisNameID)) for axis in font.font_variations.font_variations.axes]
 | 
			
		||||
		num_instances = font.font_variations.font_variations.instanceCount
 | 
			
		||||
		print(f"\tAxes: [{', '.join(axis_names)}] ({num_instances} instances)")
 | 
			
		||||
 | 
			
		||||
path = "examples/"
 | 
			
		||||
# path = "examples/android_fonts/api_level/30"
 | 
			
		||||
# path = "examples/android_fonts/api_level/30/NotoNaskhArabic-Bold.ttf"
 | 
			
		||||
path = "examples/JetBrainsMono-2.304/"
 | 
			
		||||
if os.path.isfile(path):
 | 
			
		||||
	try:
 | 
			
		||||
		font = parse_file(path)
 | 
			
		||||
	except AssertionError as err:
 | 
			
		||||
		print("Failed:", path)
 | 
			
		||||
		raise err
 | 
			
		||||
	print_font(font)
 | 
			
		||||
else:
 | 
			
		||||
	for root, dirs, files in os.walk(path):
 | 
			
		||||
		for file in files:
 | 
			
		||||
			_, ext = os.path.splitext(file)
 | 
			
		||||
			match ext:
 | 
			
		||||
				case '.ttf':
 | 
			
		||||
					file_path = os.path.join(root, file)
 | 
			
		||||
					try:
 | 
			
		||||
						font = parse_file(file_path)
 | 
			
		||||
					except AssertionError as err:
 | 
			
		||||
						print("Failed:", file_path)
 | 
			
		||||
						raise err
 | 
			
		||||
					print_font(font)
 | 
			
		||||
							
								
								
									
										26
									
								
								OpenFontFormat/read_utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								OpenFontFormat/read_utils.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
from typing import BinaryIO
 | 
			
		||||
 | 
			
		||||
def read_int(f: BinaryIO, number: int, signed:bool=False) -> int: return int.from_bytes(f.read(number), 'big', signed=signed)
 | 
			
		||||
 | 
			
		||||
def read_u64(f: BinaryIO) -> int: return read_int(f, 8)
 | 
			
		||||
def read_u32(f: BinaryIO) -> int: return read_int(f, 4)
 | 
			
		||||
def read_u24(f: BinaryIO) -> int: return read_int(f, 3)
 | 
			
		||||
def read_u16(f: BinaryIO) -> int: return read_int(f, 2)
 | 
			
		||||
def read_u8(f: BinaryIO) -> int: return read_int(f, 1)
 | 
			
		||||
 | 
			
		||||
def read_i32(f: BinaryIO) -> int: return read_int(f, 4, signed=True)
 | 
			
		||||
def read_i16(f: BinaryIO) -> int: return read_int(f, 2, signed=True)
 | 
			
		||||
def read_i8(f: BinaryIO) -> int: return read_int(f, 1, signed=True)
 | 
			
		||||
 | 
			
		||||
def read_utf8(f: BinaryIO, number: int) -> str: return f.read(number).decode(encoding='utf8')
 | 
			
		||||
def read_ascii(f: BinaryIO, number: int) -> str: return f.read(number).decode(encoding='ascii')
 | 
			
		||||
 | 
			
		||||
def read_fixed_point(f: BinaryIO, preradix_bits: int, postradix_bits:int, *, signed:bool=True) -> float:
 | 
			
		||||
	assert (preradix_bits+postradix_bits)%8 == 0
 | 
			
		||||
	raw = read_int(f, (preradix_bits+postradix_bits)//8, signed=signed)
 | 
			
		||||
	return raw/(1<<(postradix_bits))
 | 
			
		||||
 | 
			
		||||
def read_pascal_string(f: BinaryIO) -> str:
 | 
			
		||||
	string_size = read_int(f, 1)
 | 
			
		||||
	pascal_string = read_ascii(f, string_size)
 | 
			
		||||
	return pascal_string
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user