From 07b186a41edf8e8f5a83b768c3cb22443a0ec24a Mon Sep 17 00:00:00 2001 From: Simon Cozens Date: Mon, 16 Nov 2020 13:42:07 +0000 Subject: [PATCH] Build most compact lookup representation This builds all possible representations of a contextual lookup and then selects the most copact --- Lib/fontTools/otlLib/builder.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Lib/fontTools/otlLib/builder.py b/Lib/fontTools/otlLib/builder.py index 785c9e74c..3fa67f71d 100644 --- a/Lib/fontTools/otlLib/builder.py +++ b/Lib/fontTools/otlLib/builder.py @@ -359,8 +359,31 @@ class ChainContextualBuilder(LookupBuilder): rulesets = self.rulesets() chaining = any(ruleset.hasPrefixOrSuffix for ruleset in rulesets) for ruleset in rulesets: + # Determine format strategy. We try to build formats 1, 2 and 3 + # subtables and then work out which is best. candidates list holds + # the subtables in each format for this ruleset (including a dummy + # "format 0" to make the addressing match the format numbers). + + # We can always build a format 3 lookup by accumulating each of + # the rules into a list, so start with that. + candidates = [None, None, None, []] for rule in ruleset.rules: - subtables.append(self.buildFormat3Subtable(rule, chaining)) + candidates[3].append(self.buildFormat3Subtable(rule, chaining)) + + # Can we express the whole ruleset as a format 2 subtable? + classdefs = ruleset.format2ClassDefs() + if classdefs: + candidates[2] = [ + self.buildFormat2Subtable(ruleset, classdefs, chaining) + ] + + if not ruleset.hasAnyGlyphClasses: + candidates[1] = [self.buildFormat1Subtable(ruleset, chaining)] + + candidates = [x for x in candidates if x is not None] + winner = min(candidates, key=self.getCompiledSize_) + subtables.extend(winner) + # If we are not chaining, lookup type will be automatically fixed by # buildLookup_ return self.buildLookup_(subtables)