-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkern_src.go
141 lines (121 loc) · 5 KB
/
kern_src.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package tables
import (
"encoding/binary"
"errors"
"fmt"
)
type KernSubtable interface {
// Data returns the actual kerning data
Data() KernData
}
type OTKernSubtableHeader struct {
version uint16 // Kern subtable version number
length uint16 // Length of the subtable, in bytes (including this header).
format kernSTVersion // What type of information is contained in this table.
Coverage byte // What type of information is contained in this table.
data KernData `unionField:"format"`
}
// check and return the length
func (st *OTKernSubtableHeader) parseEnd(src []byte) (int, error) {
if L, E := len(src), int(st.length); L < E {
return 0, fmt.Errorf("EOF: expected length: %d, got %d", E, L)
}
return int(st.length), nil
}
type AATKernSubtableHeader struct {
length uint32 // The length of this subtable in bytes, including this header.
Coverage byte // Circumstances under which this table is used.
version kernSTVersion
TupleCount uint16 // The tuple count. This value is only used with variation fonts and should be 0 for all other fonts. The subtable's tupleCount will be ignored if the 'kerx' table version is less than 4.
data KernData `unionField:"version"`
}
// check and return the length
func (st *AATKernSubtableHeader) parseEnd(src []byte) (int, error) {
if L, E := len(src), int(st.length); L < E {
return 0, fmt.Errorf("EOF: expected length: %d, got %d", E, L)
}
return int(st.length), nil
}
type KernData interface {
isKernData()
}
func (KernData0) isKernData() {}
func (KernData1) isKernData() {}
func (KernData2) isKernData() {}
func (KernData3) isKernData() {}
type kernSTVersion byte
const (
kernSTVersion0 kernSTVersion = iota
kernSTVersion1
kernSTVersion2
kernSTVersion3
)
type KernData0 struct {
nPairs uint16 // The number of kerning pairs in this subtable.
searchRange uint16 // The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable.
entrySelector uint16 // This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop.
rangeShift uint16 // The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied b
Pairs []Kernx0Record `arrayCount:"ComputedField-nPairs"`
}
type KernData1 struct {
AATStateTable
valueTable uint16 // Offset in bytes from the beginning of the subtable to the beginning of the kerning table.
Values []int16 `isOpaque:""`
}
func (kd *KernData1) parseValues(src []byte) error {
valuesOffset := int(kd.valueTable)
// start by resolving offset -> index
for i := range kd.Entries {
entry := &kd.Entries[i]
offset := int(entry.Flags & Kern1Offset)
if offset == 0 || offset < valuesOffset {
binary.BigEndian.PutUint16(entry.data[:], 0xFFFF)
} else {
index := uint16((offset - valuesOffset) / 2)
binary.BigEndian.PutUint16(entry.data[:], index)
}
}
var err error
kd.Values, err = parseKernx1Values(src, kd.Entries, valuesOffset, 0)
return err
}
type KernData2 struct {
rowWidth uint16 // The width, in bytes, of a row in the subtable.
Left AATLoopkup8Data `offsetSize:"Offset16" offsetRelativeTo:"Parent"`
Right AATLoopkup8Data `offsetSize:"Offset16" offsetRelativeTo:"Parent"`
KerningStart Offset16 // Offset from beginning of this subtable to the start of the kerning array.
KerningData []byte `isOpaque:"" offsetRelativeTo:"Parent"` // indexed by Left + Right
}
func (kd *KernData2) parseKerningData(_ []byte, parentSrc []byte) error {
kd.KerningData = parentSrc
return nil
}
type KernData3 struct {
glyphCount uint16 // The number of glyphs in this font.
kernValueCount uint8 // The number of kerning values.
leftClassCount uint8 // The number of left-hand classes.
RightClassCount uint8 // The number of right-hand classes.
flags uint8 // Set to zero (reserved for future use).
Kernings []int16 `arrayCount:"ComputedField-kernValueCount"`
LeftClass []uint8 `arrayCount:"ComputedField-glyphCount"`
RightClass []uint8 `arrayCount:"ComputedField-glyphCount"`
KernIndex []uint8 `arrayCount:"ComputedField-nKernIndex()"`
}
func (kd *KernData3) nKernIndex() int { return int(kd.leftClassCount) * int(kd.RightClassCount) }
// sanitize index and class values
func (kd *KernData3) parseEnd(_ []byte) (int, error) {
for _, index := range kd.KernIndex {
if index >= kd.kernValueCount {
return 0, errors.New("invalid kern subtable format 3 index value")
}
}
for i := range kd.LeftClass {
if kd.LeftClass[i] >= kd.leftClassCount {
return 0, errors.New("invalid kern subtable format 3 left class value")
}
if kd.RightClass[i] >= kd.RightClassCount {
return 0, errors.New("invalid kern subtable format 3 right class value")
}
}
return 0, nil
}