From fe2fa19765cb86b31715edc83a4ee5fc5baedf89 Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Wed, 31 Oct 2018 00:12:18 +0200 Subject: [PATCH] font/sfnt: support post table version 1.0 Currently, the library produces a parsing error when the font contains a PostScript table of version 1.0. CL adds this version to the validation code and implements a glyph name lookup for it. Change-Id: Id4999d8b252e5c2d8e897f637ba31270336cfe9a Reviewed-on: https://go-review.googlesource.com/c/146080 Reviewed-by: Nigel Tao --- font/sfnt/sfnt.go | 57 +++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/font/sfnt/sfnt.go b/font/sfnt/sfnt.go index 7a8effd..3109815 100644 --- a/font/sfnt/sfnt.go +++ b/font/sfnt/sfnt.go @@ -1165,6 +1165,8 @@ func (f *Font) parsePost(buf []byte, numGlyphs int32) (buf1 []byte, postTableVer return nil, 0, err } switch u { + case 0x10000: + // No-op. case 0x20000: if f.post.length < headerSize+2+2*uint32(numGlyphs) { return nil, 0, errInvalidPostTable @@ -1299,30 +1301,20 @@ func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, opts *Load return b.segments, nil } -// GlyphName returns the name of the x'th glyph. -// -// Not every font contains glyph names. If not present, GlyphName will return -// ("", nil). -// -// If present, the glyph name, provided by the font, is assumed to follow the -// Adobe Glyph List Specification: -// https://github.com/adobe-type-tools/agl-specification/blob/master/README.md -// -// This is also known as the "Adobe Glyph Naming convention", the "Adobe -// document [for] Unicode and Glyph Names" or "PostScript glyph names". -// -// It returns ErrNotFound if the glyph index is out of range. -func (f *Font) GlyphName(b *Buffer, x GlyphIndex) (string, error) { - if int(x) >= f.NumGlyphs() { +func (f *Font) glyphNameFormat10(x GlyphIndex) (string, error) { + if x >= numBuiltInPostNames { return "", ErrNotFound } - if f.cached.postTableVersion != 0x20000 { - return "", nil - } + // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html + i := builtInPostNamesOffsets[x+0] + j := builtInPostNamesOffsets[x+1] + return builtInPostNamesData[i:j], nil +} + +func (f *Font) glyphNameFormat20(b *Buffer, x GlyphIndex) (string, error) { if b == nil { b = &Buffer{} } - // The wire format for a Version 2 post table is documented at: // https://www.microsoft.com/typography/otspec/post.htm const glyphNameIndexOffset = 34 @@ -1371,6 +1363,33 @@ func (f *Font) GlyphName(b *Buffer, x GlyphIndex) (string, error) { } } +// GlyphName returns the name of the x'th glyph. +// +// Not every font contains glyph names. If not present, GlyphName will return +// ("", nil). +// +// If present, the glyph name, provided by the font, is assumed to follow the +// Adobe Glyph List Specification: +// https://github.com/adobe-type-tools/agl-specification/blob/master/README.md +// +// This is also known as the "Adobe Glyph Naming convention", the "Adobe +// document [for] Unicode and Glyph Names" or "PostScript glyph names". +// +// It returns ErrNotFound if the glyph index is out of range. +func (f *Font) GlyphName(b *Buffer, x GlyphIndex) (string, error) { + if int(x) >= f.NumGlyphs() { + return "", ErrNotFound + } + switch f.cached.postTableVersion { + case 0x10000: + return f.glyphNameFormat10(x) + case 0x20000: + return f.glyphNameFormat20(b, x) + default: + return "", nil + } +} + // GlyphAdvance returns the advance width for the x'th glyph. ppem is the // number of pixels in 1 em. //