font-patcher: Cover alternate unicode encodings

[why]
Issue #400 recently reoccurred with the latest build of Input font, and
it turns out the dotless-j part of the small `j` now points to U+0237,
which in turn has an alternate unicode encoding to U+F6BE; overwriting
U+F6BE effectively overwrites U+0237, and in turn, alters the small `j`.
This patch aims to fix that.

[how]
In addition to references, the patcher also checks for alternate unicode
encodings which are returned by the glyph.altuni attribute, adds those
to the essential set of glyphs, and in turn recursively searches for
their references/alternate unicode encodings, making sure to handle
circular references (for example: U+2010 and U+2011 in Input Mono)
This commit is contained in:
Nathaniel Evan 2023-01-20 05:13:37 +07:00 committed by Fini Jastrow
parent ca877581f6
commit cd6ae0ca92

View file

@ -912,6 +912,23 @@ class font_patcher:
self.sourceFont.os2_typoascent += 1
self.sourceFont.os2_winascent += 1
def add_glyphrefs_to_essential(self, unicode):
self.essential.add(unicode)
# According to fontforge spec, altuni is either None or a tuple of tuples
if self.sourceFont[unicode].altuni is not None:
for r in self.sourceFont[unicode].altuni:
# If alternate unicode already exists in self.essential,
# that means it has gone through this function before.
# Therefore we skip it to avoid infinite loop.
# A unicode value of -1 basically means unused and is also worth skipping.
if r[0] in self.essential or r[0] == -1:
continue
self.add_glyphrefs_to_essential(r[0])
for r in self.sourceFont[unicode].references:
if self.sourceFont[r[0]].unicode in self.essential or self.sourceFont[r[0]].unicode == -1:
continue
self.add_glyphrefs_to_essential(self.sourceFont[r[0]].unicode)
def get_essential_references(self):
"""Find glyphs that are needed for the basic glyphs"""
# Sometimes basic glyphs are constructed from multiple other glyphs.
@ -921,8 +938,7 @@ class font_patcher:
for glyph in range(0x21, 0x17f):
if not glyph in self.sourceFont:
continue
for r in self.sourceFont[glyph].references:
self.essential.add(self.sourceFont[r[0]].unicode)
self.add_glyphrefs_to_essential(glyph)
def get_sourcefont_dimensions(self):
""" This gets the font dimensions (cell width and height), and makes them equal on all platforms """