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
}