git clone https://git.lucas.co/go_mono.git
font/sfnt/truetype.go (14.8K)
1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package sfnt
6
7 import (
8 "golang.org/x/image/math/fixed"
9 )
10
11 // Flags for simple (non-compound) glyphs.
12 //
13 // See https://www.microsoft.com/typography/OTSPEC/glyf.htm
14 const (
15 flagOnCurve = 1 << 0 // 0x0001
16 flagXShortVector = 1 << 1 // 0x0002
17 flagYShortVector = 1 << 2 // 0x0004
18 flagRepeat = 1 << 3 // 0x0008
19
20 // The same flag bits are overloaded to have two meanings, dependent on the
21 // value of the flag{X,Y}ShortVector bits.
22 flagPositiveXShortVector = 1 << 4 // 0x0010
23 flagThisXIsSame = 1 << 4 // 0x0010
24 flagPositiveYShortVector = 1 << 5 // 0x0020
25 flagThisYIsSame = 1 << 5 // 0x0020
26 )
27
28 // Flags for compound glyphs.
29 //
30 // See https://www.microsoft.com/typography/OTSPEC/glyf.htm
31 const (
32 flagArg1And2AreWords = 1 << 0 // 0x0001
33 flagArgsAreXYValues = 1 << 1 // 0x0002
34 flagRoundXYToGrid = 1 << 2 // 0x0004
35 flagWeHaveAScale = 1 << 3 // 0x0008
36 flagReserved4 = 1 << 4 // 0x0010
37 flagMoreComponents = 1 << 5 // 0x0020
38 flagWeHaveAnXAndYScale = 1 << 6 // 0x0040
39 flagWeHaveATwoByTwo = 1 << 7 // 0x0080
40 flagWeHaveInstructions = 1 << 8 // 0x0100
41 flagUseMyMetrics = 1 << 9 // 0x0200
42 flagOverlapCompound = 1 << 10 // 0x0400
43 flagScaledComponentOffset = 1 << 11 // 0x0800
44 flagUnscaledComponentOffset = 1 << 12 // 0x1000
45 )
46
47 func midPoint(p, q fixed.Point26_6) fixed.Point26_6 {
48 return fixed.Point26_6{
49 X: (p.X + q.X) / 2,
50 Y: (p.Y + q.Y) / 2,
51 }
52 }
53
54 func parseLoca(src *source, loca table, glyfOffset uint32, indexToLocFormat bool, numGlyphs int32) (locations []uint32, err error) {
55 if indexToLocFormat {
56 if loca.length != 4*uint32(numGlyphs+1) {
57 return nil, errInvalidLocaTable
58 }
59 } else {
60 if loca.length != 2*uint32(numGlyphs+1) {
61 return nil, errInvalidLocaTable
62 }
63 }
64
65 locations = make([]uint32, numGlyphs+1)
66 buf, err := src.view(nil, int(loca.offset), int(loca.length))
67 if err != nil {
68 return nil, err
69 }
70
71 if indexToLocFormat {
72 for i := range locations {
73 locations[i] = 1*uint32(u32(buf[4*i:])) + glyfOffset
74 }
75 } else {
76 for i := range locations {
77 locations[i] = 2*uint32(u16(buf[2*i:])) + glyfOffset
78 }
79 }
80 return locations, nil
81 }
82
83 // https://www.microsoft.com/typography/OTSPEC/glyf.htm says that "Each
84 // glyph begins with the following [10 byte] header".
85 const glyfHeaderLen = 10
86
87 func loadGlyf(f *Font, b *Buffer, x GlyphIndex, stackBottom, recursionDepth uint32) error {
88 data, _, _, err := f.viewGlyphData(b, x)
89 if err != nil {
90 return err
91 }
92 if len(data) == 0 {
93 return nil
94 }
95 if len(data) < glyfHeaderLen {
96 return errInvalidGlyphData
97 }
98 index := glyfHeaderLen
99
100 numContours, numPoints := int16(u16(data)), 0
101 switch {
102 case numContours == -1:
103 // We have a compound glyph. No-op.
104 case numContours == 0:
105 return nil
106 case numContours > 0:
107 // We have a simple (non-compound) glyph.
108 index += 2 * int(numContours)
109 if index > len(data) {
110 return errInvalidGlyphData
111 }
112 // The +1 for numPoints is because the value in the file format is
113 // inclusive, but Go's slice[:index] semantics are exclusive.
114 numPoints = 1 + int(u16(data[index-2:]))
115 default:
116 return errInvalidGlyphData
117 }
118
119 if numContours < 0 {
120 return loadCompoundGlyf(f, b, data[glyfHeaderLen:], stackBottom, recursionDepth)
121 }
122
123 // Skip the hinting instructions.
124 index += 2
125 if index > len(data) {
126 return errInvalidGlyphData
127 }
128 hintsLength := int(u16(data[index-2:]))
129 index += hintsLength
130 if index > len(data) {
131 return errInvalidGlyphData
132 }
133
134 // For simple (non-compound) glyphs, the remainder of the glyf data
135 // consists of (flags, x, y) points: the Bézier curve segments. These are
136 // stored in columns (all the flags first, then all the x coordinates, then
137 // all the y coordinates), not rows, as it compresses better.
138 //
139 // Decoding those points in row order involves two passes. The first pass
140 // determines the indexes (relative to the data slice) of where the flags,
141 // the x coordinates and the y coordinates each start.
142 flagIndex := int32(index)
143 xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
144 if !ok {
145 return errInvalidGlyphData
146 }
147
148 // The second pass decodes each (flags, x, y) tuple in row order.
149 g := glyfIter{
150 data: data,
151 flagIndex: flagIndex,
152 xIndex: xIndex,
153 yIndex: yIndex,
154 endIndex: glyfHeaderLen,
155 // The -1 on prevEnd and finalEnd are because the contour-end index in
156 // the file format is inclusive, but Go's slice[:index] is exclusive.
157 prevEnd: -1,
158 finalEnd: int32(numPoints - 1),
159 numContours: int32(numContours),
160 }
161 for g.nextContour() {
162 for g.nextSegment() {
163 b.segments = append(b.segments, g.seg)
164 }
165 }
166 return g.err
167 }
168
169 func findXYIndexes(data []byte, index, numPoints int) (xIndex, yIndex int32, ok bool) {
170 xDataLen := 0
171 yDataLen := 0
172 for i := 0; ; {
173 if i > numPoints {
174 return 0, 0, false
175 }
176 if i == numPoints {
177 break
178 }
179
180 repeatCount := 1
181 if index >= len(data) {
182 return 0, 0, false
183 }
184 flag := data[index]
185 index++
186 if flag&flagRepeat != 0 {
187 if index >= len(data) {
188 return 0, 0, false
189 }
190 repeatCount += int(data[index])
191 index++
192 }
193
194 xSize := 0
195 if flag&flagXShortVector != 0 {
196 xSize = 1
197 } else if flag&flagThisXIsSame == 0 {
198 xSize = 2
199 }
200 xDataLen += xSize * repeatCount
201
202 ySize := 0
203 if flag&flagYShortVector != 0 {
204 ySize = 1
205 } else if flag&flagThisYIsSame == 0 {
206 ySize = 2
207 }
208 yDataLen += ySize * repeatCount
209
210 i += repeatCount
211 }
212 if index+xDataLen+yDataLen > len(data) {
213 return 0, 0, false
214 }
215 return int32(index), int32(index + xDataLen), true
216 }
217
218 func loadCompoundGlyf(f *Font, b *Buffer, data []byte, stackBottom, recursionDepth uint32) error {
219 if recursionDepth++; recursionDepth == maxCompoundRecursionDepth {
220 return errUnsupportedCompoundGlyph
221 }
222
223 // Read and process the compound glyph's components. They are two separate
224 // for loops, since reading parses the elements of the data slice, and
225 // processing can overwrite the backing array.
226
227 stackTop := stackBottom
228 for {
229 if stackTop >= maxCompoundStackSize {
230 return errUnsupportedCompoundGlyph
231 }
232 elem := &b.compoundStack[stackTop]
233 stackTop++
234
235 if len(data) < 4 {
236 return errInvalidGlyphData
237 }
238 flags := u16(data)
239 elem.glyphIndex = GlyphIndex(u16(data[2:]))
240 if flags&flagArg1And2AreWords == 0 {
241 if len(data) < 6 {
242 return errInvalidGlyphData
243 }
244 elem.dx = int16(int8(data[4]))
245 elem.dy = int16(int8(data[5]))
246 data = data[6:]
247 } else {
248 if len(data) < 8 {
249 return errInvalidGlyphData
250 }
251 elem.dx = int16(u16(data[4:]))
252 elem.dy = int16(u16(data[6:]))
253 data = data[8:]
254 }
255
256 if flags&flagArgsAreXYValues == 0 {
257 return errUnsupportedCompoundGlyph
258 }
259 elem.hasTransform = flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0
260 if elem.hasTransform {
261 switch {
262 case flags&flagWeHaveAScale != 0:
263 if len(data) < 2 {
264 return errInvalidGlyphData
265 }
266 elem.transformXX = int16(u16(data))
267 elem.transformXY = 0
268 elem.transformYX = 0
269 elem.transformYY = elem.transformXX
270 data = data[2:]
271 case flags&flagWeHaveAnXAndYScale != 0:
272 if len(data) < 4 {
273 return errInvalidGlyphData
274 }
275 elem.transformXX = int16(u16(data[0:]))
276 elem.transformXY = 0
277 elem.transformYX = 0
278 elem.transformYY = int16(u16(data[2:]))
279 data = data[4:]
280 case flags&flagWeHaveATwoByTwo != 0:
281 if len(data) < 8 {
282 return errInvalidGlyphData
283 }
284 elem.transformXX = int16(u16(data[0:]))
285 elem.transformXY = int16(u16(data[2:]))
286 elem.transformYX = int16(u16(data[4:]))
287 elem.transformYY = int16(u16(data[6:]))
288 data = data[8:]
289 }
290 }
291
292 if flags&flagMoreComponents == 0 {
293 break
294 }
295 }
296
297 // To support hinting, we'd have to save the remaining bytes in data here
298 // and interpret them after the for loop below, since that for loop's
299 // loadGlyf calls can overwrite the backing array.
300
301 for i := stackBottom; i < stackTop; i++ {
302 elem := &b.compoundStack[i]
303 base := len(b.segments)
304 if err := loadGlyf(f, b, elem.glyphIndex, stackTop, recursionDepth); err != nil {
305 return err
306 }
307 dx, dy := fixed.Int26_6(elem.dx), fixed.Int26_6(elem.dy)
308 segments := b.segments[base:]
309 if elem.hasTransform {
310 txx := elem.transformXX
311 txy := elem.transformXY
312 tyx := elem.transformYX
313 tyy := elem.transformYY
314 for j := range segments {
315 transformArgs(&segments[j].Args, txx, txy, tyx, tyy, dx, dy)
316 }
317 } else {
318 for j := range segments {
319 translateArgs(&segments[j].Args, dx, dy)
320 }
321 }
322 }
323
324 return nil
325 }
326
327 type glyfIter struct {
328 data []byte
329 err error
330
331 // Various indices into the data slice. See the "Decoding those points in
332 // row order" comment above.
333 flagIndex int32
334 xIndex int32
335 yIndex int32
336
337 // endIndex points to the uint16 that is the inclusive point index of the
338 // current contour's end. prevEnd is the previous contour's end. finalEnd
339 // should match the final contour's end.
340 endIndex int32
341 prevEnd int32
342 finalEnd int32
343
344 // c and p count the current contour and point, up to numContours and
345 // numPoints.
346 c, numContours int32
347 p, nPoints int32
348
349 // The next two groups of fields track points and segments. Points are what
350 // the underlying file format provides. Bézier curve segments are what the
351 // rasterizer consumes.
352 //
353 // Points are either on-curve or off-curve. Two consecutive on-curve points
354 // define a linear curve segment between them. N off-curve points between
355 // on-curve points define N quadratic curve segments. The TrueType glyf
356 // format does not use cubic curves. If N is greater than 1, some of these
357 // segment end points are implicit, the midpoint of two off-curve points.
358 // Given the points A, B1, B2, ..., BN, C, where A and C are on-curve and
359 // all the Bs are off-curve, the segments are:
360 //
361 // - A, B1, midpoint(B1, B2)
362 // - midpoint(B1, B2), B2, midpoint(B2, B3)
363 // - midpoint(B2, B3), B3, midpoint(B3, B4)
364 // - ...
365 // - midpoint(BN-1, BN), BN, C
366 //
367 // Note that the sequence of Bs may wrap around from the last point in the
368 // glyf data to the first. A and C may also be the same point (the only
369 // explicit on-curve point), or there may be no explicit on-curve points at
370 // all (but still implicit ones between explicit off-curve points).
371
372 // Points.
373 x, y int16
374 on bool
375 flag uint8
376 repeats uint8
377
378 // Segments.
379 closing bool
380 closed bool
381 firstOnCurveValid bool
382 firstOffCurveValid bool
383 lastOffCurveValid bool
384 firstOnCurve fixed.Point26_6
385 firstOffCurve fixed.Point26_6
386 lastOffCurve fixed.Point26_6
387 seg Segment
388 }
389
390 func (g *glyfIter) nextContour() (ok bool) {
391 if g.c == g.numContours {
392 if g.prevEnd != g.finalEnd {
393 g.err = errInvalidGlyphData
394 }
395 return false
396 }
397 g.c++
398
399 end := int32(u16(g.data[g.endIndex:]))
400 g.endIndex += 2
401 if (end <= g.prevEnd) || (g.finalEnd < end) {
402 g.err = errInvalidGlyphData
403 return false
404 }
405 g.nPoints = end - g.prevEnd
406 g.p = 0
407 g.prevEnd = end
408
409 g.closing = false
410 g.closed = false
411 g.firstOnCurveValid = false
412 g.firstOffCurveValid = false
413 g.lastOffCurveValid = false
414
415 return true
416 }
417
418 func (g *glyfIter) close() {
419 switch {
420 case !g.firstOffCurveValid && !g.lastOffCurveValid:
421 g.closed = true
422 g.seg = Segment{
423 Op: SegmentOpLineTo,
424 Args: [3]fixed.Point26_6{g.firstOnCurve},
425 }
426 case !g.firstOffCurveValid && g.lastOffCurveValid:
427 g.closed = true
428 g.seg = Segment{
429 Op: SegmentOpQuadTo,
430 Args: [3]fixed.Point26_6{g.lastOffCurve, g.firstOnCurve},
431 }
432 case g.firstOffCurveValid && !g.lastOffCurveValid:
433 g.closed = true
434 g.seg = Segment{
435 Op: SegmentOpQuadTo,
436 Args: [3]fixed.Point26_6{g.firstOffCurve, g.firstOnCurve},
437 }
438 case g.firstOffCurveValid && g.lastOffCurveValid:
439 g.lastOffCurveValid = false
440 g.seg = Segment{
441 Op: SegmentOpQuadTo,
442 Args: [3]fixed.Point26_6{
443 g.lastOffCurve,
444 midPoint(g.lastOffCurve, g.firstOffCurve),
445 },
446 }
447 }
448 }
449
450 func (g *glyfIter) nextSegment() (ok bool) {
451 for !g.closed {
452 if g.closing || !g.nextPoint() {
453 g.closing = true
454 g.close()
455 return true
456 }
457
458 // Convert the tuple (g.x, g.y) to a fixed.Point26_6, since the latter
459 // is what's held in a Segment. The input (g.x, g.y) is a pair of int16
460 // values, measured in font units, since that is what the underlying
461 // format provides. The output is a pair of fixed.Int26_6 values. A
462 // fixed.Int26_6 usually represents a 26.6 fixed number of pixels, but
463 // this here is just a straight numerical conversion, with no scaling
464 // factor. A later step scales the Segment.Args values by such a factor
465 // to convert e.g. 1792 font units to 10.5 pixels at 2048 font units
466 // per em and 12 ppem (pixels per em).
467 p := fixed.Point26_6{
468 X: fixed.Int26_6(g.x),
469 Y: fixed.Int26_6(g.y),
470 }
471
472 if !g.firstOnCurveValid {
473 if g.on {
474 g.firstOnCurve = p
475 g.firstOnCurveValid = true
476 g.seg = Segment{
477 Op: SegmentOpMoveTo,
478 Args: [3]fixed.Point26_6{p},
479 }
480 return true
481 } else if !g.firstOffCurveValid {
482 g.firstOffCurve = p
483 g.firstOffCurveValid = true
484 continue
485 } else {
486 g.firstOnCurve = midPoint(g.firstOffCurve, p)
487 g.firstOnCurveValid = true
488 g.lastOffCurve = p
489 g.lastOffCurveValid = true
490 g.seg = Segment{
491 Op: SegmentOpMoveTo,
492 Args: [3]fixed.Point26_6{g.firstOnCurve},
493 }
494 return true
495 }
496
497 } else if !g.lastOffCurveValid {
498 if !g.on {
499 g.lastOffCurve = p
500 g.lastOffCurveValid = true
501 continue
502 } else {
503 g.seg = Segment{
504 Op: SegmentOpLineTo,
505 Args: [3]fixed.Point26_6{p},
506 }
507 return true
508 }
509
510 } else {
511 if !g.on {
512 g.seg = Segment{
513 Op: SegmentOpQuadTo,
514 Args: [3]fixed.Point26_6{
515 g.lastOffCurve,
516 midPoint(g.lastOffCurve, p),
517 },
518 }
519 g.lastOffCurve = p
520 g.lastOffCurveValid = true
521 return true
522 } else {
523 g.seg = Segment{
524 Op: SegmentOpQuadTo,
525 Args: [3]fixed.Point26_6{g.lastOffCurve, p},
526 }
527 g.lastOffCurveValid = false
528 return true
529 }
530 }
531 }
532 return false
533 }
534
535 func (g *glyfIter) nextPoint() (ok bool) {
536 if g.p == g.nPoints {
537 return false
538 }
539 g.p++
540
541 if g.repeats > 0 {
542 g.repeats--
543 } else {
544 g.flag = g.data[g.flagIndex]
545 g.flagIndex++
546 if g.flag&flagRepeat != 0 {
547 g.repeats = g.data[g.flagIndex]
548 g.flagIndex++
549 }
550 }
551
552 if g.flag&flagXShortVector != 0 {
553 if g.flag&flagPositiveXShortVector != 0 {
554 g.x += int16(g.data[g.xIndex])
555 } else {
556 g.x -= int16(g.data[g.xIndex])
557 }
558 g.xIndex += 1
559 } else if g.flag&flagThisXIsSame == 0 {
560 g.x += int16(u16(g.data[g.xIndex:]))
561 g.xIndex += 2
562 }
563
564 if g.flag&flagYShortVector != 0 {
565 if g.flag&flagPositiveYShortVector != 0 {
566 g.y += int16(g.data[g.yIndex])
567 } else {
568 g.y -= int16(g.data[g.yIndex])
569 }
570 g.yIndex += 1
571 } else if g.flag&flagThisYIsSame == 0 {
572 g.y += int16(u16(g.data[g.yIndex:]))
573 g.yIndex += 2
574 }
575
576 g.on = g.flag&flagOnCurve != 0
577 return true
578 }