from __future__ import print_function, division, absolute_import from fontTools import ttLib from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.tables.otBase import ValueRecord, valueRecordFormatDict # GSUB def buildSingleSubst(mapping): self = ot.SingleSubst() self.mapping = dict(mapping) return self def buildMultipleSubst(mapping): self = ot.MultipleSubst() self.mapping = dict(mapping) return self def buildAlternateSubst(mapping): self = ot.AlternateSubst() self.alternates = dict(mapping) return self def _getLigatureKey(components): """Computes a key for ordering ligatures in a GSUB Type-4 lookup. When building the OpenType lookup, we need to make sure that the longest sequence of components is listed first, so we use the negative length as the primary key for sorting. To make buildLigatureSubst() deterministic, we use the component sequence as the secondary key. For example, this will sort (f,f,f) < (f,f,i) < (f,f) < (f,i) < (f,l). """ return (-len(components), components) def buildLigatureSubst(mapping): self = ot.LigatureSubst() # The following single line can replace the rest of this function # with fontTools >= 3.1: # self.ligatures = dict(mapping) self.ligatures = {} for components in sorted(mapping.keys(), key=_getLigatureKey): ligature = ot.Ligature() ligature.Component = components[1:] ligature.CompCount = len(components) ligature.LigGlyph = mapping[components] firstGlyph = components[0] self.ligatures.setdefault(firstGlyph, []).append(ligature) return self # GPOS def buildAnchor(x, y, point=None, deviceX=None, deviceY=None): self = ot.Anchor() self.XCoordinate, self.YCoordinate = x, y self.Format = 1 if point is not None: self.AnchorPoint = point self.Format = 2 if deviceX is not None or deviceY is not None: assert self.Format == 2, "Either point, or both of deviceX/deviceY, must be None." self.XDeviceTable = deviceX self.YDeviceTable = deviceY self.Format = 3 return self def buildDevice(device): """[(11, 22), (7, -7), ...] --> otTables.Device""" self = ot.Device() device = tuple(sorted(device)) self.StartSize = startSize = device[0][0] self.EndSize = endSize = device[-1][0] deviceDict = dict(device) self.DeltaValue = deltaValues = [ deviceDict.get(size, 0) for size in range(startSize, endSize + 1)] maxDelta = max(deltaValues) minDelta = min(deltaValues) assert minDelta > -129 and maxDelta < 128 if minDelta > -3 and maxDelta < 2: self.DeltaFormat = 1 elif minDelta > -9 and maxDelta < 8: self.DeltaFormat = 2 else: self.DeltaFormat = 3 return self