font-patcher: Enable lowestRecPPEM fix in TTCs

[why]
The font flags and PPEM fix does not work with font collection files,
because it does not know how to handle them. It assumes a ttf or otf
font with the specified table structure.

The fix (for single font files) has been introduced with commit
  40138bee9  font-patcher: Handle lowestRecPPEM

[how]
Check if the file is of type 'ttcf', and if so fast forward to the given
single font index into the collection.

This can be rather slow...

Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
This commit is contained in:
Fini Jastrow 2022-09-23 09:26:11 +02:00
parent e8a17c71bf
commit 7c5c838122

View file

@ -88,9 +88,26 @@ class TableHEADWriter:
checksum = (checksum + extra) & 0xFFFFFFFF checksum = (checksum + extra) & 0xFFFFFFFF
return checksum return checksum
def find_head_table(self): def find_head_table(self, idx):
""" Search all tables for the HEAD table and store its metadata """ """ Search all tables for the HEAD table and store its metadata """
self.f.seek(4) # Use font with index idx if this is a font collection file
self.f.seek(0, 0)
tag = self.f.read(4)
if tag == b'ttcf':
self.f.seek(2*2, 1)
self.num_fonts = self.getlong()
if (idx >= self.num_fonts):
raise Exception('Trying to access subfont index {} but have only {} fonts'.format(idx, num_fonts))
for _ in range(idx + 1):
offset = self.getlong()
self.f.seek(offset, 0)
elif idx != 0:
raise Exception('Trying to access subfont but file is no collection')
else:
self.f.seek(0, 0)
self.num_fonts = 1
self.f.seek(4, 1)
numtables = self.getshort() numtables = self.getshort()
self.f.seek(3*2, 1) self.f.seek(3*2, 1)
@ -102,7 +119,7 @@ class TableHEADWriter:
self.tab_length = self.getlong() self.tab_length = self.getlong()
if tab_name == b'head': if tab_name == b'head':
return return
raise Exception('No HEAD table found') raise Exception('No HEAD table found in font idx {}'.format(idx))
def goto(self, where): def goto(self, where):
""" Go to a named location in the file or to the specified index """ """ Go to a named location in the file or to the specified index """
@ -146,7 +163,7 @@ class TableHEADWriter:
self.modified = False self.modified = False
self.f = open(filename, 'r+b') self.f = open(filename, 'r+b')
self.find_head_table() self.find_head_table(0)
self.flags = self.getshort('flags') self.flags = self.getshort('flags')
self.lowppem = self.getshort('lowestRecPPEM') self.lowppem = self.getshort('lowestRecPPEM')
@ -266,15 +283,19 @@ class font_patcher:
try: try:
source_font = TableHEADWriter(self.args.font) source_font = TableHEADWriter(self.args.font)
dest_font = TableHEADWriter(outfile) dest_font = TableHEADWriter(outfile)
if source_font.flags & 0x08 == 0 and dest_font.flags & 0x08 != 0: for idx in range(source_font.num_fonts):
print("Changing flags from 0x{:X} to 0x{:X}".format(dest_font.flags, dest_font.flags & ~0x08)) print("{}: Tweaking {}/{}".format(projectName, idx + 1, source_font.num_fonts))
dest_font.putshort(dest_font.flags & ~0x08, 'flags') # clear 'ppem_to_int' source_font.find_head_table(idx)
if source_font.lowppem != dest_font.lowppem: dest_font.find_head_table(idx)
print("Changing lowestRecPPEM from {} to {}".format(dest_font.lowppem, source_font.lowppem)) if source_font.flags & 0x08 == 0 and dest_font.flags & 0x08 != 0:
dest_font.putshort(source_font.lowppem, 'lowestRecPPEM') print("Changing flags from 0x{:X} to 0x{:X}".format(dest_font.flags, dest_font.flags & ~0x08))
if dest_font.modified: dest_font.putshort(dest_font.flags & ~0x08, 'flags') # clear 'ppem_to_int'
dest_font.reset_table_checksum() if source_font.lowppem != dest_font.lowppem:
dest_font.reset_full_checksum() print("Changing lowestRecPPEM from {} to {}".format(dest_font.lowppem, source_font.lowppem))
dest_font.putshort(source_font.lowppem, 'lowestRecPPEM')
if dest_font.modified:
dest_font.reset_table_checksum()
dest_font.reset_full_checksum()
except Exception as error: except Exception as error:
print("Can not handle font flags ({})".format(repr(error))) print("Can not handle font flags ({})".format(repr(error)))
finally: finally:
@ -1292,8 +1313,9 @@ def main():
patcher = font_patcher(args) patcher = font_patcher(args)
sourceFonts = [] sourceFonts = []
for subfont in fontforge.fontsInFile(args.font): all_fonts = fontforge.fontsInFile(args.font)
print("\n{}: Processing {}".format(projectName, subfont)) for i, subfont in enumerate(all_fonts):
print("\n{}: Processing {} ({}/{})".format(projectName, subfont, i + 1, len(all_fonts)))
try: try:
sourceFonts.append(fontforge.open("{}({})".format(args.font, subfont), 1)) # 1 = ("fstypepermitted",)) sourceFonts.append(fontforge.open("{}({})".format(args.font, subfont), 1)) # 1 = ("fstypepermitted",))
except Exception: except Exception: