blob: d25c62a6f8e78014c0bd3e8b1b63367fc0697f00 [file] [log] [blame]
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sfnt
/*
This file contains opt-in tests for popular, high quality, proprietary fonts,
made by companies such as Adobe and Microsoft. These fonts are generally
available, but copies are not explicitly included in this repository due to
licensing differences or file size concerns. To opt-in, run:
go test golang.org/x/image/font/sfnt -args -proprietary
Not all tests pass out-of-the-box on all systems. For example, the Microsoft
Times New Roman font is downloadable gratis even on non-Windows systems, but as
per the ttf-mscorefonts-installer Debian package, this requires accepting an
End User License Agreement (EULA) and a CAB format decoder. These tests assume
that such fonts have already been installed. You may need to specify the
directories for these fonts:
go test golang.org/x/image/font/sfnt -args -proprietary -adobeDir=/foo/bar/aFonts -microsoftDir=/foo/bar/mFonts
To only run those tests for the Microsoft fonts:
go test golang.org/x/image/font/sfnt -test.run=ProprietaryMicrosoft -args -proprietary
*/
// TODO: add Apple system fonts? Google fonts (Droid? Noto?)? Emoji fonts?
// TODO: enable Apple/Microsoft tests by default on Darwin/Windows?
import (
"flag"
"io/ioutil"
"path/filepath"
"testing"
"golang.org/x/image/math/fixed"
)
var (
proprietary = flag.Bool("proprietary", false, "test proprietary fonts not included in this repository")
adobeDir = flag.String(
"adobeDir",
// This needs to be set explicitly. There is no default dir on Debian:
// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736680
//
// Get the fonts from https://github.com/adobe-fonts, e.g.:
// - https://github.com/adobe-fonts/source-code-pro/releases/latest
// - https://github.com/adobe-fonts/source-han-sans/releases/latest
// - https://github.com/adobe-fonts/source-sans-pro/releases/latest
//
// Copy all of the TTF and OTF files to the one directory, such as
// $HOME/adobe-fonts, and pass that as the -adobeDir flag here.
"",
"directory name for the Adobe proprietary fonts",
)
microsoftDir = flag.String(
"microsoftDir",
"/usr/share/fonts/truetype/msttcorefonts",
"directory name for the Microsoft proprietary fonts",
)
)
func TestProprietaryAdobeSourceCodeProOTF(t *testing.T) {
testProprietary(t, "adobe", "SourceCodePro-Regular.otf", 1500, 2)
}
func TestProprietaryAdobeSourceCodeProTTF(t *testing.T) {
testProprietary(t, "adobe", "SourceCodePro-Regular.ttf", 1500, 36)
}
func TestProprietaryAdobeSourceHanSansSC(t *testing.T) {
testProprietary(t, "adobe", "SourceHanSansSC-Regular.otf", 65535, 2)
}
func TestProprietaryAdobeSourceSansProOTF(t *testing.T) {
testProprietary(t, "adobe", "SourceSansPro-Regular.otf", 1800, 2)
}
func TestProprietaryAdobeSourceSansProTTF(t *testing.T) {
testProprietary(t, "adobe", "SourceSansPro-Regular.ttf", 1800, 54)
}
func TestProprietaryMicrosoftArial(t *testing.T) {
testProprietary(t, "microsoft", "Arial.ttf", 1200, 98)
}
func TestProprietaryMicrosoftComicSansMS(t *testing.T) {
testProprietary(t, "microsoft", "Comic_Sans_MS.ttf", 550, 98)
}
func TestProprietaryMicrosoftTimesNewRoman(t *testing.T) {
testProprietary(t, "microsoft", "Times_New_Roman.ttf", 1200, 98)
}
func TestProprietaryMicrosoftWebdings(t *testing.T) {
testProprietary(t, "microsoft", "Webdings.ttf", 200, -1)
}
// testProprietary tests that we can load every glyph in the named font.
//
// The exact number of glyphs in the font can differ across its various
// versions, but as a sanity check, there should be at least minNumGlyphs.
//
// While this package is a work-in-progress, not every glyph can be loaded. The
// firstUnsupportedGlyph argument, if non-negative, is the index of the first
// unsupported glyph in the font. This number should increase over time (or set
// negative), as the TODO's in this package are done.
func testProprietary(t *testing.T, proprietor, filename string, minNumGlyphs, firstUnsupportedGlyph int) {
if !*proprietary {
t.Skip("skipping proprietary font test")
}
file, err := []byte(nil), error(nil)
switch proprietor {
case "adobe":
file, err = ioutil.ReadFile(filepath.Join(*adobeDir, filename))
if err != nil {
t.Fatalf("%v\nPerhaps you need to set the -adobeDir=%v flag?", err, *adobeDir)
}
case "microsoft":
file, err = ioutil.ReadFile(filepath.Join(*microsoftDir, filename))
if err != nil {
t.Fatalf("%v\nPerhaps you need to set the -microsoftDir=%v flag?", err, *microsoftDir)
}
default:
panic("unreachable")
}
f, err := Parse(file)
if err != nil {
t.Fatalf("Parse: %v", err)
}
ppem := fixed.Int26_6(f.UnitsPerEm()) << 6
numGlyphs := f.NumGlyphs()
if numGlyphs < minNumGlyphs {
t.Fatalf("NumGlyphs: got %d, want at least %d", numGlyphs, minNumGlyphs)
}
var buf Buffer
iMax := numGlyphs
if firstUnsupportedGlyph >= 0 {
iMax = firstUnsupportedGlyph
}
for i, numErrors := 0, 0; i < iMax; i++ {
if _, err := f.LoadGlyph(&buf, GlyphIndex(i), ppem, nil); err != nil {
t.Errorf("LoadGlyph(%d): %v", i, err)
numErrors++
}
if numErrors == 10 {
t.Fatal("LoadGlyph: too many errors")
}
}
for r, want := range proprietaryGlyphIndexTestCases[proprietor+"/"+filename] {
got, err := f.GlyphIndex(&buf, r)
if err != nil {
t.Errorf("GlyphIndex(%q): %v", r, err)
continue
}
if got != want {
t.Errorf("GlyphIndex(%q): got %d, want %d", r, got, want)
continue
}
}
}
// proprietaryGlyphIndexTestCases hold a sample of each font's rune to glyph
// index cmap. The numerical values can be verified by running the ttx tool.
var proprietaryGlyphIndexTestCases = map[string]map[rune]GlyphIndex{
"adobe/SourceCodePro-Regular.otf": {
'\u0030': 877, // U+0030 DIGIT ZERO
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u0061': 28, // U+0061 LATIN SMALL LETTER A
'\u0104': 64, // U+0104 LATIN CAPITAL LETTER A WITH OGONEK
'\u0125': 323, // U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX
'\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
'\u03a3': 623, // U+03A3 GREEK CAPITAL LETTER SIGMA
'\u2569': 1500, // U+2569 BOX DRAWINGS DOUBLE UP AND HORIZONTAL
'\U0001f100': 0, // U+0001F100 DIGIT ZERO FULL STOP
},
"adobe/SourceCodePro-Regular.ttf": {
'\u0030': 877, // U+0030 DIGIT ZERO
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
},
"adobe/SourceHanSansSC-Regular.otf": {
'\u0030': 17, // U+0030 DIGIT ZERO
'\u0041': 34, // U+0041 LATIN CAPITAL LETTER A
'\u00d7': 150, // U+00D7 MULTIPLICATION SIGN
'\u1100': 365, // U+1100 HANGUL CHOSEONG KIYEOK
'\u25ca': 1254, // U+25CA LOZENGE
'\u2e9c': 1359, // U+2E9C CJK RADICAL SUN
'\u304b': 1463, // U+304B HIRAGANA LETTER KA
'\u4e2d': 9893, // U+4E2D <CJK Ideograph>, δΈ­
'\ua960': 47537, // U+A960 HANGUL CHOSEONG TIKEUT-MIEUM
'\ufb00': 58919, // U+FB00 LATIN SMALL LIGATURE FF
'\uffee': 59213, // U+FFEE HALFWIDTH WHITE CIRCLE
'\U0001f100': 59214, // U+0001F100 DIGIT ZERO FULL STOP
'\U0001f248': 59449, // U+0001F248 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
'\U0002f9f4': 61768, // U+0002F9F4 CJK COMPATIBILITY IDEOGRAPH-2F9F4
},
"adobe/SourceSansPro-Regular.otf": {
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u03a3': 592, // U+03A3 GREEK CAPITAL LETTER SIGMA
'\u0435': 999, // U+0435 CYRILLIC SMALL LETTER IE
'\u2030': 1728, // U+2030 PER MILLE SIGN
},
"adobe/SourceSansPro-Regular.ttf": {
'\u0041': 2, // U+0041 LATIN CAPITAL LETTER A
'\u03a3': 592, // U+03A3 GREEK CAPITAL LETTER SIGMA
'\u0435': 999, // U+0435 CYRILLIC SMALL LETTER IE
'\u2030': 1728, // U+2030 PER MILLE SIGN
},
"microsoft/Arial.ttf": {
'\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
'\u00f1': 120, // U+00F1 LATIN SMALL LETTER N WITH TILDE
'\u0401': 556, // U+0401 CYRILLIC CAPITAL LETTER IO
'\u200d': 745, // U+200D ZERO WIDTH JOINER
'\u20ab': 1150, // U+20AB DONG SIGN
'\u2229': 320, // U+2229 INTERSECTION
'\u04e9': 1319, // U+04E9 CYRILLIC SMALL LETTER BARRED O
'\U0001f100': 0, // U+0001F100 DIGIT ZERO FULL STOP
},
"microsoft/Comic_Sans_MS.ttf": {
'\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
'\u03af': 573, // U+03AF GREEK SMALL LETTER IOTA WITH TONOS
},
"microsoft/Times_New_Roman.ttf": {
'\u0041': 36, // U+0041 LATIN CAPITAL LETTER A
'\u0042': 37, // U+0041 LATIN CAPITAL LETTER B
'\u266a': 392, // U+266A EIGHTH NOTE
'\uf041': 0, // PRIVATE USE AREA
'\uf042': 0, // PRIVATE USE AREA
},
"microsoft/Webdings.ttf": {
'\u0041': 0, // U+0041 LATIN CAPITAL LETTER A
'\u0042': 0, // U+0041 LATIN CAPITAL LETTER B
'\u266a': 0, // U+266A EIGHTH NOTE
'\uf041': 36, // PRIVATE USE AREA
'\uf042': 37, // PRIVATE USE AREA
},
}