Skip to content

Commit

Permalink
Merge pull request #679 from googlefonts/kern-splitter-v3
Browse files Browse the repository at this point in the history
Split kerning by script, not by direction (third attempt)
  • Loading branch information
madig authored Dec 6, 2022
2 parents 1c33aac + 8da23fd commit e0b810b
Show file tree
Hide file tree
Showing 23 changed files with 1,494 additions and 707 deletions.
2 changes: 2 additions & 0 deletions Lib/ufo2ft/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

UNICODE_VARIATION_SEQUENCES_KEY = "public.unicodeVariationSequences"

COMMON_SCRIPT = "Zyyy"

INDIC_SCRIPTS = [
"Beng", # Bengali
"Cham", # Cham
Expand Down
23 changes: 15 additions & 8 deletions Lib/ufo2ft/featureCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,14 @@ def setupFeatures(self):
if self.featureWriters:
featureFile = parseLayoutFeatures(self.ufo, self.feaIncludeDir)

path = self.ufo.path
for writer in self.featureWriters:
writer.write(self.ufo, featureFile, compiler=self)
try:
writer.write(self.ufo, featureFile, compiler=self)
except FeatureLibError:
if path is None:
self._write_temporary_feature_file(featureFile.asFea())
raise

# stringify AST to get correct line numbers in error messages
self.features = featureFile.asFea()
Expand Down Expand Up @@ -316,15 +322,16 @@ def buildTables(self):
addOpenTypeFeaturesFromString(self.ttFont, self.features, filename=path)
except FeatureLibError:
if path is None:
# if compilation fails, create temporary file for inspection
data = self.features.encode("utf-8")
with NamedTemporaryFile(delete=False) as tmp:
tmp.write(data)
logger.error(
"Compilation failed! Inspect temporary file: %r", tmp.name
)
self._write_temporary_feature_file(self.features)
raise

def _write_temporary_feature_file(self, features: str) -> None:
# if compilation fails, create temporary file for inspection
data = features.encode("utf-8")
with NamedTemporaryFile(delete=False) as tmp:
tmp.write(data)
logger.error("Compilation failed! Inspect temporary file: %r", tmp.name)


class MtiFeatureCompiler(BaseFeatureCompiler):
"""Compile OpenType layout tables from MTI feature files using
Expand Down
41 changes: 39 additions & 2 deletions Lib/ufo2ft/featureWriters/baseFeatureWriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from collections import OrderedDict, namedtuple
from types import SimpleNamespace

from fontTools import unicodedata

from ufo2ft.constants import OPENTYPE_CATEGORIES_KEY
from ufo2ft.errors import InvalidFeaturesData
from ufo2ft.featureWriters import ast
Expand Down Expand Up @@ -122,8 +124,12 @@ def shouldContinue(self):
def write(self, font, feaFile, compiler=None):
"""Write features and class definitions for this font to a feaLib
FeatureFile object.
Returns True if feature file was modified, False if no new features
were generated.
The main entry point for the FeatureCompiler to any of the
FeatureWriters.
Returns True if feature file was modified, False if no new features were
generated.
"""
self.setContext(font, feaFile, compiler=compiler)
try:
Expand Down Expand Up @@ -386,3 +392,34 @@ def getGDEFGlyphClasses(self):
frozenset(marks),
frozenset(components),
)

def guessFontScripts(self):
"""Returns a set of scripts the font probably supports.
This is done by:
1. Looking at all defined codepoints in a font and remembering the
script of any of the codepoints if it is associated with just one
script. This would remember the script of U+0780 THAANA LETTER HAA
(Thaa) but not U+061F ARABIC QUESTION MARK (multiple scripts).
2. Adding explicitly declared `languagesystem` scripts on top.
"""
font = self.context.font
glyphSet = self.context.glyphSet
feaFile = self.context.feaFile
single_scripts = set()

# First, detect scripts from the codepoints.
for glyph in font:
if glyph.name not in glyphSet or glyph.unicodes is None:
continue
for codepoint in glyph.unicodes:
scripts = unicodedata.script_extension(chr(codepoint))
if len(scripts) == 1:
single_scripts.update(scripts)

# Then, add explicitly declared languagesystems on top.
feaScripts = ast.getScriptLanguageSystems(feaFile)
single_scripts.update(feaScripts.keys())

return single_scripts
Loading

0 comments on commit e0b810b

Please sign in to comment.