def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType5, self).loadFromFontTools(subtable, lookup) self.MarkCoverage = Coverage().loadFromFontTools(subtable.MarkCoverage) self.LigatureCoverage = Coverage().loadFromFontTools(subtable.LigatureCoverage) self.MarkArray = MarkArray().loadFromFontTools(subtable.MarkArray) self.LigatureArray = LigatureArray().loadFromFontTools(subtable.LigatureArray) return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType2Format1, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ValueFormat1 = subtable.ValueFormat1 self.ValueFormat2 = subtable.ValueFormat2 self.PairSet = [PairSet().loadFromFontTools(pairSet) for pairSet in subtable.PairSet] return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType6, self).loadFromFontTools(subtable, lookup) self.Mark1Coverage = Coverage().loadFromFontTools(subtable.Mark1Coverage) self.Mark2Coverage = Coverage().loadFromFontTools(subtable.Mark2Coverage) self.Mark1Array = MarkArray().loadFromFontTools(subtable.Mark1Array) self.Mark2Array = Mark2Array().loadFromFontTools(subtable.Mark2Array) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType1Format2, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.Substitute = [] for glyphName, alternate in sorted(subtable.mapping.items()): coverage.append(glyphName) self.Substitute.append(alternate) self.Coverage = Coverage().loadFromFontTools(coverage) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType4, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.LigatureSet = [] for glyphName, ligature in subtable.ligatures.items(): ligatureSet = LigatureSet().loadFromFontTools(ligature) self.LigatureSet.append(ligatureSet) coverage.append(glyphName) self.Coverage = Coverage().loadFromFontTools(coverage) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType3, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.AlternateSet = [] for glyphName, alternates in subtable.alternates.items(): coverage.append(glyphName) alternateSet = AlternateSet().loadFromFontTools(alternates) self.AlternateSet.append(alternateSet) self.Coverage = Coverage().loadFromFontTools(coverage) self.AlternateSetCount = len(self.AlternateSet) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType2, self).loadFromFontTools(subtable, lookup) try: self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.Sequence = [ Sequence().loadFromFontTools(sequence) for sequence in subtable.Sequence ] except AttributeError: # the API for MultipleSubst lookups changed with fonttools 3.1: # https://github.com/fonttools/fonttools/pull/364 mapping = getattr(subtable, "mapping", {}) coverage = sorted(mapping.keys()) self.Coverage = Coverage(coverage) self.Sequence = [Sequence(mapping[glyph]) for glyph in coverage] return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType7Format3, self).loadFromFontTools(subtable, lookup) self.Coverage = [Coverage().loadFromFontTools(coverage) for coverage in subtable.Coverage] self.GlyphCount = subtable.GlyphCount self.PosCount = subtable.PosCount self.PosLookupRecord = [PosLookupRecord().loadFromFontTools(record) for record in subtable.PosLookupRecord] return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType6Format1, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ChainSubRuleSet = [ ChainSubRuleSet().loadFromFontTools(chainSubRuleSet) for chainSubRuleSet in subtable.ChainSubRuleSet ] return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType2Format2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ValueFormat1 = subtable.ValueFormat1 self.ValueFormat2 = subtable.ValueFormat2 self.ClassDef1 = ClassDef().loadFromFontTools(subtable.ClassDef1) self.ClassDef2 = ClassDef().loadFromFontTools(subtable.ClassDef2) self.Class1Record = [Class1Record().loadFromFontTools(record) for record in subtable.Class1Record] return self
class GPOSLookupType3(BaseSubTable): """ Deviation from spec: - EntryExitRecordCount attribute is not implemented. """ __slots__ = ["Coverage", "EntryExitRecord"] + globalPositionSubTableSlots def __init__(self): super(GPOSLookupType3, self).__init__() self.PosFormat = 1 self.Coverage = None self.EntryExitRecord = [] def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType3, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.EntryExitRecord = [EntryExitRecord().loadFromFontTools(entryExitRecord) for entryExitRecord in subtable.EntryExitRecord] return self def process(self, processed, glyphRecords, featureTag): performedPos = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): nextRecord, nextRecordIndex = self._nextRecord(glyphRecords[1:]) if nextRecord is not None: nextGlyph = nextRecord.glyphName if nextGlyph in self.Coverage: performedPos = True exitIndex = self.Coverage.index(currentGlyph) exitAnchor = self.EntryExitRecord[exitIndex].ExitAnchor entryIndex = self.Coverage.index(nextGlyph) entryAnchor = self.EntryExitRecord[entryIndex].EntryAnchor if exitAnchor is not None and entryAnchor is not None: currentRecord.xAdvance += exitAnchor.XCoordinate - currentRecord.advanceWidth - entryAnchor.XCoordinate currentRecord.yAdvance += exitAnchor.YCoordinate - currentRecord.advanceHeight - entryAnchor.YCoordinate processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedPos
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType1Format2, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.Substitute = [] for glyphName, alternate in sorted(subtable.mapping.items()): coverage.append(glyphName) self.Substitute.append(alternate) self.Coverage = Coverage().loadFromFontTools(coverage) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType5Format2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ClassDef = ClassDef().loadFromFontTools(subtable.ClassDef) self.SubClassSet = [] for subClassSet in subtable.SubClassSet: if subClassSet is None: self.SubClassSet.append(None) else: self.SubClassSet.append( SubClassSet().loadFromFontTools(subClassSet)) return self
class GSUBLookupType3(BaseSubTable): """ Deviation from spec: - AlternateSetCount attribute is not implemented. """ __slots__ = ["Coverage", "AlternateSet", "AlternateSetCount" ] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType3, self).__init__() self.SubstFormat = 1 self.AlternateSet = [] self.Coverage = None self.AlternateSetCount = 0 def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType3, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.AlternateSet = [] for glyphName, alternates in subtable.alternates.items(): coverage.append(glyphName) alternateSet = AlternateSet().loadFromFontTools(alternates) self.AlternateSet.append(alternateSet) self.Coverage = Coverage().loadFromFontTools(coverage) self.AlternateSetCount = len(self.AlternateSet) return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): performedSub = True index = self.Coverage.index(currentGlyph) alternateSet = self.AlternateSet[index] alternates = alternateSet.Alternate # special behavior for rand if featureTag == "rand": currentRecord.saveState(currentRecord.glyphName) currentRecord.glyphName = choice(alternates) # standard behavior else: if currentRecord._alternatesReference != currentGlyph: currentRecord._alternatesReference = currentGlyph currentRecord.alternates = [] currentRecord.alternates.extend(alternates) processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedSub
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType4, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.LigatureSet = [] for glyphName, ligature in subtable.ligatures.items(): ligatureSet = LigatureSet().loadFromFontTools(ligature) self.LigatureSet.append(ligatureSet) coverage.append(glyphName) self.Coverage = Coverage().loadFromFontTools(coverage) return self
class GSUBLookupType3(BaseSubTable): """ Deviation from spec: - AlternateSetCount attribute is not implemented. """ __slots__ = ["Coverage", "AlternateSet", "AlternateSetCount"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType3, self).__init__() self.SubstFormat = 1 self.AlternateSet = [] self.Coverage = None self.AlternateSetCount = 0 def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType3, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.AlternateSet = [] for glyphName, alternates in subtable.alternates.items(): coverage.append(glyphName) alternateSet = AlternateSet().loadFromFontTools(alternates) self.AlternateSet.append(alternateSet) self.Coverage = Coverage().loadFromFontTools(coverage) self.AlternateSetCount = len(self.AlternateSet) return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): performedSub = True index = self.Coverage.index(currentGlyph) alternateSet = self.AlternateSet[index] alternates = alternateSet.Alternate # special behavior for rand if featureTag == "rand": currentRecord.saveState(currentRecord.glyphName) currentRecord.glyphName = choice(alternates) # standard behavior else: if currentRecord._alternatesReference != currentGlyph: currentRecord._alternatesReference = currentGlyph currentRecord.alternates = [] currentRecord.alternates.extend(alternates) processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedSub
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType7Format2, self).loadFromFontTools(subtable, lookup) self.PosFormat = 2 self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ClassDef = ClassDef().loadFromFontTools(subtable.ClassDef) self.PosClassSet = [] for posClassSet in subtable.PosClassSet: if posClassSet is None: self.PosClassSet.append(None) else: self.PosClassSet.append(PosClassSet().loadFromFontTools(posClassSet)) return self
class GPOSLookupType2Format1(BaseSubTable): """ Deviation from spec: - PairSetCount attribute is not implemented. """ __slots__ = ["Coverage", "ValueFormat1", "ValueFormat2", "PairSet"] + globalPositionSubTableSlots def __init__(self): super(GPOSLookupType2Format1, self).__init__() self.PosFormat = 1 self.Coverage = None self.ValueFormat1 = None self.ValueFormat2 = None self.PairSet = [] def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType2Format1, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ValueFormat1 = subtable.ValueFormat1 self.ValueFormat2 = subtable.ValueFormat2 self.PairSet = [PairSet().loadFromFontTools(pairSet) for pairSet in subtable.PairSet] return self def process(self, processed, glyphRecords, featureTag): performedPos = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): nextRecord, nextRecordIndex = self._nextRecord(glyphRecords[1:]) nextRecordIndex += 1 if nextRecord is not None: nextGlyph = nextRecord.glyphName pairSetIndex = self.Coverage.index(currentGlyph) pairSet = self.PairSet[pairSetIndex] for pairValueRecord in pairSet.PairValueRecord: if nextGlyph == pairValueRecord.SecondGlyph: performedPos = True if self.ValueFormat1: currentRecord += pairValueRecord.Value1 if self.ValueFormat2: nextRecord += pairValueRecord.Value2 if self.ValueFormat2: processed.extend(glyphRecords[:nextRecordIndex+1]) glyphRecords = glyphRecords[nextRecordIndex+1:] else: processed.append(currentRecord) glyphRecords = glyphRecords[1:] break return processed, glyphRecords, performedPos
class GSUBLookupType1Format2(BaseSubTable): """ Deviation from spec: - fontTools interprets Lookup Type 1 formats 1 and 2 into the same object structure. As such, only format 2 is needed. - GlyphCount attribute is not implemented. """ __slots__ = ["Coverage", "Substitute"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType1Format2, self).__init__() self.SubstFormat = 2 self.Substitute = [] self.Coverage = None def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType1Format2, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.Substitute = [] for glyphName, alternate in sorted(subtable.mapping.items()): coverage.append(glyphName) self.Substitute.append(alternate) self.Coverage = Coverage().loadFromFontTools(coverage) return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): performedSub = True index = self.Coverage.index(currentGlyph) substitute = self.Substitute[index] # special behavior for aalt if featureTag == "aalt": if currentRecord._alternatesReference != currentGlyph: currentRecord._alternatesReference = currentGlyph currentRecord.alternates = [] currentRecord.alternates.append(substitute) # standard behavior else: currentRecord.saveState(currentRecord.glyphName) currentRecord.glyphName = substitute processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedSub
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType3, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.AlternateSet = [] for glyphName, alternates in subtable.alternates.items(): coverage.append(glyphName) alternateSet = AlternateSet().loadFromFontTools(alternates) self.AlternateSet.append(alternateSet) self.Coverage = Coverage().loadFromFontTools(coverage) self.AlternateSetCount = len(self.AlternateSet) return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType8Format2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.BacktrackClassDef = ClassDef().loadFromFontTools(subtable.BacktrackClassDef) self.InputClassDef = ClassDef().loadFromFontTools(subtable.InputClassDef) self.LookAheadClassDef = ClassDef().loadFromFontTools(subtable.LookAheadClassDef) self.ChainPosClassSet = [] for chainPosClassSet in subtable.ChainPosClassSet: if chainPosClassSet is None: self.ChainPosClassSet.append(None) else: self.ChainPosClassSet.append(ChainPosClassSet().loadFromFontTools(chainPosClassSet)) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType5Format3, self).loadFromFontTools(subtable, lookup) self.Coverage = [ Coverage().loadFromFontTools(coverage) for coverage in subtable.Coverage ] self.GlyphCount = subtable.GlyphCount self.SubstCount = subtable.SubstCount self.SubstLookupRecord = [ SubstLookupRecord().loadFromFontTools(record) for record in subtable.SubstLookupRecord ] return self
class GSUBLookupType1Format2(BaseSubTable): """ Deviation from spec: - fontTools interprets Lookup Type 1 formats 1 and 2 into the same object structure. As such, only format 2 is needed. - GlyphCount attribute is not implemented. """ __slots__ = ["Coverage", "Substitute"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType1Format2, self).__init__() self.SubstFormat = 2 self.Substitute = [] self.Coverage = None def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType1Format2, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.Substitute = [] for glyphName, alternate in sorted(subtable.mapping.items()): coverage.append(glyphName) self.Substitute.append(alternate) self.Coverage = Coverage().loadFromFontTools(coverage) return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): performedSub = True index = self.Coverage.index(currentGlyph) substitute = self.Substitute[index] # special behavior for aalt if featureTag == "aalt": if currentRecord._alternatesReference != currentGlyph: currentRecord._alternatesReference = currentGlyph currentRecord.alternates = [] currentRecord.alternates.append(substitute) # standard behavior else: currentRecord.saveState(currentRecord.glyphName) currentRecord.glyphName = substitute processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedSub
class GSUBLookupType2(BaseSubTable): """ Deviation from spec: - SequenceCount attribute is not implemented. """ __slots__ = ["Coverage", "Sequence"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType2, self).__init__() self.SubstFormat = 1 self.Coverage = None self.Sequence = [] def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType2, self).loadFromFontTools(subtable, lookup) try: self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.Sequence = [ Sequence().loadFromFontTools(sequence) for sequence in subtable.Sequence ] except AttributeError: # the API for MultipleSubst lookups changed with fonttools 3.1: # https://github.com/fonttools/fonttools/pull/364 mapping = getattr(subtable, "mapping", {}) coverage = sorted(mapping.keys()) self.Coverage = Coverage(coverage) self.Sequence = [Sequence(mapping[glyph]) for glyph in coverage] return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): # XXX all glyph subsitituion states are destroyed here performedSub = True index = self.Coverage.index(currentGlyph) sequence = self.Sequence[index] substitute = sequence.Substitute substitute = glyphNamesToGlyphRecords(substitute) processed.extend(substitute) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedSub
class GPOSLookupType1Format2(BaseSubTable): """ Deviation from spec: - ValueCount attribute is not implemented. XXX need to handle ValueFormat? """ __slots__ = ["Coverage", "ValueFormat", "Value"] + globalPositionSubTableSlots def __init__(self): super(GPOSLookupType1Format2, self).__init__() self.PosFormat = 2 self.Coverage = None self.ValueFormat = None self.Value = [] def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType1Format2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ValueFormat = subtable.ValueFormat self.Value = [ValueRecord().loadFromFontTools(value) for value in subtable.Value] return self def process(self, processed, glyphRecords, featureTag): performedPos = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): performedPos = True valueIndex = self.Coverage.index(currentGlyph) value = self.Value[valueIndex] currentRecord += value processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedPos
class GSUBLookupType2(BaseSubTable): """ Deviation from spec: - SequenceCount attribute is not implemented. """ __slots__ = ["Coverage", "Sequence"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType2, self).__init__() self.SubstFormat = 1 self.Coverage = None self.Sequence = [] def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.Sequence = [Sequence().loadFromFontTools(sequence) for sequence in subtable.Sequence] return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): # XXX all glyph subsitituion states are destroyed here performedSub = True index = self.Coverage.index(currentGlyph) sequence = self.Sequence[index] substitute = sequence.Substitute substitute = glyphNamesToGlyphRecords(substitute) processed.extend(substitute) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedSub
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType3, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.EntryExitRecord = [EntryExitRecord().loadFromFontTools(entryExitRecord) for entryExitRecord in subtable.EntryExitRecord] return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType7Format1, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.PosRuleSet = [PosRuleSet().loadFromFontTools(posRuleSet) for posRuleSet in subtable.PosRuleSet] return self
class GSUBLookupType4(BaseSubTable): """ Deviation from spec: - LigSetCount attribute is not implemented. """ __slots__ = ["Coverage", "LigatureSet"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType4, self).__init__() self.SubstFormat = 1 self.LigatureSet = [] self.Coverage = None def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType4, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.LigatureSet = [] for glyphName, ligature in subtable.ligatures.items(): ligatureSet = LigatureSet().loadFromFontTools(ligature) self.LigatureSet.append(ligatureSet) coverage.append(glyphName) self.Coverage = Coverage().loadFromFontTools(coverage) return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName lookupFlag = self._lookup().LookupFlag if currentGlyph in self.Coverage: if not lookupFlag.coversGlyph(currentGlyph): while not performedSub: coverageIndex = self.Coverage.index(currentGlyph) ligatureSet = self.LigatureSet[coverageIndex] for ligature in ligatureSet.Ligature: component = ligature.Component componentCount = ligature.CompCount currentComponentIndex = 0 matchedRecordIndexes = set() lastWasMatch = False for index, glyphRecord in enumerate(glyphRecords[1:]): glyphName = glyphRecord.glyphName if not lookupFlag.coversGlyph(glyphName): if not glyphName == component[currentComponentIndex]: lastWasMatch = False break else: lastWasMatch = True matchedRecordIndexes.add(index) currentComponentIndex += 1 if currentComponentIndex == componentCount - 1: break if lastWasMatch and currentComponentIndex == componentCount - 1: performedSub = True currentRecord.saveState([currentGlyph] + ligature.Component) currentRecord.glyphName = ligature.LigGlyph currentRecord.ligatureComponents = [currentGlyph] + ligature.Component processed.append(currentRecord) glyphRecords = [record for index, record in enumerate(glyphRecords[1:]) if index not in matchedRecordIndexes] break break return processed, glyphRecords, performedSub
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType1Format1, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ValueFormat = subtable.ValueFormat self.Value = ValueRecord().loadFromFontTools(subtable.Value) return self
class GPOSLookupType6(BaseSubTable): """ Deviation from spec: - ClassCount attribute is not implemented. Note: This could process things in a buggy way. Not enough test cases are available to know for sure. """ __slots__ = ["Mark1Coverage", "Mark1Array", "Mark2Coverage", "Mark2Array"] + globalPositionSubTableSlots def __init__(self): super(GPOSLookupType6, self).__init__() self.Mark1Coverage = None self.Mark2Coverage = None self.Mark1Array = None self.Mark2Array = None def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType6, self).loadFromFontTools(subtable, lookup) self.Mark1Coverage = Coverage().loadFromFontTools(subtable.Mark1Coverage) self.Mark2Coverage = Coverage().loadFromFontTools(subtable.Mark2Coverage) self.Mark1Array = MarkArray().loadFromFontTools(subtable.Mark1Array) self.Mark2Array = Mark2Array().loadFromFontTools(subtable.Mark2Array) return self def process(self, processed, glyphRecords, featureTag): performedPos = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.Mark1Coverage: if not self._lookupFlagCoversGlyph(currentGlyph): previousRecord = None previousRecordIndex = 0 gdef = self._lookup()._gdef while previousRecord is None: for _previousRecord in reversed(processed): previousRecordIndex -= 1 _previousGlyph = _previousRecord.glyphName if not self._lookupFlagCoversGlyph(_previousGlyph): previousRecord = _previousRecord break break if previousRecord is not None: previousGlyph = previousRecord.glyphName if previousGlyph in self.Mark2Coverage: performedPos = True mark1CoverageIndex = self.Mark1Coverage.index(currentGlyph) mark1Record = self.Mark1Array.MarkRecord[mark1CoverageIndex] mark1Anchor = mark1Record.MarkAnchor mark2CoverageIndex = self.Mark2Coverage.index(previousGlyph) mark2Record = self.Mark2Array.Mark2Record[mark2CoverageIndex] mark2Anchor = mark2Record.Mark2Anchor[mark1Record.Class] xOffset, yOffset = _calculateAnchorDifference(mark2Anchor, mark1Anchor) currentRecord.xPlacement += xOffset - previousRecord.advanceWidth currentRecord.yPlacement += yOffset - previousRecord.advanceHeight processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedPos
class GSUBLookupType4(BaseSubTable): """ Deviation from spec: - LigSetCount attribute is not implemented. """ __slots__ = ["Coverage", "LigatureSet"] + globalSubstitutionSubTableSlots def __init__(self): super(GSUBLookupType4, self).__init__() self.SubstFormat = 1 self.LigatureSet = [] self.Coverage = None def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType4, self).loadFromFontTools(subtable, lookup) # fontTools has a custom implementation of this # subtable type, so it needs to be converted coverage = [] self.LigatureSet = [] for glyphName, ligature in subtable.ligatures.items(): ligatureSet = LigatureSet().loadFromFontTools(ligature) self.LigatureSet.append(ligatureSet) coverage.append(glyphName) self.Coverage = Coverage().loadFromFontTools(coverage) return self def process(self, processed, glyphRecords, featureTag): performedSub = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName lookupFlag = self._lookup().LookupFlag if currentGlyph in self.Coverage: if not lookupFlag.coversGlyph(currentGlyph): while not performedSub: coverageIndex = self.Coverage.index(currentGlyph) ligatureSet = self.LigatureSet[coverageIndex] for ligature in ligatureSet.Ligature: component = ligature.Component componentCount = ligature.CompCount currentComponentIndex = 0 matchedRecordIndexes = set() lastWasMatch = False for index, glyphRecord in enumerate(glyphRecords[1:]): glyphName = glyphRecord.glyphName if not lookupFlag.coversGlyph(glyphName): if not glyphName == component[ currentComponentIndex]: lastWasMatch = False break else: lastWasMatch = True matchedRecordIndexes.add(index) currentComponentIndex += 1 if currentComponentIndex == componentCount - 1: break if lastWasMatch and currentComponentIndex == componentCount - 1: performedSub = True currentRecord.saveState([currentGlyph] + ligature.Component) currentRecord.glyphName = ligature.LigGlyph currentRecord.ligatureComponents = [ currentGlyph ] + ligature.Component processed.append(currentRecord) glyphRecords = [ record for index, record in enumerate( glyphRecords[1:]) if index not in matchedRecordIndexes ] break break return processed, glyphRecords, performedSub
class GPOSLookupType5(BaseSubTable): """ Deviation from spec: - ClassCount attribute is not implemented. Note: This could process things in a buggy way. Not enough test cases are available to know for sure. """ __slots__ = ["MarkCoverage", "LigatureCoverage", "MarkArray", "LigatureArray"] + globalPositionSubTableSlots def __init__(self): super(GPOSLookupType5, self).__init__() self.MarkCoverage = None self.LigatureCoverage = None self.MarkArray = None self.LigatureArray = None def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType5, self).loadFromFontTools(subtable, lookup) self.MarkCoverage = Coverage().loadFromFontTools(subtable.MarkCoverage) self.LigatureCoverage = Coverage().loadFromFontTools(subtable.LigatureCoverage) self.MarkArray = MarkArray().loadFromFontTools(subtable.MarkArray) self.LigatureArray = LigatureArray().loadFromFontTools(subtable.LigatureArray) return self def process(self, processed, glyphRecords, featureTag): performedPos = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.MarkCoverage: if not self._lookupFlagCoversGlyph(currentGlyph): previousRecord = None previousRecordIndex = 0 gdef = self._lookup()._gdef # look back to find the most recent glyph that: # 1. is not covered by the lookup flag # 2. is not a mark glyph (as defined in the GDEF) while previousRecord is None: for _previousRecord in reversed(processed): previousRecordIndex -= 1 _previousGlyph = _previousRecord.glyphName if not self._lookupFlagCoversGlyph(_previousGlyph): if gdef is not None and gdef.GlyphClassDef[_previousGlyph] != 3: previousRecord = _previousRecord break break if previousRecord is not None: previousGlyph = previousRecord.glyphName if previousGlyph in self.LigatureCoverage: performedPos = True markCoverageIndex = self.MarkCoverage.index(currentGlyph) markRecord = self.MarkArray.MarkRecord[markCoverageIndex] markAnchor = markRecord.MarkAnchor ligatureCoverageIndex = self.LigatureCoverage.index(previousGlyph) ligatureAttach = self.LigatureArray.LigatureAttach[ligatureCoverageIndex] componentIndex = abs(previousRecordIndex) - 1 componentRecord = ligatureAttach.ComponentRecord[componentIndex] ligatureAnchor = componentRecord.LigatureAnchor[markRecord.Class] if ligatureAnchor is not None: xOffset, yOffset = _calculateAnchorDifference(ligatureAnchor, markAnchor) currentRecord.xPlacement += xOffset - previousRecord.advanceWidth currentRecord.yPlacement += yOffset - previousRecord.advanceHeight processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedPos
def loadFromFontTools(self, attachList): self.Coverage = Coverage().loadFromFontTools(attachList.Coverage) for attachPoint in attachList.AttachPoint: attachPoint = AttachPoint().loadFromFontTools(attachPoint) self.AttachPoint.append(attachPoint) return self
def loadFromFontTools(self, subtable, lookup): super(GSUBLookupType2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.Sequence = [Sequence().loadFromFontTools(sequence) for sequence in subtable.Sequence] return self
def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType1Format2, self).loadFromFontTools(subtable, lookup) self.Coverage = Coverage().loadFromFontTools(subtable.Coverage) self.ValueFormat = subtable.ValueFormat self.Value = [ValueRecord().loadFromFontTools(value) for value in subtable.Value] return self
def loadFromFontTools(self, ligCaretList): self.Coverage = Coverage().loadFromFontTools(ligCaretList.Coverage) for ligGlyph in ligCaretList.LigGlyph: ligGlyph = LigGlyph().loadFromFontTools(ligGlyph) self.LigGlyph.append(ligGlyph) return self
class GPOSLookupType4(BaseSubTable): """ Deviation from spec: - ClassCount attribute is not implemented. """ __slots__ = ["MarkCoverage", "BaseCoverage", "MarkArray", "BaseArray"] + globalPositionSubTableSlots def __init__(self): super(GPOSLookupType4, self).__init__() self.MarkCoverage = None self.BaseCoverage = None self.MarkArray = None self.BaseArray = None def loadFromFontTools(self, subtable, lookup): super(GPOSLookupType4, self).loadFromFontTools(subtable, lookup) self.MarkCoverage = Coverage().loadFromFontTools(subtable.MarkCoverage) self.BaseCoverage = Coverage().loadFromFontTools(subtable.BaseCoverage) self.MarkArray = MarkArray().loadFromFontTools(subtable.MarkArray) self.BaseArray = BaseArray().loadFromFontTools(subtable.BaseArray) return self def process(self, processed, glyphRecords, featureTag): performedPos = False currentRecord = glyphRecords[0] currentGlyph = currentRecord.glyphName if currentGlyph in self.MarkCoverage: if not self._lookupFlagCoversGlyph(currentGlyph): previousRecord = None previousRecordIndex = 0 gdef = self._lookup()._gdef # look back to find the most recent glyph that: # 1. is not covered by the lookup flag # 2. is not a mark glyph (as defined in the GDEF) while previousRecord is None: for _previousRecord in reversed(processed): previousRecordIndex -= 1 _previousGlyph = _previousRecord.glyphName if not self._lookupFlagCoversGlyph(_previousGlyph): if gdef is not None and gdef.GlyphClassDef[_previousGlyph] != 3: previousRecord = _previousRecord break break if previousRecord is not None: previousGlyph = previousRecord.glyphName if previousGlyph in self.BaseCoverage: performedPos = True markCoverageIndex = self.MarkCoverage.index(currentGlyph) markRecord = self.MarkArray.MarkRecord[markCoverageIndex] markAnchor = markRecord.MarkAnchor baseCoverageIndex = self.BaseCoverage.index(previousGlyph) baseRecord = self.BaseArray.BaseRecord[baseCoverageIndex] baseAnchor = baseRecord.BaseAnchor[markRecord.Class] xOffset, yOffset = _calculateAnchorDifference(baseAnchor, markAnchor) currentRecord.xPlacement += xOffset - previousRecord.advanceWidth currentRecord.yPlacement += yOffset - previousRecord.advanceHeight processed.append(currentRecord) glyphRecords = glyphRecords[1:] return processed, glyphRecords, performedPos