def merge(merger, self, lst): # Align them glyphs, padded = _merge_GlyphOrders(merger.font, [[v.SecondGlyph for v in vs.PairValueRecord] for vs in lst], [vs.PairValueRecord for vs in lst]) self.PairValueRecord = pvrs = [] for glyph in glyphs: pvr = ot.PairValueRecord() pvr.SecondGlyph = glyph pvr.Value1 = otBase.ValueRecord(merger.valueFormat1) if merger.valueFormat1 else None pvr.Value2 = otBase.ValueRecord(merger.valueFormat2) if merger.valueFormat2 else None pvrs.append(pvr) self.PairValueCount = len(self.PairValueRecord) for i,values in enumerate(padded): for j,glyph in enumerate(glyphs): # Fill in value from other subtables v = ot.PairValueRecord() v.SecondGlyph = glyph if values[j] is not None: vpair = values[j] else: vpair = _Lookup_PairPos_get_effective_value_pair(merger.lookup_subtables[i], self._firstGlyph, glyph) if vpair is None: v1, v2 = None, None else: v1, v2 = vpair.Value1, vpair.Value2 v.Value1 = otBase.ValueRecord(merger.valueFormat1, src=v1) if merger.valueFormat1 else None v.Value2 = otBase.ValueRecord(merger.valueFormat2, src=v2) if merger.valueFormat2 else None values[j] = v del self._firstGlyph merger.mergeLists(self.PairValueRecord, padded)
def merge(merger, self, lst): self.ValueFormat = valueFormat = reduce(int.__or__, [l.ValueFormat for l in lst], 0) if not (len(lst) == 1 or (valueFormat & ~0xF == 0)): raise UnsupportedFormat(merger, subtable="single positioning lookup") # If all have same coverage table and all are format 1, coverageGlyphs = self.Coverage.glyphs if all(v.Format == 1 for v in lst) and all(coverageGlyphs == v.Coverage.glyphs for v in lst): self.Value = otBase.ValueRecord(valueFormat, self.Value) if valueFormat != 0: merger.mergeThings(self.Value, [v.Value for v in lst]) self.ValueFormat = self.Value.getFormat() return # Upgrade everything to Format=2 self.Format = 2 lst = [_SinglePosUpgradeToFormat2(v) for v in lst] # Align them glyphs, padded = _merge_GlyphOrders(merger.font, [v.Coverage.glyphs for v in lst], [v.Value for v in lst]) self.Coverage.glyphs = glyphs self.Value = [otBase.ValueRecord(valueFormat) for _ in glyphs] self.ValueCount = len(self.Value) for i, values in enumerate(padded): for j, glyph in enumerate(glyphs): if values[j] is not None: continue # Fill in value from other subtables # Note!!! This *might* result in behavior change if ValueFormat2-zeroedness # is different between used subtable and current subtable! # TODO(behdad) Check and warn if that happens? v = _Lookup_SinglePos_get_effective_value( merger, merger.lookup_subtables[i], glyph) if v is None: v = otBase.ValueRecord(valueFormat) values[j] = v merger.mergeLists(self.Value, padded) # Merge everything else; though, there shouldn't be anything else. :) merger.mergeObjects(self, lst, exclude=('Format', 'Coverage', 'Value', 'ValueCount', 'ValueFormat')) self.ValueFormat = reduce(int.__or__, [v.getEffectiveFormat() for v in self.Value], 0)
def merge(merger, self, lst): self.ValueFormat = valueFormat = reduce(int.__or__, [l.ValueFormat for l in lst], 0) assert valueFormat & ~0xF == 0, valueFormat # If all have same coverage table and all are format 1, if all(v.Format == 1 for v in lst) and all(self.Coverage.glyphs == v.Coverage.glyphs for v in lst): self.Value = otBase.ValueRecord(valueFormat) merger.mergeThings(self.Value, [v.Value for v in lst]) self.ValueFormat = self.Value.getFormat() return # Upgrade everything to Format=2 self.Format = 2 lst = [_SinglePosUpgradeToFormat2(v) for v in lst] # Align them glyphs, padded = _merge_GlyphOrders(merger.font, [v.Coverage.glyphs for v in lst], [v.Value for v in lst]) self.Coverage.glyphs = glyphs self.Value = [otBase.ValueRecord(valueFormat) for g in glyphs] self.ValueCount = len(self.Value) for i, values in enumerate(padded): for j, glyph in enumerate(glyphs): if values[j] is not None: continue # Fill in value from other subtables v = _Lookup_SinglePos_get_effective_value( merger.lookup_subtables[i], glyph) if v is None: v = otBase.ValueRecord(valueFormat) values[j] = v merger.mergeLists(self.Value, padded) # Merge everything else; though, there shouldn't be anything else. :) merger.mergeObjects(self, lst, exclude=('Format', 'Coverage', 'Value', 'ValueCount')) self.ValueFormat = reduce(int.__or__, [v.getFormat() for v in self.Value], 0)
def makeOpenTypeValueRecord(v): """ast.ValueRecord --> (otBase.ValueRecord, int ValueFormat)""" if v is None: return None, 0 vr = otBase.ValueRecord() if v.xPlacement: vr.XPlacement = v.xPlacement if v.yPlacement: vr.YPlacement = v.yPlacement if v.xAdvance: vr.XAdvance = v.xAdvance if v.yAdvance: vr.YAdvance = v.yAdvance if v.xPlaDevice: vr.XPlaDevice = otTables.XPlaDevice() _makeOpenTypeDeviceTable(vr.XPlaDevice, v.xPlaDevice) if v.yPlaDevice: vr.YPlaDevice = otTables.YPlaDevice() _makeOpenTypeDeviceTable(vr.YPlaDevice, v.yPlaDevice) if v.xAdvDevice: vr.XAdvDevice = otTables.XAdvDevice() _makeOpenTypeDeviceTable(vr.XAdvDevice, v.xAdvDevice) if v.yAdvDevice: vr.YAdvDevice = otTables.YAdvDevice() _makeOpenTypeDeviceTable(vr.YAdvDevice, v.yAdvDevice) vrMask = 0 for mask, name, _, _ in otBase.valueRecordFormat: if getattr(vr, name, 0) != 0: vrMask |= mask if vrMask == 0: return None, 0 else: return vr, vrMask
def _PairPosFormat2_align_matrices(self, lst, font, transparent=False): matrices = [l.Class1Record for l in lst] # Align first classes self.ClassDef1, classes = _ClassDef_merge_classify( [l.ClassDef1 for l in lst], [l.Coverage.glyphs for l in lst]) self.Class1Count = len(classes) new_matrices = [] for l, matrix in zip(lst, matrices): nullRow = None coverage = set(l.Coverage.glyphs) classDef1 = l.ClassDef1.classDefs class1Records = [] for classSet in classes: exemplarGlyph = next(iter(classSet)) if exemplarGlyph not in coverage: # Follow-up to e6125b353e1f54a0280ded5434b8e40d042de69f, # Fixes https://github.com/googlei18n/fontmake/issues/470 # Again, revert 8d441779e5afc664960d848f62c7acdbfc71d7b9 # when merger becomes selfless. nullRow = None if nullRow is None: nullRow = ot.Class1Record() class2records = nullRow.Class2Record = [] # TODO: When merger becomes selfless, revert e6125b353e1f54a0280ded5434b8e40d042de69f for _ in range(l.Class2Count): if transparent: rec2 = None else: rec2 = ot.Class2Record() rec2.Value1 = otBase.ValueRecord( self.ValueFormat1 ) if self.ValueFormat1 else None rec2.Value2 = otBase.ValueRecord( self.ValueFormat2 ) if self.ValueFormat2 else None class2records.append(rec2) rec1 = nullRow else: klass = classDef1.get(exemplarGlyph, 0) rec1 = matrix[klass] # TODO handle out-of-range? class1Records.append(rec1) new_matrices.append(class1Records) matrices = new_matrices del new_matrices # Align second classes self.ClassDef2, classes = _ClassDef_merge_classify( [l.ClassDef2 for l in lst]) self.Class2Count = len(classes) new_matrices = [] for l, matrix in zip(lst, matrices): classDef2 = l.ClassDef2.classDefs class1Records = [] for rec1old in matrix: oldClass2Records = rec1old.Class2Record rec1new = ot.Class1Record() class2Records = rec1new.Class2Record = [] for classSet in classes: if not classSet: # class=0 rec2 = oldClass2Records[0] else: exemplarGlyph = next(iter(classSet)) klass = classDef2.get(exemplarGlyph, 0) rec2 = oldClass2Records[klass] class2Records.append(copy.deepcopy(rec2)) class1Records.append(rec1new) new_matrices.append(class1Records) matrices = new_matrices del new_matrices return matrices
def _PairPosFormat2_align_matrices(self, lst, font, transparent=False): matrices = [l.Class1Record for l in lst] # Align first classes self.ClassDef1, classes = _ClassDef_merge_classify( [l.ClassDef1 for l in lst], allGlyphs=set(self.Coverage.glyphs)) _ClassDef_calculate_Format(self.ClassDef1, font) self.Class1Count = len(classes) new_matrices = [] for l, matrix in zip(lst, matrices): nullRow = None coverage = set(l.Coverage.glyphs) classDef1 = l.ClassDef1.classDefs class1Records = [] for classSet in classes: exemplarGlyph = next(iter(classSet)) if exemplarGlyph not in coverage: if nullRow is None: nullRow = ot.Class1Record() class2records = nullRow.Class2Record = [] # TODO: When merger becomes selfless, revert e6125b353e1f54a0280ded5434b8e40d042de69f for _ in range(l.Class2Count): if transparent: rec2 = None else: rec2 = ot.Class2Record() rec2.Value1 = otBase.ValueRecord( self.ValueFormat1 ) if self.ValueFormat1 else None rec2.Value2 = otBase.ValueRecord( self.ValueFormat2 ) if self.ValueFormat2 else None class2records.append(rec2) rec1 = nullRow else: klass = classDef1.get(exemplarGlyph, 0) rec1 = matrix[klass] # TODO handle out-of-range? class1Records.append(rec1) new_matrices.append(class1Records) matrices = new_matrices del new_matrices # Align second classes self.ClassDef2, classes = _ClassDef_merge_classify( [l.ClassDef2 for l in lst]) _ClassDef_calculate_Format(self.ClassDef2, font) self.Class2Count = len(classes) new_matrices = [] for l, matrix in zip(lst, matrices): classDef2 = l.ClassDef2.classDefs class1Records = [] for rec1old in matrix: oldClass2Records = rec1old.Class2Record rec1new = ot.Class1Record() class2Records = rec1new.Class2Record = [] for classSet in classes: if not classSet: # class=0 rec2 = oldClass2Records[0] else: exemplarGlyph = next(iter(classSet)) klass = classDef2.get(exemplarGlyph, 0) rec2 = oldClass2Records[klass] class2Records.append(rec2) class1Records.append(rec1new) new_matrices.append(class1Records) matrices = new_matrices del new_matrices return matrices
def _PairPosFormat2_merge(self, lst, merger): merger.mergeObjects(self, lst, exclude=('Coverage', 'ClassDef1', 'Class1Count', 'ClassDef2', 'Class2Count', 'Class1Record')) # Align coverages glyphs, _ = _merge_GlyphOrders(merger.font, [v.Coverage.glyphs for v in lst]) self.Coverage.glyphs = glyphs glyphSet = set(glyphs) # Currently, if the coverage of PairPosFormat2 subtables are different, # we do NOT bother walking down the subtable list when filling in new # rows for alignment. As such, this is only correct if current subtable # is the last subtable in the lookup. Ensure that. # # Note that our canonicalization process merges some PairPosFormat2's, # so in reality this might not be common. # # TODO: Remove this requirement for l,subtables in zip(lst,merger.lookup_subtables): if l.Coverage.glyphs != glyphs: assert l == subtables[-1] matrices = [l.Class1Record for l in lst] # Align first classes self.ClassDef1, classes = _ClassDef_merge_classify([l.ClassDef1 for l in lst], allGlyphs=glyphSet) _ClassDef_calculate_Format(self.ClassDef1, merger.font) self.Class1Count = len(classes) new_matrices = [] for l,matrix in zip(lst, matrices): nullRow = None coverage = set(l.Coverage.glyphs) classDef1 = l.ClassDef1.classDefs class1Records = [] for classSet in classes: exemplarGlyph = next(iter(classSet)) if exemplarGlyph not in coverage: if nullRow is None: nullRow = ot.Class1Record() class2records = nullRow.Class2Record = [] # TODO: When merger becomes selfless, revert e6125b353e1f54a0280ded5434b8e40d042de69f for _ in range(l.Class2Count): rec2 = ot.Class2Record() rec2.Value1 = otBase.ValueRecord(l.ValueFormat1) if l.ValueFormat1 else None rec2.Value2 = otBase.ValueRecord(l.ValueFormat2) if l.ValueFormat2 else None class2records.append(rec2) rec1 = nullRow else: klass = classDef1.get(exemplarGlyph, 0) rec1 = matrix[klass] # TODO handle out-of-range? class1Records.append(rec1) new_matrices.append(class1Records) matrices = new_matrices del new_matrices # Align second classes self.ClassDef2, classes = _ClassDef_merge_classify([l.ClassDef2 for l in lst]) _ClassDef_calculate_Format(self.ClassDef2, merger.font) self.Class2Count = len(classes) new_matrices = [] for l,matrix in zip(lst, matrices): classDef2 = l.ClassDef2.classDefs class1Records = [] for rec1old in matrix: oldClass2Records = rec1old.Class2Record rec1new = ot.Class1Record() class2Records = rec1new.Class2Record = [] for classSet in classes: if not classSet: # class=0 rec2 = oldClass2Records[0] else: exemplarGlyph = next(iter(classSet)) klass = classDef2.get(exemplarGlyph, 0) rec2 = oldClass2Records[klass] class2Records.append(rec2) class1Records.append(rec1new) new_matrices.append(class1Records) matrices = new_matrices del new_matrices self.Class1Record = list(matrices[0]) # TODO move merger to be selfless merger.mergeLists(self.Class1Record, matrices)
def _PairPosFormat2_merge(self, lst, merger): merger.mergeObjects(self, lst, exclude=('Coverage', 'ClassDef1', 'Class1Count', 'ClassDef2', 'Class2Count', 'Class1Record')) # Align coverages glyphs, _ = _merge_GlyphOrders(merger.font, [v.Coverage.glyphs for v in lst]) self.Coverage.glyphs = glyphs glyphSet = set(glyphs) # Currently, if the coverage of PairPosFormat2 subtables are different, # we do NOT bother walking down the subtable list when filling in new # rows for alignment. As such, this is only correct if current subtable # is the last subtable in the lookup. Ensure that. # TODO: Remove this requirement for l, lookup in zip(lst, merger.lookups): if l.Coverage.glyphs != glyphs: assert l == lookup.SubTable[-1] matrices = [l.Class1Record for l in lst] # Align first classes self.ClassDef1, classes = _ClassDef_merge_classify( [l.ClassDef1 for l in lst], allGlyphs=glyphSet) self.Class1Count = len(classes) new_matrices = [] for l, matrix in zip(lst, matrices): nullRow = None coverage = set(l.Coverage.glyphs) classDef1 = l.ClassDef1.classDefs class1Records = [] for classSet in classes: exemplarGlyph = next(iter(classSet)) if exemplarGlyph not in coverage: if nullRow is None: rec2 = ot.Class2Record() rec2.Value1 = otBase.ValueRecord( l.ValueFormat1) if l.ValueFormat1 else None rec2.Value2 = otBase.ValueRecord( l.ValueFormat2) if l.ValueFormat2 else None nullRow = ot.Class1Record() nullRow.Class2Record = [rec2] * l.Class2Count rec1 = nullRow else: klass = classDef1.get(exemplarGlyph, 0) rec1 = matrix[klass] # TODO handle out-of-range? class1Records.append(rec1) new_matrices.append(class1Records) matrices = new_matrices del new_matrices # Align second classes self.ClassDef2, classes = _ClassDef_merge_classify( [l.ClassDef2 for l in lst]) self.Class2Count = len(classes) new_matrices = [] for l, matrix in zip(lst, matrices): classDef2 = l.ClassDef2.classDefs class1Records = [] for rec1old in matrix: oldClass2Records = rec1old.Class2Record rec1new = ot.Class1Record() class2Records = rec1new.Class2Record = [] for classSet in classes: if not classSet: # class=0 rec2 = oldClass2Records[0] else: exemplarGlyph = next(iter(classSet)) klass = classDef2.get(exemplarGlyph, 0) rec2 = oldClass2Records[klass] class2Records.append(rec2) class1Records.append(rec1new) new_matrices.append(class1Records) matrices = new_matrices del new_matrices self.Class1Record = list(matrices[0]) # TODO move merger to be selfless merger.mergeLists(self.Class1Record, matrices)