colorLib: add option to disable PaintColrLayers' reuse of layers from LayerList

When building COLR masters, layer reuse may lead to different number of layers between masters, becasue some master may reuse specific layers while others may not. Add a flag to disable this optimization; will need to be run again after the VF COLR font has been merged
This commit is contained in:
Cosimo Lupo 2022-06-14 16:04:25 +01:00
parent 0d7d7d4e11
commit fc982c643b
2 changed files with 43 additions and 30 deletions

View File

@ -186,10 +186,12 @@ def populateCOLRv0(
def buildCOLR(
colorGlyphs: _ColorGlyphsDict,
version: Optional[int] = None,
*,
glyphMap: Optional[Mapping[str, int]] = None,
varStore: Optional[ot.VarStore] = None,
varIndexMap: Optional[ot.DeltaSetIndexMap] = None,
clipBoxes: Optional[Dict[str, _ClipBoxInput]] = None,
allowLayerReuse: bool = True,
) -> C_O_L_R_.table_C_O_L_R_:
"""Build COLR table from color layers mapping.
@ -231,7 +233,11 @@ def buildCOLR(
populateCOLRv0(colr, colorGlyphsV0, glyphMap)
colr.LayerList, colr.BaseGlyphList = buildColrV1(colorGlyphsV1, glyphMap)
colr.LayerList, colr.BaseGlyphList = buildColrV1(
colorGlyphsV1,
glyphMap,
allowLayerReuse=allowLayerReuse,
)
if version is None:
version = 1 if (varStore or colorGlyphsV1) else 0
@ -448,12 +454,14 @@ class LayerListBuilder:
reusePool: Mapping[Tuple[Any, ...], int]
tuples: Mapping[int, Tuple[Any, ...]]
keepAlive: List[ot.Paint] # we need id to remain valid
allowLayerReuse: bool
def __init__(self):
def __init__(self, *, allowLayerReuse=True):
self.layers = []
self.reusePool = {}
self.tuples = {}
self.keepAlive = []
self.allowLayerReuse = allowLayerReuse
# We need to intercept construction of PaintColrLayers
callbacks = _buildPaintCallbacks()
@ -504,6 +512,7 @@ class LayerListBuilder:
# Convert maps seqs or whatever into typed objects
layers = [self.buildPaint(l) for l in layers]
if self.allowLayerReuse:
# No reason to have a colr layers with just one entry
if len(layers) == 1:
return layers[0], {}
@ -552,7 +561,7 @@ class LayerListBuilder:
layers = [listToColrLayers(l) for l in layers]
# No reason to have a colr layers with just one entry
if len(layers) == 1:
if self.allowLayerReuse and len(layers) == 1:
return layers[0], {}
paint = ot.Paint()
@ -563,7 +572,7 @@ class LayerListBuilder:
# Register our parts for reuse provided we aren't a tree
# If we are a tree the leaves registered for reuse and that will suffice
if not is_tree:
if self.allowLayerReuse and not is_tree:
for lbound, ubound in _reuse_ranges(len(layers)):
self.reusePool[self._as_tuple(layers[lbound:ubound])] = (
lbound + paint.FirstLayerIndex
@ -603,6 +612,8 @@ def _format_glyph_errors(errors: Mapping[str, Exception]) -> str:
def buildColrV1(
colorGlyphs: _ColorGlyphsDict,
glyphMap: Optional[Mapping[str, int]] = None,
*,
allowLayerReuse: bool = True,
) -> Tuple[Optional[ot.LayerList], ot.BaseGlyphList]:
if glyphMap is not None:
colorGlyphItems = sorted(
@ -613,7 +624,7 @@ def buildColrV1(
errors = {}
baseGlyphs = []
layerBuilder = LayerListBuilder()
layerBuilder = LayerListBuilder(allowLayerReuse=allowLayerReuse)
for baseGlyph, paint in colorGlyphItems:
try:
baseGlyphs.append(buildBaseGlyphPaintRecord(baseGlyph, layerBuilder, paint))

View File

@ -838,6 +838,7 @@ class FontBuilder(object):
varStore=None,
varIndexMap=None,
clipBoxes=None,
allowLayerReuse=True,
):
"""Build new COLR table using color layers dictionary.
@ -853,6 +854,7 @@ class FontBuilder(object):
varStore=varStore,
varIndexMap=varIndexMap,
clipBoxes=clipBoxes,
allowLayerReuse=allowLayerReuse,
)
def setupCPAL(