font/sfnt: support cmap format 6 The library provides support for CMap formats 2, 4 and 12, but does not support CMap format 6. CL adds support for CMap format 6 (trimmed table mapping). Change-Id: I40657c4805c14017367af17596023da96b2c7483 Reviewed-on: https://go-review.googlesource.com/c/146079 Reviewed-by: Nigel Tao <nigeltao@golang.org> Run-TryBot: Nigel Tao <nigeltao@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/font/sfnt/cmap.go b/font/sfnt/cmap.go index 797e9d1..55b4ead 100644 --- a/font/sfnt/cmap.go +++ b/font/sfnt/cmap.go
@@ -80,6 +80,8 @@ return pid == pidMacintosh && psid == psidMacintoshRoman case 4: return true + case 6: + return true case 12: return true } @@ -92,6 +94,8 @@ return f.makeCachedGlyphIndexFormat0(buf, offset, length) case 4: return f.makeCachedGlyphIndexFormat4(buf, offset, length) + case 6: + return f.makeCachedGlyphIndexFormat6(buf, offset, length) case 12: return f.makeCachedGlyphIndexFormat12(buf, offset, length) } @@ -193,6 +197,52 @@ }, nil } +func (f *Font) makeCachedGlyphIndexFormat6(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) { + const headerSize = 10 + if offset+headerSize > f.cmap.length { + return nil, nil, errInvalidCmapTable + } + var err error + buf, err = f.src.view(buf, int(f.cmap.offset+offset), headerSize) + if err != nil { + return nil, nil, err + } + offset += headerSize + + firstCode := u16(buf[6:]) + entryCount := u16(buf[8:]) + + eLength := 2 * uint32(entryCount) + if offset+eLength > f.cmap.length { + return nil, nil, errInvalidCmapTable + } + + if entryCount != 0 { + buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength)) + if err != nil { + return nil, nil, err + } + offset += eLength + } + + entries := make([]uint16, entryCount) + for i := range entries { + entries[i] = u16(buf[2*i:]) + } + + return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) { + if uint16(r) < firstCode { + return 0, nil + } + + c := int(uint16(r) - firstCode) + if c >= len(entries) { + return 0, nil + } + return GlyphIndex(entries[c]), nil + }, nil +} + func (f *Font) makeCachedGlyphIndexFormat12(buf []byte, offset, _ uint32) ([]byte, glyphIndexFunc, error) { const headerSize = 16 if offset+headerSize > f.cmap.length {