font/sfnt: support non-zero offsets in format-4 cmap tables.
Change-Id: I52592fcde96ce2f3b7700a29169b517a813f9f3c Reviewed-on: https://go-review.googlesource.com/36371 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
993cf229e6
commit
05f0a469d9
|
@ -167,6 +167,8 @@ func (f *Font) makeCachedGlyphIndexFormat4(buf []byte, offset, length uint32) ([
|
||||||
offset: u16(buf[6*len(entries)+2+2*i:]),
|
offset: u16(buf[6*len(entries)+2+2*i:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
indexesBase := f.cmap.offset + offset
|
||||||
|
indexesLength := f.cmap.length - offset
|
||||||
|
|
||||||
f.cached.glyphIndex = func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
|
f.cached.glyphIndex = func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
|
||||||
if uint32(r) > 0xffff {
|
if uint32(r) > 0xffff {
|
||||||
|
@ -184,11 +186,15 @@ func (f *Font) makeCachedGlyphIndexFormat4(buf []byte, offset, length uint32) ([
|
||||||
} else if entry.offset == 0 {
|
} else if entry.offset == 0 {
|
||||||
return GlyphIndex(c + entry.delta), nil
|
return GlyphIndex(c + entry.delta), nil
|
||||||
} else {
|
} else {
|
||||||
// TODO: support the glyphIdArray as per
|
offset := uint32(entry.offset) + 2*uint32(h-len(entries)+int(c-entry.start))
|
||||||
// https://www.microsoft.com/typography/OTSPEC/cmap.htm
|
if offset > indexesLength || offset+2 > indexesLength {
|
||||||
//
|
return 0, errInvalidCmapTable
|
||||||
// This will probably use the *Font and *Buffer arguments.
|
}
|
||||||
return 0, errUnsupportedCmapFormat
|
x, err := b.view(&f.src, int(indexesBase+offset), 2)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return GlyphIndex(u16(x)), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
|
|
@ -73,7 +73,6 @@ var (
|
||||||
|
|
||||||
errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
|
errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
|
||||||
errUnsupportedCmapEncodings = errors.New("sfnt: unsupported cmap encodings")
|
errUnsupportedCmapEncodings = errors.New("sfnt: unsupported cmap encodings")
|
||||||
errUnsupportedCmapFormat = errors.New("sfnt: unsupported cmap format")
|
|
||||||
errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
|
errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
|
||||||
errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
|
errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
|
||||||
errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
|
errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
|
||||||
|
|
|
@ -88,6 +88,62 @@ func testTrueType(t *testing.T, f *Font) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGoRegularGlyphIndex(t *testing.T) {
|
||||||
|
f, err := Parse(goregular.TTF)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
r rune
|
||||||
|
want GlyphIndex
|
||||||
|
}{
|
||||||
|
// Glyphs that aren't present in Go Regular.
|
||||||
|
{'\u001f', 0}, // U+001F <control>
|
||||||
|
{'\u0200', 0}, // U+0200 LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
|
||||||
|
{'\u2000', 0}, // U+2000 EN QUAD
|
||||||
|
|
||||||
|
// The want values below can be verified by running the ttx tool on
|
||||||
|
// Go-Regular.ttf.
|
||||||
|
//
|
||||||
|
// The actual values are ad hoc, and result from whatever tools the
|
||||||
|
// Bigelow & Holmes type foundry used and the order in which they
|
||||||
|
// crafted the glyphs. They may change over time as newer versions of
|
||||||
|
// the font are released. In practice, though, running this test with
|
||||||
|
// coverage analysis suggests that it covers both the zero and non-zero
|
||||||
|
// cmapEntry16.offset cases for a format-4 cmap table.
|
||||||
|
|
||||||
|
{'\u0020', 3}, // U+0020 SPACE
|
||||||
|
{'\u0021', 4}, // U+0021 EXCLAMATION MARK
|
||||||
|
{'\u0022', 5}, // U+0022 QUOTATION MARK
|
||||||
|
{'\u0023', 6}, // U+0023 NUMBER SIGN
|
||||||
|
{'\u0024', 223}, // U+0024 DOLLAR SIGN
|
||||||
|
{'\u0025', 7}, // U+0025 PERCENT SIGN
|
||||||
|
{'\u0026', 8}, // U+0026 AMPERSAND
|
||||||
|
{'\u0027', 9}, // U+0027 APOSTROPHE
|
||||||
|
|
||||||
|
{'\u03bd', 423}, // U+03BD GREEK SMALL LETTER NU
|
||||||
|
{'\u03be', 424}, // U+03BE GREEK SMALL LETTER XI
|
||||||
|
{'\u03bf', 438}, // U+03BF GREEK SMALL LETTER OMICRON
|
||||||
|
{'\u03c0', 208}, // U+03C0 GREEK SMALL LETTER PI
|
||||||
|
{'\u03c1', 425}, // U+03C1 GREEK SMALL LETTER RHO
|
||||||
|
{'\u03c2', 426}, // U+03C2 GREEK SMALL LETTER FINAL SIGMA
|
||||||
|
}
|
||||||
|
|
||||||
|
var b Buffer
|
||||||
|
for _, tc := range testCases {
|
||||||
|
got, err := f.GlyphIndex(&b, tc.r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("r=%q: %v", tc.r, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("r=%q: got %d, want %d", tc.r, got, tc.want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGlyphIndex(t *testing.T) {
|
func TestGlyphIndex(t *testing.T) {
|
||||||
data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/cmapTest.ttf"))
|
data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/cmapTest.ttf"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user