From c281ee3b61e8ab53ff118866d72618ae8cce582b Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 13 Mar 2017 12:54:22 -0400 Subject: Updating server dependancies. Also adding github.com/jaytaylor/html2text and gopkg.in/gomail.v2 (#5748) --- vendor/golang.org/x/image/draw/draw.go | 42 +- vendor/golang.org/x/image/draw/gen.go | 2 +- vendor/golang.org/x/image/draw/go1_8.go | 49 ++ vendor/golang.org/x/image/draw/go1_9.go | 57 +++ vendor/golang.org/x/image/draw/impl.go | 96 ++-- vendor/golang.org/x/image/draw/stdlib_test.go | 6 +- vendor/golang.org/x/image/font/sfnt/cmap.go | 269 ++++++++++ vendor/golang.org/x/image/font/sfnt/data.go | 68 +++ .../golang.org/x/image/font/sfnt/example_test.go | 128 +++++ vendor/golang.org/x/image/font/sfnt/gen.go | 321 ++++++++++++ vendor/golang.org/x/image/font/sfnt/postscript.go | 111 ++-- .../x/image/font/sfnt/proprietary_test.go | 479 ++++++++++++++++++ vendor/golang.org/x/image/font/sfnt/sfnt.go | 561 ++++++++++++++++++--- vendor/golang.org/x/image/font/sfnt/sfnt_test.go | 370 ++++++++++++-- vendor/golang.org/x/image/font/sfnt/truetype.go | 29 +- .../golang.org/x/image/font/testdata/cmapTest.sfd | 265 ++++++++++ .../golang.org/x/image/font/testdata/cmapTest.ttf | Bin 0 -> 2528 bytes .../x/image/testdata/go-turns-two-down-ab.png | Bin 21338 -> 21092 bytes .../x/image/testdata/go-turns-two-down-bl.png | Bin 18581 -> 18169 bytes .../x/image/testdata/go-turns-two-down-cr.png | Bin 19519 -> 19141 bytes .../x/image/testdata/go-turns-two-down-nn.png | Bin 21504 -> 21320 bytes .../x/image/testdata/go-turns-two-rotate-ab.png | Bin 7654 -> 7417 bytes .../x/image/testdata/go-turns-two-rotate-bl.png | Bin 7653 -> 7421 bytes .../x/image/testdata/go-turns-two-rotate-cr.png | Bin 7808 -> 7544 bytes .../x/image/testdata/go-turns-two-rotate-nn.png | Bin 4915 -> 5128 bytes .../x/image/testdata/go-turns-two-up-ab.png | Bin 9633 -> 9427 bytes .../x/image/testdata/go-turns-two-up-bl.png | Bin 9639 -> 9427 bytes .../x/image/testdata/go-turns-two-up-cr.png | Bin 10987 -> 10694 bytes .../x/image/testdata/go-turns-two-up-nn.png | Bin 1368 -> 1369 bytes .../golang.org/x/image/testdata/tux-rotate-ab.png | Bin 3237 -> 3340 bytes .../golang.org/x/image/testdata/tux-rotate-bl.png | Bin 3751 -> 3836 bytes .../golang.org/x/image/testdata/tux-rotate-cr.png | Bin 3753 -> 3841 bytes .../golang.org/x/image/testdata/tux-rotate-nn.png | Bin 3055 -> 3159 bytes 33 files changed, 2604 insertions(+), 249 deletions(-) create mode 100644 vendor/golang.org/x/image/draw/go1_8.go create mode 100644 vendor/golang.org/x/image/draw/go1_9.go create mode 100644 vendor/golang.org/x/image/font/sfnt/cmap.go create mode 100644 vendor/golang.org/x/image/font/sfnt/data.go create mode 100644 vendor/golang.org/x/image/font/sfnt/example_test.go create mode 100644 vendor/golang.org/x/image/font/sfnt/gen.go create mode 100644 vendor/golang.org/x/image/font/sfnt/proprietary_test.go create mode 100644 vendor/golang.org/x/image/font/testdata/cmapTest.sfd create mode 100644 vendor/golang.org/x/image/font/testdata/cmapTest.ttf (limited to 'vendor/golang.org/x/image') 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 , 中 + '\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 + {'\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 + {'\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 Binary files /dev/null and b/vendor/golang.org/x/image/font/testdata/cmapTest.ttf 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png and b/vendor/golang.org/x/image/testdata/go-turns-two-down-ab.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png and b/vendor/golang.org/x/image/testdata/go-turns-two-down-bl.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png and b/vendor/golang.org/x/image/testdata/go-turns-two-down-cr.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png and b/vendor/golang.org/x/image/testdata/go-turns-two-down-nn.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png and b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-ab.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png and b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-bl.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png and b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-cr.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png and b/vendor/golang.org/x/image/testdata/go-turns-two-rotate-nn.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png and b/vendor/golang.org/x/image/testdata/go-turns-two-up-ab.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png and b/vendor/golang.org/x/image/testdata/go-turns-two-up-bl.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png and b/vendor/golang.org/x/image/testdata/go-turns-two-up-cr.png 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 Binary files a/vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png and b/vendor/golang.org/x/image/testdata/go-turns-two-up-nn.png 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 Binary files a/vendor/golang.org/x/image/testdata/tux-rotate-ab.png and b/vendor/golang.org/x/image/testdata/tux-rotate-ab.png 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 Binary files a/vendor/golang.org/x/image/testdata/tux-rotate-bl.png and b/vendor/golang.org/x/image/testdata/tux-rotate-bl.png 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 Binary files a/vendor/golang.org/x/image/testdata/tux-rotate-cr.png and b/vendor/golang.org/x/image/testdata/tux-rotate-cr.png 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 Binary files a/vendor/golang.org/x/image/testdata/tux-rotate-nn.png and b/vendor/golang.org/x/image/testdata/tux-rotate-nn.png differ -- cgit v1.2.3-1-g7c22