1from __future__ import print_function, division, absolute_import 2from fontTools import ttLib 3from fontTools.ttLib.tables import otTables as ot 4 5# VariationStore 6 7def buildVarRegionAxis(axisSupport): 8 self = ot.VarRegionAxis() 9 self.StartCoord, self.PeakCoord, self.EndCoord = [float(v) for v in axisSupport] 10 return self 11 12def buildVarRegion(support, axisTags): 13 assert all(tag in axisTags for tag in support.keys()), ("Unknown axis tag found.", support, axisTags) 14 self = ot.VarRegion() 15 self.VarRegionAxis = [] 16 for tag in axisTags: 17 self.VarRegionAxis.append(buildVarRegionAxis(support.get(tag, (0,0,0)))) 18 self.VarRegionAxisCount = len(self.VarRegionAxis) 19 return self 20 21def buildVarRegionList(supports, axisTags): 22 self = ot.VarRegionList() 23 self.RegionAxisCount = len(axisTags) 24 self.Region = [] 25 for support in supports: 26 self.Region.append(buildVarRegion(support, axisTags)) 27 self.RegionCount = len(self.Region) 28 return self 29 30 31def _reorderItem(lst, narrows, zeroes): 32 out = [] 33 count = len(lst) 34 for i in range(count): 35 if i not in narrows: 36 out.append(lst[i]) 37 for i in range(count): 38 if i in narrows and i not in zeroes: 39 out.append(lst[i]) 40 return out 41 42def VarData_calculateNumShorts(self, optimize=False): 43 count = self.VarRegionCount 44 items = self.Item 45 narrows = set(range(count)) 46 zeroes = set(range(count)) 47 for item in items: 48 wides = [i for i in narrows if not (-128 <= item[i] <= 127)] 49 narrows.difference_update(wides) 50 nonzeroes = [i for i in zeroes if item[i]] 51 zeroes.difference_update(nonzeroes) 52 if not narrows and not zeroes: 53 break 54 if optimize: 55 # Reorder columns such that all SHORT columns come before UINT8 56 self.VarRegionIndex = _reorderItem(self.VarRegionIndex, narrows, zeroes) 57 self.VarRegionCount = len(self.VarRegionIndex) 58 for i in range(len(items)): 59 items[i] = _reorderItem(items[i], narrows, zeroes) 60 self.NumShorts = count - len(narrows) 61 else: 62 wides = set(range(count)) - narrows 63 self.NumShorts = 1+max(wides) if wides else 0 64 self.VarRegionCount = len(self.VarRegionIndex) 65 return self 66 67ot.VarData.calculateNumShorts = VarData_calculateNumShorts 68 69def VarData_CalculateNumShorts(self, optimize=True): 70 """Deprecated name for VarData_calculateNumShorts() which 71 defaults to optimize=True. Use varData.calculateNumShorts() 72 or varData.optimize().""" 73 return VarData_calculateNumShorts(self, optimize=optimize) 74 75def VarData_optimize(self): 76 return VarData_calculateNumShorts(self, optimize=True) 77 78ot.VarData.optimize = VarData_optimize 79 80 81def buildVarData(varRegionIndices, items, optimize=True): 82 self = ot.VarData() 83 self.VarRegionIndex = list(varRegionIndices) 84 regionCount = self.VarRegionCount = len(self.VarRegionIndex) 85 records = self.Item = [] 86 if items: 87 for item in items: 88 assert len(item) == regionCount 89 records.append(list(item)) 90 self.ItemCount = len(self.Item) 91 self.calculateNumShorts(optimize=optimize) 92 return self 93 94 95def buildVarStore(varRegionList, varDataList): 96 self = ot.VarStore() 97 self.Format = 1 98 self.VarRegionList = varRegionList 99 self.VarData = list(varDataList) 100 self.VarDataCount = len(self.VarData) 101 return self 102 103 104# Variation helpers 105 106def buildVarIdxMap(varIdxes, glyphOrder): 107 self = ot.VarIdxMap() 108 self.mapping = {g:v for g,v in zip(glyphOrder, varIdxes)} 109 return self 110 111def buildVarDevTable(varIdx): 112 self = ot.Device() 113 self.DeltaFormat = 0x8000 114 self.StartSize = varIdx >> 16 115 self.EndSize = varIdx & 0xFFFF 116 return self 117