[feaLib] Add helper for creating glyph class definition tables
The helper will be used for building class-based kerning tables.
This commit is contained in:
parent
dd23788a53
commit
26c02e4d95
@ -1121,3 +1121,43 @@ class SinglePosBuilder(LookupBuilder):
|
||||
st.Value, st.ValueFormat = value, valueFormat
|
||||
|
||||
return self.buildLookup_(subtables)
|
||||
|
||||
|
||||
class ClassDefBuilder(object):
|
||||
"""Helper for building ClassDef tables."""
|
||||
def __init__(self, otClass):
|
||||
self.classes = set()
|
||||
self.glyphs = {}
|
||||
self.otClass = otClass
|
||||
|
||||
def canAdd(self, glyphs):
|
||||
glyphs = frozenset(glyphs)
|
||||
if glyphs in self.classes:
|
||||
return True
|
||||
for glyph in glyphs:
|
||||
if glyph in self.glyphs:
|
||||
return False
|
||||
return True
|
||||
|
||||
def add(self, glyphs):
|
||||
glyphs = frozenset(glyphs)
|
||||
if glyphs in self.classes:
|
||||
return
|
||||
self.classes.add(glyphs)
|
||||
for glyph in glyphs:
|
||||
assert glyph not in self.glyphs
|
||||
self.glyphs[glyph] = glyphs
|
||||
|
||||
def build(self):
|
||||
glyphClasses = {}
|
||||
# Class id #0 does not need to be encoded because zero is the default
|
||||
# when no class is specified. Therefore, we use id #0 for the glyph
|
||||
# class that has the largest number of members.
|
||||
classes = sorted(self.classes, key=len, reverse=True)
|
||||
for classID, glyphs in enumerate(classes):
|
||||
if classID != 0:
|
||||
for glyph in glyphs:
|
||||
glyphClasses[glyph] = classID
|
||||
classDef = self.otClass()
|
||||
classDef.classDefs = glyphClasses
|
||||
return classDef
|
||||
|
@ -1,9 +1,10 @@
|
||||
from __future__ import print_function, division, absolute_import
|
||||
from __future__ import unicode_literals
|
||||
from fontTools.feaLib.builder import Builder, addOpenTypeFeatures
|
||||
from fontTools.feaLib.builder import LigatureSubstBuilder
|
||||
from fontTools.feaLib.builder import ClassDefBuilder, LigatureSubstBuilder
|
||||
from fontTools.feaLib.error import FeatureLibError
|
||||
from fontTools.ttLib import TTFont
|
||||
from fontTools.ttLib.tables import otTables
|
||||
import codecs
|
||||
import difflib
|
||||
import os
|
||||
@ -311,10 +312,39 @@ class BuilderTest(unittest.TestCase):
|
||||
"} foo;")
|
||||
|
||||
|
||||
class ClassDefBuilderTest(unittest.TestCase):
|
||||
def test_build(self):
|
||||
builder = ClassDefBuilder(otTables.ClassDef2)
|
||||
builder.add({"a", "b"})
|
||||
builder.add({"c"})
|
||||
builder.add({"e", "f", "g", "h"})
|
||||
cdef = builder.build()
|
||||
self.assertIsInstance(cdef, otTables.ClassDef2)
|
||||
# The largest class {"e", "f", "g", "h"} should become class ID #0.
|
||||
# Zero is the default class ID, so it does not get encoded at all.
|
||||
self.assertEqual(cdef.classDefs, {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"c": 2
|
||||
})
|
||||
|
||||
def test_canAdd(self):
|
||||
b = ClassDefBuilder(otTables.ClassDef1)
|
||||
b.add({"a", "b", "c", "d"})
|
||||
b.add({"e", "f"})
|
||||
self.assertTrue(b.canAdd({"a", "b", "c", "d"}))
|
||||
self.assertTrue(b.canAdd({"e", "f"}))
|
||||
self.assertTrue(b.canAdd({"g", "h", "i"}))
|
||||
self.assertFalse(b.canAdd({"b", "c", "d"}))
|
||||
self.assertFalse(b.canAdd({"a", "b", "c", "d", "e", "f"}))
|
||||
self.assertFalse(b.canAdd({"d", "e", "f"}))
|
||||
self.assertFalse(b.canAdd({"f"}))
|
||||
|
||||
|
||||
class LigatureSubstBuilderTest(unittest.TestCase):
|
||||
def test_make_key(self):
|
||||
self.assertEqual(LigatureSubstBuilder.make_key(('f', 'f', 'i')),
|
||||
(-3, ('f', 'f', 'i')))
|
||||
self.assertEqual(LigatureSubstBuilder.make_key(("f", "f", "i")),
|
||||
(-3, ("f", "f", "i")))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
x
Reference in New Issue
Block a user