git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

font/sfnt/postscript.go (37.8K)

   1 // Copyright 2016 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 // Compact Font Format (CFF) fonts are written in PostScript, a stack-based
   8 // programming language.
   9 //
  10 // A fundamental concept is a DICT, or a key-value map, expressed in reverse
  11 // Polish notation. For example, this sequence of operations:
  12 //	- push the number 379
  13 //	- version operator
  14 //	- push the number 392
  15 //	- Notice operator
  16 //	- etc
  17 //	- push the number 100
  18 //	- push the number 0
  19 //	- push the number 500
  20 //	- push the number 800
  21 //	- FontBBox operator
  22 //	- etc
  23 // defines a DICT that maps "version" to the String ID (SID) 379, "Notice" to
  24 // the SID 392, "FontBBox" to the four numbers [100, 0, 500, 800], etc.
  25 //
  26 // The first 391 String IDs (starting at 0) are predefined as per the CFF spec
  27 // Appendix A, in 5176.CFF.pdf referenced below. For example, 379 means
  28 // "001.000". String ID 392 is not predefined, and is mapped by a separate
  29 // structure, the "String INDEX", inside the CFF data. (String ID 391 is also
  30 // not predefined. Specifically for ../testdata/CFFTest.otf, 391 means
  31 // "uni4E2D", as this font contains a glyph for U+4E2D).
  32 //
  33 // The actual glyph vectors are similarly encoded (in PostScript), in a format
  34 // called Type 2 Charstrings. The wire encoding is similar to but not exactly
  35 // the same as CFF's. For example, the byte 0x05 means FontBBox for CFF DICTs,
  36 // but means rlineto (relative line-to) for Type 2 Charstrings. See
  37 // 5176.CFF.pdf Appendix H and 5177.Type2.pdf Appendix A in the PDF files
  38 // referenced below.
  39 //
  40 // CFF is a stand-alone format, but CFF as used in SFNT fonts have further
  41 // restrictions. For example, a stand-alone CFF can contain multiple fonts, but
  42 // https://www.microsoft.com/typography/OTSPEC/cff.htm says that "The Name
  43 // INDEX in the CFF must contain only one entry; that is, there must be only
  44 // one font in the CFF FontSet".
  45 //
  46 // The relevant specifications are:
  47 // 	- http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf
  48 // 	- http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5177.Type2.pdf
  49 
  50 import (
  51 	"fmt"
  52 	"math"
  53 	"strconv"
  54 
  55 	"golang.org/x/image/math/fixed"
  56 )
  57 
  58 const (
  59 	// psArgStackSize is the argument stack size for a PostScript interpreter.
  60 	// 5176.CFF.pdf section 4 "DICT Data" says that "An operator may be
  61 	// preceded by up to a maximum of 48 operands". 5177.Type2.pdf Appendix B
  62 	// "Type 2 Charstring Implementation Limits" says that "Argument stack 48".
  63 	psArgStackSize = 48
  64 
  65 	// Similarly, Appendix B says "Subr nesting, stack limit 10".
  66 	psCallStackSize = 10
  67 )
  68 
  69 func bigEndian(b []byte) uint32 {
  70 	switch len(b) {
  71 	case 1:
  72 		return uint32(b[0])
  73 	case 2:
  74 		return uint32(b[0])<<8 | uint32(b[1])
  75 	case 3:
  76 		return uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])
  77 	case 4:
  78 		return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
  79 	}
  80 	panic("unreachable")
  81 }
  82 
  83 // fdSelect holds a CFF font's Font Dict Select data.
  84 type fdSelect struct {
  85 	format    uint8
  86 	numRanges uint16
  87 	offset    int32
  88 }
  89 
  90 func (t *fdSelect) lookup(f *Font, b *Buffer, x GlyphIndex) (int, error) {
  91 	switch t.format {
  92 	case 0:
  93 		buf, err := b.view(&f.src, int(t.offset)+int(x), 1)
  94 		if err != nil {
  95 			return 0, err
  96 		}
  97 		return int(buf[0]), nil
  98 	case 3:
  99 		lo, hi := 0, int(t.numRanges)
 100 		for lo < hi {
 101 			i := (lo + hi) / 2
 102 			buf, err := b.view(&f.src, int(t.offset)+3*i, 3+2)
 103 			if err != nil {
 104 				return 0, err
 105 			}
 106 			// buf holds the range [xlo, xhi).
 107 			if xlo := GlyphIndex(u16(buf[0:])); x < xlo {
 108 				hi = i
 109 				continue
 110 			}
 111 			if xhi := GlyphIndex(u16(buf[3:])); xhi <= x {
 112 				lo = i + 1
 113 				continue
 114 			}
 115 			return int(buf[2]), nil
 116 		}
 117 	}
 118 	return 0, ErrNotFound
 119 }
 120 
 121 // cffParser parses the CFF table from an SFNT font.
 122 type cffParser struct {
 123 	src    *source
 124 	base   int
 125 	offset int
 126 	end    int
 127 	err    error
 128 
 129 	buf    []byte
 130 	locBuf [2]uint32
 131 
 132 	psi psInterpreter
 133 }
 134 
 135 func (p *cffParser) parse(numGlyphs int32) (ret glyphData, err error) {
 136 	// Parse the header.
 137 	{
 138 		if !p.read(4) {
 139 			return glyphData{}, p.err
 140 		}
 141 		if p.buf[0] != 1 || p.buf[1] != 0 || p.buf[2] != 4 {
 142 			return glyphData{}, errUnsupportedCFFVersion
 143 		}
 144 	}
 145 
 146 	// Parse the Name INDEX.
 147 	{
 148 		count, offSize, ok := p.parseIndexHeader()
 149 		if !ok {
 150 			return glyphData{}, p.err
 151 		}
 152 		// https://www.microsoft.com/typography/OTSPEC/cff.htm says that "The
 153 		// Name INDEX in the CFF must contain only one entry".
 154 		if count != 1 {
 155 			return glyphData{}, errInvalidCFFTable
 156 		}
 157 		if !p.parseIndexLocations(p.locBuf[:2], count, offSize) {
 158 			return glyphData{}, p.err
 159 		}
 160 		p.offset = int(p.locBuf[1])
 161 	}
 162 
 163 	// Parse the Top DICT INDEX.
 164 	p.psi.topDict.initialize()
 165 	{
 166 		count, offSize, ok := p.parseIndexHeader()
 167 		if !ok {
 168 			return glyphData{}, p.err
 169 		}
 170 		// 5176.CFF.pdf section 8 "Top DICT INDEX" says that the count here
 171 		// should match the count of the Name INDEX, which is 1.
 172 		if count != 1 {
 173 			return glyphData{}, errInvalidCFFTable
 174 		}
 175 		if !p.parseIndexLocations(p.locBuf[:2], count, offSize) {
 176 			return glyphData{}, p.err
 177 		}
 178 		if !p.read(int(p.locBuf[1] - p.locBuf[0])) {
 179 			return glyphData{}, p.err
 180 		}
 181 		if p.err = p.psi.run(psContextTopDict, p.buf, 0, 0); p.err != nil {
 182 			return glyphData{}, p.err
 183 		}
 184 	}
 185 
 186 	// Skip the String INDEX.
 187 	{
 188 		count, offSize, ok := p.parseIndexHeader()
 189 		if !ok {
 190 			return glyphData{}, p.err
 191 		}
 192 		if count != 0 {
 193 			// Read the last location. Locations are off by 1 byte. See the
 194 			// comment in parseIndexLocations.
 195 			if !p.skip(int(count * offSize)) {
 196 				return glyphData{}, p.err
 197 			}
 198 			if !p.read(int(offSize)) {
 199 				return glyphData{}, p.err
 200 			}
 201 			loc := bigEndian(p.buf) - 1
 202 			// Check that locations are in bounds.
 203 			if uint32(p.end-p.offset) < loc {
 204 				return glyphData{}, errInvalidCFFTable
 205 			}
 206 			// Skip the index data.
 207 			if !p.skip(int(loc)) {
 208 				return glyphData{}, p.err
 209 			}
 210 		}
 211 	}
 212 
 213 	// Parse the Global Subrs [Subroutines] INDEX.
 214 	{
 215 		count, offSize, ok := p.parseIndexHeader()
 216 		if !ok {
 217 			return glyphData{}, p.err
 218 		}
 219 		if count != 0 {
 220 			if count > maxNumSubroutines {
 221 				return glyphData{}, errUnsupportedNumberOfSubroutines
 222 			}
 223 			ret.gsubrs = make([]uint32, count+1)
 224 			if !p.parseIndexLocations(ret.gsubrs, count, offSize) {
 225 				return glyphData{}, p.err
 226 			}
 227 		}
 228 	}
 229 
 230 	// Parse the CharStrings INDEX, whose location was found in the Top DICT.
 231 	{
 232 		if !p.seekFromBase(p.psi.topDict.charStringsOffset) {
 233 			return glyphData{}, errInvalidCFFTable
 234 		}
 235 		count, offSize, ok := p.parseIndexHeader()
 236 		if !ok {
 237 			return glyphData{}, p.err
 238 		}
 239 		if count == 0 || int32(count) != numGlyphs {
 240 			return glyphData{}, errInvalidCFFTable
 241 		}
 242 		ret.locations = make([]uint32, count+1)
 243 		if !p.parseIndexLocations(ret.locations, count, offSize) {
 244 			return glyphData{}, p.err
 245 		}
 246 	}
 247 
 248 	if !p.psi.topDict.isCIDFont {
 249 		// Parse the Private DICT, whose location was found in the Top DICT.
 250 		ret.singleSubrs, err = p.parsePrivateDICT(
 251 			p.psi.topDict.privateDictOffset,
 252 			p.psi.topDict.privateDictLength,
 253 		)
 254 		if err != nil {
 255 			return glyphData{}, err
 256 		}
 257 
 258 	} else {
 259 		// Parse the Font Dict Select data, whose location was found in the Top
 260 		// DICT.
 261 		ret.fdSelect, err = p.parseFDSelect(p.psi.topDict.fdSelect, numGlyphs)
 262 		if err != nil {
 263 			return glyphData{}, err
 264 		}
 265 
 266 		// Parse the Font Dicts. Each one contains its own Private DICT.
 267 		if !p.seekFromBase(p.psi.topDict.fdArray) {
 268 			return glyphData{}, errInvalidCFFTable
 269 		}
 270 
 271 		count, offSize, ok := p.parseIndexHeader()
 272 		if !ok {
 273 			return glyphData{}, p.err
 274 		}
 275 		if count > maxNumFontDicts {
 276 			return glyphData{}, errUnsupportedNumberOfFontDicts
 277 		}
 278 
 279 		fdLocations := make([]uint32, count+1)
 280 		if !p.parseIndexLocations(fdLocations, count, offSize) {
 281 			return glyphData{}, p.err
 282 		}
 283 
 284 		privateDicts := make([]struct {
 285 			offset, length int32
 286 		}, count)
 287 
 288 		for i := range privateDicts {
 289 			length := fdLocations[i+1] - fdLocations[i]
 290 			if !p.read(int(length)) {
 291 				return glyphData{}, errInvalidCFFTable
 292 			}
 293 			p.psi.topDict.initialize()
 294 			if p.err = p.psi.run(psContextTopDict, p.buf, 0, 0); p.err != nil {
 295 				return glyphData{}, p.err
 296 			}
 297 			privateDicts[i].offset = p.psi.topDict.privateDictOffset
 298 			privateDicts[i].length = p.psi.topDict.privateDictLength
 299 		}
 300 
 301 		ret.multiSubrs = make([][]uint32, count)
 302 		for i, pd := range privateDicts {
 303 			ret.multiSubrs[i], err = p.parsePrivateDICT(pd.offset, pd.length)
 304 			if err != nil {
 305 				return glyphData{}, err
 306 			}
 307 		}
 308 	}
 309 
 310 	return ret, err
 311 }
 312 
 313 // parseFDSelect parses the Font Dict Select data as per 5176.CFF.pdf section
 314 // 19 "FDSelect".
 315 func (p *cffParser) parseFDSelect(offset int32, numGlyphs int32) (ret fdSelect, err error) {
 316 	if !p.seekFromBase(p.psi.topDict.fdSelect) {
 317 		return fdSelect{}, errInvalidCFFTable
 318 	}
 319 	if !p.read(1) {
 320 		return fdSelect{}, p.err
 321 	}
 322 	ret.format = p.buf[0]
 323 	switch ret.format {
 324 	case 0:
 325 		if p.end-p.offset < int(numGlyphs) {
 326 			return fdSelect{}, errInvalidCFFTable
 327 		}
 328 		ret.offset = int32(p.offset)
 329 		return ret, nil
 330 	case 3:
 331 		if !p.read(2) {
 332 			return fdSelect{}, p.err
 333 		}
 334 		ret.numRanges = u16(p.buf)
 335 		if p.end-p.offset < 3*int(ret.numRanges)+2 {
 336 			return fdSelect{}, errInvalidCFFTable
 337 		}
 338 		ret.offset = int32(p.offset)
 339 		return ret, nil
 340 	}
 341 	return fdSelect{}, errUnsupportedCFFFDSelectTable
 342 }
 343 
 344 func (p *cffParser) parsePrivateDICT(offset, length int32) (subrs []uint32, err error) {
 345 	p.psi.privateDict.initialize()
 346 	if length != 0 {
 347 		fullLength := int32(p.end - p.base)
 348 		if offset <= 0 || fullLength < offset || fullLength-offset < length || length < 0 {
 349 			return nil, errInvalidCFFTable
 350 		}
 351 		p.offset = p.base + int(offset)
 352 		if !p.read(int(length)) {
 353 			return nil, p.err
 354 		}
 355 		if p.err = p.psi.run(psContextPrivateDict, p.buf, 0, 0); p.err != nil {
 356 			return nil, p.err
 357 		}
 358 	}
 359 
 360 	// Parse the Local Subrs [Subroutines] INDEX, whose location was found in
 361 	// the Private DICT.
 362 	if p.psi.privateDict.subrsOffset != 0 {
 363 		if !p.seekFromBase(offset + p.psi.privateDict.subrsOffset) {
 364 			return nil, errInvalidCFFTable
 365 		}
 366 		count, offSize, ok := p.parseIndexHeader()
 367 		if !ok {
 368 			return nil, p.err
 369 		}
 370 		if count != 0 {
 371 			if count > maxNumSubroutines {
 372 				return nil, errUnsupportedNumberOfSubroutines
 373 			}
 374 			subrs = make([]uint32, count+1)
 375 			if !p.parseIndexLocations(subrs, count, offSize) {
 376 				return nil, p.err
 377 			}
 378 		}
 379 	}
 380 
 381 	return subrs, err
 382 }
 383 
 384 // read sets p.buf to view the n bytes from p.offset to p.offset+n. It also
 385 // advances p.offset by n.
 386 //
 387 // As per the source.view method, the caller should not modify the contents of
 388 // p.buf after read returns, other than by calling read again.
 389 //
 390 // The caller should also avoid modifying the pointer / length / capacity of
 391 // the p.buf slice, not just avoid modifying the slice's contents, in order to
 392 // maximize the opportunity to re-use p.buf's allocated memory when viewing the
 393 // underlying source data for subsequent read calls.
 394 func (p *cffParser) read(n int) (ok bool) {
 395 	if n < 0 || p.end-p.offset < n {
 396 		p.err = errInvalidCFFTable
 397 		return false
 398 	}
 399 	p.buf, p.err = p.src.view(p.buf, p.offset, n)
 400 	// TODO: if p.err == io.EOF, change that to a different error??
 401 	p.offset += n
 402 	return p.err == nil
 403 }
 404 
 405 func (p *cffParser) skip(n int) (ok bool) {
 406 	if p.end-p.offset < n {
 407 		p.err = errInvalidCFFTable
 408 		return false
 409 	}
 410 	p.offset += n
 411 	return true
 412 }
 413 
 414 func (p *cffParser) seekFromBase(offset int32) (ok bool) {
 415 	if offset < 0 || int32(p.end-p.base) < offset {
 416 		return false
 417 	}
 418 	p.offset = p.base + int(offset)
 419 	return true
 420 }
 421 
 422 func (p *cffParser) parseIndexHeader() (count, offSize int32, ok bool) {
 423 	if !p.read(2) {
 424 		return 0, 0, false
 425 	}
 426 	count = int32(u16(p.buf[:2]))
 427 	// 5176.CFF.pdf section 5 "INDEX Data" says that "An empty INDEX is
 428 	// represented by a count field with a 0 value and no additional fields.
 429 	// Thus, the total size of an empty INDEX is 2 bytes".
 430 	if count == 0 {
 431 		return count, 0, true
 432 	}
 433 	if !p.read(1) {
 434 		return 0, 0, false
 435 	}
 436 	offSize = int32(p.buf[0])
 437 	if offSize < 1 || 4 < offSize {
 438 		p.err = errInvalidCFFTable
 439 		return 0, 0, false
 440 	}
 441 	return count, offSize, true
 442 }
 443 
 444 func (p *cffParser) parseIndexLocations(dst []uint32, count, offSize int32) (ok bool) {
 445 	if count == 0 {
 446 		return true
 447 	}
 448 	if len(dst) != int(count+1) {
 449 		panic("unreachable")
 450 	}
 451 	if !p.read(len(dst) * int(offSize)) {
 452 		return false
 453 	}
 454 
 455 	buf, prev := p.buf, uint32(0)
 456 	for i := range dst {
 457 		loc := bigEndian(buf[:offSize])
 458 		buf = buf[offSize:]
 459 
 460 		// Locations are off by 1 byte. 5176.CFF.pdf section 5 "INDEX Data"
 461 		// says that "Offsets in the offset array are relative to the byte that
 462 		// precedes the object data... This ensures that every object has a
 463 		// corresponding offset which is always nonzero".
 464 		if loc == 0 {
 465 			p.err = errInvalidCFFTable
 466 			return false
 467 		}
 468 		loc--
 469 
 470 		// In the same paragraph, "Therefore the first element of the offset
 471 		// array is always 1" before correcting for the off-by-1.
 472 		if i == 0 {
 473 			if loc != 0 {
 474 				p.err = errInvalidCFFTable
 475 				break
 476 			}
 477 		} else if loc <= prev { // Check that locations are increasing.
 478 			p.err = errInvalidCFFTable
 479 			break
 480 		}
 481 
 482 		// Check that locations are in bounds.
 483 		if uint32(p.end-p.offset) < loc {
 484 			p.err = errInvalidCFFTable
 485 			break
 486 		}
 487 
 488 		dst[i] = uint32(p.offset) + loc
 489 		prev = loc
 490 	}
 491 	return p.err == nil
 492 }
 493 
 494 type psCallStackEntry struct {
 495 	offset, length uint32
 496 }
 497 
 498 type psContext uint32
 499 
 500 const (
 501 	psContextTopDict psContext = iota
 502 	psContextPrivateDict
 503 	psContextType2Charstring
 504 )
 505 
 506 // psTopDictData contains fields specific to the Top DICT context.
 507 type psTopDictData struct {
 508 	charStringsOffset int32
 509 	fdArray           int32
 510 	fdSelect          int32
 511 	isCIDFont         bool
 512 	privateDictOffset int32
 513 	privateDictLength int32
 514 }
 515 
 516 func (d *psTopDictData) initialize() {
 517 	*d = psTopDictData{}
 518 }
 519 
 520 // psPrivateDictData contains fields specific to the Private DICT context.
 521 type psPrivateDictData struct {
 522 	subrsOffset int32
 523 }
 524 
 525 func (d *psPrivateDictData) initialize() {
 526 	*d = psPrivateDictData{}
 527 }
 528 
 529 // psType2CharstringsData contains fields specific to the Type 2 Charstrings
 530 // context.
 531 type psType2CharstringsData struct {
 532 	f          *Font
 533 	b          *Buffer
 534 	x          int32
 535 	y          int32
 536 	firstX     int32
 537 	firstY     int32
 538 	hintBits   int32
 539 	seenWidth  bool
 540 	ended      bool
 541 	glyphIndex GlyphIndex
 542 	// fdSelectIndexPlusOne is the result of the Font Dict Select lookup, plus
 543 	// one. That plus one lets us use the zero value to denote either unused
 544 	// (for CFF fonts with a single Font Dict) or lazily evaluated.
 545 	fdSelectIndexPlusOne int32
 546 }
 547 
 548 func (d *psType2CharstringsData) initialize(f *Font, b *Buffer, glyphIndex GlyphIndex) {
 549 	*d = psType2CharstringsData{
 550 		f:          f,
 551 		b:          b,
 552 		glyphIndex: glyphIndex,
 553 	}
 554 }
 555 
 556 func (d *psType2CharstringsData) closePath() {
 557 	if d.x != d.firstX || d.y != d.firstY {
 558 		d.b.segments = append(d.b.segments, Segment{
 559 			Op: SegmentOpLineTo,
 560 			Args: [3]fixed.Point26_6{{
 561 				X: fixed.Int26_6(d.firstX),
 562 				Y: fixed.Int26_6(d.firstY),
 563 			}},
 564 		})
 565 	}
 566 }
 567 
 568 func (d *psType2CharstringsData) moveTo(dx, dy int32) {
 569 	d.closePath()
 570 	d.x += dx
 571 	d.y += dy
 572 	d.b.segments = append(d.b.segments, Segment{
 573 		Op: SegmentOpMoveTo,
 574 		Args: [3]fixed.Point26_6{{
 575 			X: fixed.Int26_6(d.x),
 576 			Y: fixed.Int26_6(d.y),
 577 		}},
 578 	})
 579 	d.firstX = d.x
 580 	d.firstY = d.y
 581 }
 582 
 583 func (d *psType2CharstringsData) lineTo(dx, dy int32) {
 584 	d.x += dx
 585 	d.y += dy
 586 	d.b.segments = append(d.b.segments, Segment{
 587 		Op: SegmentOpLineTo,
 588 		Args: [3]fixed.Point26_6{{
 589 			X: fixed.Int26_6(d.x),
 590 			Y: fixed.Int26_6(d.y),
 591 		}},
 592 	})
 593 }
 594 
 595 func (d *psType2CharstringsData) cubeTo(dxa, dya, dxb, dyb, dxc, dyc int32) {
 596 	d.x += dxa
 597 	d.y += dya
 598 	xa := fixed.Int26_6(d.x)
 599 	ya := fixed.Int26_6(d.y)
 600 	d.x += dxb
 601 	d.y += dyb
 602 	xb := fixed.Int26_6(d.x)
 603 	yb := fixed.Int26_6(d.y)
 604 	d.x += dxc
 605 	d.y += dyc
 606 	xc := fixed.Int26_6(d.x)
 607 	yc := fixed.Int26_6(d.y)
 608 	d.b.segments = append(d.b.segments, Segment{
 609 		Op:   SegmentOpCubeTo,
 610 		Args: [3]fixed.Point26_6{{X: xa, Y: ya}, {X: xb, Y: yb}, {X: xc, Y: yc}},
 611 	})
 612 }
 613 
 614 // psInterpreter is a PostScript interpreter.
 615 type psInterpreter struct {
 616 	ctx          psContext
 617 	instructions []byte
 618 	instrOffset  uint32
 619 	instrLength  uint32
 620 	argStack     struct {
 621 		a   [psArgStackSize]int32
 622 		top int32
 623 	}
 624 	callStack struct {
 625 		a   [psCallStackSize]psCallStackEntry
 626 		top int32
 627 	}
 628 	parseNumberBuf [maxRealNumberStrLen]byte
 629 
 630 	topDict          psTopDictData
 631 	privateDict      psPrivateDictData
 632 	type2Charstrings psType2CharstringsData
 633 }
 634 
 635 func (p *psInterpreter) hasMoreInstructions() bool {
 636 	if len(p.instructions) != 0 {
 637 		return true
 638 	}
 639 	for i := int32(0); i < p.callStack.top; i++ {
 640 		if p.callStack.a[i].length != 0 {
 641 			return true
 642 		}
 643 	}
 644 	return false
 645 }
 646 
 647 // run runs the instructions in the given PostScript context. For the
 648 // psContextType2Charstring context, offset and length give the location of the
 649 // instructions in p.type2Charstrings.f.src.
 650 func (p *psInterpreter) run(ctx psContext, instructions []byte, offset, length uint32) error {
 651 	p.ctx = ctx
 652 	p.instructions = instructions
 653 	p.instrOffset = offset
 654 	p.instrLength = length
 655 	p.argStack.top = 0
 656 	p.callStack.top = 0
 657 
 658 loop:
 659 	for len(p.instructions) > 0 {
 660 		// Push a numeric operand on the stack, if applicable.
 661 		if hasResult, err := p.parseNumber(); hasResult {
 662 			if err != nil {
 663 				return err
 664 			}
 665 			continue
 666 		}
 667 
 668 		// Otherwise, execute an operator.
 669 		b := p.instructions[0]
 670 		p.instructions = p.instructions[1:]
 671 
 672 		for escaped, ops := false, psOperators[ctx][0]; ; {
 673 			if b == escapeByte && !escaped {
 674 				if len(p.instructions) <= 0 {
 675 					return errInvalidCFFTable
 676 				}
 677 				b = p.instructions[0]
 678 				p.instructions = p.instructions[1:]
 679 				escaped = true
 680 				ops = psOperators[ctx][1]
 681 				continue
 682 			}
 683 
 684 			if int(b) < len(ops) {
 685 				if op := ops[b]; op.name != "" {
 686 					if p.argStack.top < op.numPop {
 687 						return errInvalidCFFTable
 688 					}
 689 					if op.run != nil {
 690 						if err := op.run(p); err != nil {
 691 							return err
 692 						}
 693 					}
 694 					if op.numPop < 0 {
 695 						p.argStack.top = 0
 696 					} else {
 697 						p.argStack.top -= op.numPop
 698 					}
 699 					continue loop
 700 				}
 701 			}
 702 
 703 			if escaped {
 704 				return fmt.Errorf("sfnt: unrecognized CFF 2-byte operator (12 %d)", b)
 705 			} else {
 706 				return fmt.Errorf("sfnt: unrecognized CFF 1-byte operator (%d)", b)
 707 			}
 708 		}
 709 	}
 710 	return nil
 711 }
 712 
 713 // See 5176.CFF.pdf section 4 "DICT Data".
 714 func (p *psInterpreter) parseNumber() (hasResult bool, err error) {
 715 	number := int32(0)
 716 	switch b := p.instructions[0]; {
 717 	case b == 28:
 718 		if len(p.instructions) < 3 {
 719 			return true, errInvalidCFFTable
 720 		}
 721 		number, hasResult = int32(int16(u16(p.instructions[1:]))), true
 722 		p.instructions = p.instructions[3:]
 723 
 724 	case b == 29 && p.ctx != psContextType2Charstring:
 725 		if len(p.instructions) < 5 {
 726 			return true, errInvalidCFFTable
 727 		}
 728 		number, hasResult = int32(u32(p.instructions[1:])), true
 729 		p.instructions = p.instructions[5:]
 730 
 731 	case b == 30 && p.ctx != psContextType2Charstring:
 732 		// Parse a real number. This isn't listed in 5176.CFF.pdf Table 3
 733 		// "Operand Encoding" but that table lists integer encodings. Further
 734 		// down the page it says "A real number operand is provided in addition
 735 		// to integer operands. This operand begins with a byte value of 30
 736 		// followed by a variable-length sequence of bytes."
 737 
 738 		s := p.parseNumberBuf[:0]
 739 		p.instructions = p.instructions[1:]
 740 	loop:
 741 		for {
 742 			if len(p.instructions) == 0 {
 743 				return true, errInvalidCFFTable
 744 			}
 745 			b := p.instructions[0]
 746 			p.instructions = p.instructions[1:]
 747 			// Process b's two nibbles, high then low.
 748 			for i := 0; i < 2; i++ {
 749 				nib := b >> 4
 750 				b = b << 4
 751 				if nib == 0x0f {
 752 					f, err := strconv.ParseFloat(string(s), 32)
 753 					if err != nil {
 754 						return true, errInvalidCFFTable
 755 					}
 756 					number, hasResult = int32(math.Float32bits(float32(f))), true
 757 					break loop
 758 				}
 759 				if nib == 0x0d {
 760 					return true, errInvalidCFFTable
 761 				}
 762 				if len(s)+maxNibbleDefsLength > len(p.parseNumberBuf) {
 763 					return true, errUnsupportedRealNumberEncoding
 764 				}
 765 				s = append(s, nibbleDefs[nib]...)
 766 			}
 767 		}
 768 
 769 	case b < 32:
 770 		// No-op.
 771 
 772 	case b < 247:
 773 		p.instructions = p.instructions[1:]
 774 		number, hasResult = int32(b)-139, true
 775 
 776 	case b < 251:
 777 		if len(p.instructions) < 2 {
 778 			return true, errInvalidCFFTable
 779 		}
 780 		b1 := p.instructions[1]
 781 		p.instructions = p.instructions[2:]
 782 		number, hasResult = +int32(b-247)*256+int32(b1)+108, true
 783 
 784 	case b < 255:
 785 		if len(p.instructions) < 2 {
 786 			return true, errInvalidCFFTable
 787 		}
 788 		b1 := p.instructions[1]
 789 		p.instructions = p.instructions[2:]
 790 		number, hasResult = -int32(b-251)*256-int32(b1)-108, true
 791 
 792 	case b == 255 && p.ctx == psContextType2Charstring:
 793 		if len(p.instructions) < 5 {
 794 			return true, errInvalidCFFTable
 795 		}
 796 		number, hasResult = int32(u32(p.instructions[1:])), true
 797 		p.instructions = p.instructions[5:]
 798 		// 5177.Type2.pdf section 3.2 "Charstring Number Encoding" says "If the
 799 		// charstring byte contains the value 255... [this] number is
 800 		// interpreted as a Fixed; that is, a signed number with 16 bits of
 801 		// fraction".
 802 		//
 803 		// TODO: change the psType2CharstringsData.b.segments and
 804 		// psInterpreter.argStack data structures to optionally hold fixed
 805 		// point values, not just integer values. That's a substantial
 806 		// re-design, though. Until then, just round the 16.16 fixed point
 807 		// number to the closest integer value. This isn't just "number =
 808 		// ((number + 0x8000) >> 16)" because of potential overflow.
 809 		number = (number >> 16) + (1 & (number >> 15))
 810 	}
 811 
 812 	if hasResult {
 813 		if p.argStack.top == psArgStackSize {
 814 			return true, errInvalidCFFTable
 815 		}
 816 		p.argStack.a[p.argStack.top] = number
 817 		p.argStack.top++
 818 	}
 819 	return hasResult, nil
 820 }
 821 
 822 const maxNibbleDefsLength = len("E-")
 823 
 824 // nibbleDefs encodes 5176.CFF.pdf Table 5 "Nibble Definitions".
 825 var nibbleDefs = [16]string{
 826 	0x00: "0",
 827 	0x01: "1",
 828 	0x02: "2",
 829 	0x03: "3",
 830 	0x04: "4",
 831 	0x05: "5",
 832 	0x06: "6",
 833 	0x07: "7",
 834 	0x08: "8",
 835 	0x09: "9",
 836 	0x0a: ".",
 837 	0x0b: "E",
 838 	0x0c: "E-",
 839 	0x0d: "",
 840 	0x0e: "-",
 841 	0x0f: "",
 842 }
 843 
 844 type psOperator struct {
 845 	// numPop is the number of stack values to pop. -1 means "array" and -2
 846 	// means "delta" as per 5176.CFF.pdf Table 6 "Operand Types".
 847 	numPop int32
 848 	// name is the operator name. An empty name (i.e. the zero value for the
 849 	// struct overall) means an unrecognized 1-byte operator.
 850 	name string
 851 	// run is the function that implements the operator. Nil means that we
 852 	// ignore the operator, other than popping its arguments off the stack.
 853 	run func(*psInterpreter) error
 854 }
 855 
 856 // psOperators holds the 1-byte and 2-byte operators for PostScript interpreter
 857 // contexts.
 858 var psOperators = [...][2][]psOperator{
 859 	// The Top DICT operators are defined by 5176.CFF.pdf Table 9 "Top DICT
 860 	// Operator Entries" and Table 10 "CIDFont Operator Extensions".
 861 	psContextTopDict: {{
 862 		// 1-byte operators.
 863 		0:  {+1, "version", nil},
 864 		1:  {+1, "Notice", nil},
 865 		2:  {+1, "FullName", nil},
 866 		3:  {+1, "FamilyName", nil},
 867 		4:  {+1, "Weight", nil},
 868 		5:  {-1, "FontBBox", nil},
 869 		13: {+1, "UniqueID", nil},
 870 		14: {-1, "XUID", nil},
 871 		15: {+1, "charset", nil},
 872 		16: {+1, "Encoding", nil},
 873 		17: {+1, "CharStrings", func(p *psInterpreter) error {
 874 			p.topDict.charStringsOffset = p.argStack.a[p.argStack.top-1]
 875 			return nil
 876 		}},
 877 		18: {+2, "Private", func(p *psInterpreter) error {
 878 			p.topDict.privateDictLength = p.argStack.a[p.argStack.top-2]
 879 			p.topDict.privateDictOffset = p.argStack.a[p.argStack.top-1]
 880 			return nil
 881 		}},
 882 	}, {
 883 		// 2-byte operators. The first byte is the escape byte.
 884 		0:  {+1, "Copyright", nil},
 885 		1:  {+1, "isFixedPitch", nil},
 886 		2:  {+1, "ItalicAngle", nil},
 887 		3:  {+1, "UnderlinePosition", nil},
 888 		4:  {+1, "UnderlineThickness", nil},
 889 		5:  {+1, "PaintType", nil},
 890 		6:  {+1, "CharstringType", nil},
 891 		7:  {-1, "FontMatrix", nil},
 892 		8:  {+1, "StrokeWidth", nil},
 893 		20: {+1, "SyntheticBase", nil},
 894 		21: {+1, "PostScript", nil},
 895 		22: {+1, "BaseFontName", nil},
 896 		23: {-2, "BaseFontBlend", nil},
 897 		30: {+3, "ROS", func(p *psInterpreter) error {
 898 			p.topDict.isCIDFont = true
 899 			return nil
 900 		}},
 901 		31: {+1, "CIDFontVersion", nil},
 902 		32: {+1, "CIDFontRevision", nil},
 903 		33: {+1, "CIDFontType", nil},
 904 		34: {+1, "CIDCount", nil},
 905 		35: {+1, "UIDBase", nil},
 906 		36: {+1, "FDArray", func(p *psInterpreter) error {
 907 			p.topDict.fdArray = p.argStack.a[p.argStack.top-1]
 908 			return nil
 909 		}},
 910 		37: {+1, "FDSelect", func(p *psInterpreter) error {
 911 			p.topDict.fdSelect = p.argStack.a[p.argStack.top-1]
 912 			return nil
 913 		}},
 914 		38: {+1, "FontName", nil},
 915 	}},
 916 
 917 	// The Private DICT operators are defined by 5176.CFF.pdf Table 23 "Private
 918 	// DICT Operators".
 919 	psContextPrivateDict: {{
 920 		// 1-byte operators.
 921 		6:  {-2, "BlueValues", nil},
 922 		7:  {-2, "OtherBlues", nil},
 923 		8:  {-2, "FamilyBlues", nil},
 924 		9:  {-2, "FamilyOtherBlues", nil},
 925 		10: {+1, "StdHW", nil},
 926 		11: {+1, "StdVW", nil},
 927 		19: {+1, "Subrs", func(p *psInterpreter) error {
 928 			p.privateDict.subrsOffset = p.argStack.a[p.argStack.top-1]
 929 			return nil
 930 		}},
 931 		20: {+1, "defaultWidthX", nil},
 932 		21: {+1, "nominalWidthX", nil},
 933 	}, {
 934 		// 2-byte operators. The first byte is the escape byte.
 935 		9:  {+1, "BlueScale", nil},
 936 		10: {+1, "BlueShift", nil},
 937 		11: {+1, "BlueFuzz", nil},
 938 		12: {-2, "StemSnapH", nil},
 939 		13: {-2, "StemSnapV", nil},
 940 		14: {+1, "ForceBold", nil},
 941 		17: {+1, "LanguageGroup", nil},
 942 		18: {+1, "ExpansionFactor", nil},
 943 		19: {+1, "initialRandomSeed", nil},
 944 	}},
 945 
 946 	// The Type 2 Charstring operators are defined by 5177.Type2.pdf Appendix A
 947 	// "Type 2 Charstring Command Codes".
 948 	psContextType2Charstring: {{
 949 		// 1-byte operators.
 950 		0:  {}, // Reserved.
 951 		1:  {-1, "hstem", t2CStem},
 952 		2:  {}, // Reserved.
 953 		3:  {-1, "vstem", t2CStem},
 954 		4:  {-1, "vmoveto", t2CVmoveto},
 955 		5:  {-1, "rlineto", t2CRlineto},
 956 		6:  {-1, "hlineto", t2CHlineto},
 957 		7:  {-1, "vlineto", t2CVlineto},
 958 		8:  {-1, "rrcurveto", t2CRrcurveto},
 959 		9:  {}, // Reserved.
 960 		10: {+1, "callsubr", t2CCallsubr},
 961 		11: {+0, "return", t2CReturn},
 962 		12: {}, // escape.
 963 		13: {}, // Reserved.
 964 		14: {-1, "endchar", t2CEndchar},
 965 		15: {}, // Reserved.
 966 		16: {}, // Reserved.
 967 		17: {}, // Reserved.
 968 		18: {-1, "hstemhm", t2CStem},
 969 		19: {-1, "hintmask", t2CMask},
 970 		20: {-1, "cntrmask", t2CMask},
 971 		21: {-1, "rmoveto", t2CRmoveto},
 972 		22: {-1, "hmoveto", t2CHmoveto},
 973 		23: {-1, "vstemhm", t2CStem},
 974 		24: {-1, "rcurveline", t2CRcurveline},
 975 		25: {-1, "rlinecurve", t2CRlinecurve},
 976 		26: {-1, "vvcurveto", t2CVvcurveto},
 977 		27: {-1, "hhcurveto", t2CHhcurveto},
 978 		28: {}, // shortint.
 979 		29: {+1, "callgsubr", t2CCallgsubr},
 980 		30: {-1, "vhcurveto", t2CVhcurveto},
 981 		31: {-1, "hvcurveto", t2CHvcurveto},
 982 	}, {
 983 		// 2-byte operators. The first byte is the escape byte.
 984 		34: {+7, "hflex", t2CHflex},
 985 		36: {+9, "hflex1", t2CHflex1},
 986 		// TODO: more operators.
 987 	}},
 988 }
 989 
 990 // 5176.CFF.pdf section 4 "DICT Data" says that "Two-byte operators have an
 991 // initial escape byte of 12".
 992 const escapeByte = 12
 993 
 994 // t2CReadWidth reads the optional width adjustment. If present, it is on the
 995 // bottom of the arg stack. nArgs is the expected number of arguments on the
 996 // stack. A negative nArgs means a multiple of 2.
 997 //
 998 // 5177.Type2.pdf page 16 Note 4 says: "The first stack-clearing operator,
 999 // which must be one of hstem, hstemhm, vstem, vstemhm, cntrmask, hintmask,
1000 // hmoveto, vmoveto, rmoveto, or endchar, takes an additional argument — the
1001 // width... which may be expressed as zero or one numeric argument."
1002 func t2CReadWidth(p *psInterpreter, nArgs int32) {
1003 	if p.type2Charstrings.seenWidth {
1004 		return
1005 	}
1006 	p.type2Charstrings.seenWidth = true
1007 	if nArgs >= 0 {
1008 		if p.argStack.top != nArgs+1 {
1009 			return
1010 		}
1011 	} else if p.argStack.top&1 == 0 {
1012 		return
1013 	}
1014 	// When parsing a standalone CFF, we'd save the value of p.argStack.a[0]
1015 	// here as it defines the glyph's width (horizontal advance). Specifically,
1016 	// if present, it is a delta to the font-global nominalWidthX value found
1017 	// in the Private DICT. If absent, the glyph's width is the defaultWidthX
1018 	// value in that dict. See 5176.CFF.pdf section 15 "Private DICT Data".
1019 	//
1020 	// For a CFF embedded in an SFNT font (i.e. an OpenType font), glyph widths
1021 	// are already stored in the hmtx table, separate to the CFF table, and it
1022 	// is simpler to parse that table for all OpenType fonts (PostScript and
1023 	// TrueType). We therefore ignore the width value here, and just remove it
1024 	// from the bottom of the argStack.
1025 	copy(p.argStack.a[:p.argStack.top-1], p.argStack.a[1:p.argStack.top])
1026 	p.argStack.top--
1027 }
1028 
1029 func t2CStem(p *psInterpreter) error {
1030 	t2CReadWidth(p, -1)
1031 	if p.argStack.top%2 != 0 {
1032 		return errInvalidCFFTable
1033 	}
1034 	// We update the number of hintBits need to parse hintmask and cntrmask
1035 	// instructions, but this Type 2 Charstring implementation otherwise
1036 	// ignores the stem hints.
1037 	p.type2Charstrings.hintBits += p.argStack.top / 2
1038 	if p.type2Charstrings.hintBits > maxHintBits {
1039 		return errUnsupportedNumberOfHints
1040 	}
1041 	return nil
1042 }
1043 
1044 func t2CMask(p *psInterpreter) error {
1045 	// 5176.CFF.pdf section 4.3 "Hint Operators" says that "If hstem and vstem
1046 	// hints are both declared at the beginning of a charstring, and this
1047 	// sequence is followed directly by the hintmask or cntrmask operators, the
1048 	// vstem hint operator need not be included."
1049 	//
1050 	// What we implement here is more permissive (but the same as what the
1051 	// FreeType implementation does, and simpler than tracking the previous
1052 	// operator and other hinting state): if a hintmask is given any arguments
1053 	// (i.e. the argStack is non-empty), we run an implicit vstem operator.
1054 	//
1055 	// Note that the vstem operator consumes from p.argStack, but the hintmask
1056 	// or cntrmask operators consume from p.instructions.
1057 	if p.argStack.top != 0 {
1058 		if err := t2CStem(p); err != nil {
1059 			return err
1060 		}
1061 	} else if !p.type2Charstrings.seenWidth {
1062 		p.type2Charstrings.seenWidth = true
1063 	}
1064 
1065 	hintBytes := (p.type2Charstrings.hintBits + 7) / 8
1066 	if len(p.instructions) < int(hintBytes) {
1067 		return errInvalidCFFTable
1068 	}
1069 	p.instructions = p.instructions[hintBytes:]
1070 	return nil
1071 }
1072 
1073 func t2CHmoveto(p *psInterpreter) error {
1074 	t2CReadWidth(p, 1)
1075 	if p.argStack.top != 1 {
1076 		return errInvalidCFFTable
1077 	}
1078 	p.type2Charstrings.moveTo(p.argStack.a[0], 0)
1079 	return nil
1080 }
1081 
1082 func t2CVmoveto(p *psInterpreter) error {
1083 	t2CReadWidth(p, 1)
1084 	if p.argStack.top != 1 {
1085 		return errInvalidCFFTable
1086 	}
1087 	p.type2Charstrings.moveTo(0, p.argStack.a[0])
1088 	return nil
1089 }
1090 
1091 func t2CRmoveto(p *psInterpreter) error {
1092 	t2CReadWidth(p, 2)
1093 	if p.argStack.top != 2 {
1094 		return errInvalidCFFTable
1095 	}
1096 	p.type2Charstrings.moveTo(p.argStack.a[0], p.argStack.a[1])
1097 	return nil
1098 }
1099 
1100 func t2CHlineto(p *psInterpreter) error { return t2CLineto(p, false) }
1101 func t2CVlineto(p *psInterpreter) error { return t2CLineto(p, true) }
1102 
1103 func t2CLineto(p *psInterpreter, vertical bool) error {
1104 	if !p.type2Charstrings.seenWidth || p.argStack.top < 1 {
1105 		return errInvalidCFFTable
1106 	}
1107 	for i := int32(0); i < p.argStack.top; i, vertical = i+1, !vertical {
1108 		dx, dy := p.argStack.a[i], int32(0)
1109 		if vertical {
1110 			dx, dy = dy, dx
1111 		}
1112 		p.type2Charstrings.lineTo(dx, dy)
1113 	}
1114 	return nil
1115 }
1116 
1117 func t2CRlineto(p *psInterpreter) error {
1118 	if !p.type2Charstrings.seenWidth || p.argStack.top < 2 || p.argStack.top%2 != 0 {
1119 		return errInvalidCFFTable
1120 	}
1121 	for i := int32(0); i < p.argStack.top; i += 2 {
1122 		p.type2Charstrings.lineTo(p.argStack.a[i], p.argStack.a[i+1])
1123 	}
1124 	return nil
1125 }
1126 
1127 // As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
1128 //
1129 // rcurveline is:
1130 //	- {dxa dya dxb dyb dxc dyc}+ dxd dyd
1131 //
1132 // rlinecurve is:
1133 //	- {dxa dya}+ dxb dyb dxc dyc dxd dyd
1134 
1135 func t2CRcurveline(p *psInterpreter) error {
1136 	if !p.type2Charstrings.seenWidth || p.argStack.top < 8 || p.argStack.top%6 != 2 {
1137 		return errInvalidCFFTable
1138 	}
1139 	i := int32(0)
1140 	for iMax := p.argStack.top - 2; i < iMax; i += 6 {
1141 		p.type2Charstrings.cubeTo(
1142 			p.argStack.a[i+0],
1143 			p.argStack.a[i+1],
1144 			p.argStack.a[i+2],
1145 			p.argStack.a[i+3],
1146 			p.argStack.a[i+4],
1147 			p.argStack.a[i+5],
1148 		)
1149 	}
1150 	p.type2Charstrings.lineTo(p.argStack.a[i], p.argStack.a[i+1])
1151 	return nil
1152 }
1153 
1154 func t2CRlinecurve(p *psInterpreter) error {
1155 	if !p.type2Charstrings.seenWidth || p.argStack.top < 8 || p.argStack.top%2 != 0 {
1156 		return errInvalidCFFTable
1157 	}
1158 	i := int32(0)
1159 	for iMax := p.argStack.top - 6; i < iMax; i += 2 {
1160 		p.type2Charstrings.lineTo(p.argStack.a[i], p.argStack.a[i+1])
1161 	}
1162 	p.type2Charstrings.cubeTo(
1163 		p.argStack.a[i+0],
1164 		p.argStack.a[i+1],
1165 		p.argStack.a[i+2],
1166 		p.argStack.a[i+3],
1167 		p.argStack.a[i+4],
1168 		p.argStack.a[i+5],
1169 	)
1170 	return nil
1171 }
1172 
1173 // As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
1174 //
1175 // hhcurveto is:
1176 //	- dy1 {dxa dxb dyb dxc}+
1177 //
1178 // vvcurveto is:
1179 //	- dx1 {dya dxb dyb dyc}+
1180 //
1181 // hvcurveto is one of:
1182 //	- dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
1183 //	- {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
1184 //
1185 // vhcurveto is one of:
1186 //	- dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf?
1187 //	- {dya dxb dyb dxc dxd dxe dye dyf}+ dxf?
1188 
1189 func t2CHhcurveto(p *psInterpreter) error { return t2CCurveto(p, false, false) }
1190 func t2CVvcurveto(p *psInterpreter) error { return t2CCurveto(p, false, true) }
1191 func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, true, false) }
1192 func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true, true) }
1193 
1194 // t2CCurveto implements the hh / vv / hv / vh xxcurveto operators. N relative
1195 // cubic curve requires 6*N control points, but only 4*N+0 or 4*N+1 are used
1196 // here: all (or all but one) of the piecewise cubic curve's tangents are
1197 // implicitly horizontal or vertical.
1198 //
1199 // swap is whether that implicit horizontal / vertical constraint swaps as you
1200 // move along the piecewise cubic curve. If swap is false, the constraints are
1201 // either all horizontal or all vertical. If swap is true, it alternates.
1202 //
1203 // vertical is whether the first implicit constraint is vertical.
1204 func t2CCurveto(p *psInterpreter, swap, vertical bool) error {
1205 	if !p.type2Charstrings.seenWidth || p.argStack.top < 4 {
1206 		return errInvalidCFFTable
1207 	}
1208 
1209 	i := int32(0)
1210 	switch p.argStack.top & 3 {
1211 	case 0:
1212 		// No-op.
1213 	case 1:
1214 		if swap {
1215 			break
1216 		}
1217 		i = 1
1218 		if vertical {
1219 			p.type2Charstrings.x += p.argStack.a[0]
1220 		} else {
1221 			p.type2Charstrings.y += p.argStack.a[0]
1222 		}
1223 	default:
1224 		return errInvalidCFFTable
1225 	}
1226 
1227 	for i != p.argStack.top {
1228 		i = t2CCurveto4(p, swap, vertical, i)
1229 		if i < 0 {
1230 			return errInvalidCFFTable
1231 		}
1232 		if swap {
1233 			vertical = !vertical
1234 		}
1235 	}
1236 	return nil
1237 }
1238 
1239 func t2CCurveto4(p *psInterpreter, swap bool, vertical bool, i int32) (j int32) {
1240 	if i+4 > p.argStack.top {
1241 		return -1
1242 	}
1243 	dxa := p.argStack.a[i+0]
1244 	dya := int32(0)
1245 	dxb := p.argStack.a[i+1]
1246 	dyb := p.argStack.a[i+2]
1247 	dxc := p.argStack.a[i+3]
1248 	dyc := int32(0)
1249 	i += 4
1250 
1251 	if vertical {
1252 		dxa, dya = dya, dxa
1253 	}
1254 
1255 	if swap {
1256 		if i+1 == p.argStack.top {
1257 			dyc = p.argStack.a[i]
1258 			i++
1259 		}
1260 	}
1261 
1262 	if swap != vertical {
1263 		dxc, dyc = dyc, dxc
1264 	}
1265 
1266 	p.type2Charstrings.cubeTo(dxa, dya, dxb, dyb, dxc, dyc)
1267 	return i
1268 }
1269 
1270 func t2CRrcurveto(p *psInterpreter) error {
1271 	if !p.type2Charstrings.seenWidth || p.argStack.top < 6 || p.argStack.top%6 != 0 {
1272 		return errInvalidCFFTable
1273 	}
1274 	for i := int32(0); i != p.argStack.top; i += 6 {
1275 		p.type2Charstrings.cubeTo(
1276 			p.argStack.a[i+0],
1277 			p.argStack.a[i+1],
1278 			p.argStack.a[i+2],
1279 			p.argStack.a[i+3],
1280 			p.argStack.a[i+4],
1281 			p.argStack.a[i+5],
1282 		)
1283 	}
1284 	return nil
1285 }
1286 
1287 // For the flex operators, we ignore the flex depth and always produce cubic
1288 // segments, not linear segments. It's not obvious why the Type 2 Charstring
1289 // format cares about switching behavior based on a metric in pixels, not in
1290 // ideal font units. The Go vector rasterizer has no problems with almost
1291 // linear cubic segments.
1292 
1293 func t2CHflex(p *psInterpreter) error {
1294 	p.type2Charstrings.cubeTo(
1295 		p.argStack.a[0], 0,
1296 		p.argStack.a[1], +p.argStack.a[2],
1297 		p.argStack.a[3], 0,
1298 	)
1299 	p.type2Charstrings.cubeTo(
1300 		p.argStack.a[4], 0,
1301 		p.argStack.a[5], -p.argStack.a[2],
1302 		p.argStack.a[6], 0,
1303 	)
1304 	return nil
1305 }
1306 
1307 func t2CHflex1(p *psInterpreter) error {
1308 	dy1 := p.argStack.a[1]
1309 	dy2 := p.argStack.a[3]
1310 	dy5 := p.argStack.a[7]
1311 	dy6 := -dy1 - dy2 - dy5
1312 	p.type2Charstrings.cubeTo(
1313 		p.argStack.a[0], dy1,
1314 		p.argStack.a[2], dy2,
1315 		p.argStack.a[4], 0,
1316 	)
1317 	p.type2Charstrings.cubeTo(
1318 		p.argStack.a[5], 0,
1319 		p.argStack.a[6], dy5,
1320 		p.argStack.a[8], dy6,
1321 	)
1322 	return nil
1323 }
1324 
1325 // subrBias returns the subroutine index bias as per 5177.Type2.pdf section 4.7
1326 // "Subroutine Operators".
1327 func subrBias(numSubroutines int) int32 {
1328 	if numSubroutines < 1240 {
1329 		return 107
1330 	}
1331 	if numSubroutines < 33900 {
1332 		return 1131
1333 	}
1334 	return 32768
1335 }
1336 
1337 func t2CCallgsubr(p *psInterpreter) error {
1338 	return t2CCall(p, p.type2Charstrings.f.cached.glyphData.gsubrs)
1339 }
1340 
1341 func t2CCallsubr(p *psInterpreter) error {
1342 	t := &p.type2Charstrings
1343 	d := &t.f.cached.glyphData
1344 	subrs := d.singleSubrs
1345 	if d.multiSubrs != nil {
1346 		if t.fdSelectIndexPlusOne == 0 {
1347 			index, err := d.fdSelect.lookup(t.f, t.b, t.glyphIndex)
1348 			if err != nil {
1349 				return err
1350 			}
1351 			if index < 0 || len(d.multiSubrs) <= index {
1352 				return errInvalidCFFTable
1353 			}
1354 			t.fdSelectIndexPlusOne = int32(index + 1)
1355 		}
1356 		subrs = d.multiSubrs[t.fdSelectIndexPlusOne-1]
1357 	}
1358 	return t2CCall(p, subrs)
1359 }
1360 
1361 func t2CCall(p *psInterpreter, subrs []uint32) error {
1362 	if p.callStack.top == psCallStackSize || len(subrs) == 0 {
1363 		return errInvalidCFFTable
1364 	}
1365 	length := uint32(len(p.instructions))
1366 	p.callStack.a[p.callStack.top] = psCallStackEntry{
1367 		offset: p.instrOffset + p.instrLength - length,
1368 		length: length,
1369 	}
1370 	p.callStack.top++
1371 
1372 	subrIndex := p.argStack.a[p.argStack.top-1] + subrBias(len(subrs)-1)
1373 	if subrIndex < 0 || int32(len(subrs)-1) <= subrIndex {
1374 		return errInvalidCFFTable
1375 	}
1376 	i := subrs[subrIndex+0]
1377 	j := subrs[subrIndex+1]
1378 	if j < i {
1379 		return errInvalidCFFTable
1380 	}
1381 	if j-i > maxGlyphDataLength {
1382 		return errUnsupportedGlyphDataLength
1383 	}
1384 	buf, err := p.type2Charstrings.b.view(&p.type2Charstrings.f.src, int(i), int(j-i))
1385 	if err != nil {
1386 		return err
1387 	}
1388 
1389 	p.instructions = buf
1390 	p.instrOffset = i
1391 	p.instrLength = j - i
1392 	return nil
1393 }
1394 
1395 func t2CReturn(p *psInterpreter) error {
1396 	if p.callStack.top <= 0 {
1397 		return errInvalidCFFTable
1398 	}
1399 	p.callStack.top--
1400 	o := p.callStack.a[p.callStack.top].offset
1401 	n := p.callStack.a[p.callStack.top].length
1402 	buf, err := p.type2Charstrings.b.view(&p.type2Charstrings.f.src, int(o), int(n))
1403 	if err != nil {
1404 		return err
1405 	}
1406 
1407 	p.instructions = buf
1408 	p.instrOffset = o
1409 	p.instrLength = n
1410 	return nil
1411 }
1412 
1413 func t2CEndchar(p *psInterpreter) error {
1414 	t2CReadWidth(p, 0)
1415 	if p.argStack.top != 0 || p.hasMoreInstructions() {
1416 		if p.argStack.top == 4 {
1417 			// TODO: process the implicit "seac" command as per 5177.Type2.pdf
1418 			// Appendix C "Compatibility and Deprecated Operators".
1419 			return errUnsupportedType2Charstring
1420 		}
1421 		return errInvalidCFFTable
1422 	}
1423 	p.type2Charstrings.closePath()
1424 	p.type2Charstrings.ended = true
1425 	return nil
1426 }