git.lucas.co / go_mono
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 }