Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
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)
Exemple #4
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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)
Exemple #8
0
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)