summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/image/font/sfnt/sfnt_test.go')
-rw-r--r--vendor/golang.org/x/image/font/sfnt/sfnt_test.go272
1 files changed, 272 insertions, 0 deletions
diff --git a/vendor/golang.org/x/image/font/sfnt/sfnt_test.go b/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
new file mode 100644
index 000000000..4ffd72f40
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
@@ -0,0 +1,272 @@
+// Copyright 2016 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
+
+import (
+ "bytes"
+ "io/ioutil"
+ "path/filepath"
+ "testing"
+
+ "golang.org/x/image/font/gofont/goregular"
+ "golang.org/x/image/math/fixed"
+)
+
+func moveTo(xa, ya int) Segment {
+ return Segment{
+ Op: SegmentOpMoveTo,
+ Args: [6]fixed.Int26_6{
+ 0: fixed.I(xa),
+ 1: fixed.I(ya),
+ },
+ }
+}
+
+func lineTo(xa, ya int) Segment {
+ return Segment{
+ Op: SegmentOpLineTo,
+ Args: [6]fixed.Int26_6{
+ 0: fixed.I(xa),
+ 1: fixed.I(ya),
+ },
+ }
+}
+
+func quadTo(xa, ya, xb, yb int) Segment {
+ return Segment{
+ Op: SegmentOpQuadTo,
+ Args: [6]fixed.Int26_6{
+ 0: fixed.I(xa),
+ 1: fixed.I(ya),
+ 2: fixed.I(xb),
+ 3: fixed.I(yb),
+ },
+ }
+}
+
+func cubeTo(xa, ya, xb, yb, xc, yc int) Segment {
+ return Segment{
+ Op: SegmentOpCubeTo,
+ Args: [6]fixed.Int26_6{
+ 0: fixed.I(xa),
+ 1: fixed.I(ya),
+ 2: fixed.I(xb),
+ 3: fixed.I(yb),
+ 4: fixed.I(xc),
+ 5: fixed.I(yc),
+ },
+ }
+}
+
+func TestTrueTypeParse(t *testing.T) {
+ f, err := Parse(goregular.TTF)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+ testTrueType(t, f)
+}
+
+func TestTrueTypeParseReaderAt(t *testing.T) {
+ f, err := ParseReaderAt(bytes.NewReader(goregular.TTF))
+ if err != nil {
+ t.Fatalf("ParseReaderAt: %v", err)
+ }
+ testTrueType(t, f)
+}
+
+func testTrueType(t *testing.T, f *Font) {
+ if got, want := f.UnitsPerEm(), Units(2048); got != want {
+ t.Errorf("UnitsPerEm: got %d, want %d", got, want)
+ }
+ // The exact number of glyphs in goregular.TTF can vary, and future
+ // versions may add more glyphs, but https://blog.golang.org/go-fonts says
+ // that "The WGL4 character set... [has] more than 650 characters in all.
+ if got, want := f.NumGlyphs(), 650; got <= want {
+ t.Errorf("NumGlyphs: got %d, want > %d", got, want)
+ }
+}
+
+func TestPostScriptSegments(t *testing.T) {
+ // wants' vectors correspond 1-to-1 to what's in the CFFTest.sfd file,
+ // although OpenType/CFF and FontForge's SFD have reversed orders.
+ // https://fontforge.github.io/validation.html says that "All paths must be
+ // drawn in a consistent direction. Clockwise for external paths,
+ // anti-clockwise for internal paths. (Actually PostScript requires the
+ // exact opposite, but FontForge reverses PostScript contours when it loads
+ // them so that everything is consistant internally -- and reverses them
+ // again when it saves them, of course)."
+ //
+ // The .notdef glyph isn't explicitly in the SFD file, but for some unknown
+ // reason, FontForge generates it in the OpenType/CFF file.
+ wants := [][]Segment{{
+ // .notdef
+ // - contour #0
+ moveTo(50, 0),
+ lineTo(450, 0),
+ lineTo(450, 533),
+ lineTo(50, 533),
+ // - contour #1
+ moveTo(100, 50),
+ lineTo(100, 483),
+ lineTo(400, 483),
+ lineTo(400, 50),
+ }, {
+ // zero
+ // - contour #0
+ moveTo(300, 700),
+ cubeTo(380, 700, 420, 580, 420, 500),
+ cubeTo(420, 350, 390, 100, 300, 100),
+ cubeTo(220, 100, 180, 220, 180, 300),
+ cubeTo(180, 450, 210, 700, 300, 700),
+ // - contour #1
+ moveTo(300, 800),
+ cubeTo(200, 800, 100, 580, 100, 400),
+ cubeTo(100, 220, 200, 0, 300, 0),
+ cubeTo(400, 0, 500, 220, 500, 400),
+ cubeTo(500, 580, 400, 800, 300, 800),
+ }, {
+ // one
+ // - contour #0
+ moveTo(100, 0),
+ lineTo(300, 0),
+ lineTo(300, 800),
+ lineTo(100, 800),
+ }, {
+ // Q
+ // - contour #0
+ moveTo(657, 237),
+ lineTo(289, 387),
+ lineTo(519, 615),
+ // - contour #1
+ moveTo(792, 169),
+ cubeTo(867, 263, 926, 502, 791, 665),
+ cubeTo(645, 840, 380, 831, 228, 673),
+ cubeTo(71, 509, 110, 231, 242, 93),
+ cubeTo(369, -39, 641, 18, 722, 93),
+ lineTo(802, 3),
+ lineTo(864, 83),
+ }, {
+ // uni4E2D
+ // - contour #0
+ moveTo(141, 520),
+ lineTo(137, 356),
+ lineTo(245, 400),
+ lineTo(331, 26),
+ lineTo(355, 414),
+ lineTo(463, 434),
+ lineTo(453, 620),
+ lineTo(341, 592),
+ lineTo(331, 758),
+ lineTo(243, 752),
+ lineTo(235, 562),
+ // TODO: explicitly (not implicitly) close these contours?
+ }}
+
+ testSegments(t, "CFFTest.otf", wants)
+}
+
+func TestTrueTypeSegments(t *testing.T) {
+ // wants' vectors correspond 1-to-1 to what's in the glyfTest.sfd file,
+ // although FontForge's SFD format stores quadratic Bézier curves as cubics
+ // with duplicated off-curve points. quadTo(bx, by, cx, cy) is stored as
+ // "bx by bx by cx cy".
+ //
+ // The .notdef, .null and nonmarkingreturn glyphs aren't explicitly in the
+ // SFD file, but for some unknown reason, FontForge generates them in the
+ // TrueType file.
+ wants := [][]Segment{{
+ // .notdef
+ // - contour #0
+ moveTo(68, 0),
+ lineTo(68, 1365),
+ lineTo(612, 1365),
+ lineTo(612, 0),
+ lineTo(68, 0),
+ // - contour #1
+ moveTo(136, 68),
+ lineTo(544, 68),
+ lineTo(544, 1297),
+ lineTo(136, 1297),
+ lineTo(136, 68),
+ }, {
+ // .null
+ // Empty glyph.
+ }, {
+ // nonmarkingreturn
+ // Empty glyph.
+ }, {
+ // zero
+ // - contour #0
+ moveTo(614, 1434),
+ quadTo(369, 1434, 369, 614),
+ quadTo(369, 471, 435, 338),
+ quadTo(502, 205, 614, 205),
+ quadTo(860, 205, 860, 1024),
+ quadTo(860, 1167, 793, 1300),
+ quadTo(727, 1434, 614, 1434),
+ // - contour #1
+ moveTo(614, 1638),
+ quadTo(1024, 1638, 1024, 819),
+ quadTo(1024, 0, 614, 0),
+ quadTo(205, 0, 205, 819),
+ quadTo(205, 1638, 614, 1638),
+ }, {
+ // one
+ // - contour #0
+ moveTo(205, 0),
+ lineTo(205, 1638),
+ lineTo(614, 1638),
+ lineTo(614, 0),
+ lineTo(205, 0),
+ }}
+
+ testSegments(t, "glyfTest.ttf", wants)
+}
+
+func testSegments(t *testing.T, filename string, wants [][]Segment) {
+ data, err := ioutil.ReadFile(filepath.Join("..", "testdata", filename))
+ if err != nil {
+ t.Fatal(err)
+ }
+ f, err := Parse(data)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if ng := f.NumGlyphs(); ng != len(wants) {
+ t.Fatalf("NumGlyphs: got %d, want %d", ng, len(wants))
+ }
+ var b Buffer
+loop:
+ for i, want := range wants {
+ got, err := f.LoadGlyph(&b, GlyphIndex(i), nil)
+ if err != nil {
+ t.Errorf("i=%d: LoadGlyph: %v", i, err)
+ continue
+ }
+ if len(got) != len(want) {
+ t.Errorf("i=%d: got %d elements, want %d\noverall:\ngot %v\nwant %v",
+ i, len(got), len(want), got, want)
+ continue
+ }
+ for j, g := range got {
+ if w := want[j]; g != w {
+ t.Errorf("i=%d: element %d:\ngot %v\nwant %v\noverall:\ngot %v\nwant %v",
+ i, j, g, w, got, want)
+ continue loop
+ }
+ }
+ }
+ if _, err := f.LoadGlyph(nil, 0xffff, nil); err != ErrNotFound {
+ t.Errorf("LoadGlyph(..., 0xffff, ...):\ngot %v\nwant %v", err, ErrNotFound)
+ }
+
+ name, err := f.Name(nil, NameIDFamily)
+ if err != nil {
+ t.Errorf("Name: %v", err)
+ } else if want := filename[:len(filename)-len(".ttf")]; name != want {
+ t.Errorf("Name:\ngot %q\nwant %q", name, want)
+ }
+}