...

Source file src/golang.org/x/image/font/sfnt/postscript.go

Documentation: golang.org/x/image/font/sfnt

     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  }
  1427  

View as plain text