def buildCOLR( colorGlyphs: _ColorGlyphsDict, version: Optional[int] = None, glyphMap: Optional[Mapping[str, int]] = None, varStore: Optional[ot.VarStore] = None, ) -> C_O_L_R_.table_C_O_L_R_: """Build COLR table from color layers mapping. Args: colorGlyphs: map of base glyph name to, either list of (layer glyph name, color palette index) tuples for COLRv0; or a single Paint (dict) or list of Paint for COLRv1. version: the version of COLR table. If None, the version is determined by the presence of COLRv1 paints or variation data (varStore), which require version 1; otherwise, if all base glyphs use only simple color layers, version 0 is used. glyphMap: a map from glyph names to glyph indices, as returned from TTFont.getReverseGlyphMap(), to optionally sort base records by GID. varStore: Optional ItemVarationStore for deltas associated with v1 layer. Return: A new COLR table. """ self = C_O_L_R_.table_C_O_L_R_() if varStore is not None and version == 0: raise ValueError("Can't add VarStore to COLRv0") if version in (None, 0) and not varStore: # split color glyphs into v0 and v1 and encode separately colorGlyphsV0, colorGlyphsV1 = _split_color_glyphs_by_version( colorGlyphs) if version == 0 and colorGlyphsV1: raise ValueError("Can't encode COLRv1 glyphs in COLRv0") else: # unless explicitly requested for v1 or have variations, in which case # we encode all color glyph as v1 colorGlyphsV0, colorGlyphsV1 = {}, colorGlyphs colr = ot.COLR() populateCOLRv0(colr, colorGlyphsV0, glyphMap) colr.LayerV1List, colr.BaseGlyphV1List = buildColrV1( colorGlyphsV1, glyphMap) if version is None: version = 1 if (varStore or colorGlyphsV1) else 0 elif version not in (0, 1): raise NotImplementedError(version) self.version = colr.Version = version if version == 0: self.ColorLayers = self._decompileColorLayersV0(colr) else: colr.VarStore = varStore self.table = colr return self
def test_traverseEmptyPaintColrLayersNeedsNoLayerList(self): colr = parseXmlInto( self.font, otTables.COLR(), ''' <Version value="1"/> <BaseGlyphList> <BaseGlyphPaintRecord index="0"> <BaseGlyph value="meh"/> <Paint Format="1"><!-- PaintColrLayers --> <NumLayers value="0"/> <FirstLayerIndex value="42"/> </Paint> </BaseGlyphPaintRecord> </BaseGlyphList> ''', ) paint = colr.BaseGlyphList.BaseGlyphPaintRecord[0].Paint # Just want to confirm we don't crash visited = [] paint.traverse(colr, lambda p: visited.append(p)) assert len(visited) == 1
def buildCOLR( colorGlyphs: _ColorGlyphsDict, version: Optional[int] = None, glyphMap: Optional[Mapping[str, int]] = None, varStore: Optional[ot.VarStore] = None, ) -> C_O_L_R_.table_C_O_L_R_: """Build COLR table from color layers mapping. Args: colorGlyphs: map of base glyph names to lists of (layer glyph names, Paint) tuples. For COLRv0, a paint is simply the color palette index (int); for COLRv1, paint can be either solid colors (with variable opacity), linear gradients or radial gradients. version: the version of COLR table. If None, the version is determined by the presence of gradients or variation data (varStore), which require version 1; otherwise, if there are only simple colors, version 0 is used. glyphMap: a map from glyph names to glyph indices, as returned from TTFont.getReverseGlyphMap(), to optionally sort base records by GID. varStore: Optional ItemVarationStore for deltas associated with v1 layer. Return: A new COLR table. """ self = C_O_L_R_.table_C_O_L_R_() if varStore is not None and version == 0: raise ValueError("Can't add VarStore to COLRv0") if version in (None, 0) and not varStore: # split color glyphs into v0 and v1 and encode separately colorGlyphsV0, colorGlyphsV1 = _splitSolidAndGradientGlyphs( colorGlyphs) if version == 0 and colorGlyphsV1: # TODO Derive "average" solid color from gradients? raise ValueError("Can't encode gradients in COLRv0") else: # unless explicitly requested for v1 or have variations, in which case # we encode all color glyph as v1 colorGlyphsV0, colorGlyphsV1 = None, colorGlyphs colr = ot.COLR() if colorGlyphsV0: populateCOLRv0(colr, colorGlyphsV0, glyphMap) else: colr.BaseGlyphRecordCount = colr.LayerRecordCount = 0 colr.BaseGlyphRecordArray = colr.LayerRecordArray = None if colorGlyphsV1: colr.BaseGlyphV1List = buildBaseGlyphV1List(colorGlyphsV1, glyphMap) if version is None: version = 1 if (varStore or colorGlyphsV1) else 0 elif version not in (0, 1): raise NotImplementedError(version) self.version = colr.Version = version if version == 0: self._fromOTTable(colr) else: colr.VarStore = varStore self.table = colr return self