def __init__(self, axisTags): self._axisTags = axisTags self._regionMap = {} self._regionList = buildVarRegionList([], axisTags) self._store = buildVarStore(self._regionList, []) self._data = None self._model = None self._cache = {}
def _add_HVAR(font, model, master_ttfs, axisTags): print("Generating HVAR") hAdvanceDeltas = {} metricses = [m["hmtx"].metrics for m in master_ttfs] for glyph in font.getGlyphOrder(): hAdvances = [metrics[glyph][0] for metrics in metricses] # TODO move round somewhere else? hAdvanceDeltas[glyph] = tuple( round(d) for d in model.getDeltas(hAdvances)[1:]) # We only support the direct mapping right now. supports = model.supports[1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) n = len(supports) items = [] zeroes = [0] * n for glyphName in font.getGlyphOrder(): items.append(hAdvanceDeltas.get(glyphName, zeroes)) while items and items[-1] is zeroes: del items[-1] advanceMapping = None # Add indirect mapping to save on duplicates uniq = set(items) # TODO Improve heuristic if (len(items) - len(uniq)) * len(varTupleIndexes) > len(items): newItems = sorted(uniq) mapper = {v: i for i, v in enumerate(newItems)} mapping = [mapper[item] for item in items] while len(mapping) > 1 and mapping[-1] == mapping[-2]: del mapping[-1] advanceMapping = builder.buildVarIdxMap(mapping) items = newItems del mapper, mapping, newItems del uniq varData = builder.buildVarData(varTupleIndexes, items) varStore = builder.buildVarStore(varTupleList, [varData]) assert "HVAR" not in font HVAR = font["HVAR"] = newTable('HVAR') hvar = HVAR.table = ot.HVAR() hvar.Version = 0x00010000 hvar.VarStore = varStore hvar.AdvWidthMap = advanceMapping hvar.LsbMap = hvar.RsbMap = None
def _add_HVAR(font, model, master_ttfs, axisTags): log.info("Generating HVAR") hAdvanceDeltas = {} metricses = [m["hmtx"].metrics for m in master_ttfs] for glyph in font.getGlyphOrder(): hAdvances = [metrics[glyph][0] for metrics in metricses] # TODO move round somewhere else? hAdvanceDeltas[glyph] = tuple(round(d) for d in model.getDeltas(hAdvances)[1:]) # We only support the direct mapping right now. supports = model.supports[1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) n = len(supports) items = [] zeroes = [0]*n for glyphName in font.getGlyphOrder(): items.append(hAdvanceDeltas.get(glyphName, zeroes)) while items and items[-1] is zeroes: del items[-1] advanceMapping = None # Add indirect mapping to save on duplicates uniq = set(items) # TODO Improve heuristic if (len(items) - len(uniq)) * len(varTupleIndexes) > len(items): newItems = sorted(uniq) mapper = {v:i for i,v in enumerate(newItems)} mapping = [mapper[item] for item in items] while len(mapping) > 1 and mapping[-1] == mapping[-2]: del mapping[-1] advanceMapping = builder.buildVarIdxMap(mapping) items = newItems del mapper, mapping, newItems del uniq varData = builder.buildVarData(varTupleIndexes, items) varStore = builder.buildVarStore(varTupleList, [varData]) assert "HVAR" not in font HVAR = font["HVAR"] = newTable('HVAR') hvar = HVAR.table = ot.HVAR() hvar.Version = 0x00010000 hvar.VarStore = varStore hvar.AdvWidthMap = advanceMapping hvar.LsbMap = hvar.RsbMap = None
def asItemVarStore(self): regionOrder = [frozenset(axes.items()) for axes in self.regions] varDatas = [] for variations, itemCount in zip(self.tupleVarData, self.itemCounts): if variations: assert len(variations[0].coordinates) == itemCount varRegionIndices = [ regionOrder.index(frozenset(var.axes.items())) for var in variations ] varDataItems = list(zip(*(var.coordinates for var in variations))) varDatas.append( builder.buildVarData(varRegionIndices, varDataItems, optimize=False) ) else: varDatas.append( builder.buildVarData([], [[] for _ in range(itemCount)]) ) regionList = builder.buildVarRegionList(self.regions, self.axisOrder) itemVarStore = builder.buildVarStore(regionList, varDatas) # remove unused regions from VarRegionList itemVarStore.prune_regions() return itemVarStore
def _get_advance_metrics(font, masterModel, master_ttfs, axisTags, glyphOrder, advMetricses, vOrigMetricses=None): vhAdvanceDeltasAndSupports = {} vOrigDeltasAndSupports = {} for glyph in glyphOrder: vhAdvances = [ metrics[glyph][0] if glyph in metrics else None for metrics in advMetricses ] vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports( vhAdvances, round=round) singleModel = models.allEqual( id(v[1]) for v in vhAdvanceDeltasAndSupports.values()) if vOrigMetricses: singleModel = False for glyph in glyphOrder: # We need to supply a vOrigs tuple with non-None default values # for each glyph. vOrigMetricses contains values only for those # glyphs which have a non-default vOrig. vOrigs = [ metrics[glyph] if glyph in metrics else defaultVOrig for metrics, defaultVOrig in vOrigMetricses ] vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports( vOrigs, round=round) directStore = None if singleModel: # Build direct mapping supports = next(iter(vhAdvanceDeltasAndSupports.values()))[1][1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) varData = builder.buildVarData(varTupleIndexes, [], optimize=False) for glyphName in glyphOrder: varData.addItem(vhAdvanceDeltasAndSupports[glyphName][0], round=noRound) varData.optimize() directStore = builder.buildVarStore(varTupleList, [varData]) # Build optimized indirect mapping storeBuilder = varStore.OnlineVarStoreBuilder(axisTags) advMapping = {} for glyphName in glyphOrder: deltas, supports = vhAdvanceDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) advMapping[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound) if vOrigMetricses: vOrigMap = {} for glyphName in glyphOrder: deltas, supports = vOrigDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) vOrigMap[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound) indirectStore = storeBuilder.finish() mapping2 = indirectStore.optimize() advMapping = [mapping2[advMapping[g]] for g in glyphOrder] advanceMapping = builder.buildVarIdxMap(advMapping, glyphOrder) if vOrigMetricses: vOrigMap = [mapping2[vOrigMap[g]] for g in glyphOrder] useDirect = False vOrigMapping = None if directStore: # Compile both, see which is more compact writer = OTTableWriter() directStore.compile(writer, font) directSize = len(writer.getAllData()) writer = OTTableWriter() indirectStore.compile(writer, font) advanceMapping.compile(writer, font) indirectSize = len(writer.getAllData()) useDirect = directSize < indirectSize if useDirect: metricsStore = directStore advanceMapping = None else: metricsStore = indirectStore if vOrigMetricses: vOrigMapping = builder.buildVarIdxMap(vOrigMap, glyphOrder) return metricsStore, advanceMapping, vOrigMapping
def _add_HVAR(font, masterModel, master_ttfs, axisTags): log.info("Generating HVAR") glyphOrder = font.getGlyphOrder() hAdvanceDeltasAndSupports = {} metricses = [m["hmtx"].metrics for m in master_ttfs] for glyph in glyphOrder: hAdvances = [ metrics[glyph][0] if glyph in metrics else None for metrics in metricses ] hAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports( hAdvances) singleModel = models.allEqual( id(v[1]) for v in hAdvanceDeltasAndSupports.values()) directStore = None if singleModel: # Build direct mapping supports = next(iter(hAdvanceDeltasAndSupports.values()))[1][1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) varData = builder.buildVarData(varTupleIndexes, [], optimize=False) for glyphName in glyphOrder: varData.addItem(hAdvanceDeltasAndSupports[glyphName][0]) varData.optimize() directStore = builder.buildVarStore(varTupleList, [varData]) # Build optimized indirect mapping storeBuilder = varStore.OnlineVarStoreBuilder(axisTags) mapping = {} for glyphName in glyphOrder: deltas, supports = hAdvanceDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) mapping[glyphName] = storeBuilder.storeDeltas(deltas) indirectStore = storeBuilder.finish() mapping2 = indirectStore.optimize() mapping = [mapping2[mapping[g]] for g in glyphOrder] advanceMapping = builder.buildVarIdxMap(mapping, glyphOrder) use_direct = False if directStore: # Compile both, see which is more compact writer = OTTableWriter() directStore.compile(writer, font) directSize = len(writer.getAllData()) writer = OTTableWriter() indirectStore.compile(writer, font) advanceMapping.compile(writer, font) indirectSize = len(writer.getAllData()) use_direct = directSize < indirectSize # Done; put it all together. assert "HVAR" not in font HVAR = font["HVAR"] = newTable('HVAR') hvar = HVAR.table = ot.HVAR() hvar.Version = 0x00010000 hvar.LsbMap = hvar.RsbMap = None if use_direct: hvar.VarStore = directStore hvar.AdvWidthMap = None else: hvar.VarStore = indirectStore hvar.AdvWidthMap = advanceMapping
def _add_HVAR(font, model, master_ttfs, axisTags): log.info("Generating HVAR") hAdvanceDeltas = {} metricses = [m["hmtx"].metrics for m in master_ttfs] for glyph in font.getGlyphOrder(): hAdvances = [metrics[glyph][0] for metrics in metricses] # TODO move round somewhere else? hAdvanceDeltas[glyph] = tuple( round(d) for d in model.getDeltas(hAdvances)[1:]) # Direct mapping supports = model.supports[1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) n = len(supports) items = [] for glyphName in font.getGlyphOrder(): items.append(hAdvanceDeltas[glyphName]) # Build indirect mapping to save on duplicates, compare both sizes uniq = list(set(items)) mapper = {v: i for i, v in enumerate(uniq)} mapping = [mapper[item] for item in items] advanceMapping = builder.buildVarIdxMap(mapping, font.getGlyphOrder()) # Direct varData = builder.buildVarData(varTupleIndexes, items) directStore = builder.buildVarStore(varTupleList, [varData]) # Indirect varData = builder.buildVarData(varTupleIndexes, uniq) indirectStore = builder.buildVarStore(varTupleList, [varData]) mapping = indirectStore.optimize() advanceMapping.mapping = { k: mapping[v] for k, v in advanceMapping.mapping.items() } # Compile both, see which is more compact writer = OTTableWriter() directStore.compile(writer, font) directSize = len(writer.getAllData()) writer = OTTableWriter() indirectStore.compile(writer, font) advanceMapping.compile(writer, font) indirectSize = len(writer.getAllData()) use_direct = directSize < indirectSize # Done; put it all together. assert "HVAR" not in font HVAR = font["HVAR"] = newTable('HVAR') hvar = HVAR.table = ot.HVAR() hvar.Version = 0x00010000 hvar.LsbMap = hvar.RsbMap = None if use_direct: hvar.VarStore = directStore hvar.AdvWidthMap = None else: hvar.VarStore = indirectStore hvar.AdvWidthMap = advanceMapping
def _add_HVAR(font, model, master_ttfs, axisTags): log.info("Generating HVAR") hAdvanceDeltas = {} metricses = [m["hmtx"].metrics for m in master_ttfs] for glyph in font.getGlyphOrder(): hAdvances = [metrics[glyph][0] for metrics in metricses] # TODO move round somewhere else? hAdvanceDeltas[glyph] = tuple(otRound(d) for d in model.getDeltas(hAdvances)[1:]) # Direct mapping supports = model.supports[1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) n = len(supports) items = [] for glyphName in font.getGlyphOrder(): items.append(hAdvanceDeltas[glyphName]) # Build indirect mapping to save on duplicates, compare both sizes uniq = list(set(items)) mapper = {v:i for i,v in enumerate(uniq)} mapping = [mapper[item] for item in items] advanceMapping = builder.buildVarIdxMap(mapping, font.getGlyphOrder()) # Direct varData = builder.buildVarData(varTupleIndexes, items) directStore = builder.buildVarStore(varTupleList, [varData]) # Indirect varData = builder.buildVarData(varTupleIndexes, uniq) indirectStore = builder.buildVarStore(varTupleList, [varData]) mapping = indirectStore.optimize() advanceMapping.mapping = {k:mapping[v] for k,v in advanceMapping.mapping.items()} # Compile both, see which is more compact writer = OTTableWriter() directStore.compile(writer, font) directSize = len(writer.getAllData()) writer = OTTableWriter() indirectStore.compile(writer, font) advanceMapping.compile(writer, font) indirectSize = len(writer.getAllData()) use_direct = directSize < indirectSize # Done; put it all together. assert "HVAR" not in font HVAR = font["HVAR"] = newTable('HVAR') hvar = HVAR.table = ot.HVAR() hvar.Version = 0x00010000 hvar.LsbMap = hvar.RsbMap = None if use_direct: hvar.VarStore = directStore hvar.AdvWidthMap = None else: hvar.VarStore = indirectStore hvar.AdvWidthMap = advanceMapping
def _add_HVAR(font, masterModel, master_ttfs, axisTags): log.info("Generating HVAR") glyphOrder = font.getGlyphOrder() hAdvanceDeltasAndSupports = {} metricses = [m["hmtx"].metrics for m in master_ttfs] for glyph in glyphOrder: hAdvances = [metrics[glyph][0] if glyph in metrics else None for metrics in metricses] hAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(hAdvances) singleModel = models.allEqual(id(v[1]) for v in hAdvanceDeltasAndSupports.values()) directStore = None if singleModel: # Build direct mapping supports = next(iter(hAdvanceDeltasAndSupports.values()))[1][1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) varData = builder.buildVarData(varTupleIndexes, [], optimize=False) for glyphName in glyphOrder: varData.addItem(hAdvanceDeltasAndSupports[glyphName][0]) varData.optimize() directStore = builder.buildVarStore(varTupleList, [varData]) # Build optimized indirect mapping storeBuilder = varStore.OnlineVarStoreBuilder(axisTags) mapping = {} for glyphName in glyphOrder: deltas,supports = hAdvanceDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) mapping[glyphName] = storeBuilder.storeDeltas(deltas) indirectStore = storeBuilder.finish() mapping2 = indirectStore.optimize() mapping = [mapping2[mapping[g]] for g in glyphOrder] advanceMapping = builder.buildVarIdxMap(mapping, glyphOrder) use_direct = False if directStore: # Compile both, see which is more compact writer = OTTableWriter() directStore.compile(writer, font) directSize = len(writer.getAllData()) writer = OTTableWriter() indirectStore.compile(writer, font) advanceMapping.compile(writer, font) indirectSize = len(writer.getAllData()) use_direct = directSize < indirectSize # Done; put it all together. assert "HVAR" not in font HVAR = font["HVAR"] = newTable('HVAR') hvar = HVAR.table = ot.HVAR() hvar.Version = 0x00010000 hvar.LsbMap = hvar.RsbMap = None if use_direct: hvar.VarStore = directStore hvar.AdvWidthMap = None else: hvar.VarStore = indirectStore hvar.AdvWidthMap = advanceMapping
def _get_advance_metrics(font, masterModel, master_ttfs, axisTags, glyphOrder, advMetricses, vOrigMetricses=None): vhAdvanceDeltasAndSupports = {} vOrigDeltasAndSupports = {} for glyph in glyphOrder: vhAdvances = [metrics[glyph][0] if glyph in metrics else None for metrics in advMetricses] vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(vhAdvances) singleModel = models.allEqual(id(v[1]) for v in vhAdvanceDeltasAndSupports.values()) if vOrigMetricses: singleModel = False for glyph in glyphOrder: # We need to supply a vOrigs tuple with non-None default values # for each glyph. vOrigMetricses contains values only for those # glyphs which have a non-default vOrig. vOrigs = [metrics[glyph] if glyph in metrics else defaultVOrig for metrics, defaultVOrig in vOrigMetricses] vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(vOrigs) directStore = None if singleModel: # Build direct mapping supports = next(iter(vhAdvanceDeltasAndSupports.values()))[1][1:] varTupleList = builder.buildVarRegionList(supports, axisTags) varTupleIndexes = list(range(len(supports))) varData = builder.buildVarData(varTupleIndexes, [], optimize=False) for glyphName in glyphOrder: varData.addItem(vhAdvanceDeltasAndSupports[glyphName][0]) varData.optimize() directStore = builder.buildVarStore(varTupleList, [varData]) # Build optimized indirect mapping storeBuilder = varStore.OnlineVarStoreBuilder(axisTags) advMapping = {} for glyphName in glyphOrder: deltas, supports = vhAdvanceDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) advMapping[glyphName] = storeBuilder.storeDeltas(deltas) if vOrigMetricses: vOrigMap = {} for glyphName in glyphOrder: deltas, supports = vOrigDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) vOrigMap[glyphName] = storeBuilder.storeDeltas(deltas) indirectStore = storeBuilder.finish() mapping2 = indirectStore.optimize() advMapping = [mapping2[advMapping[g]] for g in glyphOrder] advanceMapping = builder.buildVarIdxMap(advMapping, glyphOrder) if vOrigMetricses: vOrigMap = [mapping2[vOrigMap[g]] for g in glyphOrder] useDirect = False vOrigMapping = None if directStore: # Compile both, see which is more compact writer = OTTableWriter() directStore.compile(writer, font) directSize = len(writer.getAllData()) writer = OTTableWriter() indirectStore.compile(writer, font) advanceMapping.compile(writer, font) indirectSize = len(writer.getAllData()) useDirect = directSize < indirectSize if useDirect: metricsStore = directStore advanceMapping = None else: metricsStore = indirectStore if vOrigMetricses: vOrigMapping = builder.buildVarIdxMap(vOrigMap, glyphOrder) return metricsStore, advanceMapping, vOrigMapping
def __init__(self, axisTags): self._axisTags = axisTags self._regionMap = {} self._regionList = buildVarRegionList([], axisTags) self._store = buildVarStore(self._regionList, [])