From 0faf01d5f1d48e5d08bc8ae815884746bbd2ead9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 19 Mar 2021 13:59:27 -0600 Subject: [PATCH] [otlLib] Generate Value1 / Value2 if respective formats are non-zero Previously otlLib was generating None if the values themselves were empty even if the value format was non-empty. This happened to work for compiling to binary since the compiler handles Value=None. But this was confusing varLib.merger module (as in when building variable fonts from such otlLib-built master GSUB/GPOS tables, without roundtripping to OTF/TTF binary first), because in varLib.merger, a None means "this master doesn't provide that info; skip it"; whereas in a PairPos table a None as generated by otlLib simply meant "all values are zero", which is different from "this master doesn't provide this value". This fixes that, such that ufo2ft can build variable-font without saving masters to binary. Part of https://github.com/googlefonts/ufo2ft/pull/486 --- Lib/fontTools/otlLib/builder.py | 14 ++++++++------ Lib/fontTools/ttLib/ttFont.py | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Lib/fontTools/otlLib/builder.py b/Lib/fontTools/otlLib/builder.py index ca9e936d6..bd053b727 100644 --- a/Lib/fontTools/otlLib/builder.py +++ b/Lib/fontTools/otlLib/builder.py @@ -2075,8 +2075,8 @@ def buildPairPosClassesSubtable(pairs, glyphMap, valueFormat1=None, valueFormat2 classDef2.add(gc2) self = ot.PairPos() self.Format = 2 - self.ValueFormat1 = _getValueFormat(valueFormat1, pairs.values(), 0) - self.ValueFormat2 = _getValueFormat(valueFormat2, pairs.values(), 1) + valueFormat1 = self.ValueFormat1 = _getValueFormat(valueFormat1, pairs.values(), 0) + valueFormat2 = self.ValueFormat2 = _getValueFormat(valueFormat2, pairs.values(), 1) self.Coverage = buildCoverage(coverage, glyphMap) self.ClassDef1 = classDef1.build() self.ClassDef2 = classDef2.build() @@ -2090,6 +2090,8 @@ def buildPairPosClassesSubtable(pairs, glyphMap, valueFormat1=None, valueFormat2 for c2 in classes2: rec2 = ot.Class2Record() rec2.Value1, rec2.Value2 = pairs.get((c1, c2), (None, None)) + if valueFormat1 and rec2.Value1 is None: rec2.Value1 = ValueRecord(valueFormat1) + if valueFormat2 and rec2.Value2 is None: rec2.Value2 = ValueRecord(valueFormat2) rec1.Class2Record.append(rec2) self.Class1Count = len(self.Class1Record) self.Class2Count = len(classes2) @@ -2174,8 +2176,8 @@ def buildPairPosGlyphsSubtable(pairs, glyphMap, valueFormat1=None, valueFormat2= """ self = ot.PairPos() self.Format = 1 - self.ValueFormat1 = _getValueFormat(valueFormat1, pairs.values(), 0) - self.ValueFormat2 = _getValueFormat(valueFormat2, pairs.values(), 1) + valueFormat1 = self.ValueFormat1 = _getValueFormat(valueFormat1, pairs.values(), 0) + valueFormat2 = self.ValueFormat2 = _getValueFormat(valueFormat2, pairs.values(), 1) p = {} for (glyphA, glyphB), (valA, valB) in pairs.items(): p.setdefault(glyphA, []).append((glyphB, valA, valB)) @@ -2188,8 +2190,8 @@ def buildPairPosGlyphsSubtable(pairs, glyphMap, valueFormat1=None, valueFormat2= for glyph2, val1, val2 in sorted(p[glyph], key=lambda x: glyphMap[x[0]]): pvr = ot.PairValueRecord() pvr.SecondGlyph = glyph2 - pvr.Value1 = val1 if val1 and val1.getFormat() != 0 else None - pvr.Value2 = val2 if val2 and val2.getFormat() != 0 else None + pvr.Value1 = val1 if valueFormat1 else None + pvr.Value2 = val2 if valueFormat2 else None ps.PairValueRecord.append(pvr) ps.PairValueCount = len(ps.PairValueRecord) self.PairSetCount = len(self.PairSet) diff --git a/Lib/fontTools/ttLib/ttFont.py b/Lib/fontTools/ttLib/ttFont.py index 811cf003a..c230e26d2 100644 --- a/Lib/fontTools/ttLib/ttFont.py +++ b/Lib/fontTools/ttLib/ttFont.py @@ -636,7 +636,7 @@ class TTFont(object): log.debug("reusing '%s' table", tag) writer.setEntry(tag, entry) return - log.debug("writing '%s' table to disk", tag) + log.debug("Writing '%s' table to disk", tag) writer[tag] = tabledata if tableCache is not None: tableCache[(Tag(tag), tabledata)] = writer[tag] @@ -646,7 +646,7 @@ class TTFont(object): """ tag = Tag(tag) if self.isLoaded(tag): - log.debug("compiling '%s' table", tag) + log.debug("Compiling '%s' table", tag) return self.tables[tag].compile(self) elif self.reader and tag in self.reader: log.debug("Reading '%s' table from disk", tag)