blob: bfcd2a818002de3f91284a7819f4d1e0d841dee6 [file] [edit]
"""Generate precision fixtures with FontTools supporting LookupVariationRecord."""
from pathlib import Path
from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
from fontTools.fontBuilder import FontBuilder
from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.ttLib import newTable
from fontTools.ttLib.tables import otTables as ot
from fontTools.varLib import builder, featureVars
def value(default, index=ot.NO_VARIATION_INDEX):
condition = ot.ConditionTable()
condition.Format, condition.DefaultValue, condition.VarIdx = 2, default, index
return condition
def compound(format, children):
condition = ot.ConditionTable()
condition.Format, condition.ConditionTable = format, children
if format != 5:
condition.ConditionCount = len(children)
return condition
for tag, default, peak in (
("GSUB", 0, 1),
("GPOS", 0, 1),
("GSUB", 32767, 1),
("GPOS", 32767, 1),
("GSUB", 0, 0.75),
("GPOS", 0, 0.75),
("GSUB", 32767, 0.75),
("GPOS", 32767, 0.75),
):
for legacy in (True, False):
fb = FontBuilder(1000)
order = [".notdef"] + [
name for char in "ABCDEF" for name in (char, char + ".alt")
]
fb.setupGlyphOrder(order)
fb.setupCharacterMap({ord(char): char for char in "ABCDEF"})
fb.setupGlyf({name: TTGlyphPen(None).glyph() for name in order})
fb.setupHorizontalMetrics({name: (600, 0) for name in order})
fb.setupHorizontalHeader(ascent=800, descent=-200)
fb.setupOS2()
fb.setupNameTable(
{"familyName": "Layout condition precision", "styleName": "Regular"}
)
fb.setupPost()
fb.setupFvar([(axis, -1, 0, 1, axis) for axis in ("TEST", "DUMY")], [])
font = fb.font
addOpenTypeFeaturesFromString(
font,
"""
languagesystem DFLT dflt;
lookup DefaultSub { sub A by A.alt; } DefaultSub;
lookup ConditionalSub { sub B by B.alt; } ConditionalSub;
feature liga { lookup DefaultSub; } liga;
feature zzzz { lookup ConditionalSub; } zzzz;
lookup DefaultPos { pos [A A.alt] 10; } DefaultPos;
lookup ConditionalPos { pos B 20; } ConditionalPos;
feature kern { lookup DefaultPos; } kern;
feature zzzz { lookup ConditionalPos; } zzzz;
""",
)
gdef = font["GDEF"] = newTable("GDEF")
gdef.table = ot.GDEF()
gdef.table.Version = 0x10003
for field in (
"GlyphClassDef",
"AttachList",
"LigCaretList",
"MarkAttachClassDef",
"MarkGlyphSetsDef",
):
setattr(gdef.table, field, None)
gdef.table.VarStore = builder.buildVarStore(
builder.buildVarRegionList(
[
{"TEST": (0, peak, 1)},
{"DUMY": (0, 1, 1)},
{"TEST": (0, peak, 1), "DUMY": (0, 1, 1)},
],
["TEST", "DUMY"],
),
[
builder.buildVarData(
[0, 1, 2],
[
[1, (-32767 if peak != 1 else -32768) if default else -1, 0],
[1, 0, -1],
],
)
],
)
position = font["GPOS"].table.LookupList.Lookup[0].SubTable[0]
position.Value.XPlaDevice = builder.buildVarDevTable(0)
position.ValueFormat |= 0x10
condition = compound(
3,
[
compound(4, [value(default, 0), value(0)]),
compound(5, compound(5, value(0, 1))),
],
)
if default and peak != 1:
# At DUMY=1 the large default cancels, leaving TEST's fraction.
condition = compound(4, [value(default, 0), value(0)])
table = font[tag].table
feature = next(
i
for i, rec in enumerate(table.FeatureList.FeatureRecord)
if rec.FeatureTag == ("liga" if tag == "GSUB" else "kern")
)
variations = table.FeatureVariations = ot.FeatureVariations()
table.Version = 0x10001
variations.Version = 0x10000 if legacy else 0x10001
variations.FeatureVariationRecord = []
variations.FeatureVariationCount = 0
if legacy:
variations.FeatureVariationRecord = [
featureVars.buildFeatureVariationRecord(
[condition],
[featureVars.buildFeatureTableSubstitutionRecord(feature, [1])],
)
]
variations.FeatureVariationCount = 1
else:
record = ot.LookupVariationRecord()
record.FeatureIndex = feature
lookups = record.FeatureLookupsTable = ot.FeatureLookupsTable()
lookups.Version, lookups.Flags = 0x10000, 1
conditional = ot.LookupConditionRecord()
conditional.ConditionTable = condition
conditional.LookupIndexList = ot.LookupIndexList()
conditional.LookupIndexList.LookupIndex = [1]
conditional.LookupIndexList.LookupIndexCount = 1
lookups.LookupConditionRecord = [conditional]
lookups.LookupConditionCount = 1
variations.LookupVariationRecord = [record]
variations.LookupVariationCount = 1
font["head"].created = font["head"].modified = 3800000000
font.recalcTimestamp = False
suffix = ("-large" if default else "") + ("-third" if peak != 1 else "")
font.save(
Path(__file__).parent
/ f"feature-variation-precision-{tag}-{'legacy' if legacy else 'lookup'}{suffix}.ttf"
)
if not default and peak == 1:
# Even an identity avar2 defers GDEF until avar has been subsetted.
avar = font["avar"] = newTable("avar")
avar.majorVersion = 2
avar.segments = {axis: {-1: -1, 0: 0, 1: 1} for axis in ("TEST", "DUMY")}
avar.table = ot.avar()
avar.table.VarIdxMap = None
avar.table.VarStore = None
font.save(
Path(__file__).parent
/ f"feature-variation-precision-{tag}-{'legacy' if legacy else 'lookup'}-avar2.ttf"
)