func()

in font/sfnt/postscript.go [135:311]


func (p *cffParser) parse(numGlyphs int32) (ret glyphData, err error) {
	// Parse the header.
	{
		if !p.read(4) {
			return glyphData{}, p.err
		}
		if p.buf[0] != 1 || p.buf[1] != 0 || p.buf[2] != 4 {
			return glyphData{}, errUnsupportedCFFVersion
		}
	}

	// Parse the Name INDEX.
	{
		count, offSize, ok := p.parseIndexHeader()
		if !ok {
			return glyphData{}, p.err
		}
		// https://www.microsoft.com/typography/OTSPEC/cff.htm says that "The
		// Name INDEX in the CFF must contain only one entry".
		if count != 1 {
			return glyphData{}, errInvalidCFFTable
		}
		if !p.parseIndexLocations(p.locBuf[:2], count, offSize) {
			return glyphData{}, p.err
		}
		p.offset = int(p.locBuf[1])
	}

	// Parse the Top DICT INDEX.
	p.psi.topDict.initialize()
	{
		count, offSize, ok := p.parseIndexHeader()
		if !ok {
			return glyphData{}, p.err
		}
		// 5176.CFF.pdf section 8 "Top DICT INDEX" says that the count here
		// should match the count of the Name INDEX, which is 1.
		if count != 1 {
			return glyphData{}, errInvalidCFFTable
		}
		if !p.parseIndexLocations(p.locBuf[:2], count, offSize) {
			return glyphData{}, p.err
		}
		if !p.read(int(p.locBuf[1] - p.locBuf[0])) {
			return glyphData{}, p.err
		}
		if p.err = p.psi.run(psContextTopDict, p.buf, 0, 0); p.err != nil {
			return glyphData{}, p.err
		}
	}

	// Skip the String INDEX.
	{
		count, offSize, ok := p.parseIndexHeader()
		if !ok {
			return glyphData{}, p.err
		}
		if count != 0 {
			// Read the last location. Locations are off by 1 byte. See the
			// comment in parseIndexLocations.
			if !p.skip(int(count * offSize)) {
				return glyphData{}, p.err
			}
			if !p.read(int(offSize)) {
				return glyphData{}, p.err
			}
			loc := bigEndian(p.buf) - 1
			// Check that locations are in bounds.
			if uint32(p.end-p.offset) < loc {
				return glyphData{}, errInvalidCFFTable
			}
			// Skip the index data.
			if !p.skip(int(loc)) {
				return glyphData{}, p.err
			}
		}
	}

	// Parse the Global Subrs [Subroutines] INDEX.
	{
		count, offSize, ok := p.parseIndexHeader()
		if !ok {
			return glyphData{}, p.err
		}
		if count != 0 {
			if count > maxNumSubroutines {
				return glyphData{}, errUnsupportedNumberOfSubroutines
			}
			ret.gsubrs = make([]uint32, count+1)
			if !p.parseIndexLocations(ret.gsubrs, count, offSize) {
				return glyphData{}, p.err
			}
		}
	}

	// Parse the CharStrings INDEX, whose location was found in the Top DICT.
	{
		if !p.seekFromBase(p.psi.topDict.charStringsOffset) {
			return glyphData{}, errInvalidCFFTable
		}
		count, offSize, ok := p.parseIndexHeader()
		if !ok {
			return glyphData{}, p.err
		}
		if count == 0 || int32(count) != numGlyphs {
			return glyphData{}, errInvalidCFFTable
		}
		ret.locations = make([]uint32, count+1)
		if !p.parseIndexLocations(ret.locations, count, offSize) {
			return glyphData{}, p.err
		}
	}

	if !p.psi.topDict.isCIDFont {
		// Parse the Private DICT, whose location was found in the Top DICT.
		ret.singleSubrs, err = p.parsePrivateDICT(
			p.psi.topDict.privateDictOffset,
			p.psi.topDict.privateDictLength,
		)
		if err != nil {
			return glyphData{}, err
		}

	} else {
		// Parse the Font Dict Select data, whose location was found in the Top
		// DICT.
		ret.fdSelect, err = p.parseFDSelect(p.psi.topDict.fdSelect, numGlyphs)
		if err != nil {
			return glyphData{}, err
		}

		// Parse the Font Dicts. Each one contains its own Private DICT.
		if !p.seekFromBase(p.psi.topDict.fdArray) {
			return glyphData{}, errInvalidCFFTable
		}

		count, offSize, ok := p.parseIndexHeader()
		if !ok {
			return glyphData{}, p.err
		}
		if count > maxNumFontDicts {
			return glyphData{}, errUnsupportedNumberOfFontDicts
		}

		fdLocations := make([]uint32, count+1)
		if !p.parseIndexLocations(fdLocations, count, offSize) {
			return glyphData{}, p.err
		}

		privateDicts := make([]struct {
			offset, length int32
		}, count)

		for i := range privateDicts {
			length := fdLocations[i+1] - fdLocations[i]
			if !p.read(int(length)) {
				return glyphData{}, errInvalidCFFTable
			}
			p.psi.topDict.initialize()
			if p.err = p.psi.run(psContextTopDict, p.buf, 0, 0); p.err != nil {
				return glyphData{}, p.err
			}
			privateDicts[i].offset = p.psi.topDict.privateDictOffset
			privateDicts[i].length = p.psi.topDict.privateDictLength
		}

		ret.multiSubrs = make([][]uint32, count)
		for i, pd := range privateDicts {
			ret.multiSubrs[i], err = p.parsePrivateDICT(pd.offset, pd.length)
			if err != nil {
				return glyphData{}, err
			}
		}
	}

	return ret, err
}