summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/image
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/image')
-rw-r--r--vendor/golang.org/x/image/draw/draw.go42
-rw-r--r--vendor/golang.org/x/image/draw/gen.go2
-rw-r--r--vendor/golang.org/x/image/draw/go1_8.go49
-rw-r--r--vendor/golang.org/x/image/draw/go1_9.go57
-rw-r--r--vendor/golang.org/x/image/draw/impl.go96
-rw-r--r--vendor/golang.org/x/image/draw/stdlib_test.go6
-rw-r--r--vendor/golang.org/x/image/font/sfnt/cmap.go269
-rw-r--r--vendor/golang.org/x/image/font/sfnt/data.go68
-rw-r--r--vendor/golang.org/x/image/font/sfnt/example_test.go128
-rw-r--r--vendor/golang.org/x/image/font/sfnt/gen.go321
-rw-r--r--vendor/golang.org/x/image/font/sfnt/postscript.go111
-rw-r--r--vendor/golang.org/x/image/font/sfnt/proprietary_test.go479
-rw-r--r--vendor/golang.org/x/image/font/sfnt/sfnt.go561
-rw-r--r--vendor/golang.org/x/image/font/sfnt/sfnt_test.go370
-rw-r--r--vendor/golang.org/x/image/font/sfnt/truetype.go29
-rw-r--r--vendor/golang.org/x/image/font/testdata/cmapTest.sfd265
-rw-r--r--vendor/golang.org/x/image/font/testdata/cmapTest.ttfbin0 -> 2528 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-down-ab.pngbin21338 -> 21092 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-down-bl.pngbin18581 -> 18169 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-down-cr.pngbin19519 -> 19141 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-down-nn.pngbin21504 -> 21320 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.pngbin7654 -> 7417 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.pngbin7653 -> 7421 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.pngbin7808 -> 7544 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.pngbin4915 -> 5128 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-up-ab.pngbin9633 -> 9427 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-up-bl.pngbin9639 -> 9427 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-up-cr.pngbin10987 -> 10694 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/go-turns-two-up-nn.pngbin1368 -> 1369 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/tux-rotate-ab.pngbin3237 -> 3340 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/tux-rotate-bl.pngbin3751 -> 3836 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/tux-rotate-cr.pngbin3753 -> 3841 bytes
-rw-r--r--vendor/golang.org/x/image/testdata/tux-rotate-nn.pngbin3055 -> 3159 bytes
33 files changed, 2604 insertions, 249 deletions
diff --git a/vendor/golang.org/x/image/draw/draw.go b/vendor/golang.org/x/image/draw/draw.go
index b92e3c7f9..dfaa7fc55 100644
--- a/vendor/golang.org/x/image/draw/draw.go
+++ b/vendor/golang.org/x/image/draw/draw.go
@@ -11,12 +11,12 @@
// package in the standard library.
package draw
-// This file just contains the API exported by the image/draw package in the
-// standard library. Other files in this package provide additional features.
+// This file, and the go1_*.go files, just contains the API exported by the
+// image/draw package in the standard library. Other files in this package
+// provide additional features.
import (
"image"
- "image/color"
"image/draw"
)
@@ -32,13 +32,6 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
draw.DrawMask(dst, r, src, sp, mask, mp, draw.Op(op))
}
-// Drawer contains the Draw method.
-type Drawer interface {
- // Draw aligns r.Min in dst with sp in src and then replaces the
- // rectangle r in dst with the result of drawing src on dst.
- Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
-}
-
// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
// diffusion.
var FloydSteinberg Drawer = floydSteinberg{}
@@ -48,32 +41,3 @@ type floydSteinberg struct{}
func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
draw.FloydSteinberg.Draw(dst, r, src, sp)
}
-
-// Image is an image.Image with a Set method to change a single pixel.
-type Image interface {
- image.Image
- Set(x, y int, c color.Color)
-}
-
-// Op is a Porter-Duff compositing operator.
-type Op int
-
-const (
- // Over specifies ``(src in mask) over dst''.
- Over Op = Op(draw.Over)
- // Src specifies ``src in mask''.
- Src Op = Op(draw.Src)
-)
-
-// Draw implements the Drawer interface by calling the Draw function with
-// this Op.
-func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
- (draw.Op(op)).Draw(dst, r, src, sp)
-}
-
-// Quantizer produces a palette for an image.
-type Quantizer interface {
- // Quantize appends up to cap(p) - len(p) colors to p and returns the
- // updated palette suitable for converting m to a paletted image.
- Quantize(p color.Palette, m image.Image) color.Palette
-}
diff --git a/vendor/golang.org/x/image/draw/gen.go b/vendor/golang.org/x/image/draw/gen.go
index 0fed47437..65a712350 100644
--- a/vendor/golang.org/x/image/draw/gen.go
+++ b/vendor/golang.org/x/image/draw/gen.go
@@ -804,7 +804,7 @@ func cOffset(x, y, sratio string) string {
func ycbcrToRGB(lhs, tmp string) string {
s := `
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- $yy1 := int(src.Y[$i]) * 0x10100
+ $yy1 := int(src.Y[$i]) * 0x10101
$cb1 := int(src.Cb[$j]) - 128
$cr1 := int(src.Cr[$j]) - 128
$r@ := ($yy1 + 91881*$cr1) >> 8
diff --git a/vendor/golang.org/x/image/draw/go1_8.go b/vendor/golang.org/x/image/draw/go1_8.go
new file mode 100644
index 000000000..ec192b717
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/go1_8.go
@@ -0,0 +1,49 @@
+// Copyright 2015 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.
+
+// +build !go1.9,!go1.8.typealias
+
+package draw
+
+import (
+ "image"
+ "image/color"
+ "image/draw"
+)
+
+// Drawer contains the Draw method.
+type Drawer interface {
+ // Draw aligns r.Min in dst with sp in src and then replaces the
+ // rectangle r in dst with the result of drawing src on dst.
+ Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
+}
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image interface {
+ image.Image
+ Set(x, y int, c color.Color)
+}
+
+// Op is a Porter-Duff compositing operator.
+type Op int
+
+const (
+ // Over specifies ``(src in mask) over dst''.
+ Over Op = Op(draw.Over)
+ // Src specifies ``src in mask''.
+ Src Op = Op(draw.Src)
+)
+
+// Draw implements the Drawer interface by calling the Draw function with
+// this Op.
+func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+ (draw.Op(op)).Draw(dst, r, src, sp)
+}
+
+// Quantizer produces a palette for an image.
+type Quantizer interface {
+ // Quantize appends up to cap(p) - len(p) colors to p and returns the
+ // updated palette suitable for converting m to a paletted image.
+ Quantize(p color.Palette, m image.Image) color.Palette
+}
diff --git a/vendor/golang.org/x/image/draw/go1_9.go b/vendor/golang.org/x/image/draw/go1_9.go
new file mode 100644
index 000000000..fc548e947
--- /dev/null
+++ b/vendor/golang.org/x/image/draw/go1_9.go
@@ -0,0 +1,57 @@
+// 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.
+
+// +build go1.9 go1.8.typealias
+
+package draw
+
+import (
+ "image/draw"
+)
+
+// We use type aliases (new in Go 1.9) for the exported names from the standard
+// library's image/draw package. This is not merely syntactic sugar for
+//
+// type Drawer draw.Drawer
+//
+// as aliasing means that the types in this package, such as draw.Image and
+// draw.Op, are identical to the corresponding draw.Image and draw.Op types in
+// the standard library. In comparison, prior to Go 1.9, the code in go1_8.go
+// defines new types that mimic the old but are different types.
+//
+// The package documentation, in draw.go, explicitly gives the intent of this
+// package:
+//
+// This package is a superset of and a drop-in replacement for the
+// image/draw package in the standard library.
+//
+// Drop-in replacement means that I can replace all of my "image/draw" imports
+// with "golang.org/x/image/draw", to access additional features in this
+// package, and no further changes are required. That's mostly true, but not
+// completely true unless we use type aliases.
+//
+// Without type aliases, users might need to import both "image/draw" and
+// "golang.org/x/image/draw" in order to convert from two conceptually
+// equivalent but different (from the compiler's point of view) types, such as
+// from one draw.Op type to another draw.Op type, to satisfy some other
+// interface or function signature.
+
+// Drawer contains the Draw method.
+type Drawer = draw.Drawer
+
+// Image is an image.Image with a Set method to change a single pixel.
+type Image = draw.Image
+
+// Op is a Porter-Duff compositing operator.
+type Op = draw.Op
+
+const (
+ // Over specifies ``(src in mask) over dst''.
+ Over Op = draw.Over
+ // Src specifies ``src in mask''.
+ Src Op = draw.Src
+)
+
+// Quantizer produces a palette for an image.
+type Quantizer = draw.Quantizer
diff --git a/vendor/golang.org/x/image/draw/impl.go b/vendor/golang.org/x/image/draw/impl.go
index d6484d734..637887be6 100644
--- a/vendor/golang.org/x/image/draw/impl.go
+++ b/vendor/golang.org/x/image/draw/impl.go
@@ -343,7 +343,7 @@ func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rec
pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -386,7 +386,7 @@ func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rec
pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -429,7 +429,7 @@ func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rec
pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -472,7 +472,7 @@ func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rec
pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -759,7 +759,7 @@ func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image
pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -803,7 +803,7 @@ func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image
pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -847,7 +847,7 @@ func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image
pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -891,7 +891,7 @@ func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image
pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pr := (pyy1 + 91881*pcr1) >> 8
@@ -1756,7 +1756,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -1785,7 +1785,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -1817,7 +1817,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -1846,7 +1846,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -1931,7 +1931,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -1960,7 +1960,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -1992,7 +1992,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2021,7 +2021,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -2106,7 +2106,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -2135,7 +2135,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -2167,7 +2167,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2196,7 +2196,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -2281,7 +2281,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -2310,7 +2310,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -2342,7 +2342,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -2371,7 +2371,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3345,7 +3345,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3374,7 +3374,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3406,7 +3406,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3435,7 +3435,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3521,7 +3521,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3550,7 +3550,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3582,7 +3582,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3611,7 +3611,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3697,7 +3697,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3726,7 +3726,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3758,7 +3758,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3787,7 +3787,7 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr imag
s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -3873,7 +3873,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10100
+ s00yy1 := int(src.Y[s00i]) * 0x10101
s00cb1 := int(src.Cb[s00j]) - 128
s00cr1 := int(src.Cr[s00j]) - 128
s00ru := (s00yy1 + 91881*s00cr1) >> 8
@@ -3902,7 +3902,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10100
+ s10yy1 := int(src.Y[s10i]) * 0x10101
s10cb1 := int(src.Cb[s10j]) - 128
s10cr1 := int(src.Cr[s10j]) - 128
s10ru := (s10yy1 + 91881*s10cr1) >> 8
@@ -3934,7 +3934,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10100
+ s01yy1 := int(src.Y[s01i]) * 0x10101
s01cb1 := int(src.Cb[s01j]) - 128
s01cr1 := int(src.Cr[s01j]) - 128
s01ru := (s01yy1 + 91881*s01cr1) >> 8
@@ -3963,7 +3963,7 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr imag
s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10100
+ s11yy1 := int(src.Y[s11i]) * 0x10101
s11cb1 := int(src.Cb[s11j]) - 128
s11cr1 := int(src.Cr[s11j]) - 128
s11ru := (s11yy1 + 91881*s11cr1) >> 8
@@ -4729,7 +4729,7 @@ func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr im
pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4776,7 +4776,7 @@ func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr im
pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4823,7 +4823,7 @@ func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr im
pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -4870,7 +4870,7 @@ func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr im
pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -5759,7 +5759,7 @@ func (q *Kernel) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rect
pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -5883,7 +5883,7 @@ func (q *Kernel) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rect
pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -6007,7 +6007,7 @@ func (q *Kernel) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rect
pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
@@ -6131,7 +6131,7 @@ func (q *Kernel) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rect
pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10100
+ pyy1 := int(src.Y[pi]) * 0x10101
pcb1 := int(src.Cb[pj]) - 128
pcr1 := int(src.Cr[pj]) - 128
pru := (pyy1 + 91881*pcr1) >> 8
diff --git a/vendor/golang.org/x/image/draw/stdlib_test.go b/vendor/golang.org/x/image/draw/stdlib_test.go
index c45f78c2e..9015bfd6f 100644
--- a/vendor/golang.org/x/image/draw/stdlib_test.go
+++ b/vendor/golang.org/x/image/draw/stdlib_test.go
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build go1.5
+// +build go1.9
package draw
// This file contains tests that depend on the exact behavior of the
// image/color package in the standard library. The color conversion formula
-// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, so this file's tests
-// are only enabled for Go 1.5 and above.
+// from YCbCr to RGBA changed between Go 1.4 and Go 1.5, and between Go 1.8 and
+// Go 1.9, so this file's tests are only enabled for Go 1.9 and above.
import (
"bytes"
diff --git a/vendor/golang.org/x/image/font/sfnt/cmap.go b/vendor/golang.org/x/image/font/sfnt/cmap.go
new file mode 100644
index 000000000..42338f1bc
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/cmap.go
@@ -0,0 +1,269 @@
+// 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
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/encoding/charmap"
+)
+
+// Platform IDs and Platform Specific IDs as per
+// https://www.microsoft.com/typography/otspec/name.htm
+const (
+ pidUnicode = 0
+ pidMacintosh = 1
+ pidWindows = 3
+
+ psidUnicode2BMPOnly = 3
+ psidUnicode2FullRepertoire = 4
+ // Note that FontForge may generate a bogus Platform Specific ID (value 10)
+ // for the Unicode Platform ID (value 0). See
+ // https://github.com/fontforge/fontforge/issues/2728
+
+ psidMacintoshRoman = 0
+
+ psidWindowsSymbol = 0
+ psidWindowsUCS2 = 1
+ psidWindowsUCS4 = 10
+)
+
+// platformEncodingWidth returns the number of bytes per character assumed by
+// the given Platform ID and Platform Specific ID.
+//
+// Very old fonts, from before Unicode was widely adopted, assume only 1 byte
+// per character: a character map.
+//
+// Old fonts, from when Unicode meant the Basic Multilingual Plane (BMP),
+// assume that 2 bytes per character is sufficient.
+//
+// Recent fonts naturally support the full range of Unicode code points, which
+// can take up to 4 bytes per character. Such fonts might still choose one of
+// the legacy encodings if e.g. their repertoire is limited to the BMP, for
+// greater compatibility with older software, or because the resultant file
+// size can be smaller.
+func platformEncodingWidth(pid, psid uint16) int {
+ switch pid {
+ case pidUnicode:
+ switch psid {
+ case psidUnicode2BMPOnly:
+ return 2
+ case psidUnicode2FullRepertoire:
+ return 4
+ }
+
+ case pidMacintosh:
+ switch psid {
+ case psidMacintoshRoman:
+ return 1
+ }
+
+ case pidWindows:
+ switch psid {
+ case psidWindowsSymbol:
+ return 2
+ case psidWindowsUCS2:
+ return 2
+ case psidWindowsUCS4:
+ return 4
+ }
+ }
+ return 0
+}
+
+// The various cmap formats are described at
+// https://www.microsoft.com/typography/otspec/cmap.htm
+
+var supportedCmapFormat = func(format, pid, psid uint16) bool {
+ switch format {
+ case 0:
+ return pid == pidMacintosh && psid == psidMacintoshRoman
+ case 4:
+ return true
+ case 12:
+ return true
+ }
+ return false
+}
+
+func (f *Font) makeCachedGlyphIndex(buf []byte, offset, length uint32, format uint16) ([]byte, glyphIndexFunc, error) {
+ switch format {
+ case 0:
+ return f.makeCachedGlyphIndexFormat0(buf, offset, length)
+ case 4:
+ return f.makeCachedGlyphIndexFormat4(buf, offset, length)
+ case 12:
+ return f.makeCachedGlyphIndexFormat12(buf, offset, length)
+ }
+ panic("unreachable")
+}
+
+func (f *Font) makeCachedGlyphIndexFormat0(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) {
+ if length != 6+256 || offset+length > f.cmap.length {
+ return nil, nil, errInvalidCmapTable
+ }
+ var err error
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(length))
+ if err != nil {
+ return nil, nil, err
+ }
+ var table [256]byte
+ copy(table[:], buf[6:])
+ return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
+ // TODO: for this closure to be goroutine-safe, the
+ // golang.org/x/text/encoding/charmap API needs to allocate a new
+ // Encoder and new []byte buffers, for every call to this closure, even
+ // though all we want to do is to encode one rune as one byte. We could
+ // possibly add some fields in the Buffer struct to re-use these
+ // allocations, but a better solution is to improve the charmap API.
+ var dst, src [utf8.UTFMax]byte
+ n := utf8.EncodeRune(src[:], r)
+ _, _, err = charmap.Macintosh.NewEncoder().Transform(dst[:], src[:n], true)
+ if err != nil {
+ // The source rune r is not representable in the Macintosh-Roman encoding.
+ return 0, nil
+ }
+ return GlyphIndex(table[dst[0]]), nil
+ }, nil
+}
+
+func (f *Font) makeCachedGlyphIndexFormat4(buf []byte, offset, length uint32) ([]byte, glyphIndexFunc, error) {
+ const headerSize = 14
+ 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
+
+ segCount := u16(buf[6:])
+ if segCount&1 != 0 {
+ return nil, nil, errInvalidCmapTable
+ }
+ segCount /= 2
+ if segCount > maxCmapSegments {
+ return nil, nil, errUnsupportedNumberOfCmapSegments
+ }
+
+ eLength := 8*uint32(segCount) + 2
+ if offset+eLength > f.cmap.length {
+ return nil, nil, errInvalidCmapTable
+ }
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength))
+ if err != nil {
+ return nil, nil, err
+ }
+ offset += eLength
+
+ entries := make([]cmapEntry16, segCount)
+ for i := range entries {
+ entries[i] = cmapEntry16{
+ end: u16(buf[0*len(entries)+0+2*i:]),
+ start: u16(buf[2*len(entries)+2+2*i:]),
+ delta: u16(buf[4*len(entries)+2+2*i:]),
+ offset: u16(buf[6*len(entries)+2+2*i:]),
+ }
+ }
+ indexesBase := f.cmap.offset + offset
+ indexesLength := f.cmap.length - offset
+
+ return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
+ if uint32(r) > 0xffff {
+ return 0, nil
+ }
+
+ c := uint16(r)
+ for i, j := 0, len(entries); i < j; {
+ h := i + (j-i)/2
+ entry := &entries[h]
+ if c < entry.start {
+ j = h
+ } else if entry.end < c {
+ i = h + 1
+ } else if entry.offset == 0 {
+ return GlyphIndex(c + entry.delta), nil
+ } else {
+ offset := uint32(entry.offset) + 2*uint32(h-len(entries)+int(c-entry.start))
+ if offset > indexesLength || offset+2 > indexesLength {
+ return 0, errInvalidCmapTable
+ }
+ x, err := b.view(&f.src, int(indexesBase+offset), 2)
+ if err != nil {
+ return 0, err
+ }
+ return GlyphIndex(u16(x)), nil
+ }
+ }
+ return 0, nil
+ }, nil
+}
+
+func (f *Font) makeCachedGlyphIndexFormat12(buf []byte, offset, _ uint32) ([]byte, glyphIndexFunc, error) {
+ const headerSize = 16
+ 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
+ }
+ length := u32(buf[4:])
+ if f.cmap.length < offset || length > f.cmap.length-offset {
+ return nil, nil, errInvalidCmapTable
+ }
+ offset += headerSize
+
+ numGroups := u32(buf[12:])
+ if numGroups > maxCmapSegments {
+ return nil, nil, errUnsupportedNumberOfCmapSegments
+ }
+
+ eLength := 12 * numGroups
+ if headerSize+eLength != length {
+ return nil, nil, errInvalidCmapTable
+ }
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), int(eLength))
+ if err != nil {
+ return nil, nil, err
+ }
+ offset += eLength
+
+ entries := make([]cmapEntry32, numGroups)
+ for i := range entries {
+ entries[i] = cmapEntry32{
+ start: u32(buf[0+12*i:]),
+ end: u32(buf[4+12*i:]),
+ delta: u32(buf[8+12*i:]),
+ }
+ }
+
+ return buf, func(f *Font, b *Buffer, r rune) (GlyphIndex, error) {
+ c := uint32(r)
+ for i, j := 0, len(entries); i < j; {
+ h := i + (j-i)/2
+ entry := &entries[h]
+ if c < entry.start {
+ j = h
+ } else if entry.end < c {
+ i = h + 1
+ } else {
+ return GlyphIndex(c - entry.start + entry.delta), nil
+ }
+ }
+ return 0, nil
+ }, nil
+}
+
+type cmapEntry16 struct {
+ end, start, delta, offset uint16
+}
+
+type cmapEntry32 struct {
+ start, end, delta uint32
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/data.go b/vendor/golang.org/x/image/font/sfnt/data.go
new file mode 100644
index 000000000..ad0c139aa
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/data.go
@@ -0,0 +1,68 @@
+// generated by go run gen.go; DO NOT EDIT
+
+package sfnt
+
+const numBuiltInPostNames = 258
+
+const builtInPostNamesData = "" +
+ ".notdef.nullnonmarkingreturnspaceexclamquotedblnumbersigndollarp" +
+ "ercentampersandquotesingleparenleftparenrightasteriskpluscommahy" +
+ "phenperiodslashzeroonetwothreefourfivesixseveneightninecolonsemi" +
+ "colonlessequalgreaterquestionatABCDEFGHIJKLMNOPQRSTUVWXYZbracket" +
+ "leftbackslashbracketrightasciicircumunderscoregraveabcdefghijklm" +
+ "nopqrstuvwxyzbraceleftbarbracerightasciitildeAdieresisAringCcedi" +
+ "llaEacuteNtildeOdieresisUdieresisaacuteagraveacircumflexadieresi" +
+ "satildearingccedillaeacuteegraveecircumflexedieresisiacuteigrave" +
+ "icircumflexidieresisntildeoacuteograveocircumflexodieresisotilde" +
+ "uacuteugraveucircumflexudieresisdaggerdegreecentsterlingsectionb" +
+ "ulletparagraphgermandblsregisteredcopyrighttrademarkacutedieresi" +
+ "snotequalAEOslashinfinityplusminuslessequalgreaterequalyenmupart" +
+ "ialdiffsummationproductpiintegralordfeminineordmasculineOmegaaeo" +
+ "slashquestiondownexclamdownlogicalnotradicalflorinapproxequalDel" +
+ "taguillemotleftguillemotrightellipsisnonbreakingspaceAgraveAtild" +
+ "eOtildeOEoeendashemdashquotedblleftquotedblrightquoteleftquoteri" +
+ "ghtdividelozengeydieresisYdieresisfractioncurrencyguilsinglleftg" +
+ "uilsinglrightfifldaggerdblperiodcenteredquotesinglbasequotedblba" +
+ "seperthousandAcircumflexEcircumflexAacuteEdieresisEgraveIacuteIc" +
+ "ircumflexIdieresisIgraveOacuteOcircumflexappleOgraveUacuteUcircu" +
+ "mflexUgravedotlessicircumflextildemacronbrevedotaccentringcedill" +
+ "ahungarumlautogonekcaronLslashlslashScaronscaronZcaronzcaronbrok" +
+ "enbarEthethYacuteyacuteThornthornminusmultiplyonesuperiortwosupe" +
+ "riorthreesuperioronehalfonequarterthreequartersfrancGbrevegbreve" +
+ "IdotaccentScedillascedillaCacutecacuteCcaronccarondcroat"
+
+var builtInPostNamesOffsets = [...]uint16{
+ 0x0000, 0x0007, 0x000c, 0x001c, 0x0021, 0x0027, 0x002f, 0x0039,
+ 0x003f, 0x0046, 0x004f, 0x005a, 0x0063, 0x006d, 0x0075, 0x0079,
+ 0x007e, 0x0084, 0x008a, 0x008f, 0x0093, 0x0096, 0x0099, 0x009e,
+ 0x00a2, 0x00a6, 0x00a9, 0x00ae, 0x00b3, 0x00b7, 0x00bc, 0x00c5,
+ 0x00c9, 0x00ce, 0x00d5, 0x00dd, 0x00df, 0x00e0, 0x00e1, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea,
+ 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
+ 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x0104,
+ 0x010d, 0x0119, 0x0124, 0x012e, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146,
+ 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d, 0x0156,
+ 0x0159, 0x0163, 0x016d, 0x0176, 0x017b, 0x0183, 0x0189, 0x018f,
+ 0x0198, 0x01a1, 0x01a7, 0x01ad, 0x01b8, 0x01c1, 0x01c7, 0x01cc,
+ 0x01d4, 0x01da, 0x01e0, 0x01eb, 0x01f4, 0x01fa, 0x0200, 0x020b,
+ 0x0214, 0x021a, 0x0220, 0x0226, 0x0231, 0x023a, 0x0240, 0x0246,
+ 0x024c, 0x0257, 0x0260, 0x0266, 0x026c, 0x0270, 0x0278, 0x027f,
+ 0x0285, 0x028e, 0x0298, 0x02a2, 0x02ab, 0x02b4, 0x02b9, 0x02c1,
+ 0x02c9, 0x02cb, 0x02d1, 0x02d9, 0x02e2, 0x02eb, 0x02f7, 0x02fa,
+ 0x02fc, 0x0307, 0x0310, 0x0317, 0x0319, 0x0321, 0x032c, 0x0338,
+ 0x033d, 0x033f, 0x0345, 0x0351, 0x035b, 0x0365, 0x036c, 0x0372,
+ 0x037d, 0x0382, 0x038f, 0x039d, 0x03a5, 0x03b5, 0x03bb, 0x03c1,
+ 0x03c7, 0x03c9, 0x03cb, 0x03d1, 0x03d7, 0x03e3, 0x03f0, 0x03f9,
+ 0x0403, 0x0409, 0x0410, 0x0419, 0x0422, 0x042a, 0x0432, 0x043f,
+ 0x044d, 0x044f, 0x0451, 0x045a, 0x0468, 0x0476, 0x0482, 0x048d,
+ 0x0498, 0x04a3, 0x04a9, 0x04b2, 0x04b8, 0x04be, 0x04c9, 0x04d2,
+ 0x04d8, 0x04de, 0x04e9, 0x04ee, 0x04f4, 0x04fa, 0x0505, 0x050b,
+ 0x0513, 0x051d, 0x0522, 0x0528, 0x052d, 0x0536, 0x053a, 0x0541,
+ 0x054d, 0x0553, 0x0558, 0x055e, 0x0564, 0x056a, 0x0570, 0x0576,
+ 0x057c, 0x0585, 0x0588, 0x058b, 0x0591, 0x0597, 0x059c, 0x05a1,
+ 0x05a6, 0x05ae, 0x05b9, 0x05c4, 0x05d1, 0x05d8, 0x05e2, 0x05ef,
+ 0x05f4, 0x05fa, 0x0600, 0x060a, 0x0612, 0x061a, 0x0620, 0x0626,
+ 0x062c, 0x0632, 0x0638,
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/example_test.go b/vendor/golang.org/x/image/font/sfnt/example_test.go
new file mode 100644
index 000000000..17431560f
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/example_test.go
@@ -0,0 +1,128 @@
+// 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_test
+
+import (
+ "image"
+ "image/draw"
+ "log"
+ "os"
+
+ "golang.org/x/image/font/gofont/goregular"
+ "golang.org/x/image/font/sfnt"
+ "golang.org/x/image/math/fixed"
+ "golang.org/x/image/vector"
+)
+
+func ExampleRasterizeGlyph() {
+ const (
+ ppem = 32
+ width = 24
+ height = 32
+ originX = 0
+ originY = 28
+ )
+
+ f, err := sfnt.Parse(goregular.TTF)
+ if err != nil {
+ log.Fatalf("Parse: %v", err)
+ }
+ var b sfnt.Buffer
+ x, err := f.GlyphIndex(&b, 'G')
+ if err != nil {
+ log.Fatalf("GlyphIndex: %v", err)
+ }
+ if x == 0 {
+ log.Fatalf("GlyphIndex: no glyph index found for the rune 'G'")
+ }
+ segments, err := f.LoadGlyph(&b, x, fixed.I(ppem), nil)
+ if err != nil {
+ log.Fatalf("LoadGlyph: %v", err)
+ }
+
+ r := vector.NewRasterizer(width, height)
+ r.DrawOp = draw.Src
+ for _, seg := range segments {
+ // The divisions by 64 below is because the seg.Args values have type
+ // fixed.Int26_6, a 26.6 fixed point number, and 1<<6 == 64.
+ switch seg.Op {
+ case sfnt.SegmentOpMoveTo:
+ r.MoveTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ )
+ case sfnt.SegmentOpLineTo:
+ r.LineTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ )
+ case sfnt.SegmentOpQuadTo:
+ r.QuadTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ originX+float32(seg.Args[2])/64,
+ originY-float32(seg.Args[3])/64,
+ )
+ case sfnt.SegmentOpCubeTo:
+ r.CubeTo(
+ originX+float32(seg.Args[0])/64,
+ originY-float32(seg.Args[1])/64,
+ originX+float32(seg.Args[2])/64,
+ originY-float32(seg.Args[3])/64,
+ originX+float32(seg.Args[4])/64,
+ originY-float32(seg.Args[5])/64,
+ )
+ }
+ }
+ // TODO: call ClosePath? Once overall or once per contour (i.e. MoveTo)?
+
+ dst := image.NewAlpha(image.Rect(0, 0, width, height))
+ r.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
+
+ const asciiArt = ".++8"
+ buf := make([]byte, 0, height*(width+1))
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ a := dst.AlphaAt(x, y).A
+ buf = append(buf, asciiArt[a>>6])
+ }
+ buf = append(buf, '\n')
+ }
+ os.Stdout.Write(buf)
+
+ // Output:
+ // ........................
+ // ........................
+ // ........................
+ // ........................
+ // ..........+++++++++.....
+ // .......+8888888888888+..
+ // ......8888888888888888..
+ // ....+8888+........++88..
+ // ....8888................
+ // ...8888.................
+ // ..+888+.................
+ // ..+888..................
+ // ..888+..................
+ // .+888+..................
+ // .+888...................
+ // .+888...................
+ // .+888...................
+ // .+888..........+++++++..
+ // .+888..........8888888..
+ // .+888+.........+++8888..
+ // ..888+............+888..
+ // ..8888............+888..
+ // ..+888+...........+888..
+ // ...8888+..........+888..
+ // ...+8888+.........+888..
+ // ....+88888+.......+888..
+ // .....+8888888888888888..
+ // .......+888888888888++..
+ // ..........++++++++......
+ // ........................
+ // ........................
+ // ........................
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/gen.go b/vendor/golang.org/x/image/font/sfnt/gen.go
new file mode 100644
index 000000000..12587d446
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/gen.go
@@ -0,0 +1,321 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "log"
+)
+
+func main() {
+ data, offsets := []byte(nil), []int{0}
+ for _, name := range names {
+ data = append(data, name...)
+ offsets = append(offsets, len(data))
+ }
+
+ b := new(bytes.Buffer)
+ fmt.Fprintf(b, "// generated by go run gen.go; DO NOT EDIT\n\n")
+ fmt.Fprintf(b, "package sfnt\n\n")
+
+ fmt.Fprintf(b, "const numBuiltInPostNames = %d\n\n", len(names))
+
+ fmt.Fprintf(b, "const builtInPostNamesData = \"\" +\n")
+ for s := data; ; {
+ if len(s) <= 64 {
+ fmt.Fprintf(b, "%q\n", s)
+ break
+ }
+ fmt.Fprintf(b, "%q +\n", s[:64])
+ s = s[64:]
+ }
+ fmt.Fprintf(b, "\n")
+
+ fmt.Fprintf(b, "var builtInPostNamesOffsets = [...]uint16{\n")
+ for i, o := range offsets {
+ fmt.Fprintf(b, "%#04x,", o)
+ if i%8 == 7 {
+ fmt.Fprintf(b, "\n")
+ }
+ }
+ fmt.Fprintf(b, "\n}\n")
+
+ dstUnformatted := b.Bytes()
+ dst, err := format.Source(dstUnformatted)
+ if err != nil {
+ log.Fatalf("format.Source: %v\n\n----\n%s\n----", err, dstUnformatted)
+ }
+ if err := ioutil.WriteFile("data.go", dst, 0666); err != nil {
+ log.Fatalf("ioutil.WriteFile: %v", err)
+ }
+}
+
+// names is the built-in post table names listed at
+// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
+var names = [258]string{
+ ".notdef",
+ ".null",
+ "nonmarkingreturn",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "summation",
+ "product",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nonbreakingspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Oacute",
+ "Ocircumflex",
+ "apple",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idotaccent",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+ "ccaron",
+ "dcroat",
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/postscript.go b/vendor/golang.org/x/image/font/sfnt/postscript.go
index d5d6d9aed..ca1b8318c 100644
--- a/vendor/golang.org/x/image/font/sfnt/postscript.go
+++ b/vendor/golang.org/x/image/font/sfnt/postscript.go
@@ -566,8 +566,8 @@ var psOperators = [...][2][]psOperator{
23: {-1, "vstemhm", t2CStem},
24: {}, // rcurveline.
25: {}, // rlinecurve.
- 26: {}, // vvcurveto.
- 27: {}, // hhcurveto.
+ 26: {-1, "vvcurveto", t2CVvcurveto},
+ 27: {-1, "hhcurveto", t2CHhcurveto},
28: {}, // shortint.
29: {}, // callgsubr.
30: {-1, "vhcurveto", t2CVhcurveto},
@@ -653,8 +653,8 @@ func t2CAppendMoveto(p *psInterpreter) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpMoveTo,
Args: [6]fixed.Int26_6{
- 0: fixed.Int26_6(p.type2Charstrings.x) << 6,
- 1: fixed.Int26_6(p.type2Charstrings.y) << 6,
+ 0: fixed.Int26_6(p.type2Charstrings.x),
+ 1: fixed.Int26_6(p.type2Charstrings.y),
},
})
}
@@ -663,8 +663,8 @@ func t2CAppendLineto(p *psInterpreter) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpLineTo,
Args: [6]fixed.Int26_6{
- 0: fixed.Int26_6(p.type2Charstrings.x) << 6,
- 1: fixed.Int26_6(p.type2Charstrings.y) << 6,
+ 0: fixed.Int26_6(p.type2Charstrings.x),
+ 1: fixed.Int26_6(p.type2Charstrings.y),
},
})
}
@@ -685,12 +685,12 @@ func t2CAppendCubeto(p *psInterpreter, dxa, dya, dxb, dyb, dxc, dyc int32) {
p.type2Charstrings.segments = append(p.type2Charstrings.segments, Segment{
Op: SegmentOpCubeTo,
Args: [6]fixed.Int26_6{
- 0: fixed.Int26_6(xa) << 6,
- 1: fixed.Int26_6(ya) << 6,
- 2: fixed.Int26_6(xb) << 6,
- 3: fixed.Int26_6(yb) << 6,
- 4: fixed.Int26_6(xc) << 6,
- 5: fixed.Int26_6(yc) << 6,
+ 0: fixed.Int26_6(xa),
+ 1: fixed.Int26_6(ya),
+ 2: fixed.Int26_6(xb),
+ 3: fixed.Int26_6(yb),
+ 4: fixed.Int26_6(xc),
+ 5: fixed.Int26_6(yc),
},
})
}
@@ -770,6 +770,12 @@ func t2CRlineto(p *psInterpreter) error {
// As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
//
+// hhcurveto is:
+// - dy1 {dxa dxb dyb dxc}+
+//
+// vvcurveto is:
+// - dx1 {dya dxb dyb dyc}+
+//
// hvcurveto is one of:
// - dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
// - {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
@@ -778,59 +784,84 @@ func t2CRlineto(p *psInterpreter) error {
// - dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf?
// - {dya dxb dyb dxc dxd dxe dye dyf}+ dxf?
-func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, false) }
-func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true) }
+func t2CHhcurveto(p *psInterpreter) error { return t2CCurveto(p, false, false) }
+func t2CVvcurveto(p *psInterpreter) error { return t2CCurveto(p, false, true) }
+func t2CHvcurveto(p *psInterpreter) error { return t2CCurveto(p, true, false) }
+func t2CVhcurveto(p *psInterpreter) error { return t2CCurveto(p, true, true) }
-func t2CCurveto(p *psInterpreter, vertical bool) error {
+// t2CCurveto implements the hh / vv / hv / vh xxcurveto operators. N relative
+// cubic curve requires 6*N control points, but only 4*N+0 or 4*N+1 are used
+// here: all (or all but one) of the piecewise cubic curve's tangents are
+// implicitly horizontal or vertical.
+//
+// swap is whether that implicit horizontal / vertical constraint swaps as you
+// move along the piecewise cubic curve. If swap is false, the constraints are
+// either all horizontal or all vertical. If swap is true, it alternates.
+//
+// vertical is whether the first implicit constraint is vertical.
+func t2CCurveto(p *psInterpreter, swap, vertical bool) error {
if !p.type2Charstrings.seenWidth || p.stack.top < 4 {
return errInvalidCFFTable
}
- for i := int32(0); i != p.stack.top; vertical = !vertical {
+
+ i := int32(0)
+ switch p.stack.top & 3 {
+ case 0:
+ // No-op.
+ case 1:
+ if swap {
+ break
+ }
+ i = 1
if vertical {
- i = t2CVcurveto(p, i)
+ p.type2Charstrings.x += p.stack.a[0]
} else {
- i = t2CHcurveto(p, i)
+ p.type2Charstrings.y += p.stack.a[0]
}
+ default:
+ return errInvalidCFFTable
+ }
+
+ for i != p.stack.top {
+ i = t2CCurveto4(p, swap, vertical, i)
if i < 0 {
return errInvalidCFFTable
}
+ if swap {
+ vertical = !vertical
+ }
}
return nil
}
-func t2CHcurveto(p *psInterpreter, i int32) (j int32) {
+func t2CCurveto4(p *psInterpreter, swap bool, vertical bool, i int32) (j int32) {
if i+4 > p.stack.top {
return -1
}
dxa := p.stack.a[i+0]
+ dya := int32(0)
dxb := p.stack.a[i+1]
dyb := p.stack.a[i+2]
- dyc := p.stack.a[i+3]
- dxc := int32(0)
+ dxc := p.stack.a[i+3]
+ dyc := int32(0)
i += 4
- if i+1 == p.stack.top {
- dxc = p.stack.a[i]
- i++
+
+ if vertical {
+ dxa, dya = dya, dxa
}
- t2CAppendCubeto(p, dxa, 0, dxb, dyb, dxc, dyc)
- return i
-}
-func t2CVcurveto(p *psInterpreter, i int32) (j int32) {
- if i+4 > p.stack.top {
- return -1
+ if swap {
+ if i+1 == p.stack.top {
+ dyc = p.stack.a[i]
+ i++
+ }
}
- dya := p.stack.a[i+0]
- dxb := p.stack.a[i+1]
- dyb := p.stack.a[i+2]
- dxc := p.stack.a[i+3]
- dyc := int32(0)
- i += 4
- if i+1 == p.stack.top {
- dyc = p.stack.a[i]
- i++
+
+ if swap != vertical {
+ dxc, dyc = dyc, dxc
}
- t2CAppendCubeto(p, 0, dya, dxb, dyb, dxc, dyc)
+
+ t2CAppendCubeto(p, dxa, dya, dxb, dyb, dxc, dyc)
return i
}
diff --git a/vendor/golang.org/x/image/font/sfnt/proprietary_test.go b/vendor/golang.org/x/image/font/sfnt/proprietary_test.go
new file mode 100644
index 000000000..b105ee593
--- /dev/null
+++ b/vendor/golang.org/x/image/font/sfnt/proprietary_test.go
@@ -0,0 +1,479 @@
+// 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 (
+ "errors"
+ "flag"
+ "io/ioutil"
+ "path/filepath"
+ "testing"
+
+ "golang.org/x/image/font"
+ "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())
+ qualifiedFilename := proprietor + "/" + filename
+ var buf Buffer
+
+ // Some of the tests below, such as which glyph index a particular rune
+ // maps to, can depend on the specific version of the proprietary font. If
+ // tested against a different version of that font, the test might (but not
+ // necessarily will) fail, even though the Go code is good. If so, log a
+ // message, but don't automatically fail (i.e. dont' call t.Fatalf).
+ gotVersion, err := f.Name(&buf, NameIDVersion)
+ if err != nil {
+ t.Fatalf("Name: %v", err)
+ }
+ wantVersion := proprietaryVersions[qualifiedFilename]
+ if gotVersion != wantVersion {
+ t.Logf("font version provided differs from the one the tests were written against:"+
+ "\ngot %q\nwant %q", gotVersion, wantVersion)
+ }
+
+ numGlyphs := f.NumGlyphs()
+ if numGlyphs < minNumGlyphs {
+ t.Fatalf("NumGlyphs: got %d, want at least %d", numGlyphs, minNumGlyphs)
+ }
+
+ 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[qualifiedFilename] {
+ 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
+ }
+ }
+
+ for r, want := range proprietaryGlyphTestCases[qualifiedFilename] {
+ x, err := f.GlyphIndex(&buf, r)
+ if err != nil {
+ t.Errorf("GlyphIndex(%q): %v", r, err)
+ continue
+ }
+ got, err := f.LoadGlyph(&buf, x, ppem, nil)
+ if err != nil {
+ t.Errorf("LoadGlyph(%q): %v", r, err)
+ continue
+ }
+ if err := checkSegmentsEqual(got, want); err != nil {
+ t.Errorf("LoadGlyph(%q): %v", r, err)
+ continue
+ }
+ }
+
+kernLoop:
+ for _, tc := range proprietaryKernTestCases[qualifiedFilename] {
+ var indexes [2]GlyphIndex
+ for i := range indexes {
+ x, err := f.GlyphIndex(&buf, tc.runes[i])
+ if x == 0 && err == nil {
+ err = errors.New("no glyph index found")
+ }
+ if err != nil {
+ t.Errorf("GlyphIndex(%q): %v", tc.runes[0], err)
+ continue kernLoop
+ }
+ indexes[i] = x
+ }
+ kern, err := f.Kern(&buf, indexes[0], indexes[1], tc.ppem, tc.hinting)
+ if err != nil {
+ t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): %v",
+ tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, err)
+ continue
+ }
+ if got := Units(kern); got != tc.want {
+ t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): got %d, want %d",
+ tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, got, tc.want)
+ continue
+ }
+ }
+}
+
+// proprietaryVersions holds the expected version string of each proprietary
+// font tested. If third parties such as Adobe or Microsoft update their fonts,
+// and the tests subsequently fail, these versions should be updated too.
+//
+// Updates are expected to be infrequent. For example, as of 2017, the fonts
+// installed by the Debian ttf-mscorefonts-installer package have last modified
+// times no later than 2001.
+var proprietaryVersions = map[string]string{
+ "adobe/SourceCodePro-Regular.otf": "Version 2.030;PS 1.0;hotconv 16.6.51;makeotf.lib2.5.65220",
+ "adobe/SourceCodePro-Regular.ttf": "Version 2.030;PS 1.000;hotconv 16.6.51;makeotf.lib2.5.65220",
+ "adobe/SourceHanSansSC-Regular.otf": "Version 1.004;PS 1.004;hotconv 1.0.82;makeotf.lib2.5.63406",
+ "adobe/SourceSansPro-Regular.otf": "Version 2.020;PS 2.0;hotconv 1.0.86;makeotf.lib2.5.63406",
+ "adobe/SourceSansPro-Regular.ttf": "Version 2.020;PS 2.000;hotconv 1.0.86;makeotf.lib2.5.63406",
+
+ "microsoft/Arial.ttf": "Version 2.82",
+ "microsoft/Comic_Sans_MS.ttf": "Version 2.10",
+ "microsoft/Times_New_Roman.ttf": "Version 2.82",
+ "microsoft/Webdings.ttf": "Version 1.03",
+}
+
+// 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
+ },
+}
+
+// proprietaryGlyphTestCases hold a sample of each font's glyph vectors. The
+// numerical values can be verified by running the ttx tool, remembering that:
+// - for PostScript glyphs, ttx coordinates are relative, and hstem / vstem
+// operators are hinting-related and can be ignored.
+// - for TrueType glyphs, ttx coordinates are absolute, and consecutive
+// off-curve points implies an on-curve point at the midpoint.
+var proprietaryGlyphTestCases = map[string]map[rune][]Segment{
+ "adobe/SourceSansPro-Regular.otf": {
+ ',': {
+ // - contour #0
+ // 67 -170 rmoveto
+ moveTo(67, -170),
+ // 81 34 50 67 86 vvcurveto
+ cubeTo(148, -136, 198, -69, 198, 17),
+ // 60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto
+ cubeTo(198, 77, 172, 114, 129, 114),
+ cubeTo(96, 114, 68, 92, 68, 56),
+ cubeTo(68, 19, 95, -1, 127, -1),
+ cubeTo(130, -1, 134, -1, 137, 0),
+ // 1 -53 -34 -44 -57 -25 rrcurveto
+ cubeTo(138, -53, 104, -97, 47, -122),
+ },
+ 'Q': {
+ // - contour #0
+ // 332 57 rmoveto
+ moveTo(332, 57),
+ // -117 -77 106 168 163 77 101 117 117 77 -101 -163 -168 -77 -106 -117 hvcurveto
+ cubeTo(215, 57, 138, 163, 138, 331),
+ cubeTo(138, 494, 215, 595, 332, 595),
+ cubeTo(449, 595, 526, 494, 526, 331),
+ cubeTo(526, 163, 449, 57, 332, 57),
+ // - contour #1
+ // 201 -222 rmoveto
+ moveTo(533, -165),
+ // 39 35 7 8 20 hvcurveto
+ cubeTo(572, -165, 607, -158, 627, -150),
+ // -16 64 rlineto
+ lineTo(611, -86),
+ // -5 -18 -22 -4 -29 hhcurveto
+ cubeTo(593, -91, 571, -95, 542, -95),
+ // -71 -60 29 58 -30 hvcurveto
+ cubeTo(471, -95, 411, -66, 381, -8),
+ // 139 24 93 126 189 vvcurveto
+ cubeTo(520, 16, 613, 142, 613, 331),
+ // 209 -116 128 -165 -165 -115 -127 -210 -193 96 -127 143 -20 vhcurveto
+ cubeTo(613, 540, 497, 668, 332, 668),
+ cubeTo(167, 668, 52, 541, 52, 331),
+ cubeTo(52, 138, 148, 11, 291, -9),
+ // -90 38 83 -66 121 hhcurveto
+ cubeTo(329, -99, 412, -165, 533, -165),
+ },
+ },
+
+ "microsoft/Arial.ttf": {
+ ',': {
+ // - contour #0
+ moveTo(182, 0),
+ lineTo(182, 205),
+ lineTo(387, 205),
+ lineTo(387, 0),
+ quadTo(387, -113, 347, -182),
+ quadTo(307, -252, 220, -290),
+ lineTo(170, -213),
+ quadTo(227, -188, 254, -139),
+ quadTo(281, -91, 284, 0),
+ lineTo(182, 0),
+ },
+ 'i': {
+ // - contour #0
+ moveTo(136, 1259),
+ lineTo(136, 1466),
+ lineTo(316, 1466),
+ lineTo(316, 1259),
+ lineTo(136, 1259),
+ // - contour #1
+ moveTo(136, 0),
+ lineTo(136, 1062),
+ lineTo(316, 1062),
+ lineTo(316, 0),
+ lineTo(136, 0),
+ },
+ 'o': {
+ // - contour #0
+ moveTo(68, 531),
+ quadTo(68, 826, 232, 968),
+ quadTo(369, 1086, 566, 1086),
+ quadTo(785, 1086, 924, 942),
+ quadTo(1063, 799, 1063, 546),
+ quadTo(1063, 341, 1001, 223),
+ quadTo(940, 106, 822, 41),
+ quadTo(705, -24, 566, -24),
+ quadTo(343, -24, 205, 119),
+ quadTo(68, 262, 68, 531),
+ // - contour #1
+ moveTo(253, 531),
+ quadTo(253, 327, 342, 225),
+ quadTo(431, 124, 566, 124),
+ quadTo(700, 124, 789, 226),
+ quadTo(878, 328, 878, 537),
+ quadTo(878, 734, 788, 835),
+ quadTo(699, 937, 566, 937),
+ quadTo(431, 937, 342, 836),
+ quadTo(253, 735, 253, 531),
+ },
+ },
+}
+
+type kernTestCase struct {
+ ppem fixed.Int26_6
+ hinting font.Hinting
+ runes [2]rune
+ want Units
+}
+
+// proprietaryKernTestCases hold a sample of each font's kerning pairs. The
+// numerical values can be verified by running the ttx tool.
+var proprietaryKernTestCases = map[string][]kernTestCase{
+ "microsoft/Arial.ttf": {
+ {2048, font.HintingNone, [2]rune{'A', 'V'}, -152},
+ // U+03B8 GREEK SMALL LETTER THETA
+ // U+03BB GREEK SMALL LETTER LAMDA
+ {2048, font.HintingNone, [2]rune{'\u03b8', '\u03bb'}, -39},
+ {2048, font.HintingNone, [2]rune{'\u03bb', '\u03b8'}, -0},
+ },
+ "microsoft/Comic_Sans_MS.ttf": {
+ {2048, font.HintingNone, [2]rune{'A', 'V'}, 0},
+ },
+ "microsoft/Times_New_Roman.ttf": {
+ {768, font.HintingNone, [2]rune{'A', 'V'}, -99},
+ {768, font.HintingFull, [2]rune{'A', 'V'}, -128},
+ {2048, font.HintingNone, [2]rune{'A', 'A'}, 0},
+ {2048, font.HintingNone, [2]rune{'A', 'T'}, -227},
+ {2048, font.HintingNone, [2]rune{'A', 'V'}, -264},
+ {2048, font.HintingNone, [2]rune{'T', 'A'}, -164},
+ {2048, font.HintingNone, [2]rune{'T', 'T'}, 0},
+ {2048, font.HintingNone, [2]rune{'T', 'V'}, 0},
+ {2048, font.HintingNone, [2]rune{'V', 'A'}, -264},
+ {2048, font.HintingNone, [2]rune{'V', 'T'}, 0},
+ {2048, font.HintingNone, [2]rune{'V', 'V'}, 0},
+ // U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+ // U+0393 GREEK CAPITAL LETTER GAMMA
+ {2048, font.HintingNone, [2]rune{'\u0390', '\u0393'}, 0},
+ {2048, font.HintingNone, [2]rune{'\u0393', '\u0390'}, 76},
+ },
+ "microsoft/Webdings.ttf": {
+ {2048, font.HintingNone, [2]rune{'\uf041', '\uf042'}, 0},
+ },
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/sfnt.go b/vendor/golang.org/x/image/font/sfnt/sfnt.go
index d4929a838..02efd5f3a 100644
--- a/vendor/golang.org/x/image/font/sfnt/sfnt.go
+++ b/vendor/golang.org/x/image/font/sfnt/sfnt.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go run gen.go
+
// Package sfnt implements a decoder for SFNT font file formats, including
// TrueType and OpenType.
package sfnt // import "golang.org/x/image/font/sfnt"
@@ -13,11 +15,15 @@ package sfnt // import "golang.org/x/image/font/sfnt"
//
// The pyftinspect tool from https://github.com/fonttools/fonttools is useful
// for inspecting SFNT fonts.
+//
+// The ttfdump tool is also useful. For example:
+// ttfdump -t cmap ../testdata/CFFTest.otf dump.txt
import (
"errors"
"io"
+ "golang.org/x/image/font"
"golang.org/x/image/math/fixed"
"golang.org/x/text/encoding/charmap"
)
@@ -25,6 +31,20 @@ import (
// These constants are not part of the specifications, but are limitations used
// by this implementation.
const (
+ // This value is arbitrary, but defends against parsing malicious font
+ // files causing excessive memory allocations. For reference, Adobe's
+ // SourceHanSansSC-Regular.otf has 65535 glyphs and:
+ // - its format-4 cmap table has 1581 segments.
+ // - its format-12 cmap table has 16498 segments.
+ //
+ // TODO: eliminate this constraint? If the cmap table is very large, load
+ // some or all of it lazily (at the time Font.GlyphIndex is called) instead
+ // of all of it eagerly (at the time Font.initialize is called), while
+ // keeping an upper bound on the memory used? This will make the code in
+ // cmap.go more complicated, considering that all of the Font methods are
+ // safe to call concurrently, as long as each call has a different *Buffer.
+ maxCmapSegments = 20000
+
maxGlyphDataLength = 64 * 1024
maxHintBits = 256
maxNumTables = 256
@@ -41,27 +61,34 @@ var (
errInvalidBounds = errors.New("sfnt: invalid bounds")
errInvalidCFFTable = errors.New("sfnt: invalid CFF table")
+ errInvalidCmapTable = errors.New("sfnt: invalid cmap table")
errInvalidGlyphData = errors.New("sfnt: invalid glyph data")
errInvalidHeadTable = errors.New("sfnt: invalid head table")
+ errInvalidKernTable = errors.New("sfnt: invalid kern table")
errInvalidLocaTable = errors.New("sfnt: invalid loca table")
errInvalidLocationData = errors.New("sfnt: invalid location data")
errInvalidMaxpTable = errors.New("sfnt: invalid maxp table")
errInvalidNameTable = errors.New("sfnt: invalid name table")
+ errInvalidPostTable = errors.New("sfnt: invalid post table")
errInvalidSourceData = errors.New("sfnt: invalid source data")
errInvalidTableOffset = errors.New("sfnt: invalid table offset")
errInvalidTableTagOrder = errors.New("sfnt: invalid table tag order")
errInvalidUCS2String = errors.New("sfnt: invalid UCS-2 string")
errInvalidVersion = errors.New("sfnt: invalid version")
- errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
- errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
- errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
- errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
- errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
- errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
- errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
- errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
- errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
+ errUnsupportedCFFVersion = errors.New("sfnt: unsupported CFF version")
+ errUnsupportedCmapEncodings = errors.New("sfnt: unsupported cmap encodings")
+ errUnsupportedCompoundGlyph = errors.New("sfnt: unsupported compound glyph")
+ errUnsupportedGlyphDataLength = errors.New("sfnt: unsupported glyph data length")
+ errUnsupportedKernTable = errors.New("sfnt: unsupported kern table")
+ errUnsupportedRealNumberEncoding = errors.New("sfnt: unsupported real number encoding")
+ errUnsupportedNumberOfCmapSegments = errors.New("sfnt: unsupported number of cmap segments")
+ errUnsupportedNumberOfHints = errors.New("sfnt: unsupported number of hints")
+ errUnsupportedNumberOfTables = errors.New("sfnt: unsupported number of tables")
+ errUnsupportedPlatformEncoding = errors.New("sfnt: unsupported platform encoding")
+ errUnsupportedPostTable = errors.New("sfnt: unsupported post table")
+ errUnsupportedTableOffsetLength = errors.New("sfnt: unsupported table offset or length")
+ errUnsupportedType2Charstring = errors.New("sfnt: unsupported Type 2 Charstring")
)
// GlyphIndex is a glyph index in a Font.
@@ -107,16 +134,16 @@ const (
// display resolution (DPI) and font size (e.g. a 12 point font).
type Units int32
-// Platform IDs and Platform Specific IDs as per
-// https://www.microsoft.com/typography/otspec/name.htm
-const (
- pidMacintosh = 1
- pidWindows = 3
-
- psidMacintoshRoman = 0
-
- psidWindowsUCS2 = 1
-)
+// scale returns x divided by unitsPerEm, rounded to the nearest fixed.Int26_6
+// value (1/64th of a pixel).
+func scale(x fixed.Int26_6, unitsPerEm Units) fixed.Int26_6 {
+ if x >= 0 {
+ x += fixed.Int26_6(unitsPerEm) / 2
+ } else {
+ x -= fixed.Int26_6(unitsPerEm) / 2
+ }
+ return x / fixed.Int26_6(unitsPerEm)
+}
func u16(b []byte) uint16 {
_ = b[1] // Bounds check hint to compiler.
@@ -208,6 +235,20 @@ func (s *source) u16(buf []byte, t table, i int) (uint16, error) {
return u16(buf), nil
}
+// u32 returns the uint32 in the table t at the relative offset i.
+//
+// buf is an optional scratch buffer as per the source.view method.
+func (s *source) u32(buf []byte, t table, i int) (uint32, error) {
+ if i < 0 || uint(t.length) < uint(i+4) {
+ return 0, errInvalidBounds
+ }
+ buf, err := s.view(buf, int(t.offset)+i, 4)
+ if err != nil {
+ return 0, err
+ }
+ return u32(buf), nil
+}
+
// table is a section of the font data.
type table struct {
offset, length uint32
@@ -247,6 +288,18 @@ func ParseReaderAt(src io.ReaderAt) (*Font, error) {
//
// The Font methods that don't take a *Buffer argument are always safe to call
// concurrently.
+//
+// Some methods provide lengths or coordinates, e.g. bounds, font metrics and
+// control points. All of these methods take a ppem parameter, which is the
+// number of pixels in 1 em, expressed as a 26.6 fixed point value. For
+// example, if 1 em is 10 pixels then ppem is fixed.I(10), which equals
+// fixed.Int26_6(10 << 6).
+//
+// To get those lengths or coordinates in terms of font units instead of
+// pixels, use ppem = fixed.Int26_6(f.UnitsPerEm()) and if those methods take a
+// font.Hinting parameter, use font.HintingNone. The return values will have
+// type fixed.Int26_6, but those numbers can be converted back to Units with no
+// further scaling necessary.
type Font struct {
src source
@@ -283,11 +336,16 @@ type Font struct {
// https://www.microsoft.com/typography/otspec/otff.htm#otttables
// "Other OpenType Tables".
//
- // TODO: hdmx, kern, vmtx? Others?
+ // TODO: hdmx, vmtx? Others?
+ kern table
cached struct {
+ glyphIndex glyphIndexFunc
indexToLocFormat bool // false means short, true means long.
isPostScript bool
+ kernNumPairs int32
+ kernOffset int32
+ postTableVersion uint32
unitsPerEm Units
// The glyph data for the glyph index i is in
@@ -306,51 +364,96 @@ func (f *Font) initialize() error {
if !f.src.valid() {
return errInvalidSourceData
}
- var buf []byte
+ buf, isPostScript, err := f.initializeTables(nil)
+ if err != nil {
+ return err
+ }
+ // The order of these parseXxx calls matters. Later calls may depend on
+ // information parsed by earlier calls, such as the maxp table's numGlyphs.
+ // To enforce these dependencies, such information is passed and returned
+ // explicitly, and the f.cached fields are only set afterwards.
+ //
+ // When implementing new parseXxx methods, take care not to call methods
+ // such as Font.NumGlyphs that implicitly depend on f.cached fields.
+
+ buf, indexToLocFormat, unitsPerEm, err := f.parseHead(buf)
+ if err != nil {
+ return err
+ }
+ buf, numGlyphs, locations, err := f.parseMaxp(buf, indexToLocFormat, isPostScript)
+ if err != nil {
+ return err
+ }
+ buf, glyphIndex, err := f.parseCmap(buf)
+ if err != nil {
+ return err
+ }
+ buf, kernNumPairs, kernOffset, err := f.parseKern(buf)
+ if err != nil {
+ return err
+ }
+ buf, postTableVersion, err := f.parsePost(buf, numGlyphs)
+ if err != nil {
+ return err
+ }
+
+ f.cached.glyphIndex = glyphIndex
+ f.cached.indexToLocFormat = indexToLocFormat
+ f.cached.isPostScript = isPostScript
+ f.cached.kernNumPairs = kernNumPairs
+ f.cached.kernOffset = kernOffset
+ f.cached.postTableVersion = postTableVersion
+ f.cached.unitsPerEm = unitsPerEm
+ f.cached.locations = locations
+
+ return nil
+}
+
+func (f *Font) initializeTables(buf []byte) (buf1 []byte, isPostScript bool, err error) {
// https://www.microsoft.com/typography/otspec/otff.htm "Organization of an
// OpenType Font" says that "The OpenType font starts with the Offset
// Table", which is 12 bytes.
- buf, err := f.src.view(buf, 0, 12)
+ buf, err = f.src.view(buf, 0, 12)
if err != nil {
- return err
+ return nil, false, err
}
switch u32(buf) {
default:
- return errInvalidVersion
+ return nil, false, errInvalidVersion
case 0x00010000:
// No-op.
case 0x4f54544f: // "OTTO".
- f.cached.isPostScript = true
+ isPostScript = true
}
numTables := int(u16(buf[4:]))
if numTables > maxNumTables {
- return errUnsupportedNumberOfTables
+ return nil, false, errUnsupportedNumberOfTables
}
// "The Offset Table is followed immediately by the Table Record entries...
// sorted in ascending order by tag", 16 bytes each.
buf, err = f.src.view(buf, 12, 16*numTables)
if err != nil {
- return err
+ return nil, false, err
}
for b, first, prevTag := buf, true, uint32(0); len(b) > 0; b = b[16:] {
tag := u32(b)
if first {
first = false
} else if tag <= prevTag {
- return errInvalidTableTagOrder
+ return nil, false, errInvalidTableTagOrder
}
prevTag = tag
o, n := u32(b[8:12]), u32(b[12:16])
if o > maxTableOffset || n > maxTableLength {
- return errUnsupportedTableOffsetLength
+ return nil, false, errUnsupportedTableOffsetLength
}
// We ignore the checksums, but "all tables must begin on four byte
// boundries [sic]".
if o&3 != 0 {
- return errInvalidTableOffset
+ return nil, false, errInvalidTableOffset
}
// Match the 4-byte tag as a uint32. For example, "OS/2" is 0x4f532f32.
@@ -369,6 +472,8 @@ func (f *Font) initialize() error {
f.hhea = table{o, n}
case 0x686d7478:
f.hmtx = table{o, n}
+ case 0x6b65726e:
+ f.kern = table{o, n}
case 0x6c6f6361:
f.loca = table{o, n}
case 0x6d617870:
@@ -379,69 +484,258 @@ func (f *Font) initialize() error {
f.post = table{o, n}
}
}
+ return buf, isPostScript, nil
+}
- var u uint16
+func (f *Font) parseCmap(buf []byte) (buf1 []byte, glyphIndex glyphIndexFunc, err error) {
+ // https://www.microsoft.com/typography/OTSPEC/cmap.htm
+ const headerSize, entrySize = 4, 8
+ if f.cmap.length < headerSize {
+ return nil, nil, errInvalidCmapTable
+ }
+ u, err := f.src.u16(buf, f.cmap, 2)
+ if err != nil {
+ return nil, nil, err
+ }
+ numSubtables := int(u)
+ if f.cmap.length < headerSize+entrySize*uint32(numSubtables) {
+ return nil, nil, errInvalidCmapTable
+ }
+
+ var (
+ bestWidth int
+ bestOffset uint32
+ bestLength uint32
+ bestFormat uint16
+ )
+
+ // Scan all of the subtables, picking the widest supported one. See the
+ // platformEncodingWidth comment for more discussion of width.
+ for i := 0; i < numSubtables; i++ {
+ buf, err = f.src.view(buf, int(f.cmap.offset)+headerSize+entrySize*i, entrySize)
+ if err != nil {
+ return nil, nil, err
+ }
+ pid := u16(buf)
+ psid := u16(buf[2:])
+ width := platformEncodingWidth(pid, psid)
+ if width <= bestWidth {
+ continue
+ }
+ offset := u32(buf[4:])
+
+ if offset > f.cmap.length-4 {
+ return nil, nil, errInvalidCmapTable
+ }
+ buf, err = f.src.view(buf, int(f.cmap.offset+offset), 4)
+ if err != nil {
+ return nil, nil, err
+ }
+ format := u16(buf)
+ if !supportedCmapFormat(format, pid, psid) {
+ continue
+ }
+ length := uint32(u16(buf[2:]))
+
+ bestWidth = width
+ bestOffset = offset
+ bestLength = length
+ bestFormat = format
+ }
+
+ if bestWidth == 0 {
+ return nil, nil, errUnsupportedCmapEncodings
+ }
+ return f.makeCachedGlyphIndex(buf, bestOffset, bestLength, bestFormat)
+}
+
+func (f *Font) parseHead(buf []byte) (buf1 []byte, indexToLocFormat bool, unitsPerEm Units, err error) {
// https://www.microsoft.com/typography/otspec/head.htm
+
if f.head.length != 54 {
- return errInvalidHeadTable
+ return nil, false, 0, errInvalidHeadTable
}
- u, err = f.src.u16(buf, f.head, 18)
+ u, err := f.src.u16(buf, f.head, 18)
if err != nil {
- return err
+ return nil, false, 0, err
}
if u == 0 {
- return errInvalidHeadTable
+ return nil, false, 0, errInvalidHeadTable
}
- f.cached.unitsPerEm = Units(u)
+ unitsPerEm = Units(u)
u, err = f.src.u16(buf, f.head, 50)
if err != nil {
- return err
+ return nil, false, 0, err
+ }
+ indexToLocFormat = u != 0
+ return buf, indexToLocFormat, unitsPerEm, nil
+}
+
+func (f *Font) parseKern(buf []byte) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
+ // https://www.microsoft.com/typography/otspec/kern.htm
+
+ if f.kern.length == 0 {
+ return buf, 0, 0, nil
+ }
+ const headerSize = 4
+ if f.kern.length < headerSize {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ buf, err = f.src.view(buf, int(f.kern.offset), headerSize)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ offset := int(f.kern.offset) + headerSize
+ length := int(f.kern.length) - headerSize
+
+ switch version := u16(buf); version {
+ case 0:
+ // TODO: support numTables != 1. Testing that requires finding such a font.
+ if numTables := int(u16(buf[2:])); numTables != 1 {
+ return nil, 0, 0, errUnsupportedKernTable
+ }
+ return f.parseKernVersion0(buf, offset, length)
+ case 1:
+ // TODO: find such a (proprietary?) font, and support it. Both of
+ // https://www.microsoft.com/typography/otspec/kern.htm
+ // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
+ // say that such fonts work on Mac OS but not on Windows.
+ }
+ return nil, 0, 0, errUnsupportedKernTable
+}
+
+func (f *Font) parseKernVersion0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
+ const headerSize = 6
+ if length < headerSize {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ buf, err = f.src.view(buf, offset, headerSize)
+ if err != nil {
+ return nil, 0, 0, err
}
- f.cached.indexToLocFormat = u != 0
+ if version := u16(buf); version != 0 {
+ return nil, 0, 0, errUnsupportedKernTable
+ }
+ subtableLength := int(u16(buf[2:]))
+ if subtableLength < headerSize || length < subtableLength {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ if coverageBits := buf[5]; coverageBits != 0x01 {
+ // We only support horizontal kerning.
+ return nil, 0, 0, errUnsupportedKernTable
+ }
+ offset += headerSize
+ length -= headerSize
+ subtableLength -= headerSize
+
+ switch format := buf[4]; format {
+ case 0:
+ return f.parseKernFormat0(buf, offset, subtableLength)
+ case 2:
+ // TODO: find such a (proprietary?) font, and support it.
+ }
+ return nil, 0, 0, errUnsupportedKernTable
+}
+func (f *Font) parseKernFormat0(buf []byte, offset, length int) (buf1 []byte, kernNumPairs, kernOffset int32, err error) {
+ const headerSize, entrySize = 8, 6
+ if length < headerSize {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ buf, err = f.src.view(buf, offset, headerSize)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ kernNumPairs = int32(u16(buf))
+ if length != headerSize+entrySize*int(kernNumPairs) {
+ return nil, 0, 0, errInvalidKernTable
+ }
+ return buf, kernNumPairs, int32(offset) + headerSize, nil
+}
+
+func (f *Font) parseMaxp(buf []byte, indexToLocFormat, isPostScript bool) (buf1 []byte, numGlyphs int, locations []uint32, err error) {
// https://www.microsoft.com/typography/otspec/maxp.htm
- if f.cached.isPostScript {
+
+ if isPostScript {
if f.maxp.length != 6 {
- return errInvalidMaxpTable
+ return nil, 0, nil, errInvalidMaxpTable
}
} else {
if f.maxp.length != 32 {
- return errInvalidMaxpTable
+ return nil, 0, nil, errInvalidMaxpTable
}
}
- u, err = f.src.u16(buf, f.maxp, 4)
+ u, err := f.src.u16(buf, f.maxp, 4)
if err != nil {
- return err
+ return nil, 0, nil, err
}
- numGlyphs := int(u)
+ numGlyphs = int(u)
- if f.cached.isPostScript {
+ if isPostScript {
p := cffParser{
src: &f.src,
base: int(f.cff.offset),
offset: int(f.cff.offset),
end: int(f.cff.offset + f.cff.length),
}
- f.cached.locations, err = p.parse()
+ locations, err = p.parse()
if err != nil {
- return err
+ return nil, 0, nil, err
}
} else {
- f.cached.locations, err = parseLoca(
- &f.src, f.loca, f.glyf.offset, f.cached.indexToLocFormat, numGlyphs)
+ locations, err = parseLoca(&f.src, f.loca, f.glyf.offset, indexToLocFormat, numGlyphs)
if err != nil {
- return err
+ return nil, 0, nil, err
}
}
- if len(f.cached.locations) != numGlyphs+1 {
- return errInvalidLocationData
+ if len(locations) != numGlyphs+1 {
+ return nil, 0, nil, errInvalidLocationData
}
- return nil
+
+ return buf, numGlyphs, locations, nil
}
-// TODO: func (f *Font) GlyphIndex(r rune) (x GlyphIndex, ok bool)
-// This will require parsing the cmap table.
+func (f *Font) parsePost(buf []byte, numGlyphs int) (buf1 []byte, postTableVersion uint32, err error) {
+ // https://www.microsoft.com/typography/otspec/post.htm
+
+ const headerSize = 32
+ if f.post.length < headerSize {
+ return nil, 0, errInvalidPostTable
+ }
+ u, err := f.src.u32(buf, f.post, 0)
+ if err != nil {
+ return nil, 0, err
+ }
+ switch u {
+ case 0x20000:
+ if f.post.length < headerSize+2+2*uint32(numGlyphs) {
+ return nil, 0, errInvalidPostTable
+ }
+ case 0x30000:
+ // No-op.
+ default:
+ return nil, 0, errUnsupportedPostTable
+ }
+ return buf, u, nil
+}
+
+// TODO: API for looking up glyph variants?? For example, some fonts may
+// provide both slashed and dotted zero glyphs ('0'), or regular and 'old
+// style' numerals, and users can direct software to choose a variant.
+
+type glyphIndexFunc func(f *Font, b *Buffer, r rune) (GlyphIndex, error)
+
+// GlyphIndex returns the glyph index for the given rune.
+//
+// It returns (0, nil) if there is no glyph for r.
+// https://www.microsoft.com/typography/OTSPEC/cmap.htm says that "Character
+// codes that do not correspond to any glyph in the font should be mapped to
+// glyph index 0. The glyph at this location must be a special glyph
+// representing a missing character, commonly known as .notdef."
+func (f *Font) GlyphIndex(b *Buffer, r rune) (GlyphIndex, error) {
+ return f.cached.glyphIndex(f, b, r)
+}
func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) ([]byte, error) {
xx := int(x)
@@ -458,15 +752,16 @@ func (f *Font) viewGlyphData(b *Buffer, x GlyphIndex) ([]byte, error) {
// LoadGlyphOptions are the options to the Font.LoadGlyph method.
type LoadGlyphOptions struct {
- // TODO: scale / transform / hinting.
+ // TODO: transform / hinting.
}
-// LoadGlyph returns the vector segments for the x'th glyph.
+// LoadGlyph returns the vector segments for the x'th glyph. ppem is the number
+// of pixels in 1 em.
//
// If b is non-nil, the segments become invalid to use once b is re-used.
//
// It returns ErrNotFound if the glyph index is out of range.
-func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, opts *LoadGlyphOptions) ([]Segment, error) {
+func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, ppem fixed.Int26_6, opts *LoadGlyphOptions) ([]Segment, error) {
if b == nil {
b = &Buffer{}
}
@@ -491,11 +786,153 @@ func (f *Font) LoadGlyph(b *Buffer, x GlyphIndex, opts *LoadGlyphOptions) ([]Seg
b.segments = segments
}
- // TODO: look at opts to scale / transform / hint the Buffer.segments.
+ // Scale the segments. If we want to support hinting, we'll have to push
+ // the scaling computation into the PostScript / TrueType specific glyph
+ // loading code, such as the appendGlyfSegments body, since TrueType
+ // hinting bytecode works on the scaled glyph vectors. For now, though,
+ // it's simpler to scale as a post-processing step.
+ for i := range b.segments {
+ s := &b.segments[i]
+ for j := range s.Args {
+ s.Args[j] = scale(s.Args[j]*ppem, f.cached.unitsPerEm)
+ }
+ }
+
+ // TODO: look at opts to transform / hint the Buffer.segments.
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() {
+ return "", ErrNotFound
+ }
+ if f.cached.postTableVersion != 0x20000 {
+ return "", nil
+ }
+ 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
+
+ buf, err := b.view(&f.src, int(f.post.offset)+glyphNameIndexOffset+2*int(x), 2)
+ if err != nil {
+ return "", err
+ }
+ u := u16(buf)
+ if u < numBuiltInPostNames {
+ i := builtInPostNamesOffsets[u+0]
+ j := builtInPostNamesOffsets[u+1]
+ return builtInPostNamesData[i:j], nil
+ }
+ // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html
+ // says that "32768 through 65535 are reserved for future use".
+ if u > 32767 {
+ return "", errUnsupportedPostTable
+ }
+ u -= numBuiltInPostNames
+
+ // Iterate through the list of Pascal-formatted strings. A linear scan is
+ // clearly O(u), which isn't great (as the obvious loop, calling
+ // Font.GlyphName, to get all of the glyph names in a font has quadratic
+ // complexity), but the wire format doesn't suggest a better alternative.
+
+ offset := glyphNameIndexOffset + 2*f.NumGlyphs()
+ buf, err = b.view(&f.src, int(f.post.offset)+offset, int(f.post.length)-offset)
+ if err != nil {
+ return "", err
+ }
+
+ for {
+ if len(buf) == 0 {
+ return "", errInvalidPostTable
+ }
+ n := 1 + int(buf[0])
+ if len(buf) < n {
+ return "", errInvalidPostTable
+ }
+ if u == 0 {
+ return string(buf[1:n]), nil
+ }
+ buf = buf[n:]
+ u--
+ }
+}
+
+// Kern returns the horizontal adjustment for the kerning pair (x0, x1). A
+// positive kern means to move the glyphs further apart. ppem is the number of
+// pixels in 1 em.
+//
+// It returns ErrNotFound if either glyph index is out of range.
+func (f *Font) Kern(b *Buffer, x0, x1 GlyphIndex, ppem fixed.Int26_6, h font.Hinting) (fixed.Int26_6, error) {
+ // TODO: how should this work with the GPOS table and CFF fonts?
+ // https://www.microsoft.com/typography/otspec/kern.htm says that
+ // "OpenType™ fonts containing CFF outlines are not supported by the 'kern'
+ // table and must use the 'GPOS' OpenType Layout table."
+
+ if n := f.NumGlyphs(); int(x0) >= n || int(x1) >= n {
+ return 0, ErrNotFound
+ }
+ // Not every font has a kern table. If it doesn't, there's no need to
+ // allocate a Buffer.
+ if f.kern.length == 0 {
+ return 0, nil
+ }
+ if b == nil {
+ b = &Buffer{}
+ }
+
+ key := uint32(x0)<<16 | uint32(x1)
+ lo, hi := int32(0), f.cached.kernNumPairs
+ for lo < hi {
+ i := (lo + hi) / 2
+
+ // TODO: this view call inside the inner loop can lead to many small
+ // reads instead of fewer larger reads, which can be expensive. We
+ // should be able to do better, although we don't want to make (one)
+ // arbitrarily large read. Perhaps we should round up reads to 4K or 8K
+ // chunks. For reference, Arial.ttf's kern table is 5472 bytes.
+ // Times_New_Roman.ttf's kern table is 5220 bytes.
+ const entrySize = 6
+ buf, err := b.view(&f.src, int(f.cached.kernOffset+i*entrySize), entrySize)
+ if err != nil {
+ return 0, err
+ }
+
+ k := u32(buf)
+ if k < key {
+ lo = i + 1
+ } else if k > key {
+ hi = i
+ } else {
+ kern := fixed.Int26_6(int16(u16(buf[4:])))
+ kern = scale(kern*ppem, f.cached.unitsPerEm)
+ if h == font.HintingFull {
+ // Quantize the fixed.Int26_6 value to the nearest pixel.
+ kern = (kern + 32) &^ 63
+ }
+ return kern, nil
+ }
+ }
+ return 0, nil
+}
+
// Name returns the name value keyed by the given NameID.
//
// It returns ErrNotFound if there is no value for that key.
@@ -512,14 +949,14 @@ func (f *Font) Name(b *Buffer, id NameID) (string, error) {
if err != nil {
return "", err
}
- nSubtables := u16(buf[2:])
- if f.name.length < headerSize+entrySize*uint32(nSubtables) {
+ numSubtables := u16(buf[2:])
+ if f.name.length < headerSize+entrySize*uint32(numSubtables) {
return "", errInvalidNameTable
}
stringOffset := u16(buf[4:])
seen := false
- for i, n := 0, int(nSubtables); i < n; i++ {
+ for i, n := 0, int(numSubtables); i < n; i++ {
buf, err := b.view(&f.src, int(f.name.offset)+headerSize+entrySize*i, entrySize)
if err != nil {
return "", err
diff --git a/vendor/golang.org/x/image/font/sfnt/sfnt_test.go b/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
index 4ffd72f40..85d96a96f 100644
--- a/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
+++ b/vendor/golang.org/x/image/font/sfnt/sfnt_test.go
@@ -6,6 +6,7 @@ package sfnt
import (
"bytes"
+ "fmt"
"io/ioutil"
"path/filepath"
"testing"
@@ -14,52 +15,48 @@ import (
"golang.org/x/image/math/fixed"
)
-func moveTo(xa, ya int) Segment {
+func moveTo(xa, ya fixed.Int26_6) Segment {
return Segment{
- Op: SegmentOpMoveTo,
- Args: [6]fixed.Int26_6{
- 0: fixed.I(xa),
- 1: fixed.I(ya),
- },
+ Op: SegmentOpMoveTo,
+ Args: [6]fixed.Int26_6{xa, ya},
}
}
-func lineTo(xa, ya int) Segment {
+func lineTo(xa, ya fixed.Int26_6) Segment {
return Segment{
- Op: SegmentOpLineTo,
- Args: [6]fixed.Int26_6{
- 0: fixed.I(xa),
- 1: fixed.I(ya),
- },
+ Op: SegmentOpLineTo,
+ Args: [6]fixed.Int26_6{xa, ya},
}
}
-func quadTo(xa, ya, xb, yb int) Segment {
+func quadTo(xa, ya, xb, yb fixed.Int26_6) 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),
- },
+ Op: SegmentOpQuadTo,
+ Args: [6]fixed.Int26_6{xa, ya, xb, yb},
}
}
-func cubeTo(xa, ya, xb, yb, xc, yc int) Segment {
+func cubeTo(xa, ya, xb, yb, xc, yc fixed.Int26_6) 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),
- },
+ Op: SegmentOpCubeTo,
+ Args: [6]fixed.Int26_6{xa, ya, xb, yb, xc, yc},
}
}
+func checkSegmentsEqual(got, want []Segment) error {
+ if len(got) != len(want) {
+ return fmt.Errorf("got %d elements, want %d\noverall:\ngot %v\nwant %v",
+ len(got), len(want), got, want)
+ }
+ for i, g := range got {
+ if w := want[i]; g != w {
+ return fmt.Errorf("element %d:\ngot %v\nwant %v\noverall:\ngot %v\nwant %v",
+ i, g, w, got, want)
+ }
+ }
+ return nil
+}
+
func TestTrueTypeParse(t *testing.T) {
f, err := Parse(goregular.TTF)
if err != nil {
@@ -88,6 +85,167 @@ 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) {
+ data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/cmapTest.ttf"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, format := range []int{-1, 0, 4, 12} {
+ testGlyphIndex(t, data, format)
+ }
+}
+
+func testGlyphIndex(t *testing.T, data []byte, cmapFormat int) {
+ if cmapFormat >= 0 {
+ originalSupportedCmapFormat := supportedCmapFormat
+ defer func() {
+ supportedCmapFormat = originalSupportedCmapFormat
+ }()
+ supportedCmapFormat = func(format, pid, psid uint16) bool {
+ return int(format) == cmapFormat && originalSupportedCmapFormat(format, pid, psid)
+ }
+ }
+
+ f, err := Parse(data)
+ if err != nil {
+ t.Errorf("cmapFormat=%d: %v", cmapFormat, err)
+ return
+ }
+
+ testCases := []struct {
+ r rune
+ want GlyphIndex
+ }{
+ // Glyphs that aren't present in cmapTest.ttf.
+ {'?', 0},
+ {'\ufffd', 0},
+ {'\U0001f4a9', 0},
+
+ // For a .TTF file, FontForge maps:
+ // - ".notdef" to glyph index 0.
+ // - ".null" to glyph index 1.
+ // - "nonmarkingreturn" to glyph index 2.
+
+ {'/', 0},
+ {'0', 3},
+ {'1', 4},
+ {'2', 5},
+ {'3', 0},
+
+ {'@', 0},
+ {'A', 6},
+ {'B', 7},
+ {'C', 0},
+
+ {'`', 0},
+ {'a', 8},
+ {'b', 0},
+
+ // Of the remaining runes, only U+00FF LATIN SMALL LETTER Y WITH
+ // DIAERESIS is in both the Mac Roman encoding and the cmapTest.ttf
+ // font file.
+ {'\u00fe', 0},
+ {'\u00ff', 9},
+ {'\u0100', 10},
+ {'\u0101', 11},
+ {'\u0102', 0},
+
+ {'\u4e2c', 0},
+ {'\u4e2d', 12},
+ {'\u4e2e', 0},
+
+ {'\U0001f0a0', 0},
+ {'\U0001f0a1', 13},
+ {'\U0001f0a2', 0},
+
+ {'\U0001f0b0', 0},
+ {'\U0001f0b1', 14},
+ {'\U0001f0b2', 15},
+ {'\U0001f0b3', 0},
+ }
+
+ var b Buffer
+ for _, tc := range testCases {
+ want := tc.want
+ switch {
+ case cmapFormat == 0 && tc.r > '\u007f' && tc.r != '\u00ff':
+ // cmap format 0, with the Macintosh Roman encoding, can only
+ // represent a limited set of non-ASCII runes, e.g. U+00FF.
+ want = 0
+ case cmapFormat == 4 && tc.r > '\uffff':
+ // cmap format 4 only supports the Basic Multilingual Plane (BMP).
+ want = 0
+ }
+
+ got, err := f.GlyphIndex(&b, tc.r)
+ if err != nil {
+ t.Errorf("cmapFormat=%d, r=%q: %v", cmapFormat, tc.r, err)
+ continue
+ }
+ if got != want {
+ t.Errorf("cmapFormat=%d, r=%q: got %d, want %d", cmapFormat, tc.r, got, want)
+ continue
+ }
+ }
+}
+
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.
@@ -226,40 +384,32 @@ func TestTrueTypeSegments(t *testing.T) {
}
func testSegments(t *testing.T, filename string, wants [][]Segment) {
- data, err := ioutil.ReadFile(filepath.Join("..", "testdata", filename))
+ data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/" + filename))
if err != nil {
- t.Fatal(err)
+ t.Fatalf("ReadFile: %v", err)
}
f, err := Parse(data)
if err != nil {
- t.Fatal(err)
+ t.Fatalf("Parse: %v", err)
}
+ ppem := fixed.Int26_6(f.UnitsPerEm())
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)
+ got, err := f.LoadGlyph(&b, GlyphIndex(i), ppem, 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)
+ if err := checkSegmentsEqual(got, want); err != nil {
+ t.Errorf("i=%d: %v", i, err)
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 {
+ if _, err := f.LoadGlyph(nil, 0xffff, ppem, nil); err != ErrNotFound {
t.Errorf("LoadGlyph(..., 0xffff, ...):\ngot %v\nwant %v", err, ErrNotFound)
}
@@ -270,3 +420,131 @@ loop:
t.Errorf("Name:\ngot %q\nwant %q", name, want)
}
}
+
+func TestPPEM(t *testing.T) {
+ data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/glyfTest.ttf"))
+ if err != nil {
+ t.Fatalf("ReadFile: %v", err)
+ }
+ f, err := Parse(data)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+ var b Buffer
+ x, err := f.GlyphIndex(&b, '1')
+ if err != nil {
+ t.Fatalf("GlyphIndex: %v", err)
+ }
+ if x == 0 {
+ t.Fatalf("GlyphIndex: no glyph index found for the rune '1'")
+ }
+
+ testCases := []struct {
+ ppem fixed.Int26_6
+ want []Segment
+ }{{
+ ppem: fixed.Int26_6(12 << 6),
+ want: []Segment{
+ moveTo(77, 0),
+ lineTo(77, 614),
+ lineTo(230, 614),
+ lineTo(230, 0),
+ lineTo(77, 0),
+ },
+ }, {
+ ppem: fixed.Int26_6(2048),
+ want: []Segment{
+ moveTo(205, 0),
+ lineTo(205, 1638),
+ lineTo(614, 1638),
+ lineTo(614, 0),
+ lineTo(205, 0),
+ },
+ }}
+
+ for i, tc := range testCases {
+ got, err := f.LoadGlyph(&b, x, tc.ppem, nil)
+ if err != nil {
+ t.Errorf("i=%d: LoadGlyph: %v", i, err)
+ continue
+ }
+ if err := checkSegmentsEqual(got, tc.want); err != nil {
+ t.Errorf("i=%d: %v", i, err)
+ continue
+ }
+ }
+}
+
+func TestGlyphName(t *testing.T) {
+ f, err := Parse(goregular.TTF)
+ if err != nil {
+ t.Fatalf("Parse: %v", err)
+ }
+
+ testCases := []struct {
+ r rune
+ want string
+ }{
+ {'\x00', "NULL"},
+ {'!', "exclam"},
+ {'A', "A"},
+ {'{', "braceleft"},
+ {'\u00c4', "Adieresis"}, // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
+ {'\u2020', "dagger"}, // U+2020 DAGGER
+ {'\u2660', "spade"}, // U+2660 BLACK SPADE SUIT
+ {'\uf800', "gopher"}, // U+F800 <Private Use>
+ {'\ufffe', ".notdef"}, // Not in the Go Regular font, so GlyphIndex returns (0, nil).
+ }
+
+ var b Buffer
+ for _, tc := range testCases {
+ x, err := f.GlyphIndex(&b, tc.r)
+ if err != nil {
+ t.Errorf("r=%q: GlyphIndex: %v", tc.r, err)
+ continue
+ }
+ got, err := f.GlyphName(&b, x)
+ if err != nil {
+ t.Errorf("r=%q: GlyphName: %v", tc.r, err)
+ continue
+ }
+ if got != tc.want {
+ t.Errorf("r=%q: got %q, want %q", tc.r, got, tc.want)
+ continue
+ }
+ }
+}
+
+func TestBuiltInPostNames(t *testing.T) {
+ testCases := []struct {
+ x GlyphIndex
+ want string
+ }{
+ {0, ".notdef"},
+ {1, ".null"},
+ {2, "nonmarkingreturn"},
+ {13, "asterisk"},
+ {36, "A"},
+ {93, "z"},
+ {123, "ocircumflex"},
+ {202, "Edieresis"},
+ {255, "Ccaron"},
+ {256, "ccaron"},
+ {257, "dcroat"},
+ {258, ""},
+ {999, ""},
+ {0xffff, ""},
+ }
+
+ for _, tc := range testCases {
+ if tc.x >= numBuiltInPostNames {
+ continue
+ }
+ i := builtInPostNamesOffsets[tc.x+0]
+ j := builtInPostNamesOffsets[tc.x+1]
+ got := builtInPostNamesData[i:j]
+ if got != tc.want {
+ t.Errorf("x=%d: got %q, want %q", tc.x, got, tc.want)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/font/sfnt/truetype.go b/vendor/golang.org/x/image/font/sfnt/truetype.go
index 851904d10..c0eefba56 100644
--- a/vendor/golang.org/x/image/font/sfnt/truetype.go
+++ b/vendor/golang.org/x/image/font/sfnt/truetype.go
@@ -113,6 +113,11 @@ func appendGlyfSegments(dst []Segment, data []byte) ([]Segment, error) {
return nil, errInvalidGlyphData
}
+ // TODO: support compound glyphs.
+ if numContours < 0 {
+ return nil, errUnsupportedCompoundGlyph
+ }
+
// Skip the hinting instructions.
index += 2
if index > len(data) {
@@ -124,19 +129,14 @@ func appendGlyfSegments(dst []Segment, data []byte) ([]Segment, error) {
return nil, errInvalidGlyphData
}
- // TODO: support compound glyphs.
- if numContours < 0 {
- return nil, errUnsupportedCompoundGlyph
- }
-
// For simple (non-compound) glyphs, the remainder of the glyf data
// consists of (flags, x, y) points: the Bézier curve segments. These are
- // stored in columns (all the flags first, then all the x co-ordinates,
- // then all the y co-ordinates), not rows, as it compresses better.
+ // stored in columns (all the flags first, then all the x coordinates, then
+ // all the y coordinates), not rows, as it compresses better.
//
// Decoding those points in row order involves two passes. The first pass
// determines the indexes (relative to the data slice) of where the flags,
- // the x co-ordinates and the y co-ordinates each start.
+ // the x coordinates and the y coordinates each start.
flagIndex := int32(index)
xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
if !ok {
@@ -357,9 +357,18 @@ func (g *glyfIter) nextSegment() (ok bool) {
return true
}
+ // Convert the tuple (g.x, g.y) to a fixed.Point26_6, since the latter
+ // is what's held in a Segment. The input (g.x, g.y) is a pair of int16
+ // values, measured in font units, since that is what the underlying
+ // format provides. The output is a pair of fixed.Int26_6 values. A
+ // fixed.Int26_6 usually represents a 26.6 fixed number of pixels, but
+ // this here is just a straight numerical conversion, with no scaling
+ // factor. A later step scales the Segment.Args values by such a factor
+ // to convert e.g. 1792 font units to 10.5 pixels at 2048 font units
+ // per em and 12 ppem (pixels per em).
p := fixed.Point26_6{
- X: fixed.Int26_6(g.x) << 6,
- Y: fixed.Int26_6(g.y) << 6,
+ X: fixed.Int26_6(g.x),
+ Y: fixed.Int26_6(g.y),
}
if !g.firstOnCurveValid {
diff --git a/vendor/golang.org/x/image/font/testdata/cmapTest.sfd b/vendor/golang.org/x/image/font/testdata/cmapTest.sfd
new file mode 100644
index 000000000..34c7cd659
--- /dev/null
+++ b/vendor/golang.org/x/image/font/testdata/cmapTest.sfd
@@ -0,0 +1,265 @@
+SplineFontDB: 3.0
+FontName: cmapTest
+FullName: cmapTest
+FamilyName: cmapTest
+Weight: Regular
+Copyright: Copyright 2016 The Go Authors. All rights reserved.\nUse of this font is governed by a BSD-style license that can be found at https://golang.org/LICENSE.
+Version: 001.000
+ItalicAngle: -11.25
+UnderlinePosition: -204
+UnderlineWidth: 102
+Ascent: 1638
+Descent: 410
+LayerCount: 2
+Layer: 0 1 "Back" 1
+Layer: 1 1 "Fore" 0
+XUID: [1021 367 888937226 7862908]
+FSType: 8
+OS2Version: 0
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 1
+CreationTime: 1484386143
+ModificationTime: 1486021330
+PfmFamily: 17
+TTFWeight: 400
+TTFWidth: 5
+LineGap: 184
+VLineGap: 0
+OS2TypoAscent: 0
+OS2TypoAOffset: 1
+OS2TypoDescent: 0
+OS2TypoDOffset: 1
+OS2TypoLinegap: 184
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+OS2Vendor: 'PfEd'
+MarkAttachClasses: 1
+DEI: 91125
+LangName: 1033
+Encoding: UnicodeFull
+UnicodeInterp: none
+NameList: Adobe Glyph List
+DisplaySize: -24
+AntiAlias: 1
+FitToEm: 1
+WinInfo: 126976 32 23
+BeginPrivate: 0
+EndPrivate
+TeXData: 1 0 0 346030 173015 115343 0 -1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144
+BeginChars: 1114112 13
+
+StartChar: zero
+Encoding: 48 48 0
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: one
+Encoding: 49 49 1
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: two
+Encoding: 50 50 2
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: A
+Encoding: 65 65 3
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni4E2D
+Encoding: 20013 20013 4
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: u1F0A1
+Encoding: 127137 127137 5
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ydieresis
+Encoding: 255 255 6
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Amacron
+Encoding: 256 256 7
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: amacron
+Encoding: 257 257 8
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: B
+Encoding: 66 66 9
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: a
+Encoding: 97 97 10
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: u1F0B1
+Encoding: 127153 127153 11
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: u1F0B2
+Encoding: 127154 127154 12
+Width: 800
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29,0,-1
+ 400 800 l 25,1,-1
+ 800 0 l 25,2,-1
+ 0 0 l 29,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+EndChars
+EndSplineFont
diff --git a/vendor/golang.org/x/image/font/testdata/cmapTest.ttf b/vendor/golang.org/x/image/font/testdata/cmapTest.ttf
new file mode 100644
index 000000000..ebe6be200
--- /dev/null
+++ b/vendor/golang.org/x/image/font/testdata/cmapTest.ttf
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png b/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png
index 317c3afa1..ed5a2f6b2 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png b/vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png
index 597d3628d..5c8b6529e 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png b/vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png
index ad1c20a2f..633354d52 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png b/vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png
index 166841a76..1debc306a 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png
index 04fceaa77..a3703a92a 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png
index c8b717e22..23105b3bd 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png
index 7e5cd9f62..d8d9d21e9 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png
index 702c86352..a5ba2822f 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png b/vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png
index 072446dc9..98e92e258 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png b/vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png
index c1bf630f4..4a2323dd1 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png b/vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png
index 0ac83002f..1d9603332 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png b/vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png
index eb63cb91e..93a2806a3 100644
--- a/vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png
+++ b/vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/tux-rotate-ab.png b/vendor/golang.org/x/image/testdata/tux-rotate-ab.png
index 181966cae..d604ec912 100644
--- a/vendor/golang.org/x/image/testdata/tux-rotate-ab.png
+++ b/vendor/golang.org/x/image/testdata/tux-rotate-ab.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/tux-rotate-bl.png b/vendor/golang.org/x/image/testdata/tux-rotate-bl.png
index af3f4b0d5..85b860282 100644
--- a/vendor/golang.org/x/image/testdata/tux-rotate-bl.png
+++ b/vendor/golang.org/x/image/testdata/tux-rotate-bl.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/tux-rotate-cr.png b/vendor/golang.org/x/image/testdata/tux-rotate-cr.png
index e5cff31f1..dbc42ab52 100644
--- a/vendor/golang.org/x/image/testdata/tux-rotate-cr.png
+++ b/vendor/golang.org/x/image/testdata/tux-rotate-cr.png
Binary files differ
diff --git a/vendor/golang.org/x/image/testdata/tux-rotate-nn.png b/vendor/golang.org/x/image/testdata/tux-rotate-nn.png
index c775c61dc..0d40c0d95 100644
--- a/vendor/golang.org/x/image/testdata/tux-rotate-nn.png
+++ b/vendor/golang.org/x/image/testdata/tux-rotate-nn.png
Binary files differ