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