classes.c15_kern_table

 1from fontTools.ttLib import TTFont
 2
 3
 4class KKernTable:
 5    def __init__(self, fontPath: str):
 6        self.fontPath = fontPath
 7        self.font = TTFont(fontPath)
 8        self.kerningPairs = self.prepareKerningTable()
 9
10    def prepareKerningTable(self):
11        """Prepare kerning data structure for quick lookup."""
12        kerning = {}
13        if "GPOS" not in self.font:
14            print("No GPOS table found")
15            self.kerningPairs = kerning
16            return
17
18        gpos = self.font["GPOS"].table
19        for lookup in gpos.LookupList.Lookup:
20            if lookup.LookupType == 2:  # Pair Adjustment
21                for subtable in lookup.SubTable:
22                    # Format 1: PairSet
23                    if (
24                        hasattr(subtable, "Format")
25                        and subtable.Format == 1
26                        and hasattr(subtable, "PairSet")
27                    ):
28                        left_glyphs = subtable.Coverage.glyphs
29                        for idx, left in enumerate(left_glyphs):
30                            pairSet = subtable.PairSet[idx]
31                            for pairValueRecord in pairSet.PairValueRecord:
32                                right = pairValueRecord.SecondGlyph
33                                value = pairValueRecord.Value1.XAdvance or 0
34                                kerning[(left, right)] = value
35                    # Format 2: Class-based
36                    elif (
37                        hasattr(subtable, "Format")
38                        and subtable.Format == 2
39                        and hasattr(subtable, "Class1Record")
40                    ):
41                        classDef1 = subtable.ClassDef1.classDefs
42                        classDef2 = subtable.ClassDef2.classDefs
43                        class1Records = subtable.Class1Record
44                        for left, class1 in classDef1.items():
45                            for right, class2 in classDef2.items():
46                                valueRecord = class1Records[class1].Class2Record[class2]
47                                if valueRecord.Value1 and valueRecord.Value1.XAdvance:
48                                    value = valueRecord.Value1.XAdvance
49                                    kerning[(left, right)] = value
50        return kerning
51
52    def findKerningForPair(self, left: str, right: str) -> int | None:
53        """Quickly look up kerning value for a given glyph pair."""
54        return self.kerningPairs.get((left, right))
class KKernTable:
 5class KKernTable:
 6    def __init__(self, fontPath: str):
 7        self.fontPath = fontPath
 8        self.font = TTFont(fontPath)
 9        self.kerningPairs = self.prepareKerningTable()
10
11    def prepareKerningTable(self):
12        """Prepare kerning data structure for quick lookup."""
13        kerning = {}
14        if "GPOS" not in self.font:
15            print("No GPOS table found")
16            self.kerningPairs = kerning
17            return
18
19        gpos = self.font["GPOS"].table
20        for lookup in gpos.LookupList.Lookup:
21            if lookup.LookupType == 2:  # Pair Adjustment
22                for subtable in lookup.SubTable:
23                    # Format 1: PairSet
24                    if (
25                        hasattr(subtable, "Format")
26                        and subtable.Format == 1
27                        and hasattr(subtable, "PairSet")
28                    ):
29                        left_glyphs = subtable.Coverage.glyphs
30                        for idx, left in enumerate(left_glyphs):
31                            pairSet = subtable.PairSet[idx]
32                            for pairValueRecord in pairSet.PairValueRecord:
33                                right = pairValueRecord.SecondGlyph
34                                value = pairValueRecord.Value1.XAdvance or 0
35                                kerning[(left, right)] = value
36                    # Format 2: Class-based
37                    elif (
38                        hasattr(subtable, "Format")
39                        and subtable.Format == 2
40                        and hasattr(subtable, "Class1Record")
41                    ):
42                        classDef1 = subtable.ClassDef1.classDefs
43                        classDef2 = subtable.ClassDef2.classDefs
44                        class1Records = subtable.Class1Record
45                        for left, class1 in classDef1.items():
46                            for right, class2 in classDef2.items():
47                                valueRecord = class1Records[class1].Class2Record[class2]
48                                if valueRecord.Value1 and valueRecord.Value1.XAdvance:
49                                    value = valueRecord.Value1.XAdvance
50                                    kerning[(left, right)] = value
51        return kerning
52
53    def findKerningForPair(self, left: str, right: str) -> int | None:
54        """Quickly look up kerning value for a given glyph pair."""
55        return self.kerningPairs.get((left, right))
KKernTable(fontPath: str)
6    def __init__(self, fontPath: str):
7        self.fontPath = fontPath
8        self.font = TTFont(fontPath)
9        self.kerningPairs = self.prepareKerningTable()
fontPath
font
kerningPairs
def prepareKerningTable(self):
11    def prepareKerningTable(self):
12        """Prepare kerning data structure for quick lookup."""
13        kerning = {}
14        if "GPOS" not in self.font:
15            print("No GPOS table found")
16            self.kerningPairs = kerning
17            return
18
19        gpos = self.font["GPOS"].table
20        for lookup in gpos.LookupList.Lookup:
21            if lookup.LookupType == 2:  # Pair Adjustment
22                for subtable in lookup.SubTable:
23                    # Format 1: PairSet
24                    if (
25                        hasattr(subtable, "Format")
26                        and subtable.Format == 1
27                        and hasattr(subtable, "PairSet")
28                    ):
29                        left_glyphs = subtable.Coverage.glyphs
30                        for idx, left in enumerate(left_glyphs):
31                            pairSet = subtable.PairSet[idx]
32                            for pairValueRecord in pairSet.PairValueRecord:
33                                right = pairValueRecord.SecondGlyph
34                                value = pairValueRecord.Value1.XAdvance or 0
35                                kerning[(left, right)] = value
36                    # Format 2: Class-based
37                    elif (
38                        hasattr(subtable, "Format")
39                        and subtable.Format == 2
40                        and hasattr(subtable, "Class1Record")
41                    ):
42                        classDef1 = subtable.ClassDef1.classDefs
43                        classDef2 = subtable.ClassDef2.classDefs
44                        class1Records = subtable.Class1Record
45                        for left, class1 in classDef1.items():
46                            for right, class2 in classDef2.items():
47                                valueRecord = class1Records[class1].Class2Record[class2]
48                                if valueRecord.Value1 and valueRecord.Value1.XAdvance:
49                                    value = valueRecord.Value1.XAdvance
50                                    kerning[(left, right)] = value
51        return kerning

Prepare kerning data structure for quick lookup.

def findKerningForPair(self, left: str, right: str) -> int | None:
53    def findKerningForPair(self, left: str, right: str) -> int | None:
54        """Quickly look up kerning value for a given glyph pair."""
55        return self.kerningPairs.get((left, right))

Quickly look up kerning value for a given glyph pair.