vendor: update golang.org/x/image
This commit is contained in:
parent
92e0c58b22
commit
161914c34c
10
vendor/golang.org/x/image/.gitattributes
generated
vendored
10
vendor/golang.org/x/image/.gitattributes
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
# Treat all files in this repo as binary, with no git magic updating
|
|
||||||
# line endings. Windows users contributing to Go will need to use a
|
|
||||||
# modern version of git and editors capable of LF line endings.
|
|
||||||
#
|
|
||||||
# We'll prevent accidental CRLF line endings from entering the repo
|
|
||||||
# via the git-review gofmt checks.
|
|
||||||
#
|
|
||||||
# See golang.org/issue/9281
|
|
||||||
|
|
||||||
* -text
|
|
2
vendor/golang.org/x/image/.gitignore
generated
vendored
2
vendor/golang.org/x/image/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
# Add no patterns to .hgignore except for files generated by the build.
|
|
||||||
last-change
|
|
26
vendor/golang.org/x/image/CONTRIBUTING.md
generated
vendored
26
vendor/golang.org/x/image/CONTRIBUTING.md
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
# Contributing to Go
|
|
||||||
|
|
||||||
Go is an open source project.
|
|
||||||
|
|
||||||
It is the work of hundreds of contributors. We appreciate your help!
|
|
||||||
|
|
||||||
## Filing issues
|
|
||||||
|
|
||||||
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
|
|
||||||
|
|
||||||
1. What version of Go are you using (`go version`)?
|
|
||||||
2. What operating system and processor architecture are you using?
|
|
||||||
3. What did you do?
|
|
||||||
4. What did you expect to see?
|
|
||||||
5. What did you see instead?
|
|
||||||
|
|
||||||
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
|
||||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
|
||||||
|
|
||||||
## Contributing code
|
|
||||||
|
|
||||||
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
|
|
||||||
before sending patches.
|
|
||||||
|
|
||||||
Unless otherwise noted, the Go source files are distributed under
|
|
||||||
the BSD-style license found in the LICENSE file.
|
|
17
vendor/golang.org/x/image/README.md
generated
vendored
17
vendor/golang.org/x/image/README.md
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
# Go Images
|
|
||||||
|
|
||||||
This repository holds supplementary Go image libraries.
|
|
||||||
|
|
||||||
## Download/Install
|
|
||||||
|
|
||||||
The easiest way to install is to run `go get -u golang.org/x/image/...`. You can
|
|
||||||
also manually git clone the repository to `$GOPATH/src/golang.org/x/image`.
|
|
||||||
|
|
||||||
## Report Issues / Send Patches
|
|
||||||
|
|
||||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
|
||||||
this repository, see https://golang.org/doc/contribute.html.
|
|
||||||
|
|
||||||
The main issue tracker for the image repository is located at
|
|
||||||
https://github.com/golang/go/issues. Prefix your issue with "x/image:" in the
|
|
||||||
subject line, so it is easy to find.
|
|
75
vendor/golang.org/x/image/bmp/reader_test.go
generated
vendored
75
vendor/golang.org/x/image/bmp/reader_test.go
generated
vendored
@ -1,75 +0,0 @@
|
|||||||
// Copyright 2012 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 bmp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
_ "image/png"
|
|
||||||
)
|
|
||||||
|
|
||||||
const testdataDir = "../testdata/"
|
|
||||||
|
|
||||||
func compare(t *testing.T, img0, img1 image.Image) error {
|
|
||||||
b := img1.Bounds()
|
|
||||||
if !b.Eq(img0.Bounds()) {
|
|
||||||
return fmt.Errorf("wrong image size: want %s, got %s", img0.Bounds(), b)
|
|
||||||
}
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
for x := b.Min.X; x < b.Max.X; x++ {
|
|
||||||
c0 := img0.At(x, y)
|
|
||||||
c1 := img1.At(x, y)
|
|
||||||
r0, g0, b0, a0 := c0.RGBA()
|
|
||||||
r1, g1, b1, a1 := c1.RGBA()
|
|
||||||
if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
|
|
||||||
return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestDecode tests that decoding a PNG image and a BMP image result in the
|
|
||||||
// same pixel data.
|
|
||||||
func TestDecode(t *testing.T) {
|
|
||||||
testCases := []string{
|
|
||||||
"video-001",
|
|
||||||
"yellow_rose-small",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
f0, err := os.Open(testdataDir + tc + ".png")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: Open PNG: %v", tc, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer f0.Close()
|
|
||||||
img0, _, err := image.Decode(f0)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: Decode PNG: %v", tc, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
f1, err := os.Open(testdataDir + tc + ".bmp")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: Open BMP: %v", tc, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer f1.Close()
|
|
||||||
img1, _, err := image.Decode(f1)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: Decode BMP: %v", tc, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := compare(t, img0, img1); err != nil {
|
|
||||||
t.Errorf("%s: %v", tc, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
91
vendor/golang.org/x/image/bmp/writer_test.go
generated
vendored
91
vendor/golang.org/x/image/bmp/writer_test.go
generated
vendored
@ -1,91 +0,0 @@
|
|||||||
// Copyright 2013 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 bmp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func openImage(filename string) (image.Image, error) {
|
|
||||||
f, err := os.Open(testdataDir + filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
return Decode(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncode(t *testing.T) {
|
|
||||||
img0, err := openImage("video-001.bmp")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err = Encode(buf, img0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
img1, err := Decode(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
compare(t, img0, img1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestZeroWidthVeryLargeHeight tests that encoding and decoding a degenerate
|
|
||||||
// image with zero width but over one billion pixels in height is faster than
|
|
||||||
// naively calling an io.Reader or io.Writer method once per row.
|
|
||||||
func TestZeroWidthVeryLargeHeight(t *testing.T) {
|
|
||||||
c := make(chan error, 1)
|
|
||||||
go func() {
|
|
||||||
b := image.Rect(0, 0, 0, 0x3fffffff)
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := Encode(&buf, image.NewRGBA(b)); err != nil {
|
|
||||||
c <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m, err := Decode(&buf)
|
|
||||||
if err != nil {
|
|
||||||
c <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if got := m.Bounds(); got != b {
|
|
||||||
c <- fmt.Errorf("bounds: got %v, want %v", got, b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c <- nil
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case err := <-c:
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
case <-time.After(3 * time.Second):
|
|
||||||
t.Fatalf("timed out")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BenchmarkEncode benchmarks the encoding of an image.
|
|
||||||
func BenchmarkEncode(b *testing.B) {
|
|
||||||
img, err := openImage("video-001.bmp")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
s := img.Bounds().Size()
|
|
||||||
b.SetBytes(int64(s.X * s.Y * 4))
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Encode(ioutil.Discard, img)
|
|
||||||
}
|
|
||||||
}
|
|
215
vendor/golang.org/x/image/cmd/webp-manual-test/main.go
generated
vendored
215
vendor/golang.org/x/image/cmd/webp-manual-test/main.go
generated
vendored
@ -1,215 +0,0 @@
|
|||||||
// Copyright 2014 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
|
|
||||||
//
|
|
||||||
// This build tag means that "go install golang.org/x/image/..." doesn't
|
|
||||||
// install this manual test. Use "go run main.go" to explicitly run it.
|
|
||||||
|
|
||||||
// Program webp-manual-test checks that the Go WEBP library's decodings match
|
|
||||||
// the C WEBP library's.
|
|
||||||
package main // import "golang.org/x/image/cmd/webp-manual-test"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/image/webp"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
dwebp = flag.String("dwebp", "/usr/bin/dwebp", "path to the dwebp program "+
|
|
||||||
"installed from https://developers.google.com/speed/webp/download")
|
|
||||||
testdata = flag.String("testdata", "", "path to the libwebp-test-data directory "+
|
|
||||||
"checked out from https://chromium.googlesource.com/webm/libwebp-test-data")
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
if err := checkDwebp(); err != nil {
|
|
||||||
flag.Usage()
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if *testdata == "" {
|
|
||||||
flag.Usage()
|
|
||||||
log.Fatal("testdata flag was not specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(*testdata)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
names, err := f.Readdirnames(-1)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Readdirnames: %v", err)
|
|
||||||
}
|
|
||||||
sort.Strings(names)
|
|
||||||
|
|
||||||
nFail, nPass := 0, 0
|
|
||||||
for _, name := range names {
|
|
||||||
if !strings.HasSuffix(name, "webp") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := test(name); err != nil {
|
|
||||||
fmt.Printf("FAIL\t%s\t%v\n", name, err)
|
|
||||||
nFail++
|
|
||||||
} else {
|
|
||||||
fmt.Printf("PASS\t%s\n", name)
|
|
||||||
nPass++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("%d PASS, %d FAIL, %d TOTAL\n", nPass, nFail, nPass+nFail)
|
|
||||||
if nFail != 0 {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkDwebp() error {
|
|
||||||
if *dwebp == "" {
|
|
||||||
return fmt.Errorf("dwebp flag was not specified")
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(*dwebp); err != nil {
|
|
||||||
return fmt.Errorf("could not find dwebp program at %q", *dwebp)
|
|
||||||
}
|
|
||||||
b, err := exec.Command(*dwebp, "-version").Output()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not determine the dwebp program version for %q: %v", *dwebp, err)
|
|
||||||
}
|
|
||||||
switch s := string(bytes.TrimSpace(b)); s {
|
|
||||||
case "0.4.0", "0.4.1", "0.4.2":
|
|
||||||
return fmt.Errorf("the dwebp program version %q for %q has a known bug "+
|
|
||||||
"(https://bugs.chromium.org/p/webp/issues/detail?id=239). Please use a newer version.", s, *dwebp)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// test tests a single WEBP image.
|
|
||||||
func test(name string) error {
|
|
||||||
filename := filepath.Join(*testdata, name)
|
|
||||||
f, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
gotImage, err := webp.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
format, encode := "-pgm", encodePGM
|
|
||||||
if _, lossless := gotImage.(*image.NRGBA); lossless {
|
|
||||||
format, encode = "-pam", encodePAM
|
|
||||||
}
|
|
||||||
got, err := encode(gotImage)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("encode: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout := new(bytes.Buffer)
|
|
||||||
stderr := new(bytes.Buffer)
|
|
||||||
c := exec.Command(*dwebp, filename, format, "-o", "/dev/stdout")
|
|
||||||
c.Stdout = stdout
|
|
||||||
c.Stderr = stderr
|
|
||||||
if err := c.Run(); err != nil {
|
|
||||||
os.Stderr.Write(stderr.Bytes())
|
|
||||||
return fmt.Errorf("executing dwebp: %v", err)
|
|
||||||
}
|
|
||||||
want := stdout.Bytes()
|
|
||||||
|
|
||||||
if len(got) != len(want) {
|
|
||||||
return fmt.Errorf("encodings have different length: got %d, want %d", len(got), len(want))
|
|
||||||
}
|
|
||||||
for i, g := range got {
|
|
||||||
if w := want[i]; g != w {
|
|
||||||
return fmt.Errorf("encodings differ at position 0x%x: got 0x%02x, want 0x%02x", i, g, w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodePAM encodes gotImage in the PAM format.
|
|
||||||
func encodePAM(gotImage image.Image) ([]byte, error) {
|
|
||||||
m, ok := gotImage.(*image.NRGBA)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("lossless image did not decode to an *image.NRGBA")
|
|
||||||
}
|
|
||||||
b := m.Bounds()
|
|
||||||
w, h := b.Dx(), b.Dy()
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
fmt.Fprintf(buf, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n", w, h)
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
o := m.PixOffset(b.Min.X, y)
|
|
||||||
buf.Write(m.Pix[o : o+4*w])
|
|
||||||
}
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodePGM encodes gotImage in the PGM format in the IMC4 layout.
|
|
||||||
func encodePGM(gotImage image.Image) ([]byte, error) {
|
|
||||||
var (
|
|
||||||
m *image.YCbCr
|
|
||||||
ma *image.NYCbCrA
|
|
||||||
)
|
|
||||||
switch g := gotImage.(type) {
|
|
||||||
case *image.YCbCr:
|
|
||||||
m = g
|
|
||||||
case *image.NYCbCrA:
|
|
||||||
m = &g.YCbCr
|
|
||||||
ma = g
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("lossy image did not decode to an *image.YCbCr")
|
|
||||||
}
|
|
||||||
if m.SubsampleRatio != image.YCbCrSubsampleRatio420 {
|
|
||||||
return nil, fmt.Errorf("lossy image did not decode to a 4:2:0 YCbCr")
|
|
||||||
}
|
|
||||||
b := m.Bounds()
|
|
||||||
w, h := b.Dx(), b.Dy()
|
|
||||||
w2, h2 := (w+1)/2, (h+1)/2
|
|
||||||
outW, outH := 2*w2, h+h2
|
|
||||||
if ma != nil {
|
|
||||||
outH += h
|
|
||||||
}
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
fmt.Fprintf(buf, "P5\n%d %d\n255\n", outW, outH)
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
o := m.YOffset(b.Min.X, y)
|
|
||||||
buf.Write(m.Y[o : o+w])
|
|
||||||
if w&1 != 0 {
|
|
||||||
buf.WriteByte(0x00)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y += 2 {
|
|
||||||
o := m.COffset(b.Min.X, y)
|
|
||||||
buf.Write(m.Cb[o : o+w2])
|
|
||||||
buf.Write(m.Cr[o : o+w2])
|
|
||||||
}
|
|
||||||
if ma != nil {
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
o := ma.AOffset(b.Min.X, y)
|
|
||||||
buf.Write(ma.A[o : o+w])
|
|
||||||
if w&1 != 0 {
|
|
||||||
buf.WriteByte(0x00)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// dump can be useful for debugging.
|
|
||||||
func dump(w io.Writer, b []byte) {
|
|
||||||
h := hex.Dumper(w)
|
|
||||||
h.Write(b)
|
|
||||||
h.Close()
|
|
||||||
}
|
|
1
vendor/golang.org/x/image/codereview.cfg
generated
vendored
1
vendor/golang.org/x/image/codereview.cfg
generated
vendored
@ -1 +0,0 @@
|
|||||||
issuerepo: golang/go
|
|
10
vendor/golang.org/x/image/colornames/colornames.go
generated
vendored
10
vendor/golang.org/x/image/colornames/colornames.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// Package colornames provides named colors as defined in the SVG 1.1 spec.
|
|
||||||
//
|
|
||||||
// See http://www.w3.org/TR/SVG/types.html#ColorKeywords
|
|
||||||
package colornames
|
|
42
vendor/golang.org/x/image/colornames/colornames_test.go
generated
vendored
42
vendor/golang.org/x/image/colornames/colornames_test.go
generated
vendored
@ -1,42 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
package colornames
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image/color"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestColornames(t *testing.T) {
|
|
||||||
if len(Map) != len(Names) {
|
|
||||||
t.Fatalf("Map and Names have different length: %d vs %d", len(Map), len(Names))
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, want := range testCases {
|
|
||||||
got, ok := Map[name]
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("Did not find %s", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("%s:\ngot %v\nwant %v", name, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testCases = map[string]color.RGBA{
|
|
||||||
"aliceblue": color.RGBA{240, 248, 255, 255},
|
|
||||||
"crimson": color.RGBA{220, 20, 60, 255},
|
|
||||||
"darkorange": color.RGBA{255, 140, 0, 255},
|
|
||||||
"deepskyblue": color.RGBA{0, 191, 255, 255},
|
|
||||||
"greenyellow": color.RGBA{173, 255, 47, 255},
|
|
||||||
"lightgrey": color.RGBA{211, 211, 211, 255},
|
|
||||||
"lightpink": color.RGBA{255, 182, 193, 255},
|
|
||||||
"mediumseagreen": color.RGBA{60, 179, 113, 255},
|
|
||||||
"olivedrab": color.RGBA{107, 142, 35, 255},
|
|
||||||
"purple": color.RGBA{128, 0, 128, 255},
|
|
||||||
"slategrey": color.RGBA{112, 128, 144, 255},
|
|
||||||
"yellowgreen": color.RGBA{154, 205, 50, 255},
|
|
||||||
}
|
|
197
vendor/golang.org/x/image/colornames/gen.go
generated
vendored
197
vendor/golang.org/x/image/colornames/gen.go
generated
vendored
@ -1,197 +0,0 @@
|
|||||||
// 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 ignore
|
|
||||||
|
|
||||||
// This program generates table.go from
|
|
||||||
// http://www.w3.org/TR/SVG/types.html#ColorKeywords
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"image/color"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/net/html"
|
|
||||||
"golang.org/x/net/html/atom"
|
|
||||||
)
|
|
||||||
|
|
||||||
// matchFunc matches HTML nodes.
|
|
||||||
type matchFunc func(*html.Node) bool
|
|
||||||
|
|
||||||
// appendAll recursively traverses the parse tree rooted under the provided
|
|
||||||
// node and appends all nodes matched by the matchFunc to dst.
|
|
||||||
func appendAll(dst []*html.Node, n *html.Node, mf matchFunc) []*html.Node {
|
|
||||||
if mf(n) {
|
|
||||||
dst = append(dst, n)
|
|
||||||
}
|
|
||||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
||||||
dst = appendAll(dst, c, mf)
|
|
||||||
}
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// matchAtom returns a matchFunc that matches a Node with the specified Atom.
|
|
||||||
func matchAtom(a atom.Atom) matchFunc {
|
|
||||||
return func(n *html.Node) bool {
|
|
||||||
return n.DataAtom == a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// matchAtomAttr returns a matchFunc that matches a Node with the specified
|
|
||||||
// Atom and a html.Attribute's namespace, key and value.
|
|
||||||
func matchAtomAttr(a atom.Atom, namespace, key, value string) matchFunc {
|
|
||||||
return func(n *html.Node) bool {
|
|
||||||
return n.DataAtom == a && getAttr(n, namespace, key) == value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getAttr fetches the value of a html.Attribute for a given namespace and key.
|
|
||||||
func getAttr(n *html.Node, namespace, key string) string {
|
|
||||||
for _, attr := range n.Attr {
|
|
||||||
if attr.Namespace == namespace && attr.Key == key {
|
|
||||||
return attr.Val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// re extracts RGB values from strings like "rgb( 0, 223, 128)".
|
|
||||||
var re = regexp.MustCompile(`rgb\(\s*([0-9]+),\s*([0-9]+),\s*([0-9]+)\)`)
|
|
||||||
|
|
||||||
// parseRGB parses a color from a string like "rgb( 0, 233, 128)". It sets
|
|
||||||
// the alpha value of the color to full opacity.
|
|
||||||
func parseRGB(s string) (color.RGBA, error) {
|
|
||||||
m := re.FindStringSubmatch(s)
|
|
||||||
if m == nil {
|
|
||||||
return color.RGBA{}, fmt.Errorf("malformed color: %q", s)
|
|
||||||
}
|
|
||||||
var rgb [3]uint8
|
|
||||||
for i, t := range m[1:] {
|
|
||||||
num, err := strconv.ParseUint(t, 10, 8)
|
|
||||||
if err != nil {
|
|
||||||
return color.RGBA{}, fmt.Errorf("malformed value %q in %q: %s", t, s, err)
|
|
||||||
}
|
|
||||||
rgb[i] = uint8(num)
|
|
||||||
}
|
|
||||||
return color.RGBA{rgb[0], rgb[1], rgb[2], 0xFF}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractSVGColors extracts named colors from the parse tree of the SVG 1.1
|
|
||||||
// spec HTML document "Chapter 4: Basic data types and interfaces".
|
|
||||||
func extractSVGColors(tree *html.Node) (map[string]color.RGBA, error) {
|
|
||||||
ret := make(map[string]color.RGBA)
|
|
||||||
|
|
||||||
// Find the tables which store the color keywords in the parse tree.
|
|
||||||
colorTables := appendAll(nil, tree, func(n *html.Node) bool {
|
|
||||||
return n.DataAtom == atom.Table && strings.Contains(getAttr(n, "", "summary"), "color keywords part")
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, table := range colorTables {
|
|
||||||
// Color names and values are stored in TextNodes within spans in each row.
|
|
||||||
for _, tr := range appendAll(nil, table, matchAtom(atom.Tr)) {
|
|
||||||
nameSpan := appendAll(nil, tr, matchAtomAttr(atom.Span, "", "class", "prop-value"))
|
|
||||||
valueSpan := appendAll(nil, tr, matchAtomAttr(atom.Span, "", "class", "color-keyword-value"))
|
|
||||||
|
|
||||||
// Since SVG 1.1 defines an odd number of colors, the last row
|
|
||||||
// in the second table does not have contents. We skip it.
|
|
||||||
if len(nameSpan) != 1 || len(valueSpan) != 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
n, v := nameSpan[0].FirstChild, valueSpan[0].FirstChild
|
|
||||||
// This sanity checks for the existence of TextNodes under spans.
|
|
||||||
if n == nil || n.Type != html.TextNode || v == nil || v.Type != html.TextNode {
|
|
||||||
return nil, fmt.Errorf("extractSVGColors: couldn't find name/value text nodes")
|
|
||||||
}
|
|
||||||
val, err := parseRGB(v.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("extractSVGColors: couldn't parse name/value %q/%q: %s", n.Data, v.Data, err)
|
|
||||||
}
|
|
||||||
ret[n.Data] = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const preamble = `// generated by go generate; DO NOT EDIT.
|
|
||||||
|
|
||||||
package colornames
|
|
||||||
|
|
||||||
import "image/color"
|
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
// WriteColorNames writes table.go.
|
|
||||||
func writeColorNames(w io.Writer, m map[string]color.RGBA) {
|
|
||||||
keys := make([]string, 0, len(m))
|
|
||||||
for k := range m {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
fmt.Fprintln(w, preamble)
|
|
||||||
fmt.Fprintln(w, "// Map contains named colors defined in the SVG 1.1 spec.")
|
|
||||||
fmt.Fprintln(w, "var Map = map[string]color.RGBA{")
|
|
||||||
for _, k := range keys {
|
|
||||||
c := m[k]
|
|
||||||
fmt.Fprintf(w, "%q:color.RGBA{%#02x, %#02x, %#02x, %#02x}, // rgb(%d, %d, %d)\n",
|
|
||||||
k, c.R, c.G, c.B, c.A, c.R, c.G, c.B)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, "}\n")
|
|
||||||
fmt.Fprintln(w, "// Names contains the color names defined in the SVG 1.1 spec.")
|
|
||||||
fmt.Fprintln(w, "var Names = []string{")
|
|
||||||
for _, k := range keys {
|
|
||||||
fmt.Fprintf(w, "%q,\n", k)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, "}\n")
|
|
||||||
fmt.Fprintln(w, "var (")
|
|
||||||
for _, k := range keys {
|
|
||||||
c := m[k]
|
|
||||||
// Make the upper case version of k: "Darkred" instead of "darkred".
|
|
||||||
k = string(k[0]-0x20) + k[1:]
|
|
||||||
fmt.Fprintf(w, "%s=color.RGBA{%#02x, %#02x, %#02x, %#02x} // rgb(%d, %d, %d)\n",
|
|
||||||
k, c.R, c.G, c.B, c.A, c.R, c.G, c.B)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = "http://www.w3.org/TR/SVG/types.html"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
res, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Couldn't read from %s: %s\n", url, err)
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
|
|
||||||
tree, err := html.Parse(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Couldn't parse %s: %s\n", url, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
colors, err := extractSVGColors(tree)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Couldn't extract colors: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
writeColorNames(buf, colors)
|
|
||||||
fmted, err := format.Source(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error while formatting code: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ioutil.WriteFile("table.go", fmted, 0644); err != nil {
|
|
||||||
log.Fatalf("Error writing table.go: %s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
457
vendor/golang.org/x/image/colornames/table.go
generated
vendored
457
vendor/golang.org/x/image/colornames/table.go
generated
vendored
@ -1,457 +0,0 @@
|
|||||||
// generated by go generate; DO NOT EDIT.
|
|
||||||
|
|
||||||
package colornames
|
|
||||||
|
|
||||||
import "image/color"
|
|
||||||
|
|
||||||
// Map contains named colors defined in the SVG 1.1 spec.
|
|
||||||
var Map = map[string]color.RGBA{
|
|
||||||
"aliceblue": color.RGBA{0xf0, 0xf8, 0xff, 0xff}, // rgb(240, 248, 255)
|
|
||||||
"antiquewhite": color.RGBA{0xfa, 0xeb, 0xd7, 0xff}, // rgb(250, 235, 215)
|
|
||||||
"aqua": color.RGBA{0x00, 0xff, 0xff, 0xff}, // rgb(0, 255, 255)
|
|
||||||
"aquamarine": color.RGBA{0x7f, 0xff, 0xd4, 0xff}, // rgb(127, 255, 212)
|
|
||||||
"azure": color.RGBA{0xf0, 0xff, 0xff, 0xff}, // rgb(240, 255, 255)
|
|
||||||
"beige": color.RGBA{0xf5, 0xf5, 0xdc, 0xff}, // rgb(245, 245, 220)
|
|
||||||
"bisque": color.RGBA{0xff, 0xe4, 0xc4, 0xff}, // rgb(255, 228, 196)
|
|
||||||
"black": color.RGBA{0x00, 0x00, 0x00, 0xff}, // rgb(0, 0, 0)
|
|
||||||
"blanchedalmond": color.RGBA{0xff, 0xeb, 0xcd, 0xff}, // rgb(255, 235, 205)
|
|
||||||
"blue": color.RGBA{0x00, 0x00, 0xff, 0xff}, // rgb(0, 0, 255)
|
|
||||||
"blueviolet": color.RGBA{0x8a, 0x2b, 0xe2, 0xff}, // rgb(138, 43, 226)
|
|
||||||
"brown": color.RGBA{0xa5, 0x2a, 0x2a, 0xff}, // rgb(165, 42, 42)
|
|
||||||
"burlywood": color.RGBA{0xde, 0xb8, 0x87, 0xff}, // rgb(222, 184, 135)
|
|
||||||
"cadetblue": color.RGBA{0x5f, 0x9e, 0xa0, 0xff}, // rgb(95, 158, 160)
|
|
||||||
"chartreuse": color.RGBA{0x7f, 0xff, 0x00, 0xff}, // rgb(127, 255, 0)
|
|
||||||
"chocolate": color.RGBA{0xd2, 0x69, 0x1e, 0xff}, // rgb(210, 105, 30)
|
|
||||||
"coral": color.RGBA{0xff, 0x7f, 0x50, 0xff}, // rgb(255, 127, 80)
|
|
||||||
"cornflowerblue": color.RGBA{0x64, 0x95, 0xed, 0xff}, // rgb(100, 149, 237)
|
|
||||||
"cornsilk": color.RGBA{0xff, 0xf8, 0xdc, 0xff}, // rgb(255, 248, 220)
|
|
||||||
"crimson": color.RGBA{0xdc, 0x14, 0x3c, 0xff}, // rgb(220, 20, 60)
|
|
||||||
"cyan": color.RGBA{0x00, 0xff, 0xff, 0xff}, // rgb(0, 255, 255)
|
|
||||||
"darkblue": color.RGBA{0x00, 0x00, 0x8b, 0xff}, // rgb(0, 0, 139)
|
|
||||||
"darkcyan": color.RGBA{0x00, 0x8b, 0x8b, 0xff}, // rgb(0, 139, 139)
|
|
||||||
"darkgoldenrod": color.RGBA{0xb8, 0x86, 0x0b, 0xff}, // rgb(184, 134, 11)
|
|
||||||
"darkgray": color.RGBA{0xa9, 0xa9, 0xa9, 0xff}, // rgb(169, 169, 169)
|
|
||||||
"darkgreen": color.RGBA{0x00, 0x64, 0x00, 0xff}, // rgb(0, 100, 0)
|
|
||||||
"darkgrey": color.RGBA{0xa9, 0xa9, 0xa9, 0xff}, // rgb(169, 169, 169)
|
|
||||||
"darkkhaki": color.RGBA{0xbd, 0xb7, 0x6b, 0xff}, // rgb(189, 183, 107)
|
|
||||||
"darkmagenta": color.RGBA{0x8b, 0x00, 0x8b, 0xff}, // rgb(139, 0, 139)
|
|
||||||
"darkolivegreen": color.RGBA{0x55, 0x6b, 0x2f, 0xff}, // rgb(85, 107, 47)
|
|
||||||
"darkorange": color.RGBA{0xff, 0x8c, 0x00, 0xff}, // rgb(255, 140, 0)
|
|
||||||
"darkorchid": color.RGBA{0x99, 0x32, 0xcc, 0xff}, // rgb(153, 50, 204)
|
|
||||||
"darkred": color.RGBA{0x8b, 0x00, 0x00, 0xff}, // rgb(139, 0, 0)
|
|
||||||
"darksalmon": color.RGBA{0xe9, 0x96, 0x7a, 0xff}, // rgb(233, 150, 122)
|
|
||||||
"darkseagreen": color.RGBA{0x8f, 0xbc, 0x8f, 0xff}, // rgb(143, 188, 143)
|
|
||||||
"darkslateblue": color.RGBA{0x48, 0x3d, 0x8b, 0xff}, // rgb(72, 61, 139)
|
|
||||||
"darkslategray": color.RGBA{0x2f, 0x4f, 0x4f, 0xff}, // rgb(47, 79, 79)
|
|
||||||
"darkslategrey": color.RGBA{0x2f, 0x4f, 0x4f, 0xff}, // rgb(47, 79, 79)
|
|
||||||
"darkturquoise": color.RGBA{0x00, 0xce, 0xd1, 0xff}, // rgb(0, 206, 209)
|
|
||||||
"darkviolet": color.RGBA{0x94, 0x00, 0xd3, 0xff}, // rgb(148, 0, 211)
|
|
||||||
"deeppink": color.RGBA{0xff, 0x14, 0x93, 0xff}, // rgb(255, 20, 147)
|
|
||||||
"deepskyblue": color.RGBA{0x00, 0xbf, 0xff, 0xff}, // rgb(0, 191, 255)
|
|
||||||
"dimgray": color.RGBA{0x69, 0x69, 0x69, 0xff}, // rgb(105, 105, 105)
|
|
||||||
"dimgrey": color.RGBA{0x69, 0x69, 0x69, 0xff}, // rgb(105, 105, 105)
|
|
||||||
"dodgerblue": color.RGBA{0x1e, 0x90, 0xff, 0xff}, // rgb(30, 144, 255)
|
|
||||||
"firebrick": color.RGBA{0xb2, 0x22, 0x22, 0xff}, // rgb(178, 34, 34)
|
|
||||||
"floralwhite": color.RGBA{0xff, 0xfa, 0xf0, 0xff}, // rgb(255, 250, 240)
|
|
||||||
"forestgreen": color.RGBA{0x22, 0x8b, 0x22, 0xff}, // rgb(34, 139, 34)
|
|
||||||
"fuchsia": color.RGBA{0xff, 0x00, 0xff, 0xff}, // rgb(255, 0, 255)
|
|
||||||
"gainsboro": color.RGBA{0xdc, 0xdc, 0xdc, 0xff}, // rgb(220, 220, 220)
|
|
||||||
"ghostwhite": color.RGBA{0xf8, 0xf8, 0xff, 0xff}, // rgb(248, 248, 255)
|
|
||||||
"gold": color.RGBA{0xff, 0xd7, 0x00, 0xff}, // rgb(255, 215, 0)
|
|
||||||
"goldenrod": color.RGBA{0xda, 0xa5, 0x20, 0xff}, // rgb(218, 165, 32)
|
|
||||||
"gray": color.RGBA{0x80, 0x80, 0x80, 0xff}, // rgb(128, 128, 128)
|
|
||||||
"green": color.RGBA{0x00, 0x80, 0x00, 0xff}, // rgb(0, 128, 0)
|
|
||||||
"greenyellow": color.RGBA{0xad, 0xff, 0x2f, 0xff}, // rgb(173, 255, 47)
|
|
||||||
"grey": color.RGBA{0x80, 0x80, 0x80, 0xff}, // rgb(128, 128, 128)
|
|
||||||
"honeydew": color.RGBA{0xf0, 0xff, 0xf0, 0xff}, // rgb(240, 255, 240)
|
|
||||||
"hotpink": color.RGBA{0xff, 0x69, 0xb4, 0xff}, // rgb(255, 105, 180)
|
|
||||||
"indianred": color.RGBA{0xcd, 0x5c, 0x5c, 0xff}, // rgb(205, 92, 92)
|
|
||||||
"indigo": color.RGBA{0x4b, 0x00, 0x82, 0xff}, // rgb(75, 0, 130)
|
|
||||||
"ivory": color.RGBA{0xff, 0xff, 0xf0, 0xff}, // rgb(255, 255, 240)
|
|
||||||
"khaki": color.RGBA{0xf0, 0xe6, 0x8c, 0xff}, // rgb(240, 230, 140)
|
|
||||||
"lavender": color.RGBA{0xe6, 0xe6, 0xfa, 0xff}, // rgb(230, 230, 250)
|
|
||||||
"lavenderblush": color.RGBA{0xff, 0xf0, 0xf5, 0xff}, // rgb(255, 240, 245)
|
|
||||||
"lawngreen": color.RGBA{0x7c, 0xfc, 0x00, 0xff}, // rgb(124, 252, 0)
|
|
||||||
"lemonchiffon": color.RGBA{0xff, 0xfa, 0xcd, 0xff}, // rgb(255, 250, 205)
|
|
||||||
"lightblue": color.RGBA{0xad, 0xd8, 0xe6, 0xff}, // rgb(173, 216, 230)
|
|
||||||
"lightcoral": color.RGBA{0xf0, 0x80, 0x80, 0xff}, // rgb(240, 128, 128)
|
|
||||||
"lightcyan": color.RGBA{0xe0, 0xff, 0xff, 0xff}, // rgb(224, 255, 255)
|
|
||||||
"lightgoldenrodyellow": color.RGBA{0xfa, 0xfa, 0xd2, 0xff}, // rgb(250, 250, 210)
|
|
||||||
"lightgray": color.RGBA{0xd3, 0xd3, 0xd3, 0xff}, // rgb(211, 211, 211)
|
|
||||||
"lightgreen": color.RGBA{0x90, 0xee, 0x90, 0xff}, // rgb(144, 238, 144)
|
|
||||||
"lightgrey": color.RGBA{0xd3, 0xd3, 0xd3, 0xff}, // rgb(211, 211, 211)
|
|
||||||
"lightpink": color.RGBA{0xff, 0xb6, 0xc1, 0xff}, // rgb(255, 182, 193)
|
|
||||||
"lightsalmon": color.RGBA{0xff, 0xa0, 0x7a, 0xff}, // rgb(255, 160, 122)
|
|
||||||
"lightseagreen": color.RGBA{0x20, 0xb2, 0xaa, 0xff}, // rgb(32, 178, 170)
|
|
||||||
"lightskyblue": color.RGBA{0x87, 0xce, 0xfa, 0xff}, // rgb(135, 206, 250)
|
|
||||||
"lightslategray": color.RGBA{0x77, 0x88, 0x99, 0xff}, // rgb(119, 136, 153)
|
|
||||||
"lightslategrey": color.RGBA{0x77, 0x88, 0x99, 0xff}, // rgb(119, 136, 153)
|
|
||||||
"lightsteelblue": color.RGBA{0xb0, 0xc4, 0xde, 0xff}, // rgb(176, 196, 222)
|
|
||||||
"lightyellow": color.RGBA{0xff, 0xff, 0xe0, 0xff}, // rgb(255, 255, 224)
|
|
||||||
"lime": color.RGBA{0x00, 0xff, 0x00, 0xff}, // rgb(0, 255, 0)
|
|
||||||
"limegreen": color.RGBA{0x32, 0xcd, 0x32, 0xff}, // rgb(50, 205, 50)
|
|
||||||
"linen": color.RGBA{0xfa, 0xf0, 0xe6, 0xff}, // rgb(250, 240, 230)
|
|
||||||
"magenta": color.RGBA{0xff, 0x00, 0xff, 0xff}, // rgb(255, 0, 255)
|
|
||||||
"maroon": color.RGBA{0x80, 0x00, 0x00, 0xff}, // rgb(128, 0, 0)
|
|
||||||
"mediumaquamarine": color.RGBA{0x66, 0xcd, 0xaa, 0xff}, // rgb(102, 205, 170)
|
|
||||||
"mediumblue": color.RGBA{0x00, 0x00, 0xcd, 0xff}, // rgb(0, 0, 205)
|
|
||||||
"mediumorchid": color.RGBA{0xba, 0x55, 0xd3, 0xff}, // rgb(186, 85, 211)
|
|
||||||
"mediumpurple": color.RGBA{0x93, 0x70, 0xdb, 0xff}, // rgb(147, 112, 219)
|
|
||||||
"mediumseagreen": color.RGBA{0x3c, 0xb3, 0x71, 0xff}, // rgb(60, 179, 113)
|
|
||||||
"mediumslateblue": color.RGBA{0x7b, 0x68, 0xee, 0xff}, // rgb(123, 104, 238)
|
|
||||||
"mediumspringgreen": color.RGBA{0x00, 0xfa, 0x9a, 0xff}, // rgb(0, 250, 154)
|
|
||||||
"mediumturquoise": color.RGBA{0x48, 0xd1, 0xcc, 0xff}, // rgb(72, 209, 204)
|
|
||||||
"mediumvioletred": color.RGBA{0xc7, 0x15, 0x85, 0xff}, // rgb(199, 21, 133)
|
|
||||||
"midnightblue": color.RGBA{0x19, 0x19, 0x70, 0xff}, // rgb(25, 25, 112)
|
|
||||||
"mintcream": color.RGBA{0xf5, 0xff, 0xfa, 0xff}, // rgb(245, 255, 250)
|
|
||||||
"mistyrose": color.RGBA{0xff, 0xe4, 0xe1, 0xff}, // rgb(255, 228, 225)
|
|
||||||
"moccasin": color.RGBA{0xff, 0xe4, 0xb5, 0xff}, // rgb(255, 228, 181)
|
|
||||||
"navajowhite": color.RGBA{0xff, 0xde, 0xad, 0xff}, // rgb(255, 222, 173)
|
|
||||||
"navy": color.RGBA{0x00, 0x00, 0x80, 0xff}, // rgb(0, 0, 128)
|
|
||||||
"oldlace": color.RGBA{0xfd, 0xf5, 0xe6, 0xff}, // rgb(253, 245, 230)
|
|
||||||
"olive": color.RGBA{0x80, 0x80, 0x00, 0xff}, // rgb(128, 128, 0)
|
|
||||||
"olivedrab": color.RGBA{0x6b, 0x8e, 0x23, 0xff}, // rgb(107, 142, 35)
|
|
||||||
"orange": color.RGBA{0xff, 0xa5, 0x00, 0xff}, // rgb(255, 165, 0)
|
|
||||||
"orangered": color.RGBA{0xff, 0x45, 0x00, 0xff}, // rgb(255, 69, 0)
|
|
||||||
"orchid": color.RGBA{0xda, 0x70, 0xd6, 0xff}, // rgb(218, 112, 214)
|
|
||||||
"palegoldenrod": color.RGBA{0xee, 0xe8, 0xaa, 0xff}, // rgb(238, 232, 170)
|
|
||||||
"palegreen": color.RGBA{0x98, 0xfb, 0x98, 0xff}, // rgb(152, 251, 152)
|
|
||||||
"paleturquoise": color.RGBA{0xaf, 0xee, 0xee, 0xff}, // rgb(175, 238, 238)
|
|
||||||
"palevioletred": color.RGBA{0xdb, 0x70, 0x93, 0xff}, // rgb(219, 112, 147)
|
|
||||||
"papayawhip": color.RGBA{0xff, 0xef, 0xd5, 0xff}, // rgb(255, 239, 213)
|
|
||||||
"peachpuff": color.RGBA{0xff, 0xda, 0xb9, 0xff}, // rgb(255, 218, 185)
|
|
||||||
"peru": color.RGBA{0xcd, 0x85, 0x3f, 0xff}, // rgb(205, 133, 63)
|
|
||||||
"pink": color.RGBA{0xff, 0xc0, 0xcb, 0xff}, // rgb(255, 192, 203)
|
|
||||||
"plum": color.RGBA{0xdd, 0xa0, 0xdd, 0xff}, // rgb(221, 160, 221)
|
|
||||||
"powderblue": color.RGBA{0xb0, 0xe0, 0xe6, 0xff}, // rgb(176, 224, 230)
|
|
||||||
"purple": color.RGBA{0x80, 0x00, 0x80, 0xff}, // rgb(128, 0, 128)
|
|
||||||
"red": color.RGBA{0xff, 0x00, 0x00, 0xff}, // rgb(255, 0, 0)
|
|
||||||
"rosybrown": color.RGBA{0xbc, 0x8f, 0x8f, 0xff}, // rgb(188, 143, 143)
|
|
||||||
"royalblue": color.RGBA{0x41, 0x69, 0xe1, 0xff}, // rgb(65, 105, 225)
|
|
||||||
"saddlebrown": color.RGBA{0x8b, 0x45, 0x13, 0xff}, // rgb(139, 69, 19)
|
|
||||||
"salmon": color.RGBA{0xfa, 0x80, 0x72, 0xff}, // rgb(250, 128, 114)
|
|
||||||
"sandybrown": color.RGBA{0xf4, 0xa4, 0x60, 0xff}, // rgb(244, 164, 96)
|
|
||||||
"seagreen": color.RGBA{0x2e, 0x8b, 0x57, 0xff}, // rgb(46, 139, 87)
|
|
||||||
"seashell": color.RGBA{0xff, 0xf5, 0xee, 0xff}, // rgb(255, 245, 238)
|
|
||||||
"sienna": color.RGBA{0xa0, 0x52, 0x2d, 0xff}, // rgb(160, 82, 45)
|
|
||||||
"silver": color.RGBA{0xc0, 0xc0, 0xc0, 0xff}, // rgb(192, 192, 192)
|
|
||||||
"skyblue": color.RGBA{0x87, 0xce, 0xeb, 0xff}, // rgb(135, 206, 235)
|
|
||||||
"slateblue": color.RGBA{0x6a, 0x5a, 0xcd, 0xff}, // rgb(106, 90, 205)
|
|
||||||
"slategray": color.RGBA{0x70, 0x80, 0x90, 0xff}, // rgb(112, 128, 144)
|
|
||||||
"slategrey": color.RGBA{0x70, 0x80, 0x90, 0xff}, // rgb(112, 128, 144)
|
|
||||||
"snow": color.RGBA{0xff, 0xfa, 0xfa, 0xff}, // rgb(255, 250, 250)
|
|
||||||
"springgreen": color.RGBA{0x00, 0xff, 0x7f, 0xff}, // rgb(0, 255, 127)
|
|
||||||
"steelblue": color.RGBA{0x46, 0x82, 0xb4, 0xff}, // rgb(70, 130, 180)
|
|
||||||
"tan": color.RGBA{0xd2, 0xb4, 0x8c, 0xff}, // rgb(210, 180, 140)
|
|
||||||
"teal": color.RGBA{0x00, 0x80, 0x80, 0xff}, // rgb(0, 128, 128)
|
|
||||||
"thistle": color.RGBA{0xd8, 0xbf, 0xd8, 0xff}, // rgb(216, 191, 216)
|
|
||||||
"tomato": color.RGBA{0xff, 0x63, 0x47, 0xff}, // rgb(255, 99, 71)
|
|
||||||
"turquoise": color.RGBA{0x40, 0xe0, 0xd0, 0xff}, // rgb(64, 224, 208)
|
|
||||||
"violet": color.RGBA{0xee, 0x82, 0xee, 0xff}, // rgb(238, 130, 238)
|
|
||||||
"wheat": color.RGBA{0xf5, 0xde, 0xb3, 0xff}, // rgb(245, 222, 179)
|
|
||||||
"white": color.RGBA{0xff, 0xff, 0xff, 0xff}, // rgb(255, 255, 255)
|
|
||||||
"whitesmoke": color.RGBA{0xf5, 0xf5, 0xf5, 0xff}, // rgb(245, 245, 245)
|
|
||||||
"yellow": color.RGBA{0xff, 0xff, 0x00, 0xff}, // rgb(255, 255, 0)
|
|
||||||
"yellowgreen": color.RGBA{0x9a, 0xcd, 0x32, 0xff}, // rgb(154, 205, 50)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Names contains the color names defined in the SVG 1.1 spec.
|
|
||||||
var Names = []string{
|
|
||||||
"aliceblue",
|
|
||||||
"antiquewhite",
|
|
||||||
"aqua",
|
|
||||||
"aquamarine",
|
|
||||||
"azure",
|
|
||||||
"beige",
|
|
||||||
"bisque",
|
|
||||||
"black",
|
|
||||||
"blanchedalmond",
|
|
||||||
"blue",
|
|
||||||
"blueviolet",
|
|
||||||
"brown",
|
|
||||||
"burlywood",
|
|
||||||
"cadetblue",
|
|
||||||
"chartreuse",
|
|
||||||
"chocolate",
|
|
||||||
"coral",
|
|
||||||
"cornflowerblue",
|
|
||||||
"cornsilk",
|
|
||||||
"crimson",
|
|
||||||
"cyan",
|
|
||||||
"darkblue",
|
|
||||||
"darkcyan",
|
|
||||||
"darkgoldenrod",
|
|
||||||
"darkgray",
|
|
||||||
"darkgreen",
|
|
||||||
"darkgrey",
|
|
||||||
"darkkhaki",
|
|
||||||
"darkmagenta",
|
|
||||||
"darkolivegreen",
|
|
||||||
"darkorange",
|
|
||||||
"darkorchid",
|
|
||||||
"darkred",
|
|
||||||
"darksalmon",
|
|
||||||
"darkseagreen",
|
|
||||||
"darkslateblue",
|
|
||||||
"darkslategray",
|
|
||||||
"darkslategrey",
|
|
||||||
"darkturquoise",
|
|
||||||
"darkviolet",
|
|
||||||
"deeppink",
|
|
||||||
"deepskyblue",
|
|
||||||
"dimgray",
|
|
||||||
"dimgrey",
|
|
||||||
"dodgerblue",
|
|
||||||
"firebrick",
|
|
||||||
"floralwhite",
|
|
||||||
"forestgreen",
|
|
||||||
"fuchsia",
|
|
||||||
"gainsboro",
|
|
||||||
"ghostwhite",
|
|
||||||
"gold",
|
|
||||||
"goldenrod",
|
|
||||||
"gray",
|
|
||||||
"green",
|
|
||||||
"greenyellow",
|
|
||||||
"grey",
|
|
||||||
"honeydew",
|
|
||||||
"hotpink",
|
|
||||||
"indianred",
|
|
||||||
"indigo",
|
|
||||||
"ivory",
|
|
||||||
"khaki",
|
|
||||||
"lavender",
|
|
||||||
"lavenderblush",
|
|
||||||
"lawngreen",
|
|
||||||
"lemonchiffon",
|
|
||||||
"lightblue",
|
|
||||||
"lightcoral",
|
|
||||||
"lightcyan",
|
|
||||||
"lightgoldenrodyellow",
|
|
||||||
"lightgray",
|
|
||||||
"lightgreen",
|
|
||||||
"lightgrey",
|
|
||||||
"lightpink",
|
|
||||||
"lightsalmon",
|
|
||||||
"lightseagreen",
|
|
||||||
"lightskyblue",
|
|
||||||
"lightslategray",
|
|
||||||
"lightslategrey",
|
|
||||||
"lightsteelblue",
|
|
||||||
"lightyellow",
|
|
||||||
"lime",
|
|
||||||
"limegreen",
|
|
||||||
"linen",
|
|
||||||
"magenta",
|
|
||||||
"maroon",
|
|
||||||
"mediumaquamarine",
|
|
||||||
"mediumblue",
|
|
||||||
"mediumorchid",
|
|
||||||
"mediumpurple",
|
|
||||||
"mediumseagreen",
|
|
||||||
"mediumslateblue",
|
|
||||||
"mediumspringgreen",
|
|
||||||
"mediumturquoise",
|
|
||||||
"mediumvioletred",
|
|
||||||
"midnightblue",
|
|
||||||
"mintcream",
|
|
||||||
"mistyrose",
|
|
||||||
"moccasin",
|
|
||||||
"navajowhite",
|
|
||||||
"navy",
|
|
||||||
"oldlace",
|
|
||||||
"olive",
|
|
||||||
"olivedrab",
|
|
||||||
"orange",
|
|
||||||
"orangered",
|
|
||||||
"orchid",
|
|
||||||
"palegoldenrod",
|
|
||||||
"palegreen",
|
|
||||||
"paleturquoise",
|
|
||||||
"palevioletred",
|
|
||||||
"papayawhip",
|
|
||||||
"peachpuff",
|
|
||||||
"peru",
|
|
||||||
"pink",
|
|
||||||
"plum",
|
|
||||||
"powderblue",
|
|
||||||
"purple",
|
|
||||||
"red",
|
|
||||||
"rosybrown",
|
|
||||||
"royalblue",
|
|
||||||
"saddlebrown",
|
|
||||||
"salmon",
|
|
||||||
"sandybrown",
|
|
||||||
"seagreen",
|
|
||||||
"seashell",
|
|
||||||
"sienna",
|
|
||||||
"silver",
|
|
||||||
"skyblue",
|
|
||||||
"slateblue",
|
|
||||||
"slategray",
|
|
||||||
"slategrey",
|
|
||||||
"snow",
|
|
||||||
"springgreen",
|
|
||||||
"steelblue",
|
|
||||||
"tan",
|
|
||||||
"teal",
|
|
||||||
"thistle",
|
|
||||||
"tomato",
|
|
||||||
"turquoise",
|
|
||||||
"violet",
|
|
||||||
"wheat",
|
|
||||||
"white",
|
|
||||||
"whitesmoke",
|
|
||||||
"yellow",
|
|
||||||
"yellowgreen",
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
Aliceblue = color.RGBA{0xf0, 0xf8, 0xff, 0xff} // rgb(240, 248, 255)
|
|
||||||
Antiquewhite = color.RGBA{0xfa, 0xeb, 0xd7, 0xff} // rgb(250, 235, 215)
|
|
||||||
Aqua = color.RGBA{0x00, 0xff, 0xff, 0xff} // rgb(0, 255, 255)
|
|
||||||
Aquamarine = color.RGBA{0x7f, 0xff, 0xd4, 0xff} // rgb(127, 255, 212)
|
|
||||||
Azure = color.RGBA{0xf0, 0xff, 0xff, 0xff} // rgb(240, 255, 255)
|
|
||||||
Beige = color.RGBA{0xf5, 0xf5, 0xdc, 0xff} // rgb(245, 245, 220)
|
|
||||||
Bisque = color.RGBA{0xff, 0xe4, 0xc4, 0xff} // rgb(255, 228, 196)
|
|
||||||
Black = color.RGBA{0x00, 0x00, 0x00, 0xff} // rgb(0, 0, 0)
|
|
||||||
Blanchedalmond = color.RGBA{0xff, 0xeb, 0xcd, 0xff} // rgb(255, 235, 205)
|
|
||||||
Blue = color.RGBA{0x00, 0x00, 0xff, 0xff} // rgb(0, 0, 255)
|
|
||||||
Blueviolet = color.RGBA{0x8a, 0x2b, 0xe2, 0xff} // rgb(138, 43, 226)
|
|
||||||
Brown = color.RGBA{0xa5, 0x2a, 0x2a, 0xff} // rgb(165, 42, 42)
|
|
||||||
Burlywood = color.RGBA{0xde, 0xb8, 0x87, 0xff} // rgb(222, 184, 135)
|
|
||||||
Cadetblue = color.RGBA{0x5f, 0x9e, 0xa0, 0xff} // rgb(95, 158, 160)
|
|
||||||
Chartreuse = color.RGBA{0x7f, 0xff, 0x00, 0xff} // rgb(127, 255, 0)
|
|
||||||
Chocolate = color.RGBA{0xd2, 0x69, 0x1e, 0xff} // rgb(210, 105, 30)
|
|
||||||
Coral = color.RGBA{0xff, 0x7f, 0x50, 0xff} // rgb(255, 127, 80)
|
|
||||||
Cornflowerblue = color.RGBA{0x64, 0x95, 0xed, 0xff} // rgb(100, 149, 237)
|
|
||||||
Cornsilk = color.RGBA{0xff, 0xf8, 0xdc, 0xff} // rgb(255, 248, 220)
|
|
||||||
Crimson = color.RGBA{0xdc, 0x14, 0x3c, 0xff} // rgb(220, 20, 60)
|
|
||||||
Cyan = color.RGBA{0x00, 0xff, 0xff, 0xff} // rgb(0, 255, 255)
|
|
||||||
Darkblue = color.RGBA{0x00, 0x00, 0x8b, 0xff} // rgb(0, 0, 139)
|
|
||||||
Darkcyan = color.RGBA{0x00, 0x8b, 0x8b, 0xff} // rgb(0, 139, 139)
|
|
||||||
Darkgoldenrod = color.RGBA{0xb8, 0x86, 0x0b, 0xff} // rgb(184, 134, 11)
|
|
||||||
Darkgray = color.RGBA{0xa9, 0xa9, 0xa9, 0xff} // rgb(169, 169, 169)
|
|
||||||
Darkgreen = color.RGBA{0x00, 0x64, 0x00, 0xff} // rgb(0, 100, 0)
|
|
||||||
Darkgrey = color.RGBA{0xa9, 0xa9, 0xa9, 0xff} // rgb(169, 169, 169)
|
|
||||||
Darkkhaki = color.RGBA{0xbd, 0xb7, 0x6b, 0xff} // rgb(189, 183, 107)
|
|
||||||
Darkmagenta = color.RGBA{0x8b, 0x00, 0x8b, 0xff} // rgb(139, 0, 139)
|
|
||||||
Darkolivegreen = color.RGBA{0x55, 0x6b, 0x2f, 0xff} // rgb(85, 107, 47)
|
|
||||||
Darkorange = color.RGBA{0xff, 0x8c, 0x00, 0xff} // rgb(255, 140, 0)
|
|
||||||
Darkorchid = color.RGBA{0x99, 0x32, 0xcc, 0xff} // rgb(153, 50, 204)
|
|
||||||
Darkred = color.RGBA{0x8b, 0x00, 0x00, 0xff} // rgb(139, 0, 0)
|
|
||||||
Darksalmon = color.RGBA{0xe9, 0x96, 0x7a, 0xff} // rgb(233, 150, 122)
|
|
||||||
Darkseagreen = color.RGBA{0x8f, 0xbc, 0x8f, 0xff} // rgb(143, 188, 143)
|
|
||||||
Darkslateblue = color.RGBA{0x48, 0x3d, 0x8b, 0xff} // rgb(72, 61, 139)
|
|
||||||
Darkslategray = color.RGBA{0x2f, 0x4f, 0x4f, 0xff} // rgb(47, 79, 79)
|
|
||||||
Darkslategrey = color.RGBA{0x2f, 0x4f, 0x4f, 0xff} // rgb(47, 79, 79)
|
|
||||||
Darkturquoise = color.RGBA{0x00, 0xce, 0xd1, 0xff} // rgb(0, 206, 209)
|
|
||||||
Darkviolet = color.RGBA{0x94, 0x00, 0xd3, 0xff} // rgb(148, 0, 211)
|
|
||||||
Deeppink = color.RGBA{0xff, 0x14, 0x93, 0xff} // rgb(255, 20, 147)
|
|
||||||
Deepskyblue = color.RGBA{0x00, 0xbf, 0xff, 0xff} // rgb(0, 191, 255)
|
|
||||||
Dimgray = color.RGBA{0x69, 0x69, 0x69, 0xff} // rgb(105, 105, 105)
|
|
||||||
Dimgrey = color.RGBA{0x69, 0x69, 0x69, 0xff} // rgb(105, 105, 105)
|
|
||||||
Dodgerblue = color.RGBA{0x1e, 0x90, 0xff, 0xff} // rgb(30, 144, 255)
|
|
||||||
Firebrick = color.RGBA{0xb2, 0x22, 0x22, 0xff} // rgb(178, 34, 34)
|
|
||||||
Floralwhite = color.RGBA{0xff, 0xfa, 0xf0, 0xff} // rgb(255, 250, 240)
|
|
||||||
Forestgreen = color.RGBA{0x22, 0x8b, 0x22, 0xff} // rgb(34, 139, 34)
|
|
||||||
Fuchsia = color.RGBA{0xff, 0x00, 0xff, 0xff} // rgb(255, 0, 255)
|
|
||||||
Gainsboro = color.RGBA{0xdc, 0xdc, 0xdc, 0xff} // rgb(220, 220, 220)
|
|
||||||
Ghostwhite = color.RGBA{0xf8, 0xf8, 0xff, 0xff} // rgb(248, 248, 255)
|
|
||||||
Gold = color.RGBA{0xff, 0xd7, 0x00, 0xff} // rgb(255, 215, 0)
|
|
||||||
Goldenrod = color.RGBA{0xda, 0xa5, 0x20, 0xff} // rgb(218, 165, 32)
|
|
||||||
Gray = color.RGBA{0x80, 0x80, 0x80, 0xff} // rgb(128, 128, 128)
|
|
||||||
Green = color.RGBA{0x00, 0x80, 0x00, 0xff} // rgb(0, 128, 0)
|
|
||||||
Greenyellow = color.RGBA{0xad, 0xff, 0x2f, 0xff} // rgb(173, 255, 47)
|
|
||||||
Grey = color.RGBA{0x80, 0x80, 0x80, 0xff} // rgb(128, 128, 128)
|
|
||||||
Honeydew = color.RGBA{0xf0, 0xff, 0xf0, 0xff} // rgb(240, 255, 240)
|
|
||||||
Hotpink = color.RGBA{0xff, 0x69, 0xb4, 0xff} // rgb(255, 105, 180)
|
|
||||||
Indianred = color.RGBA{0xcd, 0x5c, 0x5c, 0xff} // rgb(205, 92, 92)
|
|
||||||
Indigo = color.RGBA{0x4b, 0x00, 0x82, 0xff} // rgb(75, 0, 130)
|
|
||||||
Ivory = color.RGBA{0xff, 0xff, 0xf0, 0xff} // rgb(255, 255, 240)
|
|
||||||
Khaki = color.RGBA{0xf0, 0xe6, 0x8c, 0xff} // rgb(240, 230, 140)
|
|
||||||
Lavender = color.RGBA{0xe6, 0xe6, 0xfa, 0xff} // rgb(230, 230, 250)
|
|
||||||
Lavenderblush = color.RGBA{0xff, 0xf0, 0xf5, 0xff} // rgb(255, 240, 245)
|
|
||||||
Lawngreen = color.RGBA{0x7c, 0xfc, 0x00, 0xff} // rgb(124, 252, 0)
|
|
||||||
Lemonchiffon = color.RGBA{0xff, 0xfa, 0xcd, 0xff} // rgb(255, 250, 205)
|
|
||||||
Lightblue = color.RGBA{0xad, 0xd8, 0xe6, 0xff} // rgb(173, 216, 230)
|
|
||||||
Lightcoral = color.RGBA{0xf0, 0x80, 0x80, 0xff} // rgb(240, 128, 128)
|
|
||||||
Lightcyan = color.RGBA{0xe0, 0xff, 0xff, 0xff} // rgb(224, 255, 255)
|
|
||||||
Lightgoldenrodyellow = color.RGBA{0xfa, 0xfa, 0xd2, 0xff} // rgb(250, 250, 210)
|
|
||||||
Lightgray = color.RGBA{0xd3, 0xd3, 0xd3, 0xff} // rgb(211, 211, 211)
|
|
||||||
Lightgreen = color.RGBA{0x90, 0xee, 0x90, 0xff} // rgb(144, 238, 144)
|
|
||||||
Lightgrey = color.RGBA{0xd3, 0xd3, 0xd3, 0xff} // rgb(211, 211, 211)
|
|
||||||
Lightpink = color.RGBA{0xff, 0xb6, 0xc1, 0xff} // rgb(255, 182, 193)
|
|
||||||
Lightsalmon = color.RGBA{0xff, 0xa0, 0x7a, 0xff} // rgb(255, 160, 122)
|
|
||||||
Lightseagreen = color.RGBA{0x20, 0xb2, 0xaa, 0xff} // rgb(32, 178, 170)
|
|
||||||
Lightskyblue = color.RGBA{0x87, 0xce, 0xfa, 0xff} // rgb(135, 206, 250)
|
|
||||||
Lightslategray = color.RGBA{0x77, 0x88, 0x99, 0xff} // rgb(119, 136, 153)
|
|
||||||
Lightslategrey = color.RGBA{0x77, 0x88, 0x99, 0xff} // rgb(119, 136, 153)
|
|
||||||
Lightsteelblue = color.RGBA{0xb0, 0xc4, 0xde, 0xff} // rgb(176, 196, 222)
|
|
||||||
Lightyellow = color.RGBA{0xff, 0xff, 0xe0, 0xff} // rgb(255, 255, 224)
|
|
||||||
Lime = color.RGBA{0x00, 0xff, 0x00, 0xff} // rgb(0, 255, 0)
|
|
||||||
Limegreen = color.RGBA{0x32, 0xcd, 0x32, 0xff} // rgb(50, 205, 50)
|
|
||||||
Linen = color.RGBA{0xfa, 0xf0, 0xe6, 0xff} // rgb(250, 240, 230)
|
|
||||||
Magenta = color.RGBA{0xff, 0x00, 0xff, 0xff} // rgb(255, 0, 255)
|
|
||||||
Maroon = color.RGBA{0x80, 0x00, 0x00, 0xff} // rgb(128, 0, 0)
|
|
||||||
Mediumaquamarine = color.RGBA{0x66, 0xcd, 0xaa, 0xff} // rgb(102, 205, 170)
|
|
||||||
Mediumblue = color.RGBA{0x00, 0x00, 0xcd, 0xff} // rgb(0, 0, 205)
|
|
||||||
Mediumorchid = color.RGBA{0xba, 0x55, 0xd3, 0xff} // rgb(186, 85, 211)
|
|
||||||
Mediumpurple = color.RGBA{0x93, 0x70, 0xdb, 0xff} // rgb(147, 112, 219)
|
|
||||||
Mediumseagreen = color.RGBA{0x3c, 0xb3, 0x71, 0xff} // rgb(60, 179, 113)
|
|
||||||
Mediumslateblue = color.RGBA{0x7b, 0x68, 0xee, 0xff} // rgb(123, 104, 238)
|
|
||||||
Mediumspringgreen = color.RGBA{0x00, 0xfa, 0x9a, 0xff} // rgb(0, 250, 154)
|
|
||||||
Mediumturquoise = color.RGBA{0x48, 0xd1, 0xcc, 0xff} // rgb(72, 209, 204)
|
|
||||||
Mediumvioletred = color.RGBA{0xc7, 0x15, 0x85, 0xff} // rgb(199, 21, 133)
|
|
||||||
Midnightblue = color.RGBA{0x19, 0x19, 0x70, 0xff} // rgb(25, 25, 112)
|
|
||||||
Mintcream = color.RGBA{0xf5, 0xff, 0xfa, 0xff} // rgb(245, 255, 250)
|
|
||||||
Mistyrose = color.RGBA{0xff, 0xe4, 0xe1, 0xff} // rgb(255, 228, 225)
|
|
||||||
Moccasin = color.RGBA{0xff, 0xe4, 0xb5, 0xff} // rgb(255, 228, 181)
|
|
||||||
Navajowhite = color.RGBA{0xff, 0xde, 0xad, 0xff} // rgb(255, 222, 173)
|
|
||||||
Navy = color.RGBA{0x00, 0x00, 0x80, 0xff} // rgb(0, 0, 128)
|
|
||||||
Oldlace = color.RGBA{0xfd, 0xf5, 0xe6, 0xff} // rgb(253, 245, 230)
|
|
||||||
Olive = color.RGBA{0x80, 0x80, 0x00, 0xff} // rgb(128, 128, 0)
|
|
||||||
Olivedrab = color.RGBA{0x6b, 0x8e, 0x23, 0xff} // rgb(107, 142, 35)
|
|
||||||
Orange = color.RGBA{0xff, 0xa5, 0x00, 0xff} // rgb(255, 165, 0)
|
|
||||||
Orangered = color.RGBA{0xff, 0x45, 0x00, 0xff} // rgb(255, 69, 0)
|
|
||||||
Orchid = color.RGBA{0xda, 0x70, 0xd6, 0xff} // rgb(218, 112, 214)
|
|
||||||
Palegoldenrod = color.RGBA{0xee, 0xe8, 0xaa, 0xff} // rgb(238, 232, 170)
|
|
||||||
Palegreen = color.RGBA{0x98, 0xfb, 0x98, 0xff} // rgb(152, 251, 152)
|
|
||||||
Paleturquoise = color.RGBA{0xaf, 0xee, 0xee, 0xff} // rgb(175, 238, 238)
|
|
||||||
Palevioletred = color.RGBA{0xdb, 0x70, 0x93, 0xff} // rgb(219, 112, 147)
|
|
||||||
Papayawhip = color.RGBA{0xff, 0xef, 0xd5, 0xff} // rgb(255, 239, 213)
|
|
||||||
Peachpuff = color.RGBA{0xff, 0xda, 0xb9, 0xff} // rgb(255, 218, 185)
|
|
||||||
Peru = color.RGBA{0xcd, 0x85, 0x3f, 0xff} // rgb(205, 133, 63)
|
|
||||||
Pink = color.RGBA{0xff, 0xc0, 0xcb, 0xff} // rgb(255, 192, 203)
|
|
||||||
Plum = color.RGBA{0xdd, 0xa0, 0xdd, 0xff} // rgb(221, 160, 221)
|
|
||||||
Powderblue = color.RGBA{0xb0, 0xe0, 0xe6, 0xff} // rgb(176, 224, 230)
|
|
||||||
Purple = color.RGBA{0x80, 0x00, 0x80, 0xff} // rgb(128, 0, 128)
|
|
||||||
Red = color.RGBA{0xff, 0x00, 0x00, 0xff} // rgb(255, 0, 0)
|
|
||||||
Rosybrown = color.RGBA{0xbc, 0x8f, 0x8f, 0xff} // rgb(188, 143, 143)
|
|
||||||
Royalblue = color.RGBA{0x41, 0x69, 0xe1, 0xff} // rgb(65, 105, 225)
|
|
||||||
Saddlebrown = color.RGBA{0x8b, 0x45, 0x13, 0xff} // rgb(139, 69, 19)
|
|
||||||
Salmon = color.RGBA{0xfa, 0x80, 0x72, 0xff} // rgb(250, 128, 114)
|
|
||||||
Sandybrown = color.RGBA{0xf4, 0xa4, 0x60, 0xff} // rgb(244, 164, 96)
|
|
||||||
Seagreen = color.RGBA{0x2e, 0x8b, 0x57, 0xff} // rgb(46, 139, 87)
|
|
||||||
Seashell = color.RGBA{0xff, 0xf5, 0xee, 0xff} // rgb(255, 245, 238)
|
|
||||||
Sienna = color.RGBA{0xa0, 0x52, 0x2d, 0xff} // rgb(160, 82, 45)
|
|
||||||
Silver = color.RGBA{0xc0, 0xc0, 0xc0, 0xff} // rgb(192, 192, 192)
|
|
||||||
Skyblue = color.RGBA{0x87, 0xce, 0xeb, 0xff} // rgb(135, 206, 235)
|
|
||||||
Slateblue = color.RGBA{0x6a, 0x5a, 0xcd, 0xff} // rgb(106, 90, 205)
|
|
||||||
Slategray = color.RGBA{0x70, 0x80, 0x90, 0xff} // rgb(112, 128, 144)
|
|
||||||
Slategrey = color.RGBA{0x70, 0x80, 0x90, 0xff} // rgb(112, 128, 144)
|
|
||||||
Snow = color.RGBA{0xff, 0xfa, 0xfa, 0xff} // rgb(255, 250, 250)
|
|
||||||
Springgreen = color.RGBA{0x00, 0xff, 0x7f, 0xff} // rgb(0, 255, 127)
|
|
||||||
Steelblue = color.RGBA{0x46, 0x82, 0xb4, 0xff} // rgb(70, 130, 180)
|
|
||||||
Tan = color.RGBA{0xd2, 0xb4, 0x8c, 0xff} // rgb(210, 180, 140)
|
|
||||||
Teal = color.RGBA{0x00, 0x80, 0x80, 0xff} // rgb(0, 128, 128)
|
|
||||||
Thistle = color.RGBA{0xd8, 0xbf, 0xd8, 0xff} // rgb(216, 191, 216)
|
|
||||||
Tomato = color.RGBA{0xff, 0x63, 0x47, 0xff} // rgb(255, 99, 71)
|
|
||||||
Turquoise = color.RGBA{0x40, 0xe0, 0xd0, 0xff} // rgb(64, 224, 208)
|
|
||||||
Violet = color.RGBA{0xee, 0x82, 0xee, 0xff} // rgb(238, 130, 238)
|
|
||||||
Wheat = color.RGBA{0xf5, 0xde, 0xb3, 0xff} // rgb(245, 222, 179)
|
|
||||||
White = color.RGBA{0xff, 0xff, 0xff, 0xff} // rgb(255, 255, 255)
|
|
||||||
Whitesmoke = color.RGBA{0xf5, 0xf5, 0xf5, 0xff} // rgb(245, 245, 245)
|
|
||||||
Yellow = color.RGBA{0xff, 0xff, 0x00, 0xff} // rgb(255, 255, 0)
|
|
||||||
Yellowgreen = color.RGBA{0x9a, 0xcd, 0x32, 0xff} // rgb(154, 205, 50)
|
|
||||||
)
|
|
118
vendor/golang.org/x/image/draw/example_test.go
generated
vendored
118
vendor/golang.org/x/image/draw/example_test.go
generated
vendored
@ -1,118 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
package draw_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/png"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/image/draw"
|
|
||||||
"golang.org/x/image/math/f64"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleDraw() {
|
|
||||||
fSrc, err := os.Open("../testdata/blue-purple-pink.png")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer fSrc.Close()
|
|
||||||
src, err := png.Decode(fSrc)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 400, 300))
|
|
||||||
green := image.NewUniform(color.RGBA{0x00, 0x1f, 0x00, 0xff})
|
|
||||||
draw.Copy(dst, image.Point{}, green, dst.Bounds(), draw.Src, nil)
|
|
||||||
qs := []draw.Interpolator{
|
|
||||||
draw.NearestNeighbor,
|
|
||||||
draw.ApproxBiLinear,
|
|
||||||
draw.CatmullRom,
|
|
||||||
}
|
|
||||||
const cos60, sin60 = 0.5, 0.866025404
|
|
||||||
t := f64.Aff3{
|
|
||||||
+2 * cos60, -2 * sin60, 100,
|
|
||||||
+2 * sin60, +2 * cos60, 100,
|
|
||||||
}
|
|
||||||
|
|
||||||
draw.Copy(dst, image.Point{20, 30}, src, src.Bounds(), draw.Over, nil)
|
|
||||||
for i, q := range qs {
|
|
||||||
q.Scale(dst, image.Rect(200+10*i, 100*i, 600+10*i, 150+100*i), src, src.Bounds(), draw.Over, nil)
|
|
||||||
}
|
|
||||||
draw.NearestNeighbor.Transform(dst, t, src, src.Bounds(), draw.Over, nil)
|
|
||||||
|
|
||||||
red := image.NewNRGBA(image.Rect(0, 0, 16, 16))
|
|
||||||
for y := 0; y < 16; y++ {
|
|
||||||
for x := 0; x < 16; x++ {
|
|
||||||
red.SetNRGBA(x, y, color.NRGBA{
|
|
||||||
R: uint8(x * 0x11),
|
|
||||||
A: uint8(y * 0x11),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
red.SetNRGBA(0, 0, color.NRGBA{0xff, 0xff, 0x00, 0xff})
|
|
||||||
red.SetNRGBA(15, 15, color.NRGBA{0xff, 0xff, 0x00, 0xff})
|
|
||||||
|
|
||||||
ops := []draw.Op{
|
|
||||||
draw.Over,
|
|
||||||
draw.Src,
|
|
||||||
}
|
|
||||||
for i, op := range ops {
|
|
||||||
dr := image.Rect(120+10*i, 150+60*i, 170+10*i, 200+60*i)
|
|
||||||
draw.NearestNeighbor.Scale(dst, dr, red, red.Bounds(), op, nil)
|
|
||||||
t := f64.Aff3{
|
|
||||||
+cos60, -sin60, float64(190 + 10*i),
|
|
||||||
+sin60, +cos60, float64(140 + 50*i),
|
|
||||||
}
|
|
||||||
draw.NearestNeighbor.Transform(dst, t, red, red.Bounds(), op, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
dr := image.Rect(0, 0, 128, 128)
|
|
||||||
checkerboard := image.NewAlpha(dr)
|
|
||||||
for y := dr.Min.Y; y < dr.Max.Y; y++ {
|
|
||||||
for x := dr.Min.X; x < dr.Max.X; x++ {
|
|
||||||
if (x/20)%2 == (y/20)%2 {
|
|
||||||
checkerboard.SetAlpha(x, y, color.Alpha{0xff})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sr := image.Rect(0, 0, 16, 16)
|
|
||||||
circle := image.NewAlpha(sr)
|
|
||||||
for y := sr.Min.Y; y < sr.Max.Y; y++ {
|
|
||||||
for x := sr.Min.X; x < sr.Max.X; x++ {
|
|
||||||
dx, dy := x-10, y-8
|
|
||||||
if d := 32 * math.Sqrt(float64(dx*dx)+float64(dy*dy)); d < 0xff {
|
|
||||||
circle.SetAlpha(x, y, color.Alpha{0xff - uint8(d)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cyan := image.NewUniform(color.RGBA{0x00, 0xff, 0xff, 0xff})
|
|
||||||
draw.NearestNeighbor.Scale(dst, dr, cyan, sr, draw.Over, &draw.Options{
|
|
||||||
DstMask: checkerboard,
|
|
||||||
SrcMask: circle,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Change false to true to write the resultant image to disk.
|
|
||||||
if false {
|
|
||||||
fDst, err := os.Create("out.png")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer fDst.Close()
|
|
||||||
err = png.Encode(fDst, dst)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("dst has bounds %v.\n", dst.Bounds())
|
|
||||||
// Output:
|
|
||||||
// dst has bounds (0,0)-(400,300).
|
|
||||||
}
|
|
742
vendor/golang.org/x/image/draw/scale_test.go
generated
vendored
742
vendor/golang.org/x/image/draw/scale_test.go
generated
vendored
@ -1,742 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
package draw
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/png"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/image/math/f64"
|
|
||||||
|
|
||||||
_ "image/jpeg"
|
|
||||||
)
|
|
||||||
|
|
||||||
var genGoldenFiles = flag.Bool("gen_golden_files", false, "whether to generate the TestXxx golden files.")
|
|
||||||
|
|
||||||
var transformMatrix = func(scale, tx, ty float64) f64.Aff3 {
|
|
||||||
const cos30, sin30 = 0.866025404, 0.5
|
|
||||||
return f64.Aff3{
|
|
||||||
+scale * cos30, -scale * sin30, tx,
|
|
||||||
+scale * sin30, +scale * cos30, ty,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(filename string, m image.Image) error {
|
|
||||||
f, err := os.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Create: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if err := png.Encode(f, m); err != nil {
|
|
||||||
return fmt.Errorf("Encode: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// testInterp tests that interpolating the source image gives the exact
|
|
||||||
// destination image. This is to ensure that any refactoring or optimization of
|
|
||||||
// the interpolation code doesn't change the behavior. Changing the actual
|
|
||||||
// algorithm or kernel used by any particular quality setting will obviously
|
|
||||||
// change the resultant pixels. In such a case, use the gen_golden_files flag
|
|
||||||
// to regenerate the golden files.
|
|
||||||
func testInterp(t *testing.T, w int, h int, direction, prefix, suffix string) {
|
|
||||||
f, err := os.Open("../testdata/" + prefix + suffix)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
src, _, err := image.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
op, scale := Src, 3.75
|
|
||||||
if prefix == "tux" {
|
|
||||||
op, scale = Over, 0.125
|
|
||||||
}
|
|
||||||
green := image.NewUniform(color.RGBA{0x00, 0x22, 0x11, 0xff})
|
|
||||||
|
|
||||||
testCases := map[string]Interpolator{
|
|
||||||
"nn": NearestNeighbor,
|
|
||||||
"ab": ApproxBiLinear,
|
|
||||||
"bl": BiLinear,
|
|
||||||
"cr": CatmullRom,
|
|
||||||
}
|
|
||||||
for name, q := range testCases {
|
|
||||||
goldenFilename := fmt.Sprintf("../testdata/%s-%s-%s.png", prefix, direction, name)
|
|
||||||
|
|
||||||
got := image.NewRGBA(image.Rect(0, 0, w, h))
|
|
||||||
Copy(got, image.Point{}, green, got.Bounds(), Src, nil)
|
|
||||||
if direction == "rotate" {
|
|
||||||
q.Transform(got, transformMatrix(scale, 40, 10), src, src.Bounds(), op, nil)
|
|
||||||
} else {
|
|
||||||
q.Scale(got, got.Bounds(), src, src.Bounds(), op, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *genGoldenFiles {
|
|
||||||
if err := encode(goldenFilename, got); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
g, err := os.Open(goldenFilename)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Open: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer g.Close()
|
|
||||||
wantRaw, err := png.Decode(g)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Decode: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// convert wantRaw to RGBA.
|
|
||||||
want, ok := wantRaw.(*image.RGBA)
|
|
||||||
if !ok {
|
|
||||||
b := wantRaw.Bounds()
|
|
||||||
want = image.NewRGBA(b)
|
|
||||||
Draw(want, b, wantRaw, b.Min, Src)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("%s: actual image differs from golden image", goldenFilename)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestScaleDown(t *testing.T) { testInterp(t, 100, 100, "down", "go-turns-two", "-280x360.jpeg") }
|
|
||||||
func TestScaleUp(t *testing.T) { testInterp(t, 75, 100, "up", "go-turns-two", "-14x18.png") }
|
|
||||||
func TestTformSrc(t *testing.T) { testInterp(t, 100, 100, "rotate", "go-turns-two", "-14x18.png") }
|
|
||||||
func TestTformOver(t *testing.T) { testInterp(t, 100, 100, "rotate", "tux", ".png") }
|
|
||||||
|
|
||||||
// TestSimpleTransforms tests Scale and Transform calls that simplify to Copy
|
|
||||||
// or Scale calls.
|
|
||||||
func TestSimpleTransforms(t *testing.T) {
|
|
||||||
f, err := os.Open("../testdata/testpattern.png") // A 100x100 image.
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
src, _, err := image.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dst0 := image.NewRGBA(image.Rect(0, 0, 120, 150))
|
|
||||||
dst1 := image.NewRGBA(image.Rect(0, 0, 120, 150))
|
|
||||||
for _, op := range []string{"scale/copy", "tform/copy", "tform/scale"} {
|
|
||||||
for _, epsilon := range []float64{0, 1e-50, 1e-1} {
|
|
||||||
Copy(dst0, image.Point{}, image.Transparent, dst0.Bounds(), Src, nil)
|
|
||||||
Copy(dst1, image.Point{}, image.Transparent, dst1.Bounds(), Src, nil)
|
|
||||||
|
|
||||||
switch op {
|
|
||||||
case "scale/copy":
|
|
||||||
dr := image.Rect(10, 30, 10+100, 30+100)
|
|
||||||
if epsilon > 1e-10 {
|
|
||||||
dr.Max.X++
|
|
||||||
}
|
|
||||||
Copy(dst0, image.Point{10, 30}, src, src.Bounds(), Src, nil)
|
|
||||||
ApproxBiLinear.Scale(dst1, dr, src, src.Bounds(), Src, nil)
|
|
||||||
case "tform/copy":
|
|
||||||
Copy(dst0, image.Point{10, 30}, src, src.Bounds(), Src, nil)
|
|
||||||
ApproxBiLinear.Transform(dst1, f64.Aff3{
|
|
||||||
1, 0 + epsilon, 10,
|
|
||||||
0, 1, 30,
|
|
||||||
}, src, src.Bounds(), Src, nil)
|
|
||||||
case "tform/scale":
|
|
||||||
ApproxBiLinear.Scale(dst0, image.Rect(10, 50, 10+50, 50+50), src, src.Bounds(), Src, nil)
|
|
||||||
ApproxBiLinear.Transform(dst1, f64.Aff3{
|
|
||||||
0.5, 0.0 + epsilon, 10,
|
|
||||||
0.0, 0.5, 50,
|
|
||||||
}, src, src.Bounds(), Src, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
differ := !bytes.Equal(dst0.Pix, dst1.Pix)
|
|
||||||
if epsilon > 1e-10 {
|
|
||||||
if !differ {
|
|
||||||
t.Errorf("%s yielded same pixels, want different pixels: epsilon=%v", op, epsilon)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if differ {
|
|
||||||
t.Errorf("%s yielded different pixels, want same pixels: epsilon=%v", op, epsilon)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSimpleScaleCopy(b *testing.B) {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
|
|
||||||
src := image.NewRGBA(image.Rect(0, 0, 400, 300))
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
ApproxBiLinear.Scale(dst, image.Rect(10, 20, 10+400, 20+300), src, src.Bounds(), Src, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSimpleTransformCopy(b *testing.B) {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
|
|
||||||
src := image.NewRGBA(image.Rect(0, 0, 400, 300))
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
ApproxBiLinear.Transform(dst, f64.Aff3{
|
|
||||||
1, 0, 10,
|
|
||||||
0, 1, 20,
|
|
||||||
}, src, src.Bounds(), Src, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSimpleTransformScale(b *testing.B) {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
|
|
||||||
src := image.NewRGBA(image.Rect(0, 0, 400, 300))
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
ApproxBiLinear.Transform(dst, f64.Aff3{
|
|
||||||
0.5, 0.0, 10,
|
|
||||||
0.0, 0.5, 20,
|
|
||||||
}, src, src.Bounds(), Src, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOps(t *testing.T) {
|
|
||||||
blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
|
|
||||||
testCases := map[Op]color.RGBA{
|
|
||||||
Over: color.RGBA{0x7f, 0x00, 0x80, 0xff},
|
|
||||||
Src: color.RGBA{0x7f, 0x00, 0x00, 0x7f},
|
|
||||||
}
|
|
||||||
for op, want := range testCases {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 2, 2))
|
|
||||||
Copy(dst, image.Point{}, blue, dst.Bounds(), Src, nil)
|
|
||||||
|
|
||||||
src := image.NewRGBA(image.Rect(0, 0, 1, 1))
|
|
||||||
src.SetRGBA(0, 0, color.RGBA{0x7f, 0x00, 0x00, 0x7f})
|
|
||||||
|
|
||||||
NearestNeighbor.Scale(dst, dst.Bounds(), src, src.Bounds(), op, nil)
|
|
||||||
|
|
||||||
if got := dst.RGBAAt(0, 0); got != want {
|
|
||||||
t.Errorf("op=%v: got %v, want %v", op, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestNegativeWeights tests that scaling by a kernel that produces negative
|
|
||||||
// weights, such as the Catmull-Rom kernel, doesn't produce an invalid color
|
|
||||||
// according to Go's alpha-premultiplied model.
|
|
||||||
func TestNegativeWeights(t *testing.T) {
|
|
||||||
check := func(m *image.RGBA) error {
|
|
||||||
b := m.Bounds()
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
for x := b.Min.X; x < b.Max.X; x++ {
|
|
||||||
if c := m.RGBAAt(x, y); c.R > c.A || c.G > c.A || c.B > c.A {
|
|
||||||
return fmt.Errorf("invalid color.RGBA at (%d, %d): %v", x, y, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
src := image.NewRGBA(image.Rect(0, 0, 16, 16))
|
|
||||||
for y := 0; y < 16; y++ {
|
|
||||||
for x := 0; x < 16; x++ {
|
|
||||||
a := y * 0x11
|
|
||||||
src.Set(x, y, color.RGBA{
|
|
||||||
R: uint8(x * 0x11 * a / 0xff),
|
|
||||||
A: uint8(a),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := check(src); err != nil {
|
|
||||||
t.Fatalf("src image: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 32, 32))
|
|
||||||
CatmullRom.Scale(dst, dst.Bounds(), src, src.Bounds(), Over, nil)
|
|
||||||
if err := check(dst); err != nil {
|
|
||||||
t.Fatalf("dst image: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fillPix(r *rand.Rand, pixs ...[]byte) {
|
|
||||||
for _, pix := range pixs {
|
|
||||||
for i := range pix {
|
|
||||||
pix[i] = uint8(r.Intn(256))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInterpClipCommute(t *testing.T) {
|
|
||||||
src := image.NewNRGBA(image.Rect(0, 0, 20, 20))
|
|
||||||
fillPix(rand.New(rand.NewSource(0)), src.Pix)
|
|
||||||
|
|
||||||
outer := image.Rect(1, 1, 8, 5)
|
|
||||||
inner := image.Rect(2, 3, 6, 5)
|
|
||||||
qs := []Interpolator{
|
|
||||||
NearestNeighbor,
|
|
||||||
ApproxBiLinear,
|
|
||||||
CatmullRom,
|
|
||||||
}
|
|
||||||
for _, transform := range []bool{false, true} {
|
|
||||||
for _, q := range qs {
|
|
||||||
dst0 := image.NewRGBA(image.Rect(1, 1, 10, 10))
|
|
||||||
dst1 := image.NewRGBA(image.Rect(1, 1, 10, 10))
|
|
||||||
for i := range dst0.Pix {
|
|
||||||
dst0.Pix[i] = uint8(i / 4)
|
|
||||||
dst1.Pix[i] = uint8(i / 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
var interp func(dst *image.RGBA)
|
|
||||||
if transform {
|
|
||||||
interp = func(dst *image.RGBA) {
|
|
||||||
q.Transform(dst, transformMatrix(3.75, 2, 1), src, src.Bounds(), Over, nil)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
interp = func(dst *image.RGBA) {
|
|
||||||
q.Scale(dst, outer, src, src.Bounds(), Over, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interpolate then clip.
|
|
||||||
interp(dst0)
|
|
||||||
dst0 = dst0.SubImage(inner).(*image.RGBA)
|
|
||||||
|
|
||||||
// Clip then interpolate.
|
|
||||||
dst1 = dst1.SubImage(inner).(*image.RGBA)
|
|
||||||
interp(dst1)
|
|
||||||
|
|
||||||
loop:
|
|
||||||
for y := inner.Min.Y; y < inner.Max.Y; y++ {
|
|
||||||
for x := inner.Min.X; x < inner.Max.X; x++ {
|
|
||||||
if c0, c1 := dst0.RGBAAt(x, y), dst1.RGBAAt(x, y); c0 != c1 {
|
|
||||||
t.Errorf("q=%T: at (%d, %d): c0=%v, c1=%v", q, x, y, c0, c1)
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// translatedImage is an image m translated by t.
|
|
||||||
type translatedImage struct {
|
|
||||||
m image.Image
|
|
||||||
t image.Point
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *translatedImage) At(x, y int) color.Color { return t.m.At(x-t.t.X, y-t.t.Y) }
|
|
||||||
func (t *translatedImage) Bounds() image.Rectangle { return t.m.Bounds().Add(t.t) }
|
|
||||||
func (t *translatedImage) ColorModel() color.Model { return t.m.ColorModel() }
|
|
||||||
|
|
||||||
// TestSrcTranslationInvariance tests that Scale and Transform are invariant
|
|
||||||
// under src translations. Specifically, when some source pixels are not in the
|
|
||||||
// bottom-right quadrant of src coordinate space, we consistently round down,
|
|
||||||
// not round towards zero.
|
|
||||||
func TestSrcTranslationInvariance(t *testing.T) {
|
|
||||||
f, err := os.Open("../testdata/testpattern.png")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
src, _, err := image.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
sr := image.Rect(2, 3, 16, 12)
|
|
||||||
if !sr.In(src.Bounds()) {
|
|
||||||
t.Fatalf("src bounds too small: got %v", src.Bounds())
|
|
||||||
}
|
|
||||||
qs := []Interpolator{
|
|
||||||
NearestNeighbor,
|
|
||||||
ApproxBiLinear,
|
|
||||||
CatmullRom,
|
|
||||||
}
|
|
||||||
deltas := []image.Point{
|
|
||||||
{+0, +0},
|
|
||||||
{+0, +5},
|
|
||||||
{+0, -5},
|
|
||||||
{+5, +0},
|
|
||||||
{-5, +0},
|
|
||||||
{+8, +8},
|
|
||||||
{+8, -8},
|
|
||||||
{-8, +8},
|
|
||||||
{-8, -8},
|
|
||||||
}
|
|
||||||
m00 := transformMatrix(3.75, 0, 0)
|
|
||||||
|
|
||||||
for _, transform := range []bool{false, true} {
|
|
||||||
for _, q := range qs {
|
|
||||||
want := image.NewRGBA(image.Rect(0, 0, 20, 20))
|
|
||||||
if transform {
|
|
||||||
q.Transform(want, m00, src, sr, Over, nil)
|
|
||||||
} else {
|
|
||||||
q.Scale(want, want.Bounds(), src, sr, Over, nil)
|
|
||||||
}
|
|
||||||
for _, delta := range deltas {
|
|
||||||
tsrc := &translatedImage{src, delta}
|
|
||||||
got := image.NewRGBA(image.Rect(0, 0, 20, 20))
|
|
||||||
if transform {
|
|
||||||
m := matMul(&m00, &f64.Aff3{
|
|
||||||
1, 0, -float64(delta.X),
|
|
||||||
0, 1, -float64(delta.Y),
|
|
||||||
})
|
|
||||||
q.Transform(got, m, tsrc, sr.Add(delta), Over, nil)
|
|
||||||
} else {
|
|
||||||
q.Scale(got, got.Bounds(), tsrc, sr.Add(delta), Over, nil)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(got.Pix, want.Pix) {
|
|
||||||
t.Errorf("pix differ for delta=%v, transform=%t, q=%T", delta, transform, q)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSrcMask(t *testing.T) {
|
|
||||||
srcMask := image.NewRGBA(image.Rect(0, 0, 23, 1))
|
|
||||||
srcMask.SetRGBA(19, 0, color.RGBA{0x00, 0x00, 0x00, 0x7f})
|
|
||||||
srcMask.SetRGBA(20, 0, color.RGBA{0x00, 0x00, 0x00, 0xff})
|
|
||||||
srcMask.SetRGBA(21, 0, color.RGBA{0x00, 0x00, 0x00, 0x3f})
|
|
||||||
srcMask.SetRGBA(22, 0, color.RGBA{0x00, 0x00, 0x00, 0x00})
|
|
||||||
red := image.NewUniform(color.RGBA{0xff, 0x00, 0x00, 0xff})
|
|
||||||
blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 6, 1))
|
|
||||||
Copy(dst, image.Point{}, blue, dst.Bounds(), Src, nil)
|
|
||||||
NearestNeighbor.Scale(dst, dst.Bounds(), red, image.Rect(0, 0, 3, 1), Over, &Options{
|
|
||||||
SrcMask: srcMask,
|
|
||||||
SrcMaskP: image.Point{20, 0},
|
|
||||||
})
|
|
||||||
got := [6]color.RGBA{
|
|
||||||
dst.RGBAAt(0, 0),
|
|
||||||
dst.RGBAAt(1, 0),
|
|
||||||
dst.RGBAAt(2, 0),
|
|
||||||
dst.RGBAAt(3, 0),
|
|
||||||
dst.RGBAAt(4, 0),
|
|
||||||
dst.RGBAAt(5, 0),
|
|
||||||
}
|
|
||||||
want := [6]color.RGBA{
|
|
||||||
{0xff, 0x00, 0x00, 0xff},
|
|
||||||
{0xff, 0x00, 0x00, 0xff},
|
|
||||||
{0x3f, 0x00, 0xc0, 0xff},
|
|
||||||
{0x3f, 0x00, 0xc0, 0xff},
|
|
||||||
{0x00, 0x00, 0xff, 0xff},
|
|
||||||
{0x00, 0x00, 0xff, 0xff},
|
|
||||||
}
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("\ngot %v\nwant %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDstMask(t *testing.T) {
|
|
||||||
dstMask := image.NewRGBA(image.Rect(0, 0, 23, 1))
|
|
||||||
dstMask.SetRGBA(19, 0, color.RGBA{0x00, 0x00, 0x00, 0x7f})
|
|
||||||
dstMask.SetRGBA(20, 0, color.RGBA{0x00, 0x00, 0x00, 0xff})
|
|
||||||
dstMask.SetRGBA(21, 0, color.RGBA{0x00, 0x00, 0x00, 0x3f})
|
|
||||||
dstMask.SetRGBA(22, 0, color.RGBA{0x00, 0x00, 0x00, 0x00})
|
|
||||||
red := image.NewRGBA(image.Rect(0, 0, 1, 1))
|
|
||||||
red.SetRGBA(0, 0, color.RGBA{0xff, 0x00, 0x00, 0xff})
|
|
||||||
blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
|
|
||||||
qs := []Interpolator{
|
|
||||||
NearestNeighbor,
|
|
||||||
ApproxBiLinear,
|
|
||||||
CatmullRom,
|
|
||||||
}
|
|
||||||
for _, q := range qs {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 3, 1))
|
|
||||||
Copy(dst, image.Point{}, blue, dst.Bounds(), Src, nil)
|
|
||||||
q.Scale(dst, dst.Bounds(), red, red.Bounds(), Over, &Options{
|
|
||||||
DstMask: dstMask,
|
|
||||||
DstMaskP: image.Point{20, 0},
|
|
||||||
})
|
|
||||||
got := [3]color.RGBA{
|
|
||||||
dst.RGBAAt(0, 0),
|
|
||||||
dst.RGBAAt(1, 0),
|
|
||||||
dst.RGBAAt(2, 0),
|
|
||||||
}
|
|
||||||
want := [3]color.RGBA{
|
|
||||||
{0xff, 0x00, 0x00, 0xff},
|
|
||||||
{0x3f, 0x00, 0xc0, 0xff},
|
|
||||||
{0x00, 0x00, 0xff, 0xff},
|
|
||||||
}
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("q=%T:\ngot %v\nwant %v", q, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRectDstMask(t *testing.T) {
|
|
||||||
f, err := os.Open("../testdata/testpattern.png")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
src, _, err := image.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
m00 := transformMatrix(1, 0, 0)
|
|
||||||
|
|
||||||
bounds := image.Rect(0, 0, 50, 50)
|
|
||||||
dstOutside := image.NewRGBA(bounds)
|
|
||||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
|
||||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
|
||||||
dstOutside.SetRGBA(x, y, color.RGBA{uint8(5 * x), uint8(5 * y), 0x00, 0xff})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mk := func(q Transformer, dstMask image.Image, dstMaskP image.Point) *image.RGBA {
|
|
||||||
m := image.NewRGBA(bounds)
|
|
||||||
Copy(m, bounds.Min, dstOutside, bounds, Src, nil)
|
|
||||||
q.Transform(m, m00, src, src.Bounds(), Over, &Options{
|
|
||||||
DstMask: dstMask,
|
|
||||||
DstMaskP: dstMaskP,
|
|
||||||
})
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
qs := []Interpolator{
|
|
||||||
NearestNeighbor,
|
|
||||||
ApproxBiLinear,
|
|
||||||
CatmullRom,
|
|
||||||
}
|
|
||||||
dstMaskPs := []image.Point{
|
|
||||||
{0, 0},
|
|
||||||
{5, 7},
|
|
||||||
{-3, 0},
|
|
||||||
}
|
|
||||||
rect := image.Rect(10, 10, 30, 40)
|
|
||||||
for _, q := range qs {
|
|
||||||
for _, dstMaskP := range dstMaskPs {
|
|
||||||
dstInside := mk(q, nil, image.Point{})
|
|
||||||
for _, wrap := range []bool{false, true} {
|
|
||||||
// TODO: replace "rectImage(rect)" with "rect" once Go 1.5 is
|
|
||||||
// released, where an image.Rectangle implements image.Image.
|
|
||||||
dstMask := image.Image(rectImage(rect))
|
|
||||||
if wrap {
|
|
||||||
dstMask = srcWrapper{dstMask}
|
|
||||||
}
|
|
||||||
dst := mk(q, dstMask, dstMaskP)
|
|
||||||
|
|
||||||
nError := 0
|
|
||||||
loop:
|
|
||||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
|
||||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
|
||||||
which := dstOutside
|
|
||||||
if (image.Point{x, y}).Add(dstMaskP).In(rect) {
|
|
||||||
which = dstInside
|
|
||||||
}
|
|
||||||
if got, want := dst.RGBAAt(x, y), which.RGBAAt(x, y); got != want {
|
|
||||||
if nError == 10 {
|
|
||||||
t.Errorf("q=%T dmp=%v wrap=%v: ...and more errors", q, dstMaskP, wrap)
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
nError++
|
|
||||||
t.Errorf("q=%T dmp=%v wrap=%v: x=%3d y=%3d: got %v, want %v",
|
|
||||||
q, dstMaskP, wrap, x, y, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDstMaskSameSizeCopy(t *testing.T) {
|
|
||||||
bounds := image.Rect(0, 0, 42, 42)
|
|
||||||
src := image.Opaque
|
|
||||||
dst := image.NewRGBA(bounds)
|
|
||||||
mask := image.NewRGBA(bounds)
|
|
||||||
|
|
||||||
Copy(dst, image.ZP, src, bounds, Src, &Options{
|
|
||||||
DstMask: mask,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: delete this wrapper type once Go 1.5 is released, where an
|
|
||||||
// image.Rectangle implements image.Image.
|
|
||||||
type rectImage image.Rectangle
|
|
||||||
|
|
||||||
func (r rectImage) ColorModel() color.Model { return color.Alpha16Model }
|
|
||||||
func (r rectImage) Bounds() image.Rectangle { return image.Rectangle(r) }
|
|
||||||
func (r rectImage) At(x, y int) color.Color {
|
|
||||||
if (image.Point{x, y}).In(image.Rectangle(r)) {
|
|
||||||
return color.Opaque
|
|
||||||
}
|
|
||||||
return color.Transparent
|
|
||||||
}
|
|
||||||
|
|
||||||
// The fooWrapper types wrap the dst or src image to avoid triggering the
|
|
||||||
// type-specific fast path implementations.
|
|
||||||
type (
|
|
||||||
dstWrapper struct{ Image }
|
|
||||||
srcWrapper struct{ image.Image }
|
|
||||||
)
|
|
||||||
|
|
||||||
func srcGray(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
m := image.NewGray(boundsHint)
|
|
||||||
fillPix(rand.New(rand.NewSource(0)), m.Pix)
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func srcNRGBA(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
m := image.NewNRGBA(boundsHint)
|
|
||||||
fillPix(rand.New(rand.NewSource(1)), m.Pix)
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func srcRGBA(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
m := image.NewRGBA(boundsHint)
|
|
||||||
fillPix(rand.New(rand.NewSource(2)), m.Pix)
|
|
||||||
// RGBA is alpha-premultiplied, so the R, G and B values should
|
|
||||||
// be <= the A values.
|
|
||||||
for i := 0; i < len(m.Pix); i += 4 {
|
|
||||||
m.Pix[i+0] = uint8(uint32(m.Pix[i+0]) * uint32(m.Pix[i+3]) / 0xff)
|
|
||||||
m.Pix[i+1] = uint8(uint32(m.Pix[i+1]) * uint32(m.Pix[i+3]) / 0xff)
|
|
||||||
m.Pix[i+2] = uint8(uint32(m.Pix[i+2]) * uint32(m.Pix[i+3]) / 0xff)
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func srcUnif(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
return image.NewUniform(color.RGBA64{0x1234, 0x5555, 0x9181, 0xbeef}), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func srcYCbCr(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
m := image.NewYCbCr(boundsHint, image.YCbCrSubsampleRatio420)
|
|
||||||
fillPix(rand.New(rand.NewSource(3)), m.Y, m.Cb, m.Cr)
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func srcLarge(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
// 3072 x 2304 is over 7 million pixels at 4:3, comparable to a
|
|
||||||
// 2015 smart-phone camera's output.
|
|
||||||
return srcYCbCr(image.Rect(0, 0, 3072, 2304))
|
|
||||||
}
|
|
||||||
|
|
||||||
func srcTux(boundsHint image.Rectangle) (image.Image, error) {
|
|
||||||
// tux.png is a 386 x 395 image.
|
|
||||||
f, err := os.Open("../testdata/tux.png")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Open: %v", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
src, err := png.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
return src, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchScale(b *testing.B, w int, h int, op Op, srcf func(image.Rectangle) (image.Image, error), q Interpolator) {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, w, h))
|
|
||||||
src, err := srcf(image.Rect(0, 0, 1024, 768))
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
dr, sr := dst.Bounds(), src.Bounds()
|
|
||||||
scaler := Scaler(q)
|
|
||||||
if n, ok := q.(interface {
|
|
||||||
NewScaler(int, int, int, int) Scaler
|
|
||||||
}); ok {
|
|
||||||
scaler = n.NewScaler(dr.Dx(), dr.Dy(), sr.Dx(), sr.Dy())
|
|
||||||
}
|
|
||||||
|
|
||||||
b.ReportAllocs()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
scaler.Scale(dst, dr, src, sr, op, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchTform(b *testing.B, w int, h int, op Op, srcf func(image.Rectangle) (image.Image, error), q Interpolator) {
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, w, h))
|
|
||||||
src, err := srcf(image.Rect(0, 0, 1024, 768))
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
sr := src.Bounds()
|
|
||||||
m := transformMatrix(3.75, 40, 10)
|
|
||||||
|
|
||||||
b.ReportAllocs()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
q.Transform(dst, m, src, sr, op, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkScaleNNLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, NearestNeighbor) }
|
|
||||||
func BenchmarkScaleABLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleBLLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, BiLinear) }
|
|
||||||
func BenchmarkScaleCRLargeDown(b *testing.B) { benchScale(b, 200, 150, Src, srcLarge, CatmullRom) }
|
|
||||||
|
|
||||||
func BenchmarkScaleNNDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, NearestNeighbor) }
|
|
||||||
func BenchmarkScaleABDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleBLDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, BiLinear) }
|
|
||||||
func BenchmarkScaleCRDown(b *testing.B) { benchScale(b, 120, 80, Src, srcTux, CatmullRom) }
|
|
||||||
|
|
||||||
func BenchmarkScaleNNUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, NearestNeighbor) }
|
|
||||||
func BenchmarkScaleABUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleBLUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, BiLinear) }
|
|
||||||
func BenchmarkScaleCRUp(b *testing.B) { benchScale(b, 800, 600, Src, srcTux, CatmullRom) }
|
|
||||||
|
|
||||||
func BenchmarkScaleNNSrcRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcRGBA, NearestNeighbor) }
|
|
||||||
func BenchmarkScaleNNSrcUnif(b *testing.B) { benchScale(b, 200, 150, Src, srcUnif, NearestNeighbor) }
|
|
||||||
|
|
||||||
func BenchmarkScaleNNOverRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcRGBA, NearestNeighbor) }
|
|
||||||
func BenchmarkScaleNNOverUnif(b *testing.B) { benchScale(b, 200, 150, Over, srcUnif, NearestNeighbor) }
|
|
||||||
|
|
||||||
func BenchmarkTformNNSrcRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcRGBA, NearestNeighbor) }
|
|
||||||
func BenchmarkTformNNSrcUnif(b *testing.B) { benchTform(b, 200, 150, Src, srcUnif, NearestNeighbor) }
|
|
||||||
|
|
||||||
func BenchmarkTformNNOverRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcRGBA, NearestNeighbor) }
|
|
||||||
func BenchmarkTformNNOverUnif(b *testing.B) { benchTform(b, 200, 150, Over, srcUnif, NearestNeighbor) }
|
|
||||||
|
|
||||||
func BenchmarkScaleABSrcGray(b *testing.B) { benchScale(b, 200, 150, Src, srcGray, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleABSrcNRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcNRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleABSrcRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleABSrcYCbCr(b *testing.B) { benchScale(b, 200, 150, Src, srcYCbCr, ApproxBiLinear) }
|
|
||||||
|
|
||||||
func BenchmarkScaleABOverGray(b *testing.B) { benchScale(b, 200, 150, Over, srcGray, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleABOverNRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcNRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleABOverRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkScaleABOverYCbCr(b *testing.B) { benchScale(b, 200, 150, Over, srcYCbCr, ApproxBiLinear) }
|
|
||||||
|
|
||||||
func BenchmarkTformABSrcGray(b *testing.B) { benchTform(b, 200, 150, Src, srcGray, ApproxBiLinear) }
|
|
||||||
func BenchmarkTformABSrcNRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcNRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkTformABSrcRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkTformABSrcYCbCr(b *testing.B) { benchTform(b, 200, 150, Src, srcYCbCr, ApproxBiLinear) }
|
|
||||||
|
|
||||||
func BenchmarkTformABOverGray(b *testing.B) { benchTform(b, 200, 150, Over, srcGray, ApproxBiLinear) }
|
|
||||||
func BenchmarkTformABOverNRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcNRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkTformABOverRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcRGBA, ApproxBiLinear) }
|
|
||||||
func BenchmarkTformABOverYCbCr(b *testing.B) { benchTform(b, 200, 150, Over, srcYCbCr, ApproxBiLinear) }
|
|
||||||
|
|
||||||
func BenchmarkScaleCRSrcGray(b *testing.B) { benchScale(b, 200, 150, Src, srcGray, CatmullRom) }
|
|
||||||
func BenchmarkScaleCRSrcNRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcNRGBA, CatmullRom) }
|
|
||||||
func BenchmarkScaleCRSrcRGBA(b *testing.B) { benchScale(b, 200, 150, Src, srcRGBA, CatmullRom) }
|
|
||||||
func BenchmarkScaleCRSrcYCbCr(b *testing.B) { benchScale(b, 200, 150, Src, srcYCbCr, CatmullRom) }
|
|
||||||
|
|
||||||
func BenchmarkScaleCROverGray(b *testing.B) { benchScale(b, 200, 150, Over, srcGray, CatmullRom) }
|
|
||||||
func BenchmarkScaleCROverNRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcNRGBA, CatmullRom) }
|
|
||||||
func BenchmarkScaleCROverRGBA(b *testing.B) { benchScale(b, 200, 150, Over, srcRGBA, CatmullRom) }
|
|
||||||
func BenchmarkScaleCROverYCbCr(b *testing.B) { benchScale(b, 200, 150, Over, srcYCbCr, CatmullRom) }
|
|
||||||
|
|
||||||
func BenchmarkTformCRSrcGray(b *testing.B) { benchTform(b, 200, 150, Src, srcGray, CatmullRom) }
|
|
||||||
func BenchmarkTformCRSrcNRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcNRGBA, CatmullRom) }
|
|
||||||
func BenchmarkTformCRSrcRGBA(b *testing.B) { benchTform(b, 200, 150, Src, srcRGBA, CatmullRom) }
|
|
||||||
func BenchmarkTformCRSrcYCbCr(b *testing.B) { benchTform(b, 200, 150, Src, srcYCbCr, CatmullRom) }
|
|
||||||
|
|
||||||
func BenchmarkTformCROverGray(b *testing.B) { benchTform(b, 200, 150, Over, srcGray, CatmullRom) }
|
|
||||||
func BenchmarkTformCROverNRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcNRGBA, CatmullRom) }
|
|
||||||
func BenchmarkTformCROverRGBA(b *testing.B) { benchTform(b, 200, 150, Over, srcRGBA, CatmullRom) }
|
|
||||||
func BenchmarkTformCROverYCbCr(b *testing.B) { benchTform(b, 200, 150, Over, srcYCbCr, CatmullRom) }
|
|
96
vendor/golang.org/x/image/draw/stdlib_test.go
generated
vendored
96
vendor/golang.org/x/image/draw/stdlib_test.go
generated
vendored
@ -1,96 +0,0 @@
|
|||||||
// 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
|
|
||||||
|
|
||||||
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, 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"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestFastPaths tests that the fast path implementations produce identical
|
|
||||||
// results to the generic implementation.
|
|
||||||
func TestFastPaths(t *testing.T) {
|
|
||||||
drs := []image.Rectangle{
|
|
||||||
image.Rect(0, 0, 10, 10), // The dst bounds.
|
|
||||||
image.Rect(3, 4, 8, 6), // A strict subset of the dst bounds.
|
|
||||||
image.Rect(-3, -5, 2, 4), // Partial out-of-bounds #0.
|
|
||||||
image.Rect(4, -2, 6, 12), // Partial out-of-bounds #1.
|
|
||||||
image.Rect(12, 14, 23, 45), // Complete out-of-bounds.
|
|
||||||
image.Rect(5, 5, 5, 5), // Empty.
|
|
||||||
}
|
|
||||||
srs := []image.Rectangle{
|
|
||||||
image.Rect(0, 0, 12, 9), // The src bounds.
|
|
||||||
image.Rect(2, 2, 10, 8), // A strict subset of the src bounds.
|
|
||||||
image.Rect(10, 5, 20, 20), // Partial out-of-bounds #0.
|
|
||||||
image.Rect(-40, 0, 40, 8), // Partial out-of-bounds #1.
|
|
||||||
image.Rect(-8, -8, -4, -4), // Complete out-of-bounds.
|
|
||||||
image.Rect(5, 5, 5, 5), // Empty.
|
|
||||||
}
|
|
||||||
srcfs := []func(image.Rectangle) (image.Image, error){
|
|
||||||
srcGray,
|
|
||||||
srcNRGBA,
|
|
||||||
srcRGBA,
|
|
||||||
srcUnif,
|
|
||||||
srcYCbCr,
|
|
||||||
}
|
|
||||||
var srcs []image.Image
|
|
||||||
for _, srcf := range srcfs {
|
|
||||||
src, err := srcf(srs[0])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
srcs = append(srcs, src)
|
|
||||||
}
|
|
||||||
qs := []Interpolator{
|
|
||||||
NearestNeighbor,
|
|
||||||
ApproxBiLinear,
|
|
||||||
CatmullRom,
|
|
||||||
}
|
|
||||||
ops := []Op{
|
|
||||||
Over,
|
|
||||||
Src,
|
|
||||||
}
|
|
||||||
blue := image.NewUniform(color.RGBA{0x11, 0x22, 0x44, 0x7f})
|
|
||||||
|
|
||||||
for _, dr := range drs {
|
|
||||||
for _, src := range srcs {
|
|
||||||
for _, sr := range srs {
|
|
||||||
for _, transform := range []bool{false, true} {
|
|
||||||
for _, q := range qs {
|
|
||||||
for _, op := range ops {
|
|
||||||
dst0 := image.NewRGBA(drs[0])
|
|
||||||
dst1 := image.NewRGBA(drs[0])
|
|
||||||
Draw(dst0, dst0.Bounds(), blue, image.Point{}, Src)
|
|
||||||
Draw(dstWrapper{dst1}, dst1.Bounds(), srcWrapper{blue}, image.Point{}, Src)
|
|
||||||
|
|
||||||
if transform {
|
|
||||||
m := transformMatrix(3.75, 2, 1)
|
|
||||||
q.Transform(dst0, m, src, sr, op, nil)
|
|
||||||
q.Transform(dstWrapper{dst1}, m, srcWrapper{src}, sr, op, nil)
|
|
||||||
} else {
|
|
||||||
q.Scale(dst0, dr, src, sr, op, nil)
|
|
||||||
q.Scale(dstWrapper{dst1}, dr, srcWrapper{src}, sr, op, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(dst0.Pix, dst1.Pix) {
|
|
||||||
t.Errorf("pix differ for dr=%v, src=%T, sr=%v, transform=%t, q=%T",
|
|
||||||
dr, src, sr, transform, q)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
106
vendor/golang.org/x/image/example/font/main.go
generated
vendored
106
vendor/golang.org/x/image/example/font/main.go
generated
vendored
@ -1,106 +0,0 @@
|
|||||||
// 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 example
|
|
||||||
//
|
|
||||||
// This build tag means that "go install golang.org/x/image/..." doesn't
|
|
||||||
// install this example program. Use "go run main.go" to run it or "go install
|
|
||||||
// -tags=example" to install it.
|
|
||||||
|
|
||||||
// Font is a basic example of using fonts.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/draw"
|
|
||||||
"image/png"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/plan9font"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
fontFlag = flag.String("font", "",
|
|
||||||
`filename of the Plan 9 font or subfont file, such as "lucsans/unicode.8.font" or "lucsans/lsr.14"`)
|
|
||||||
firstRuneFlag = flag.Int("firstrune", 0, "the Unicode code point of the first rune in the subfont file")
|
|
||||||
)
|
|
||||||
|
|
||||||
func pt(p fixed.Point26_6) image.Point {
|
|
||||||
return image.Point{
|
|
||||||
X: int(p.X+32) >> 6,
|
|
||||||
Y: int(p.Y+32) >> 6,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
// TODO: mmap the files.
|
|
||||||
if *fontFlag == "" {
|
|
||||||
flag.Usage()
|
|
||||||
log.Fatal("no font specified")
|
|
||||||
}
|
|
||||||
var face font.Face
|
|
||||||
if strings.HasSuffix(*fontFlag, ".font") {
|
|
||||||
fontData, err := ioutil.ReadFile(*fontFlag)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
dir := filepath.Dir(*fontFlag)
|
|
||||||
face, err = plan9font.ParseFont(fontData, func(name string) ([]byte, error) {
|
|
||||||
return ioutil.ReadFile(filepath.Join(dir, filepath.FromSlash(name)))
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fontData, err := ioutil.ReadFile(*fontFlag)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
face, err = plan9font.ParseSubfont(fontData, rune(*firstRuneFlag))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 800, 300))
|
|
||||||
draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src)
|
|
||||||
|
|
||||||
d := &font.Drawer{
|
|
||||||
Dst: dst,
|
|
||||||
Src: image.White,
|
|
||||||
Face: face,
|
|
||||||
}
|
|
||||||
ss := []string{
|
|
||||||
"The quick brown fox jumps over the lazy dog.",
|
|
||||||
"Hello, 世界.",
|
|
||||||
"U+FFFD is \ufffd.",
|
|
||||||
}
|
|
||||||
for i, s := range ss {
|
|
||||||
d.Dot = fixed.P(20, 100*i+80)
|
|
||||||
dot0 := pt(d.Dot)
|
|
||||||
d.DrawString(s)
|
|
||||||
dot1 := pt(d.Dot)
|
|
||||||
dst.SetRGBA(dot0.X, dot0.Y, color.RGBA{0xff, 0x00, 0x00, 0xff})
|
|
||||||
dst.SetRGBA(dot1.X, dot1.Y, color.RGBA{0x00, 0x00, 0xff, 0xff})
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := os.Create("out.png")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
if err := png.Encode(out, dst); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
126
vendor/golang.org/x/image/font/basicfont/basicfont.go
generated
vendored
126
vendor/golang.org/x/image/font/basicfont/basicfont.go
generated
vendored
@ -1,126 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// Package basicfont provides fixed-size font faces.
|
|
||||||
package basicfont // import "golang.org/x/image/font/basicfont"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Range maps a contiguous range of runes to vertically adjacent sub-images of
|
|
||||||
// a Face's Mask image. The rune range is inclusive on the low end and
|
|
||||||
// exclusive on the high end.
|
|
||||||
//
|
|
||||||
// If Low <= r && r < High, then the rune r is mapped to the sub-image of
|
|
||||||
// Face.Mask whose bounds are image.Rect(0, y*h, Face.Width, (y+1)*h),
|
|
||||||
// where y = (int(r-Low) + Offset) and h = (Face.Ascent + Face.Descent).
|
|
||||||
type Range struct {
|
|
||||||
Low, High rune
|
|
||||||
Offset int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Face7x13 is a Face derived from the public domain X11 misc-fixed font files.
|
|
||||||
//
|
|
||||||
// At the moment, it holds the printable characters in ASCII starting with
|
|
||||||
// space, and the Unicode replacement character U+FFFD.
|
|
||||||
//
|
|
||||||
// Its data is entirely self-contained and does not require loading from
|
|
||||||
// separate files.
|
|
||||||
var Face7x13 = &Face{
|
|
||||||
Advance: 7,
|
|
||||||
Width: 6,
|
|
||||||
Height: 13,
|
|
||||||
Ascent: 11,
|
|
||||||
Descent: 2,
|
|
||||||
Mask: mask7x13,
|
|
||||||
Ranges: []Range{
|
|
||||||
{'\u0020', '\u007f', 0},
|
|
||||||
{'\ufffd', '\ufffe', 95},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Face is a basic font face whose glyphs all have the same metrics.
|
|
||||||
//
|
|
||||||
// It is safe to use concurrently.
|
|
||||||
type Face struct {
|
|
||||||
// Advance is the glyph advance, in pixels.
|
|
||||||
Advance int
|
|
||||||
// Width is the glyph width, in pixels.
|
|
||||||
Width int
|
|
||||||
// Height is the inter-line height, in pixels.
|
|
||||||
Height int
|
|
||||||
// Ascent is the glyph ascent, in pixels.
|
|
||||||
Ascent int
|
|
||||||
// Descent is the glyph descent, in pixels.
|
|
||||||
Descent int
|
|
||||||
// Left is the left side bearing, in pixels. A positive value means that
|
|
||||||
// all of a glyph is to the right of the dot.
|
|
||||||
Left int
|
|
||||||
|
|
||||||
// Mask contains all of the glyph masks. Its width is typically the Face's
|
|
||||||
// Width, and its height a multiple of the Face's Height.
|
|
||||||
Mask image.Image
|
|
||||||
// Ranges map runes to sub-images of Mask. The rune ranges must not
|
|
||||||
// overlap, and must be in increasing rune order.
|
|
||||||
Ranges []Range
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Face) Close() error { return nil }
|
|
||||||
func (f *Face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
|
|
||||||
|
|
||||||
func (f *Face) Metrics() font.Metrics {
|
|
||||||
return font.Metrics{
|
|
||||||
Height: fixed.I(f.Height),
|
|
||||||
Ascent: fixed.I(f.Ascent),
|
|
||||||
Descent: fixed.I(f.Descent),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Face) Glyph(dot fixed.Point26_6, r rune) (
|
|
||||||
dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
|
||||||
|
|
||||||
loop:
|
|
||||||
for _, rr := range [2]rune{r, '\ufffd'} {
|
|
||||||
for _, rng := range f.Ranges {
|
|
||||||
if rr < rng.Low || rng.High <= rr {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
maskp.Y = (int(rr-rng.Low) + rng.Offset) * (f.Ascent + f.Descent)
|
|
||||||
ok = true
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return image.Rectangle{}, nil, image.Point{}, 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
x := int(dot.X+32)>>6 + f.Left
|
|
||||||
y := int(dot.Y+32) >> 6
|
|
||||||
dr = image.Rectangle{
|
|
||||||
Min: image.Point{
|
|
||||||
X: x,
|
|
||||||
Y: y - f.Ascent,
|
|
||||||
},
|
|
||||||
Max: image.Point{
|
|
||||||
X: x + f.Width,
|
|
||||||
Y: y + f.Descent,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return dr, f.Mask, maskp, fixed.I(f.Advance), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
|
||||||
return fixed.R(0, -f.Ascent, f.Width, +f.Descent), fixed.I(f.Advance), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
|
||||||
return fixed.I(f.Advance), true
|
|
||||||
}
|
|
1456
vendor/golang.org/x/image/font/basicfont/data.go
generated
vendored
1456
vendor/golang.org/x/image/font/basicfont/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
115
vendor/golang.org/x/image/font/basicfont/gen.go
generated
vendored
115
vendor/golang.org/x/image/font/basicfont/gen.go
generated
vendored
@ -1,115 +0,0 @@
|
|||||||
// 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 ignore
|
|
||||||
|
|
||||||
// This program generates data.go.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/plan9font"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// nGlyphs is the number of glyphs to generate: 95 characters in the range
|
|
||||||
// [0x20, 0x7e], plus the replacement character.
|
|
||||||
const nGlyphs = 95 + 1
|
|
||||||
// The particular font (unicode.7x13.font) leaves the right-most column
|
|
||||||
// empty in its ASCII glyphs. We don't have to include that column in the
|
|
||||||
// generated glyphs, so we subtract one off the effective width.
|
|
||||||
const width, height, ascent = 7 - 1, 13, 11
|
|
||||||
|
|
||||||
readFile := func(name string) ([]byte, error) {
|
|
||||||
return ioutil.ReadFile(filepath.FromSlash(path.Join("../testdata/fixed", name)))
|
|
||||||
}
|
|
||||||
fontData, err := readFile("unicode.7x13.font")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("readFile: %v", err)
|
|
||||||
}
|
|
||||||
face, err := plan9font.ParseFont(fontData, readFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("plan9font.ParseFont: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, width, nGlyphs*height))
|
|
||||||
draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src)
|
|
||||||
d := &font.Drawer{
|
|
||||||
Dst: dst,
|
|
||||||
Src: image.White,
|
|
||||||
Face: face,
|
|
||||||
}
|
|
||||||
for i := 0; i < nGlyphs; i++ {
|
|
||||||
r := '\ufffd'
|
|
||||||
if i < nGlyphs-1 {
|
|
||||||
r = 0x20 + rune(i)
|
|
||||||
}
|
|
||||||
d.Dot = fixed.P(0, height*i+ascent)
|
|
||||||
d.DrawString(string(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
w := bytes.NewBuffer(nil)
|
|
||||||
w.WriteString(preamble)
|
|
||||||
fmt.Fprintf(w, "// mask7x13 contains %d %d×%d glyphs in %d Pix bytes.\n", nGlyphs, width, height, nGlyphs*width*height)
|
|
||||||
fmt.Fprintf(w, "var mask7x13 = &image.Alpha{\n")
|
|
||||||
fmt.Fprintf(w, " Stride: %d,\n", width)
|
|
||||||
fmt.Fprintf(w, " Rect: image.Rectangle{Max: image.Point{%d, %d*%d}},\n", width, nGlyphs, height)
|
|
||||||
fmt.Fprintf(w, " Pix: []byte{\n")
|
|
||||||
b := dst.Bounds()
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
if y%height == 0 {
|
|
||||||
if y != 0 {
|
|
||||||
w.WriteByte('\n')
|
|
||||||
}
|
|
||||||
i := y / height
|
|
||||||
if i < nGlyphs-1 {
|
|
||||||
i += 0x20
|
|
||||||
fmt.Fprintf(w, "// %#2x %q\n", i, rune(i))
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(w, "// U+FFFD REPLACEMENT CHARACTER\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for x := b.Min.X; x < b.Max.X; x++ {
|
|
||||||
if dst.RGBAAt(x, y).R > 0 {
|
|
||||||
w.WriteString("0xff,")
|
|
||||||
} else {
|
|
||||||
w.WriteString("0x00,")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.WriteByte('\n')
|
|
||||||
}
|
|
||||||
w.WriteString("},\n}\n")
|
|
||||||
|
|
||||||
fmted, err := format.Source(w.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("format.Source: %v", err)
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile("data.go", fmted, 0644); err != nil {
|
|
||||||
log.Fatalf("ioutil.WriteFile: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const preamble = `// generated by go generate; DO NOT EDIT.
|
|
||||||
|
|
||||||
package basicfont
|
|
||||||
|
|
||||||
// This data is derived from files in the font/fixed directory of the Plan 9
|
|
||||||
// Port source code (https://github.com/9fans/plan9port) which were originally
|
|
||||||
// based on the public domain X11 misc-fixed font files.
|
|
||||||
|
|
||||||
import "image"
|
|
||||||
|
|
||||||
`
|
|
359
vendor/golang.org/x/image/font/font.go
generated
vendored
359
vendor/golang.org/x/image/font/font.go
generated
vendored
@ -1,359 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Package font defines an interface for font faces, for drawing text on an
|
|
||||||
// image.
|
|
||||||
//
|
|
||||||
// Other packages provide font face implementations. For example, a truetype
|
|
||||||
// package would provide one based on .ttf font files.
|
|
||||||
package font // import "golang.org/x/image/font"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
"io"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: who is responsible for caches (glyph images, glyph indices, kerns)?
|
|
||||||
// The Drawer or the Face?
|
|
||||||
|
|
||||||
// Face is a font face. Its glyphs are often derived from a font file, such as
|
|
||||||
// "Comic_Sans_MS.ttf", but a face has a specific size, style, weight and
|
|
||||||
// hinting. For example, the 12pt and 18pt versions of Comic Sans are two
|
|
||||||
// different faces, even if derived from the same font file.
|
|
||||||
//
|
|
||||||
// A Face is not safe for concurrent use by multiple goroutines, as its methods
|
|
||||||
// may re-use implementation-specific caches and mask image buffers.
|
|
||||||
//
|
|
||||||
// To create a Face, look to other packages that implement specific font file
|
|
||||||
// formats.
|
|
||||||
type Face interface {
|
|
||||||
io.Closer
|
|
||||||
|
|
||||||
// Glyph returns the draw.DrawMask parameters (dr, mask, maskp) to draw r's
|
|
||||||
// glyph at the sub-pixel destination location dot, and that glyph's
|
|
||||||
// advance width.
|
|
||||||
//
|
|
||||||
// It returns !ok if the face does not contain a glyph for r.
|
|
||||||
//
|
|
||||||
// The contents of the mask image returned by one Glyph call may change
|
|
||||||
// after the next Glyph call. Callers that want to cache the mask must make
|
|
||||||
// a copy.
|
|
||||||
Glyph(dot fixed.Point26_6, r rune) (
|
|
||||||
dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool)
|
|
||||||
|
|
||||||
// GlyphBounds returns the bounding box of r's glyph, drawn at a dot equal
|
|
||||||
// to the origin, and that glyph's advance width.
|
|
||||||
//
|
|
||||||
// It returns !ok if the face does not contain a glyph for r.
|
|
||||||
//
|
|
||||||
// The glyph's ascent and descent equal -bounds.Min.Y and +bounds.Max.Y. A
|
|
||||||
// visual depiction of what these metrics are is at
|
|
||||||
// https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png
|
|
||||||
GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool)
|
|
||||||
|
|
||||||
// GlyphAdvance returns the advance width of r's glyph.
|
|
||||||
//
|
|
||||||
// It returns !ok if the face does not contain a glyph for r.
|
|
||||||
GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool)
|
|
||||||
|
|
||||||
// Kern returns the horizontal adjustment for the kerning pair (r0, r1). A
|
|
||||||
// positive kern means to move the glyphs further apart.
|
|
||||||
Kern(r0, r1 rune) fixed.Int26_6
|
|
||||||
|
|
||||||
// Metrics returns the metrics for this Face.
|
|
||||||
Metrics() Metrics
|
|
||||||
|
|
||||||
// TODO: ColoredGlyph for various emoji?
|
|
||||||
// TODO: Ligatures? Shaping?
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metrics holds the metrics for a Face. A visual depiction is at
|
|
||||||
// https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png
|
|
||||||
type Metrics struct {
|
|
||||||
// Height is the recommended amount of vertical space between two lines of
|
|
||||||
// text.
|
|
||||||
Height fixed.Int26_6
|
|
||||||
|
|
||||||
// Ascent is the distance from the top of a line to its baseline.
|
|
||||||
Ascent fixed.Int26_6
|
|
||||||
|
|
||||||
// Descent is the distance from the bottom of a line to its baseline. The
|
|
||||||
// value is typically positive, even though a descender goes below the
|
|
||||||
// baseline.
|
|
||||||
Descent fixed.Int26_6
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drawer draws text on a destination image.
|
|
||||||
//
|
|
||||||
// A Drawer is not safe for concurrent use by multiple goroutines, since its
|
|
||||||
// Face is not.
|
|
||||||
type Drawer struct {
|
|
||||||
// Dst is the destination image.
|
|
||||||
Dst draw.Image
|
|
||||||
// Src is the source image.
|
|
||||||
Src image.Image
|
|
||||||
// Face provides the glyph mask images.
|
|
||||||
Face Face
|
|
||||||
// Dot is the baseline location to draw the next glyph. The majority of the
|
|
||||||
// affected pixels will be above and to the right of the dot, but some may
|
|
||||||
// be below or to the left. For example, drawing a 'j' in an italic face
|
|
||||||
// may affect pixels below and to the left of the dot.
|
|
||||||
Dot fixed.Point26_6
|
|
||||||
|
|
||||||
// TODO: Clip image.Image?
|
|
||||||
// TODO: SrcP image.Point for Src images other than *image.Uniform? How
|
|
||||||
// does it get updated during DrawString?
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: should DrawString return the last rune drawn, so the next DrawString
|
|
||||||
// call can kern beforehand? Or should that be the responsibility of the caller
|
|
||||||
// if they really want to do that, since they have to explicitly shift d.Dot
|
|
||||||
// anyway? What if ligatures span more than two runes? What if grapheme
|
|
||||||
// clusters span multiple runes?
|
|
||||||
//
|
|
||||||
// TODO: do we assume that the input is in any particular Unicode Normalization
|
|
||||||
// Form?
|
|
||||||
//
|
|
||||||
// TODO: have DrawRunes(s []rune)? DrawRuneReader(io.RuneReader)?? If we take
|
|
||||||
// io.RuneReader, we can't assume that we can rewind the stream.
|
|
||||||
//
|
|
||||||
// TODO: how does this work with line breaking: drawing text up until a
|
|
||||||
// vertical line? Should DrawString return the number of runes drawn?
|
|
||||||
|
|
||||||
// DrawBytes draws s at the dot and advances the dot's location.
|
|
||||||
//
|
|
||||||
// It is equivalent to DrawString(string(s)) but may be more efficient.
|
|
||||||
func (d *Drawer) DrawBytes(s []byte) {
|
|
||||||
prevC := rune(-1)
|
|
||||||
for len(s) > 0 {
|
|
||||||
c, size := utf8.DecodeRune(s)
|
|
||||||
s = s[size:]
|
|
||||||
if prevC >= 0 {
|
|
||||||
d.Dot.X += d.Face.Kern(prevC, c)
|
|
||||||
}
|
|
||||||
dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
|
|
||||||
if !ok {
|
|
||||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
|
||||||
// the Drawer or the Face?
|
|
||||||
// TODO: set prevC = '\ufffd'?
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over)
|
|
||||||
d.Dot.X += advance
|
|
||||||
prevC = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DrawString draws s at the dot and advances the dot's location.
|
|
||||||
func (d *Drawer) DrawString(s string) {
|
|
||||||
prevC := rune(-1)
|
|
||||||
for _, c := range s {
|
|
||||||
if prevC >= 0 {
|
|
||||||
d.Dot.X += d.Face.Kern(prevC, c)
|
|
||||||
}
|
|
||||||
dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
|
|
||||||
if !ok {
|
|
||||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
|
||||||
// the Drawer or the Face?
|
|
||||||
// TODO: set prevC = '\ufffd'?
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over)
|
|
||||||
d.Dot.X += advance
|
|
||||||
prevC = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoundBytes returns the bounding box of s, drawn at the drawer dot, as well as
|
|
||||||
// the advance.
|
|
||||||
//
|
|
||||||
// It is equivalent to BoundBytes(string(s)) but may be more efficient.
|
|
||||||
func (d *Drawer) BoundBytes(s []byte) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
|
|
||||||
bounds, advance = BoundBytes(d.Face, s)
|
|
||||||
bounds.Min = bounds.Min.Add(d.Dot)
|
|
||||||
bounds.Max = bounds.Max.Add(d.Dot)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoundString returns the bounding box of s, drawn at the drawer dot, as well
|
|
||||||
// as the advance.
|
|
||||||
func (d *Drawer) BoundString(s string) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
|
|
||||||
bounds, advance = BoundString(d.Face, s)
|
|
||||||
bounds.Min = bounds.Min.Add(d.Dot)
|
|
||||||
bounds.Max = bounds.Max.Add(d.Dot)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// MeasureBytes returns how far dot would advance by drawing s.
|
|
||||||
//
|
|
||||||
// It is equivalent to MeasureString(string(s)) but may be more efficient.
|
|
||||||
func (d *Drawer) MeasureBytes(s []byte) (advance fixed.Int26_6) {
|
|
||||||
return MeasureBytes(d.Face, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MeasureString returns how far dot would advance by drawing s.
|
|
||||||
func (d *Drawer) MeasureString(s string) (advance fixed.Int26_6) {
|
|
||||||
return MeasureString(d.Face, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoundBytes returns the bounding box of s with f, drawn at a dot equal to the
|
|
||||||
// origin, as well as the advance.
|
|
||||||
//
|
|
||||||
// It is equivalent to BoundString(string(s)) but may be more efficient.
|
|
||||||
func BoundBytes(f Face, s []byte) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
|
|
||||||
prevC := rune(-1)
|
|
||||||
for len(s) > 0 {
|
|
||||||
c, size := utf8.DecodeRune(s)
|
|
||||||
s = s[size:]
|
|
||||||
if prevC >= 0 {
|
|
||||||
advance += f.Kern(prevC, c)
|
|
||||||
}
|
|
||||||
b, a, ok := f.GlyphBounds(c)
|
|
||||||
if !ok {
|
|
||||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
|
||||||
// the Drawer or the Face?
|
|
||||||
// TODO: set prevC = '\ufffd'?
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b.Min.X += advance
|
|
||||||
b.Max.X += advance
|
|
||||||
bounds = bounds.Union(b)
|
|
||||||
advance += a
|
|
||||||
prevC = c
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoundString returns the bounding box of s with f, drawn at a dot equal to the
|
|
||||||
// origin, as well as the advance.
|
|
||||||
func BoundString(f Face, s string) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
|
|
||||||
prevC := rune(-1)
|
|
||||||
for _, c := range s {
|
|
||||||
if prevC >= 0 {
|
|
||||||
advance += f.Kern(prevC, c)
|
|
||||||
}
|
|
||||||
b, a, ok := f.GlyphBounds(c)
|
|
||||||
if !ok {
|
|
||||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
|
||||||
// the Drawer or the Face?
|
|
||||||
// TODO: set prevC = '\ufffd'?
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b.Min.X += advance
|
|
||||||
b.Max.X += advance
|
|
||||||
bounds = bounds.Union(b)
|
|
||||||
advance += a
|
|
||||||
prevC = c
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// MeasureBytes returns how far dot would advance by drawing s with f.
|
|
||||||
//
|
|
||||||
// It is equivalent to MeasureString(string(s)) but may be more efficient.
|
|
||||||
func MeasureBytes(f Face, s []byte) (advance fixed.Int26_6) {
|
|
||||||
prevC := rune(-1)
|
|
||||||
for len(s) > 0 {
|
|
||||||
c, size := utf8.DecodeRune(s)
|
|
||||||
s = s[size:]
|
|
||||||
if prevC >= 0 {
|
|
||||||
advance += f.Kern(prevC, c)
|
|
||||||
}
|
|
||||||
a, ok := f.GlyphAdvance(c)
|
|
||||||
if !ok {
|
|
||||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
|
||||||
// the Drawer or the Face?
|
|
||||||
// TODO: set prevC = '\ufffd'?
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
advance += a
|
|
||||||
prevC = c
|
|
||||||
}
|
|
||||||
return advance
|
|
||||||
}
|
|
||||||
|
|
||||||
// MeasureString returns how far dot would advance by drawing s with f.
|
|
||||||
func MeasureString(f Face, s string) (advance fixed.Int26_6) {
|
|
||||||
prevC := rune(-1)
|
|
||||||
for _, c := range s {
|
|
||||||
if prevC >= 0 {
|
|
||||||
advance += f.Kern(prevC, c)
|
|
||||||
}
|
|
||||||
a, ok := f.GlyphAdvance(c)
|
|
||||||
if !ok {
|
|
||||||
// TODO: is falling back on the U+FFFD glyph the responsibility of
|
|
||||||
// the Drawer or the Face?
|
|
||||||
// TODO: set prevC = '\ufffd'?
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
advance += a
|
|
||||||
prevC = c
|
|
||||||
}
|
|
||||||
return advance
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hinting selects how to quantize a vector font's glyph nodes.
|
|
||||||
//
|
|
||||||
// Not all fonts support hinting.
|
|
||||||
type Hinting int
|
|
||||||
|
|
||||||
const (
|
|
||||||
HintingNone Hinting = iota
|
|
||||||
HintingVertical
|
|
||||||
HintingFull
|
|
||||||
)
|
|
||||||
|
|
||||||
// Stretch selects a normal, condensed, or expanded face.
|
|
||||||
//
|
|
||||||
// Not all fonts support stretches.
|
|
||||||
type Stretch int
|
|
||||||
|
|
||||||
const (
|
|
||||||
StretchUltraCondensed Stretch = -4
|
|
||||||
StretchExtraCondensed Stretch = -3
|
|
||||||
StretchCondensed Stretch = -2
|
|
||||||
StretchSemiCondensed Stretch = -1
|
|
||||||
StretchNormal Stretch = +0
|
|
||||||
StretchSemiExpanded Stretch = +1
|
|
||||||
StretchExpanded Stretch = +2
|
|
||||||
StretchExtraExpanded Stretch = +3
|
|
||||||
StretchUltraExpanded Stretch = +4
|
|
||||||
)
|
|
||||||
|
|
||||||
// Style selects a normal, italic, or oblique face.
|
|
||||||
//
|
|
||||||
// Not all fonts support styles.
|
|
||||||
type Style int
|
|
||||||
|
|
||||||
const (
|
|
||||||
StyleNormal Style = iota
|
|
||||||
StyleItalic
|
|
||||||
StyleOblique
|
|
||||||
)
|
|
||||||
|
|
||||||
// Weight selects a normal, light or bold face.
|
|
||||||
//
|
|
||||||
// Not all fonts support weights.
|
|
||||||
//
|
|
||||||
// The named Weight constants (e.g. WeightBold) correspond to CSS' common
|
|
||||||
// weight names (e.g. "Bold"), but the numerical values differ, so that in Go,
|
|
||||||
// the zero value means to use a normal weight. For the CSS names and values,
|
|
||||||
// see https://developer.mozilla.org/en/docs/Web/CSS/font-weight
|
|
||||||
type Weight int
|
|
||||||
|
|
||||||
const (
|
|
||||||
WeightThin Weight = -3 // CSS font-weight value 100.
|
|
||||||
WeightExtraLight Weight = -2 // CSS font-weight value 200.
|
|
||||||
WeightLight Weight = -1 // CSS font-weight value 300.
|
|
||||||
WeightNormal Weight = +0 // CSS font-weight value 400.
|
|
||||||
WeightMedium Weight = +1 // CSS font-weight value 500.
|
|
||||||
WeightSemiBold Weight = +2 // CSS font-weight value 600.
|
|
||||||
WeightBold Weight = +3 // CSS font-weight value 700.
|
|
||||||
WeightExtraBold Weight = +4 // CSS font-weight value 800.
|
|
||||||
WeightBlack Weight = +5 // CSS font-weight value 900.
|
|
||||||
)
|
|
65
vendor/golang.org/x/image/font/font_test.go
generated
vendored
65
vendor/golang.org/x/image/font/font_test.go
generated
vendored
@ -1,65 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package font
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
const toyAdvance = fixed.Int26_6(10 << 6)
|
|
||||||
|
|
||||||
type toyFace struct{}
|
|
||||||
|
|
||||||
func (toyFace) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (toyFace) Glyph(dot fixed.Point26_6, r rune) (image.Rectangle, image.Image, image.Point, fixed.Int26_6, bool) {
|
|
||||||
panic("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (toyFace) GlyphBounds(r rune) (fixed.Rectangle26_6, fixed.Int26_6, bool) {
|
|
||||||
return fixed.Rectangle26_6{
|
|
||||||
Min: fixed.P(2, 0),
|
|
||||||
Max: fixed.P(6, 1),
|
|
||||||
}, toyAdvance, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (toyFace) GlyphAdvance(r rune) (fixed.Int26_6, bool) {
|
|
||||||
return toyAdvance, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (toyFace) Kern(r0, r1 rune) fixed.Int26_6 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (toyFace) Metrics() Metrics {
|
|
||||||
return Metrics{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBound(t *testing.T) {
|
|
||||||
wantBounds := []fixed.Rectangle26_6{
|
|
||||||
{Min: fixed.P(0, 0), Max: fixed.P(0, 0)},
|
|
||||||
{Min: fixed.P(2, 0), Max: fixed.P(6, 1)},
|
|
||||||
{Min: fixed.P(2, 0), Max: fixed.P(16, 1)},
|
|
||||||
{Min: fixed.P(2, 0), Max: fixed.P(26, 1)},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, wantBound := range wantBounds {
|
|
||||||
s := strings.Repeat("x", i)
|
|
||||||
gotBound, gotAdvance := BoundString(toyFace{}, s)
|
|
||||||
if gotBound != wantBound {
|
|
||||||
t.Errorf("i=%d: bound: got %v, want %v", i, gotBound, wantBound)
|
|
||||||
}
|
|
||||||
wantAdvance := toyAdvance * fixed.Int26_6(i)
|
|
||||||
if gotAdvance != wantAdvance {
|
|
||||||
t.Errorf("i=%d: advance: got %v, want %v", i, gotAdvance, wantAdvance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
107
vendor/golang.org/x/image/font/gofont/gen.go
generated
vendored
107
vendor/golang.org/x/image/font/gofont/gen.go
generated
vendored
@ -1,107 +0,0 @@
|
|||||||
// 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 ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
// This program generates the subdirectories of Go packages that contain []byte
|
|
||||||
// versions of the TrueType font files under ./ttfs.
|
|
||||||
//
|
|
||||||
// Currently, "go run gen.go" needs to be run manually. This isn't done by the
|
|
||||||
// usual "go generate" mechanism as there isn't any other Go code in this
|
|
||||||
// directory (excluding sub-directories) to attach a "go:generate" line to.
|
|
||||||
//
|
|
||||||
// In any case, code generation should only need to happen when the underlying
|
|
||||||
// TTF files change, which isn't expected to happen frequently.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const suffix = ".ttf"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ttfs, err := os.Open("ttfs")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer ttfs.Close()
|
|
||||||
|
|
||||||
infos, err := ttfs.Readdir(-1)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
for _, info := range infos {
|
|
||||||
ttfName := info.Name()
|
|
||||||
if !strings.HasSuffix(ttfName, suffix) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
do(ttfName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func do(ttfName string) {
|
|
||||||
fontName := fontName(ttfName)
|
|
||||||
pkgName := pkgName(ttfName)
|
|
||||||
if err := os.Mkdir(pkgName, 0777); err != nil && !os.IsExist(err) {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
src, err := ioutil.ReadFile(filepath.Join("ttfs", ttfName))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
desc := "a proportional-width, sans-serif"
|
|
||||||
if strings.Contains(ttfName, "Mono") {
|
|
||||||
desc = "a fixed-width, slab-serif"
|
|
||||||
}
|
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
|
||||||
fmt.Fprintf(b, "// generated by go run gen.go; DO NOT EDIT\n\n")
|
|
||||||
fmt.Fprintf(b, "// Package %s provides the %q TrueType font\n", pkgName, fontName)
|
|
||||||
fmt.Fprintf(b, "// from the Go font family. It is %s font.\n", desc)
|
|
||||||
fmt.Fprintf(b, "//\n")
|
|
||||||
fmt.Fprintf(b, "// See https://blog.golang.org/go-fonts for details.\n")
|
|
||||||
fmt.Fprintf(b, "package %s\n\n", pkgName)
|
|
||||||
fmt.Fprintf(b, "// TTF is the data for the %q TrueType font.\n", fontName)
|
|
||||||
fmt.Fprintf(b, "var TTF = []byte{")
|
|
||||||
for i, x := range src {
|
|
||||||
if i&15 == 0 {
|
|
||||||
b.WriteByte('\n')
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "%#02x,", x)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "\n}\n")
|
|
||||||
|
|
||||||
dst, err := format.Source(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(pkgName, "data.go"), dst, 0666); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fontName maps "Go-Regular.ttf" to "Go Regular".
|
|
||||||
func fontName(ttfName string) string {
|
|
||||||
s := ttfName[:len(ttfName)-len(suffix)]
|
|
||||||
s = strings.Replace(s, "-", " ", -1)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// pkgName maps "Go-Regular.ttf" to "goregular".
|
|
||||||
func pkgName(ttfName string) string {
|
|
||||||
s := ttfName[:len(ttfName)-len(suffix)]
|
|
||||||
s = strings.Replace(s, "-", "", -1)
|
|
||||||
s = strings.ToLower(s)
|
|
||||||
return s
|
|
||||||
}
|
|
9047
vendor/golang.org/x/image/font/gofont/gobold/data.go
generated
vendored
9047
vendor/golang.org/x/image/font/gofont/gobold/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9432
vendor/golang.org/x/image/font/gofont/gobolditalic/data.go
generated
vendored
9432
vendor/golang.org/x/image/font/gofont/gobolditalic/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9198
vendor/golang.org/x/image/font/gofont/goitalic/data.go
generated
vendored
9198
vendor/golang.org/x/image/font/gofont/goitalic/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9192
vendor/golang.org/x/image/font/gofont/gomedium/data.go
generated
vendored
9192
vendor/golang.org/x/image/font/gofont/gomedium/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9726
vendor/golang.org/x/image/font/gofont/gomediumitalic/data.go
generated
vendored
9726
vendor/golang.org/x/image/font/gofont/gomediumitalic/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
10274
vendor/golang.org/x/image/font/gofont/gomono/data.go
generated
vendored
10274
vendor/golang.org/x/image/font/gofont/gomono/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
10533
vendor/golang.org/x/image/font/gofont/gomonobold/data.go
generated
vendored
10533
vendor/golang.org/x/image/font/gofont/gomonobold/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
11063
vendor/golang.org/x/image/font/gofont/gomonobolditalic/data.go
generated
vendored
11063
vendor/golang.org/x/image/font/gofont/gomonobolditalic/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
10858
vendor/golang.org/x/image/font/gofont/gomonoitalic/data.go
generated
vendored
10858
vendor/golang.org/x/image/font/gofont/gomonoitalic/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
8781
vendor/golang.org/x/image/font/gofont/goregular/data.go
generated
vendored
8781
vendor/golang.org/x/image/font/gofont/goregular/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
8362
vendor/golang.org/x/image/font/gofont/gosmallcaps/data.go
generated
vendored
8362
vendor/golang.org/x/image/font/gofont/gosmallcaps/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
8794
vendor/golang.org/x/image/font/gofont/gosmallcapsitalic/data.go
generated
vendored
8794
vendor/golang.org/x/image/font/gofont/gosmallcapsitalic/data.go
generated
vendored
File diff suppressed because it is too large
Load Diff
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Bold-Italic.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Bold-Italic.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Bold.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Bold.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Italic.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Italic.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Medium-Italic.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Medium-Italic.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Medium.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Medium.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono-Bold-Italic.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono-Bold-Italic.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono-Bold.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono-Bold.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono-Italic.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono-Italic.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Mono.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Regular.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Regular.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Smallcaps-Italic.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Smallcaps-Italic.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Smallcaps.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/gofont/ttfs/Go-Smallcaps.ttf
generated
vendored
Binary file not shown.
36
vendor/golang.org/x/image/font/gofont/ttfs/README
generated
vendored
36
vendor/golang.org/x/image/font/gofont/ttfs/README
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
These fonts were created by the Bigelow & Holmes foundry specifically for the
|
|
||||||
Go project. See https://blog.golang.org/go-fonts for details.
|
|
||||||
|
|
||||||
They are licensed under the same open source license as the rest of the Go
|
|
||||||
project's software:
|
|
||||||
|
|
||||||
Copyright (c) 2016 Bigelow & Holmes Inc.. All rights reserved.
|
|
||||||
|
|
||||||
Distribution of this font is governed by the following license. If you do not
|
|
||||||
agree to this license, including the disclaimer, do not distribute or modify
|
|
||||||
this font.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of Google Inc. nor the names of its contributors may be
|
|
||||||
used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
5557
vendor/golang.org/x/image/font/inconsolata/bold8x16.go
generated
vendored
5557
vendor/golang.org/x/image/font/inconsolata/bold8x16.go
generated
vendored
File diff suppressed because it is too large
Load Diff
29
vendor/golang.org/x/image/font/inconsolata/inconsolata.go
generated
vendored
29
vendor/golang.org/x/image/font/inconsolata/inconsolata.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
//go:generate genbasicfont -size=16 -pkg=inconsolata -hinting=full -var=regular8x16 -fontfile=http://www.levien.com/type/myfonts/inconsolata/InconsolataGo-Regular.ttf
|
|
||||||
//go:generate genbasicfont -size=16 -pkg=inconsolata -hinting=full -var=bold8x16 -fontfile=http://www.levien.com/type/myfonts/inconsolata/InconsolataGo-Bold.ttf
|
|
||||||
|
|
||||||
// The genbasicfont program is github.com/golang/freetype/example/genbasicfont
|
|
||||||
|
|
||||||
// Package inconsolata provides pre-rendered bitmap versions of the Inconsolata
|
|
||||||
// font family.
|
|
||||||
//
|
|
||||||
// Inconsolata is copyright Raph Levien and Cyreal. This package is licensed
|
|
||||||
// under Go's BSD-style license (https://golang.org/LICENSE) with their
|
|
||||||
// permission.
|
|
||||||
//
|
|
||||||
// Inconsolata's home page is at
|
|
||||||
// http://www.levien.com/type/myfonts/inconsolata.html
|
|
||||||
package inconsolata // import "golang.org/x/image/font/inconsolata"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/image/font/basicfont"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Regular8x16 is a regular weight, 8x16 font face.
|
|
||||||
var Regular8x16 *basicfont.Face = ®ular8x16
|
|
||||||
|
|
||||||
// Bold8x16 is a bold weight, 8x16 font face.
|
|
||||||
var Bold8x16 *basicfont.Face = &bold8x16
|
|
5557
vendor/golang.org/x/image/font/inconsolata/regular8x16.go
generated
vendored
5557
vendor/golang.org/x/image/font/inconsolata/regular8x16.go
generated
vendored
File diff suppressed because it is too large
Load Diff
103
vendor/golang.org/x/image/font/opentype/face.go
generated
vendored
103
vendor/golang.org/x/image/font/opentype/face.go
generated
vendored
@ -1,103 +0,0 @@
|
|||||||
// 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 opentype
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/sfnt"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FaceOptions describes the possible options given to NewFace when
|
|
||||||
// creating a new font.Face from a sfnt.Font.
|
|
||||||
type FaceOptions struct {
|
|
||||||
Size float64 // Size is the font size in points
|
|
||||||
DPI float64 // DPI is the dots per inch resolution
|
|
||||||
Hinting font.Hinting // Hinting selects how to quantize a vector font's glyph nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultFaceOptions() *FaceOptions {
|
|
||||||
return &FaceOptions{
|
|
||||||
Size: 12,
|
|
||||||
DPI: 72,
|
|
||||||
Hinting: font.HintingNone,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Face implements the font.Face interface for sfnt.Font values.
|
|
||||||
type Face struct {
|
|
||||||
f *sfnt.Font
|
|
||||||
hinting font.Hinting
|
|
||||||
scale fixed.Int26_6
|
|
||||||
|
|
||||||
buf sfnt.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFace returns a new font.Face for the given sfnt.Font.
|
|
||||||
// if opts is nil, sensible defaults will be used.
|
|
||||||
func NewFace(f *sfnt.Font, opts *FaceOptions) (font.Face, error) {
|
|
||||||
if opts == nil {
|
|
||||||
opts = defaultFaceOptions()
|
|
||||||
}
|
|
||||||
face := &Face{
|
|
||||||
f: f,
|
|
||||||
hinting: opts.Hinting,
|
|
||||||
scale: fixed.Int26_6(0.5 + (opts.Size * opts.DPI * 64 / 72)),
|
|
||||||
}
|
|
||||||
return face, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close satisfies the font.Face interface.
|
|
||||||
func (f *Face) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metrics satisfies the font.Face interface.
|
|
||||||
func (f *Face) Metrics() font.Metrics {
|
|
||||||
m, err := f.f.Metrics(&f.buf, f.scale, f.hinting)
|
|
||||||
if err != nil {
|
|
||||||
return font.Metrics{}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kern satisfies the font.Face interface.
|
|
||||||
func (f *Face) Kern(r0, r1 rune) fixed.Int26_6 {
|
|
||||||
x0 := f.index(r0)
|
|
||||||
x1 := f.index(r1)
|
|
||||||
k, err := f.f.Kern(&f.buf, x0, x1, fixed.Int26_6(f.f.UnitsPerEm()), f.hinting)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
|
|
||||||
// Glyph satisfies the font.Face interface.
|
|
||||||
func (f *Face) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlyphBounds satisfies the font.Face interface.
|
|
||||||
func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
|
||||||
advance, ok = f.GlyphAdvance(r)
|
|
||||||
if !ok {
|
|
||||||
return bounds, advance, ok
|
|
||||||
}
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlyphAdvance satisfies the font.Face interface.
|
|
||||||
func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
|
||||||
idx := f.index(r)
|
|
||||||
advance, err := f.f.GlyphAdvance(&f.buf, idx, f.scale, f.hinting)
|
|
||||||
return advance, err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Face) index(r rune) sfnt.GlyphIndex {
|
|
||||||
x, _ := f.f.GlyphIndex(&f.buf, r)
|
|
||||||
return x
|
|
||||||
}
|
|
90
vendor/golang.org/x/image/font/opentype/face_test.go
generated
vendored
90
vendor/golang.org/x/image/font/opentype/face_test.go
generated
vendored
@ -1,90 +0,0 @@
|
|||||||
// 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 opentype
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/gofont/goregular"
|
|
||||||
"golang.org/x/image/font/sfnt"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
regular font.Face
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
font, err := sfnt.Parse(goregular.TTF)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
regular, err = NewFace(font, defaultFaceOptions())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFaceGlyphAdvance(t *testing.T) {
|
|
||||||
for _, test := range []struct {
|
|
||||||
r rune
|
|
||||||
want fixed.Int26_6
|
|
||||||
}{
|
|
||||||
{' ', 213},
|
|
||||||
{'A', 512},
|
|
||||||
{'Á', 512},
|
|
||||||
{'Æ', 768},
|
|
||||||
{'i', 189},
|
|
||||||
{'x', 384},
|
|
||||||
} {
|
|
||||||
got, ok := regular.GlyphAdvance(test.r)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("could not get glyph advance width for %q", test.r)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if got != test.want {
|
|
||||||
t.Errorf("%q: glyph advance width=%d. want=%d", test.r, got, test.want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFaceKern(t *testing.T) {
|
|
||||||
// FIXME(sbinet) there is no kerning with gofont/goregular
|
|
||||||
for _, test := range []struct {
|
|
||||||
r1, r2 rune
|
|
||||||
want fixed.Int26_6
|
|
||||||
}{
|
|
||||||
{'A', 'A', 0},
|
|
||||||
{'A', 'V', 0},
|
|
||||||
{'V', 'A', 0},
|
|
||||||
{'A', 'v', 0},
|
|
||||||
{'W', 'a', 0},
|
|
||||||
{'W', 'i', 0},
|
|
||||||
{'Y', 'i', 0},
|
|
||||||
{'f', '(', 0},
|
|
||||||
{'f', 'f', 0},
|
|
||||||
{'f', 'i', 0},
|
|
||||||
{'T', 'a', 0},
|
|
||||||
{'T', 'e', 0},
|
|
||||||
} {
|
|
||||||
got := regular.Kern(test.r1, test.r2)
|
|
||||||
if got != test.want {
|
|
||||||
t.Errorf("(%q, %q): glyph kerning=%d. want=%d", test.r1, test.r2, got, test.want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFaceMetrics(t *testing.T) {
|
|
||||||
want := font.Metrics{Height: 768, Ascent: 726, Descent: 162}
|
|
||||||
got := regular.Metrics()
|
|
||||||
if got != want {
|
|
||||||
t.Fatalf("metrics failed. got=%#v. want=%#v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
7
vendor/golang.org/x/image/font/opentype/opentype.go
generated
vendored
7
vendor/golang.org/x/image/font/opentype/opentype.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
// 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 opentype implements the font.Face interface based on SFNT
|
|
||||||
// font file formats.
|
|
||||||
package opentype // import "golang.org/x/image/font/opentype"
|
|
92
vendor/golang.org/x/image/font/plan9font/example_test.go
generated
vendored
92
vendor/golang.org/x/image/font/plan9font/example_test.go
generated
vendored
@ -1,92 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
package plan9font_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/plan9font"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleParseFont() {
|
|
||||||
readFile := func(name string) ([]byte, error) {
|
|
||||||
return ioutil.ReadFile(filepath.FromSlash(path.Join("../testdata/fixed", name)))
|
|
||||||
}
|
|
||||||
fontData, err := readFile("unicode.7x13.font")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
face, err := plan9font.ParseFont(fontData, readFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
ascent := face.Metrics().Ascent.Ceil()
|
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 4*7, 13))
|
|
||||||
draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src)
|
|
||||||
d := &font.Drawer{
|
|
||||||
Dst: dst,
|
|
||||||
Src: image.White,
|
|
||||||
Face: face,
|
|
||||||
Dot: fixed.P(0, ascent),
|
|
||||||
}
|
|
||||||
// Draw:
|
|
||||||
// - U+0053 LATIN CAPITAL LETTER S
|
|
||||||
// - U+03A3 GREEK CAPITAL LETTER SIGMA
|
|
||||||
// - U+222B INTEGRAL
|
|
||||||
// - U+3055 HIRAGANA LETTER SA
|
|
||||||
// The testdata does not contain the CJK subfont files, so U+3055 HIRAGANA
|
|
||||||
// LETTER SA (さ) should be rendered as U+FFFD REPLACEMENT CHARACTER (<28>).
|
|
||||||
//
|
|
||||||
// The missing subfont file will trigger an "open
|
|
||||||
// ../testdata/shinonome/k12.3000: no such file or directory" log message.
|
|
||||||
// This is expected and can be ignored.
|
|
||||||
d.DrawString("SΣ∫さ")
|
|
||||||
|
|
||||||
// Convert the dst image to ASCII art.
|
|
||||||
var out []byte
|
|
||||||
b := dst.Bounds()
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
out = append(out, '0'+byte(y%10), ' ')
|
|
||||||
for x := b.Min.X; x < b.Max.X; x++ {
|
|
||||||
if dst.RGBAAt(x, y).R > 0 {
|
|
||||||
out = append(out, 'X')
|
|
||||||
} else {
|
|
||||||
out = append(out, '.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Highlight the last row before the baseline. Glyphs like 'S' without
|
|
||||||
// descenders should not affect any pixels whose Y coordinate is >= the
|
|
||||||
// baseline.
|
|
||||||
if y == ascent-1 {
|
|
||||||
out = append(out, '_')
|
|
||||||
}
|
|
||||||
out = append(out, '\n')
|
|
||||||
}
|
|
||||||
os.Stdout.Write(out)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// 0 ..................X.........
|
|
||||||
// 1 .................X.X........
|
|
||||||
// 2 .XXXX..XXXXXX....X.....XXX..
|
|
||||||
// 3 X....X.X.........X....XX.XX.
|
|
||||||
// 4 X.......X........X....X.X.X.
|
|
||||||
// 5 X........X.......X....XXX.X.
|
|
||||||
// 6 .XXXX.....X......X....XX.XX.
|
|
||||||
// 7 .....X...X.......X....XX.XX.
|
|
||||||
// 8 .....X..X........X....XXXXX.
|
|
||||||
// 9 X....X.X.........X....XX.XX.
|
|
||||||
// 0 .XXXX..XXXXXX....X.....XXX.._
|
|
||||||
// 1 ...............X.X..........
|
|
||||||
// 2 ................X...........
|
|
||||||
}
|
|
610
vendor/golang.org/x/image/font/plan9font/plan9font.go
generated
vendored
610
vendor/golang.org/x/image/font/plan9font/plan9font.go
generated
vendored
@ -1,610 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Package plan9font implements font faces for the Plan 9 font and subfont file
|
|
||||||
// formats. These formats are described at
|
|
||||||
// http://plan9.bell-labs.com/magic/man2html/6/font
|
|
||||||
package plan9font // import "golang.org/x/image/font/plan9font"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"log"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// fontchar describes one character glyph in a subfont.
|
|
||||||
//
|
|
||||||
// For more detail, look for "struct Fontchar" in
|
|
||||||
// http://plan9.bell-labs.com/magic/man2html/2/cachechars
|
|
||||||
type fontchar struct {
|
|
||||||
x uint32 // X position in the image holding the glyphs.
|
|
||||||
top uint8 // First non-zero scan line.
|
|
||||||
bottom uint8 // Last non-zero scan line.
|
|
||||||
left int8 // Offset of baseline.
|
|
||||||
width uint8 // Width of baseline.
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseFontchars(p []byte) []fontchar {
|
|
||||||
fc := make([]fontchar, len(p)/6)
|
|
||||||
for i := range fc {
|
|
||||||
fc[i] = fontchar{
|
|
||||||
x: uint32(p[0]) | uint32(p[1])<<8,
|
|
||||||
top: uint8(p[2]),
|
|
||||||
bottom: uint8(p[3]),
|
|
||||||
left: int8(p[4]),
|
|
||||||
width: uint8(p[5]),
|
|
||||||
}
|
|
||||||
p = p[6:]
|
|
||||||
}
|
|
||||||
return fc
|
|
||||||
}
|
|
||||||
|
|
||||||
// subface implements font.Face for a Plan 9 subfont.
|
|
||||||
type subface struct {
|
|
||||||
firstRune rune // First rune in the subfont.
|
|
||||||
n int // Number of characters in the subfont.
|
|
||||||
height int // Inter-line spacing.
|
|
||||||
ascent int // Height above the baseline.
|
|
||||||
fontchars []fontchar // Character descriptions.
|
|
||||||
img *image.Alpha // Image holding the glyphs.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *subface) Close() error { return nil }
|
|
||||||
func (f *subface) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
|
|
||||||
|
|
||||||
func (f *subface) Metrics() font.Metrics {
|
|
||||||
return font.Metrics{
|
|
||||||
Height: fixed.I(f.height),
|
|
||||||
Ascent: fixed.I(f.ascent),
|
|
||||||
Descent: fixed.I(f.height - f.ascent),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *subface) Glyph(dot fixed.Point26_6, r rune) (
|
|
||||||
dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
|
||||||
|
|
||||||
r -= f.firstRune
|
|
||||||
if r < 0 || f.n <= int(r) {
|
|
||||||
return image.Rectangle{}, nil, image.Point{}, 0, false
|
|
||||||
}
|
|
||||||
i := &f.fontchars[r+0]
|
|
||||||
j := &f.fontchars[r+1]
|
|
||||||
|
|
||||||
minX := int(dot.X+32)>>6 + int(i.left)
|
|
||||||
minY := int(dot.Y+32)>>6 + int(i.top) - f.ascent
|
|
||||||
dr = image.Rectangle{
|
|
||||||
Min: image.Point{
|
|
||||||
X: minX,
|
|
||||||
Y: minY,
|
|
||||||
},
|
|
||||||
Max: image.Point{
|
|
||||||
X: minX + int(j.x-i.x),
|
|
||||||
Y: minY + int(i.bottom) - int(i.top),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return dr, f.img, image.Point{int(i.x), int(i.top)}, fixed.Int26_6(i.width) << 6, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *subface) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
|
||||||
r -= f.firstRune
|
|
||||||
if r < 0 || f.n <= int(r) {
|
|
||||||
return fixed.Rectangle26_6{}, 0, false
|
|
||||||
}
|
|
||||||
i := &f.fontchars[r+0]
|
|
||||||
j := &f.fontchars[r+1]
|
|
||||||
|
|
||||||
bounds = fixed.R(
|
|
||||||
int(i.left),
|
|
||||||
int(i.top)-f.ascent,
|
|
||||||
int(i.left)+int(j.x-i.x),
|
|
||||||
int(i.bottom)-f.ascent,
|
|
||||||
)
|
|
||||||
return bounds, fixed.Int26_6(i.width) << 6, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *subface) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
|
||||||
r -= f.firstRune
|
|
||||||
if r < 0 || f.n <= int(r) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return fixed.Int26_6(f.fontchars[r].width) << 6, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// runeRange maps a single rune range [lo, hi] to a lazily loaded subface. Both
|
|
||||||
// ends of the range are inclusive.
|
|
||||||
type runeRange struct {
|
|
||||||
lo, hi rune
|
|
||||||
offset rune // subfont index that the lo rune maps to.
|
|
||||||
relFilename string
|
|
||||||
subface *subface
|
|
||||||
bad bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// face implements font.Face for a Plan 9 font.
|
|
||||||
//
|
|
||||||
// It maps multiple rune ranges to *subface values. Rune ranges may overlap;
|
|
||||||
// the first match wins.
|
|
||||||
type face struct {
|
|
||||||
height int
|
|
||||||
ascent int
|
|
||||||
readFile func(relFilename string) ([]byte, error)
|
|
||||||
runeRanges []runeRange
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *face) Close() error { return nil }
|
|
||||||
func (f *face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
|
|
||||||
|
|
||||||
func (f *face) Metrics() font.Metrics {
|
|
||||||
return font.Metrics{
|
|
||||||
Height: fixed.I(f.height),
|
|
||||||
Ascent: fixed.I(f.ascent),
|
|
||||||
Descent: fixed.I(f.height - f.ascent),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *face) Glyph(dot fixed.Point26_6, r rune) (
|
|
||||||
dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
|
|
||||||
|
|
||||||
if s, rr := f.subface(r); s != nil {
|
|
||||||
return s.Glyph(dot, rr)
|
|
||||||
}
|
|
||||||
return image.Rectangle{}, nil, image.Point{}, 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
|
|
||||||
if s, rr := f.subface(r); s != nil {
|
|
||||||
return s.GlyphBounds(rr)
|
|
||||||
}
|
|
||||||
return fixed.Rectangle26_6{}, 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
|
|
||||||
if s, rr := f.subface(r); s != nil {
|
|
||||||
return s.GlyphAdvance(rr)
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// For subfont files, if reading the given file name fails, we try appending
|
|
||||||
// ".n" where n is the log2 of the grayscale depth in bits (so at most 3) and
|
|
||||||
// then work down to 0. This was done in Plan 9 when antialiased fonts were
|
|
||||||
// introduced so that the 1-bit displays could keep using the 1-bit forms but
|
|
||||||
// higher depth displays could use the antialiased forms.
|
|
||||||
var subfontSuffixes = [...]string{
|
|
||||||
"",
|
|
||||||
".3",
|
|
||||||
".2",
|
|
||||||
".1",
|
|
||||||
".0",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *face) readSubfontFile(name string) ([]byte, error) {
|
|
||||||
var firstErr error
|
|
||||||
for _, suffix := range subfontSuffixes {
|
|
||||||
if b, err := f.readFile(name + suffix); err == nil {
|
|
||||||
return b, nil
|
|
||||||
} else if firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, firstErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *face) subface(r rune) (*subface, rune) {
|
|
||||||
// Fall back on U+FFFD if we can't find r.
|
|
||||||
for _, rr := range [2]rune{r, '\ufffd'} {
|
|
||||||
// We have to do linear, not binary search. plan9port's
|
|
||||||
// lucsans/unicode.8.font says:
|
|
||||||
// 0x2591 0x2593 ../luc/Altshades.7.0
|
|
||||||
// 0x2500 0x25ee ../luc/FormBlock.7.0
|
|
||||||
// and the rune ranges overlap.
|
|
||||||
for i := range f.runeRanges {
|
|
||||||
x := &f.runeRanges[i]
|
|
||||||
if rr < x.lo || x.hi < rr || x.bad {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if x.subface == nil {
|
|
||||||
data, err := f.readSubfontFile(x.relFilename)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("plan9font: couldn't read subfont %q: %v", x.relFilename, err)
|
|
||||||
x.bad = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sub, err := ParseSubfont(data, x.lo-x.offset)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("plan9font: couldn't parse subfont %q: %v", x.relFilename, err)
|
|
||||||
x.bad = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
x.subface = sub.(*subface)
|
|
||||||
}
|
|
||||||
return x.subface, rr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFont parses a Plan 9 font file. data is the contents of that font file,
|
|
||||||
// which gives relative filenames for subfont files. readFile returns the
|
|
||||||
// contents of those subfont files. It is similar to io/ioutil's ReadFile
|
|
||||||
// function, except that it takes a relative filename instead of an absolute
|
|
||||||
// one.
|
|
||||||
func ParseFont(data []byte, readFile func(relFilename string) ([]byte, error)) (font.Face, error) {
|
|
||||||
f := &face{
|
|
||||||
readFile: readFile,
|
|
||||||
}
|
|
||||||
// TODO: don't use strconv, to avoid the conversions from []byte to string?
|
|
||||||
for first := true; len(data) > 0; first = false {
|
|
||||||
i := bytes.IndexByte(data, '\n')
|
|
||||||
if i < 0 {
|
|
||||||
return nil, errors.New("plan9font: invalid font: no final newline")
|
|
||||||
}
|
|
||||||
row := string(data[:i])
|
|
||||||
data = data[i+1:]
|
|
||||||
if first {
|
|
||||||
height, s, ok := nextInt32(row)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row)
|
|
||||||
}
|
|
||||||
ascent, s, ok := nextInt32(s)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row)
|
|
||||||
}
|
|
||||||
if height < 0 || 0xffff < height || ascent < 0 || 0xffff < ascent {
|
|
||||||
return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row)
|
|
||||||
}
|
|
||||||
f.height, f.ascent = int(height), int(ascent)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lo, s, ok := nextInt32(row)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row)
|
|
||||||
}
|
|
||||||
hi, s, ok := nextInt32(s)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row)
|
|
||||||
}
|
|
||||||
offset, s, _ := nextInt32(s)
|
|
||||||
|
|
||||||
f.runeRanges = append(f.runeRanges, runeRange{
|
|
||||||
lo: lo,
|
|
||||||
hi: hi,
|
|
||||||
offset: offset,
|
|
||||||
relFilename: s,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextInt32(s string) (ret int32, remaining string, ok bool) {
|
|
||||||
i := 0
|
|
||||||
for ; i < len(s) && s[i] <= ' '; i++ {
|
|
||||||
}
|
|
||||||
j := i
|
|
||||||
for ; j < len(s) && s[j] > ' '; j++ {
|
|
||||||
}
|
|
||||||
n, err := strconv.ParseInt(s[i:j], 0, 32)
|
|
||||||
if err != nil {
|
|
||||||
return 0, s, false
|
|
||||||
}
|
|
||||||
for ; j < len(s) && s[j] <= ' '; j++ {
|
|
||||||
}
|
|
||||||
return int32(n), s[j:], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSubfont parses a Plan 9 subfont file.
|
|
||||||
//
|
|
||||||
// firstRune is the first rune in the subfont file. For example, the
|
|
||||||
// Phonetic.6.0 subfont, containing glyphs in the range U+0250 to U+02E9, would
|
|
||||||
// set firstRune to '\u0250'.
|
|
||||||
func ParseSubfont(data []byte, firstRune rune) (font.Face, error) {
|
|
||||||
data, m, err := parseImage(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(data) < 3*12 {
|
|
||||||
return nil, errors.New("plan9font: invalid subfont: header too short")
|
|
||||||
}
|
|
||||||
n := atoi(data[0*12:])
|
|
||||||
height := atoi(data[1*12:])
|
|
||||||
ascent := atoi(data[2*12:])
|
|
||||||
data = data[3*12:]
|
|
||||||
if len(data) != 6*(n+1) {
|
|
||||||
return nil, errors.New("plan9font: invalid subfont: data length mismatch")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert from plan9Image to image.Alpha, as the standard library's
|
|
||||||
// image/draw package works best when glyph masks are of that type.
|
|
||||||
img := image.NewAlpha(m.Bounds())
|
|
||||||
for y := img.Rect.Min.Y; y < img.Rect.Max.Y; y++ {
|
|
||||||
i := img.PixOffset(img.Rect.Min.X, y)
|
|
||||||
for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
|
|
||||||
img.Pix[i] = m.at(x, y)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &subface{
|
|
||||||
firstRune: firstRune,
|
|
||||||
n: n,
|
|
||||||
height: height,
|
|
||||||
ascent: ascent,
|
|
||||||
fontchars: parseFontchars(data),
|
|
||||||
img: img,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// plan9Image implements that subset of the Plan 9 image feature set that is
|
|
||||||
// used by this font file format.
|
|
||||||
//
|
|
||||||
// Some features, such as the repl bit and a clip rectangle, are omitted for
|
|
||||||
// simplicity.
|
|
||||||
type plan9Image struct {
|
|
||||||
depth int // Depth of the pixels in bits.
|
|
||||||
width int // Width in bytes of a single scan line.
|
|
||||||
rect image.Rectangle // Extent of the image.
|
|
||||||
pix []byte // Pixel bits.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *plan9Image) byteoffset(x, y int) int {
|
|
||||||
a := y * m.width
|
|
||||||
if m.depth < 8 {
|
|
||||||
// We need to always round down, but Go rounds toward zero.
|
|
||||||
np := 8 / m.depth
|
|
||||||
if x < 0 {
|
|
||||||
return a + (x-np+1)/np
|
|
||||||
}
|
|
||||||
return a + x/np
|
|
||||||
}
|
|
||||||
return a + x*(m.depth/8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *plan9Image) Bounds() image.Rectangle { return m.rect }
|
|
||||||
func (m *plan9Image) ColorModel() color.Model { return color.AlphaModel }
|
|
||||||
|
|
||||||
func (m *plan9Image) At(x, y int) color.Color {
|
|
||||||
if (image.Point{x, y}).In(m.rect) {
|
|
||||||
return color.Alpha{m.at(x, y)}
|
|
||||||
}
|
|
||||||
return color.Alpha{0x00}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *plan9Image) at(x, y int) uint8 {
|
|
||||||
b := m.pix[m.byteoffset(x, y)]
|
|
||||||
switch m.depth {
|
|
||||||
case 1:
|
|
||||||
// CGrey, 1.
|
|
||||||
mask := uint8(1 << uint8(7-x&7))
|
|
||||||
if (b & mask) != 0 {
|
|
||||||
return 0xff
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
case 2:
|
|
||||||
// CGrey, 2.
|
|
||||||
shift := uint(x&3) << 1
|
|
||||||
// Place pixel at top of word.
|
|
||||||
y := b << shift
|
|
||||||
y &= 0xc0
|
|
||||||
// Replicate throughout.
|
|
||||||
y |= y >> 2
|
|
||||||
y |= y >> 4
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var compressed = []byte("compressed\n")
|
|
||||||
|
|
||||||
func parseImage(data []byte) (remainingData []byte, m *plan9Image, retErr error) {
|
|
||||||
if !bytes.HasPrefix(data, compressed) {
|
|
||||||
return nil, nil, errors.New("plan9font: unsupported uncompressed format")
|
|
||||||
}
|
|
||||||
data = data[len(compressed):]
|
|
||||||
|
|
||||||
const hdrSize = 5 * 12
|
|
||||||
if len(data) < hdrSize {
|
|
||||||
return nil, nil, errors.New("plan9font: invalid image: header too short")
|
|
||||||
}
|
|
||||||
hdr, data := data[:hdrSize], data[hdrSize:]
|
|
||||||
|
|
||||||
// Distinguish new channel descriptor from old ldepth. Channel descriptors
|
|
||||||
// have letters as well as numbers, while ldepths are a single digit
|
|
||||||
// formatted as %-11d.
|
|
||||||
new := false
|
|
||||||
for m := 0; m < 10; m++ {
|
|
||||||
if hdr[m] != ' ' {
|
|
||||||
new = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if hdr[11] != ' ' {
|
|
||||||
return nil, nil, errors.New("plan9font: invalid image: bad header")
|
|
||||||
}
|
|
||||||
if !new {
|
|
||||||
return nil, nil, errors.New("plan9font: unsupported ldepth format")
|
|
||||||
}
|
|
||||||
|
|
||||||
depth := 0
|
|
||||||
switch s := strings.TrimSpace(string(hdr[:1*12])); s {
|
|
||||||
default:
|
|
||||||
return nil, nil, fmt.Errorf("plan9font: unsupported pixel format %q", s)
|
|
||||||
case "k1":
|
|
||||||
depth = 1
|
|
||||||
case "k2":
|
|
||||||
depth = 2
|
|
||||||
}
|
|
||||||
r := ator(hdr[1*12:])
|
|
||||||
if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y {
|
|
||||||
return nil, nil, errors.New("plan9font: invalid image: bad rectangle")
|
|
||||||
}
|
|
||||||
|
|
||||||
width := bytesPerLine(r, depth)
|
|
||||||
m = &plan9Image{
|
|
||||||
depth: depth,
|
|
||||||
width: width,
|
|
||||||
rect: r,
|
|
||||||
pix: make([]byte, width*r.Dy()),
|
|
||||||
}
|
|
||||||
|
|
||||||
miny := r.Min.Y
|
|
||||||
for miny != r.Max.Y {
|
|
||||||
if len(data) < 2*12 {
|
|
||||||
return nil, nil, errors.New("plan9font: invalid image: data band too short")
|
|
||||||
}
|
|
||||||
maxy := atoi(data[0*12:])
|
|
||||||
nb := atoi(data[1*12:])
|
|
||||||
data = data[2*12:]
|
|
||||||
|
|
||||||
if len(data) < nb {
|
|
||||||
return nil, nil, errors.New("plan9font: invalid image: data band length mismatch")
|
|
||||||
}
|
|
||||||
buf := data[:nb]
|
|
||||||
data = data[nb:]
|
|
||||||
|
|
||||||
if maxy <= miny || r.Max.Y < maxy {
|
|
||||||
return nil, nil, fmt.Errorf("plan9font: bad maxy %d", maxy)
|
|
||||||
}
|
|
||||||
// An old-format image would flip the bits here, but we don't support
|
|
||||||
// the old format.
|
|
||||||
rr := r
|
|
||||||
rr.Min.Y = miny
|
|
||||||
rr.Max.Y = maxy
|
|
||||||
if err := decompress(m, rr, buf); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
miny = maxy
|
|
||||||
}
|
|
||||||
return data, m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compressed data are sequences of byte codes. If the first byte b has the
|
|
||||||
// 0x80 bit set, the next (b^0x80)+1 bytes are data. Otherwise, these two bytes
|
|
||||||
// specify a previous string to repeat.
|
|
||||||
const (
|
|
||||||
compShortestMatch = 3 // shortest match possible.
|
|
||||||
compWindowSize = 1024 // window size.
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errDecompressBufferTooSmall = errors.New("plan9font: decompress: buffer too small")
|
|
||||||
errDecompressPhaseError = errors.New("plan9font: decompress: phase error")
|
|
||||||
)
|
|
||||||
|
|
||||||
func decompress(m *plan9Image, r image.Rectangle, data []byte) error {
|
|
||||||
if !r.In(m.rect) {
|
|
||||||
return errors.New("plan9font: decompress: bad rectangle")
|
|
||||||
}
|
|
||||||
bpl := bytesPerLine(r, m.depth)
|
|
||||||
mem := make([]byte, compWindowSize)
|
|
||||||
memi := 0
|
|
||||||
omemi := -1
|
|
||||||
y := r.Min.Y
|
|
||||||
linei := m.byteoffset(r.Min.X, y)
|
|
||||||
eline := linei + bpl
|
|
||||||
datai := 0
|
|
||||||
for {
|
|
||||||
if linei == eline {
|
|
||||||
y++
|
|
||||||
if y == r.Max.Y {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
linei = m.byteoffset(r.Min.X, y)
|
|
||||||
eline = linei + bpl
|
|
||||||
}
|
|
||||||
if datai == len(data) {
|
|
||||||
return errDecompressBufferTooSmall
|
|
||||||
}
|
|
||||||
c := data[datai]
|
|
||||||
datai++
|
|
||||||
if c >= 128 {
|
|
||||||
for cnt := c - 128 + 1; cnt != 0; cnt-- {
|
|
||||||
if datai == len(data) {
|
|
||||||
return errDecompressBufferTooSmall
|
|
||||||
}
|
|
||||||
if linei == eline {
|
|
||||||
return errDecompressPhaseError
|
|
||||||
}
|
|
||||||
m.pix[linei] = data[datai]
|
|
||||||
linei++
|
|
||||||
mem[memi] = data[datai]
|
|
||||||
memi++
|
|
||||||
datai++
|
|
||||||
if memi == len(mem) {
|
|
||||||
memi = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if datai == len(data) {
|
|
||||||
return errDecompressBufferTooSmall
|
|
||||||
}
|
|
||||||
offs := int(data[datai]) + ((int(c) & 3) << 8) + 1
|
|
||||||
datai++
|
|
||||||
if memi < offs {
|
|
||||||
omemi = memi + (compWindowSize - offs)
|
|
||||||
} else {
|
|
||||||
omemi = memi - offs
|
|
||||||
}
|
|
||||||
for cnt := (c >> 2) + compShortestMatch; cnt != 0; cnt-- {
|
|
||||||
if linei == eline {
|
|
||||||
return errDecompressPhaseError
|
|
||||||
}
|
|
||||||
m.pix[linei] = mem[omemi]
|
|
||||||
linei++
|
|
||||||
mem[memi] = mem[omemi]
|
|
||||||
memi++
|
|
||||||
omemi++
|
|
||||||
if omemi == len(mem) {
|
|
||||||
omemi = 0
|
|
||||||
}
|
|
||||||
if memi == len(mem) {
|
|
||||||
memi = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ator(b []byte) image.Rectangle {
|
|
||||||
return image.Rectangle{atop(b), atop(b[2*12:])}
|
|
||||||
}
|
|
||||||
|
|
||||||
func atop(b []byte) image.Point {
|
|
||||||
return image.Pt(atoi(b), atoi(b[12:]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func atoi(b []byte) int {
|
|
||||||
i := 0
|
|
||||||
for ; i < len(b) && b[i] == ' '; i++ {
|
|
||||||
}
|
|
||||||
n := 0
|
|
||||||
for ; i < len(b) && '0' <= b[i] && b[i] <= '9'; i++ {
|
|
||||||
n = n*10 + int(b[i]) - '0'
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func bytesPerLine(r image.Rectangle, depth int) int {
|
|
||||||
if depth <= 0 || 32 < depth {
|
|
||||||
panic("invalid depth")
|
|
||||||
}
|
|
||||||
var l int
|
|
||||||
if r.Min.X >= 0 {
|
|
||||||
l = (r.Max.X*depth + 7) / 8
|
|
||||||
l -= (r.Min.X * depth) / 8
|
|
||||||
} else {
|
|
||||||
// Make positive before divide.
|
|
||||||
t := (-r.Min.X*depth + 7) / 8
|
|
||||||
l = t + (r.Max.X*depth+7)/8
|
|
||||||
}
|
|
||||||
return l
|
|
||||||
}
|
|
24
vendor/golang.org/x/image/font/plan9font/plan9font_test.go
generated
vendored
24
vendor/golang.org/x/image/font/plan9font/plan9font_test.go
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package plan9font
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkParseSubfont(b *testing.B) {
|
|
||||||
subfontData, err := ioutil.ReadFile(filepath.FromSlash("../testdata/fixed/7x13.0000"))
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, err := ParseSubfont(subfontData, 0); err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
259
vendor/golang.org/x/image/font/sfnt/cmap.go
generated
vendored
259
vendor/golang.org/x/image/font/sfnt/cmap.go
generated
vendored
@ -1,259 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"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) {
|
|
||||||
x, ok := charmap.Macintosh.EncodeRune(r)
|
|
||||||
if !ok {
|
|
||||||
// The source rune r is not representable in the Macintosh-Roman encoding.
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
return GlyphIndex(table[x]), 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
|
|
||||||
}
|
|
68
vendor/golang.org/x/image/font/sfnt/data.go
generated
vendored
68
vendor/golang.org/x/image/font/sfnt/data.go
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
// 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,
|
|
||||||
}
|
|
131
vendor/golang.org/x/image/font/sfnt/example_test.go
generated
vendored
131
vendor/golang.org/x/image/font/sfnt/example_test.go
generated
vendored
@ -1,131 +0,0 @@
|
|||||||
// 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 = 36
|
|
||||||
originX = 0
|
|
||||||
originY = 32
|
|
||||||
)
|
|
||||||
|
|
||||||
f, err := sfnt.Parse(goregular.TTF)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Parse: %v", err)
|
|
||||||
}
|
|
||||||
var b sfnt.Buffer
|
|
||||||
x, err := f.GlyphIndex(&b, 'Ġ')
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("GlyphIndex: %v", err)
|
|
||||||
}
|
|
||||||
if x == 0 {
|
|
||||||
log.Fatalf("GlyphIndex: no glyph index found for the rune 'Ġ'")
|
|
||||||
}
|
|
||||||
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].X)/64,
|
|
||||||
originY+float32(seg.Args[0].Y)/64,
|
|
||||||
)
|
|
||||||
case sfnt.SegmentOpLineTo:
|
|
||||||
r.LineTo(
|
|
||||||
originX+float32(seg.Args[0].X)/64,
|
|
||||||
originY+float32(seg.Args[0].Y)/64,
|
|
||||||
)
|
|
||||||
case sfnt.SegmentOpQuadTo:
|
|
||||||
r.QuadTo(
|
|
||||||
originX+float32(seg.Args[0].X)/64,
|
|
||||||
originY+float32(seg.Args[0].Y)/64,
|
|
||||||
originX+float32(seg.Args[1].X)/64,
|
|
||||||
originY+float32(seg.Args[1].Y)/64,
|
|
||||||
)
|
|
||||||
case sfnt.SegmentOpCubeTo:
|
|
||||||
r.CubeTo(
|
|
||||||
originX+float32(seg.Args[0].X)/64,
|
|
||||||
originY+float32(seg.Args[0].Y)/64,
|
|
||||||
originX+float32(seg.Args[1].X)/64,
|
|
||||||
originY+float32(seg.Args[1].Y)/64,
|
|
||||||
originX+float32(seg.Args[2].X)/64,
|
|
||||||
originY+float32(seg.Args[2].Y)/64,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
// ........................
|
|
||||||
// ........................
|
|
||||||
// ........................
|
|
||||||
// ............888.........
|
|
||||||
// ............888.........
|
|
||||||
// ............888.........
|
|
||||||
// ............+++.........
|
|
||||||
// ........................
|
|
||||||
// ..........+++++++++.....
|
|
||||||
// .......+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++..
|
|
||||||
// ..........++++++++......
|
|
||||||
// ........................
|
|
||||||
// ........................
|
|
||||||
// ........................
|
|
||||||
}
|
|
321
vendor/golang.org/x/image/font/sfnt/gen.go
generated
vendored
321
vendor/golang.org/x/image/font/sfnt/gen.go
generated
vendored
@ -1,321 +0,0 @@
|
|||||||
// 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",
|
|
||||||
}
|
|
1414
vendor/golang.org/x/image/font/sfnt/postscript.go
generated
vendored
1414
vendor/golang.org/x/image/font/sfnt/postscript.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1390
vendor/golang.org/x/image/font/sfnt/proprietary_test.go
generated
vendored
1390
vendor/golang.org/x/image/font/sfnt/proprietary_test.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1538
vendor/golang.org/x/image/font/sfnt/sfnt.go
generated
vendored
1538
vendor/golang.org/x/image/font/sfnt/sfnt.go
generated
vendored
File diff suppressed because it is too large
Load Diff
839
vendor/golang.org/x/image/font/sfnt/sfnt_test.go
generated
vendored
839
vendor/golang.org/x/image/font/sfnt/sfnt_test.go
generated
vendored
@ -1,839 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package sfnt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/gofont/gobold"
|
|
||||||
"golang.org/x/image/font/gofont/gomono"
|
|
||||||
"golang.org/x/image/font/gofont/goregular"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
func pt(x, y fixed.Int26_6) fixed.Point26_6 {
|
|
||||||
return fixed.Point26_6{X: x, Y: y}
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveTo(xa, ya fixed.Int26_6) Segment {
|
|
||||||
return Segment{
|
|
||||||
Op: SegmentOpMoveTo,
|
|
||||||
Args: [3]fixed.Point26_6{pt(xa, ya)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lineTo(xa, ya fixed.Int26_6) Segment {
|
|
||||||
return Segment{
|
|
||||||
Op: SegmentOpLineTo,
|
|
||||||
Args: [3]fixed.Point26_6{pt(xa, ya)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func quadTo(xa, ya, xb, yb fixed.Int26_6) Segment {
|
|
||||||
return Segment{
|
|
||||||
Op: SegmentOpQuadTo,
|
|
||||||
Args: [3]fixed.Point26_6{pt(xa, ya), pt(xb, yb)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func cubeTo(xa, ya, xb, yb, xc, yc fixed.Int26_6) Segment {
|
|
||||||
return Segment{
|
|
||||||
Op: SegmentOpCubeTo,
|
|
||||||
Args: [3]fixed.Point26_6{pt(xa, ya), pt(xb, yb), pt(xc, yc)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func translate(dx, dy fixed.Int26_6, s Segment) Segment {
|
|
||||||
translateArgs(&s.Args, dx, dy)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func transform(txx, txy, tyx, tyy int16, dx, dy fixed.Int26_6, s Segment) Segment {
|
|
||||||
transformArgs(&s.Args, txx, txy, tyx, tyy, dx, dy)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkSegmentsEqual(got, want []Segment) error {
|
|
||||||
// Flip got's Y axis. The test cases' coordinates are given with the Y axis
|
|
||||||
// increasing up, as that is what the ttx tool gives, and is the model for
|
|
||||||
// the underlying font format. The Go API returns coordinates with the Y
|
|
||||||
// axis increasing down, the same as the standard graphics libraries.
|
|
||||||
for i := range got {
|
|
||||||
for j := range got[i].Args {
|
|
||||||
got[i].Args[j].Y *= -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that every contour is closed.
|
|
||||||
if len(got) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if got[0].Op != SegmentOpMoveTo {
|
|
||||||
return fmt.Errorf("segments do not start with a moveTo")
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
first, last fixed.Point26_6
|
|
||||||
firstI int
|
|
||||||
)
|
|
||||||
checkClosed := func(lastI int) error {
|
|
||||||
if first != last {
|
|
||||||
return fmt.Errorf("segments[%d:%d] not closed:\nfirst %v\nlast %v", firstI, lastI, first, last)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for i, g := range got {
|
|
||||||
switch g.Op {
|
|
||||||
case SegmentOpMoveTo:
|
|
||||||
if i != 0 {
|
|
||||||
if err := checkClosed(i); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
firstI, first, last = i, g.Args[0], g.Args[0]
|
|
||||||
case SegmentOpLineTo:
|
|
||||||
last = g.Args[0]
|
|
||||||
case SegmentOpQuadTo:
|
|
||||||
last = g.Args[1]
|
|
||||||
case SegmentOpCubeTo:
|
|
||||||
last = g.Args[2]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return checkClosed(len(got))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTrueTypeParse(t *testing.T) {
|
|
||||||
f, err := Parse(goregular.TTF)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Parse: %v", err)
|
|
||||||
}
|
|
||||||
testTrueType(t, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTrueTypeParseReaderAt(t *testing.T) {
|
|
||||||
f, err := ParseReaderAt(bytes.NewReader(goregular.TTF))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ParseReaderAt: %v", err)
|
|
||||||
}
|
|
||||||
testTrueType(t, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testTrueType(t *testing.T, f *Font) {
|
|
||||||
if got, want := f.UnitsPerEm(), Units(2048); got != want {
|
|
||||||
t.Errorf("UnitsPerEm: got %d, want %d", got, want)
|
|
||||||
}
|
|
||||||
// The exact number of glyphs in goregular.TTF can vary, and future
|
|
||||||
// versions may add more glyphs, but https://blog.golang.org/go-fonts says
|
|
||||||
// that "The WGL4 character set... [has] more than 650 characters in all.
|
|
||||||
if got, want := f.NumGlyphs(), 650; got <= want {
|
|
||||||
t.Errorf("NumGlyphs: got %d, want > %d", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fontData(name string) []byte {
|
|
||||||
switch name {
|
|
||||||
case "gobold":
|
|
||||||
return gobold.TTF
|
|
||||||
case "gomono":
|
|
||||||
return gomono.TTF
|
|
||||||
case "goregular":
|
|
||||||
return goregular.TTF
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBounds(t *testing.T) {
|
|
||||||
testCases := map[string]fixed.Rectangle26_6{
|
|
||||||
"gobold": {
|
|
||||||
Min: fixed.Point26_6{
|
|
||||||
X: -452,
|
|
||||||
Y: -2193,
|
|
||||||
},
|
|
||||||
Max: fixed.Point26_6{
|
|
||||||
X: 2190,
|
|
||||||
Y: 432,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"gomono": {
|
|
||||||
Min: fixed.Point26_6{
|
|
||||||
X: 0,
|
|
||||||
Y: -2227,
|
|
||||||
},
|
|
||||||
Max: fixed.Point26_6{
|
|
||||||
X: 1229,
|
|
||||||
Y: 432,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"goregular": {
|
|
||||||
Min: fixed.Point26_6{
|
|
||||||
X: -440,
|
|
||||||
Y: -2118,
|
|
||||||
},
|
|
||||||
Max: fixed.Point26_6{
|
|
||||||
X: 2160,
|
|
||||||
Y: 543,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var b Buffer
|
|
||||||
for name, want := range testCases {
|
|
||||||
f, err := Parse(fontData(name))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Parse(%q): %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ppem := fixed.Int26_6(f.UnitsPerEm())
|
|
||||||
|
|
||||||
got, err := f.Bounds(&b, ppem, font.HintingNone)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("name=%q: Bounds: %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("name=%q: Bounds: got %v, want %v", name, got, want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMetrics(t *testing.T) {
|
|
||||||
cmapFont, err := ioutil.ReadFile(filepath.FromSlash("../testdata/cmapTest.ttf"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
testCases := map[string]struct {
|
|
||||||
font []byte
|
|
||||||
want font.Metrics
|
|
||||||
}{
|
|
||||||
"goregular": {goregular.TTF, font.Metrics{Height: 2048, Ascent: 1935, Descent: 432}},
|
|
||||||
// cmapTest.ttf has a non-zero lineGap.
|
|
||||||
"cmapTest": {cmapFont, font.Metrics{Height: 2232, Ascent: 1365, Descent: 0}},
|
|
||||||
}
|
|
||||||
var b Buffer
|
|
||||||
for name, tc := range testCases {
|
|
||||||
f, err := Parse(tc.font)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("name=%q: Parse: %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ppem := fixed.Int26_6(f.UnitsPerEm())
|
|
||||||
|
|
||||||
got, err := f.Metrics(&b, ppem, font.HintingNone)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("name=%q: Metrics: %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if got != tc.want {
|
|
||||||
t.Errorf("name=%q: Metrics: got %v, want %v", name, got, tc.want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGlyphAdvance(t *testing.T) {
|
|
||||||
testCases := map[string][]struct {
|
|
||||||
r rune
|
|
||||||
want fixed.Int26_6
|
|
||||||
}{
|
|
||||||
"gobold": {
|
|
||||||
{' ', 569},
|
|
||||||
{'A', 1479},
|
|
||||||
{'Á', 1479},
|
|
||||||
{'Æ', 2048},
|
|
||||||
{'i', 592},
|
|
||||||
{'x', 1139},
|
|
||||||
},
|
|
||||||
"gomono": {
|
|
||||||
{' ', 1229},
|
|
||||||
{'A', 1229},
|
|
||||||
{'Á', 1229},
|
|
||||||
{'Æ', 1229},
|
|
||||||
{'i', 1229},
|
|
||||||
{'x', 1229},
|
|
||||||
},
|
|
||||||
"goregular": {
|
|
||||||
{' ', 569},
|
|
||||||
{'A', 1366},
|
|
||||||
{'Á', 1366},
|
|
||||||
{'Æ', 2048},
|
|
||||||
{'i', 505},
|
|
||||||
{'x', 1024},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var b Buffer
|
|
||||||
for name, testCases1 := range testCases {
|
|
||||||
f, err := Parse(fontData(name))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Parse(%q): %v", name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ppem := fixed.Int26_6(f.UnitsPerEm())
|
|
||||||
|
|
||||||
for _, tc := range testCases1 {
|
|
||||||
x, err := f.GlyphIndex(&b, tc.r)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("name=%q, r=%q: GlyphIndex: %v", name, tc.r, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
got, err := f.GlyphAdvance(&b, x, ppem, font.HintingNone)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("name=%q, r=%q: GlyphAdvance: %v", name, tc.r, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if got != tc.want {
|
|
||||||
t.Errorf("name=%q, r=%q: GlyphAdvance: got %d, want %d", name, tc.r, got, tc.want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGoRegularGlyphIndex(t *testing.T) {
|
|
||||||
f, err := Parse(goregular.TTF)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Parse: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
r rune
|
|
||||||
want GlyphIndex
|
|
||||||
}{
|
|
||||||
// Glyphs that aren't present in Go Regular.
|
|
||||||
{'\u001f', 0}, // U+001F <control>
|
|
||||||
{'\u0200', 0}, // U+0200 LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
|
|
||||||
{'\u2000', 0}, // U+2000 EN QUAD
|
|
||||||
|
|
||||||
// The want values below can be verified by running the ttx tool on
|
|
||||||
// Go-Regular.ttf.
|
|
||||||
//
|
|
||||||
// The actual values are ad hoc, and result from whatever tools the
|
|
||||||
// Bigelow & Holmes type foundry used and the order in which they
|
|
||||||
// crafted the glyphs. They may change over time as newer versions of
|
|
||||||
// the font are released.
|
|
||||||
|
|
||||||
{'\u0020', 3}, // U+0020 SPACE
|
|
||||||
{'\u0021', 4}, // U+0021 EXCLAMATION MARK
|
|
||||||
{'\u0022', 5}, // U+0022 QUOTATION MARK
|
|
||||||
{'\u0023', 6}, // U+0023 NUMBER SIGN
|
|
||||||
{'\u0024', 7}, // U+0024 DOLLAR SIGN
|
|
||||||
{'\u0025', 8}, // U+0025 PERCENT SIGN
|
|
||||||
{'\u0026', 9}, // U+0026 AMPERSAND
|
|
||||||
{'\u0027', 10}, // U+0027 APOSTROPHE
|
|
||||||
|
|
||||||
{'\u03bd', 396}, // U+03BD GREEK SMALL LETTER NU
|
|
||||||
{'\u03be', 397}, // U+03BE GREEK SMALL LETTER XI
|
|
||||||
{'\u03bf', 398}, // U+03BF GREEK SMALL LETTER OMICRON
|
|
||||||
{'\u03c0', 399}, // U+03C0 GREEK SMALL LETTER PI
|
|
||||||
{'\u03c1', 400}, // U+03C1 GREEK SMALL LETTER RHO
|
|
||||||
{'\u03c2', 401}, // 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.
|
|
||||||
// https://fontforge.github.io/validation.html says that "All paths must be
|
|
||||||
// drawn in a consistent direction. Clockwise for external paths,
|
|
||||||
// anti-clockwise for internal paths. (Actually PostScript requires the
|
|
||||||
// exact opposite, but FontForge reverses PostScript contours when it loads
|
|
||||||
// them so that everything is consistant internally -- and reverses them
|
|
||||||
// again when it saves them, of course)."
|
|
||||||
//
|
|
||||||
// The .notdef glyph isn't explicitly in the SFD file, but for some unknown
|
|
||||||
// reason, FontForge generates it in the OpenType/CFF file.
|
|
||||||
wants := [][]Segment{{
|
|
||||||
// .notdef
|
|
||||||
// - contour #0
|
|
||||||
moveTo(50, 0),
|
|
||||||
lineTo(450, 0),
|
|
||||||
lineTo(450, 533),
|
|
||||||
lineTo(50, 533),
|
|
||||||
lineTo(50, 0),
|
|
||||||
// - contour #1
|
|
||||||
moveTo(100, 50),
|
|
||||||
lineTo(100, 483),
|
|
||||||
lineTo(400, 483),
|
|
||||||
lineTo(400, 50),
|
|
||||||
lineTo(100, 50),
|
|
||||||
}, {
|
|
||||||
// zero
|
|
||||||
// - contour #0
|
|
||||||
moveTo(300, 700),
|
|
||||||
cubeTo(380, 700, 420, 580, 420, 500),
|
|
||||||
cubeTo(420, 350, 390, 100, 300, 100),
|
|
||||||
cubeTo(220, 100, 180, 220, 180, 300),
|
|
||||||
cubeTo(180, 450, 210, 700, 300, 700),
|
|
||||||
// - contour #1
|
|
||||||
moveTo(300, 800),
|
|
||||||
cubeTo(200, 800, 100, 580, 100, 400),
|
|
||||||
cubeTo(100, 220, 200, 0, 300, 0),
|
|
||||||
cubeTo(400, 0, 500, 220, 500, 400),
|
|
||||||
cubeTo(500, 580, 400, 800, 300, 800),
|
|
||||||
}, {
|
|
||||||
// one
|
|
||||||
// - contour #0
|
|
||||||
moveTo(100, 0),
|
|
||||||
lineTo(300, 0),
|
|
||||||
lineTo(300, 800),
|
|
||||||
lineTo(100, 800),
|
|
||||||
lineTo(100, 0),
|
|
||||||
}, {
|
|
||||||
// Q
|
|
||||||
// - contour #0
|
|
||||||
moveTo(657, 237),
|
|
||||||
lineTo(289, 387),
|
|
||||||
lineTo(519, 615),
|
|
||||||
lineTo(657, 237),
|
|
||||||
// - contour #1
|
|
||||||
moveTo(792, 169),
|
|
||||||
cubeTo(867, 263, 926, 502, 791, 665),
|
|
||||||
cubeTo(645, 840, 380, 831, 228, 673),
|
|
||||||
cubeTo(71, 509, 110, 231, 242, 93),
|
|
||||||
cubeTo(369, -39, 641, 18, 722, 93),
|
|
||||||
lineTo(802, 3),
|
|
||||||
lineTo(864, 83),
|
|
||||||
lineTo(792, 169),
|
|
||||||
}, {
|
|
||||||
// uni4E2D
|
|
||||||
// - contour #0
|
|
||||||
moveTo(141, 520),
|
|
||||||
lineTo(137, 356),
|
|
||||||
lineTo(245, 400),
|
|
||||||
lineTo(331, 26),
|
|
||||||
lineTo(355, 414),
|
|
||||||
lineTo(463, 434),
|
|
||||||
lineTo(453, 620),
|
|
||||||
lineTo(341, 592),
|
|
||||||
lineTo(331, 758),
|
|
||||||
lineTo(243, 752),
|
|
||||||
lineTo(235, 562),
|
|
||||||
lineTo(141, 520),
|
|
||||||
}}
|
|
||||||
|
|
||||||
testSegments(t, "CFFTest.otf", wants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTrueTypeSegments(t *testing.T) {
|
|
||||||
// wants' vectors correspond 1-to-1 to what's in the glyfTest.sfd file,
|
|
||||||
// although FontForge's SFD format stores quadratic Bézier curves as cubics
|
|
||||||
// with duplicated off-curve points. quadTo(bx, by, cx, cy) is stored as
|
|
||||||
// "bx by bx by cx cy".
|
|
||||||
//
|
|
||||||
// The .notdef, .null and nonmarkingreturn glyphs aren't explicitly in the
|
|
||||||
// SFD file, but for some unknown reason, FontForge generates them in the
|
|
||||||
// TrueType file.
|
|
||||||
wants := [][]Segment{{
|
|
||||||
// .notdef
|
|
||||||
// - contour #0
|
|
||||||
moveTo(68, 0),
|
|
||||||
lineTo(68, 1365),
|
|
||||||
lineTo(612, 1365),
|
|
||||||
lineTo(612, 0),
|
|
||||||
lineTo(68, 0),
|
|
||||||
// - contour #1
|
|
||||||
moveTo(136, 68),
|
|
||||||
lineTo(544, 68),
|
|
||||||
lineTo(544, 1297),
|
|
||||||
lineTo(136, 1297),
|
|
||||||
lineTo(136, 68),
|
|
||||||
}, {
|
|
||||||
// .null
|
|
||||||
// Empty glyph.
|
|
||||||
}, {
|
|
||||||
// nonmarkingreturn
|
|
||||||
// Empty glyph.
|
|
||||||
}, {
|
|
||||||
// zero
|
|
||||||
// - contour #0
|
|
||||||
moveTo(614, 1434),
|
|
||||||
quadTo(369, 1434, 369, 614),
|
|
||||||
quadTo(369, 471, 435, 338),
|
|
||||||
quadTo(502, 205, 614, 205),
|
|
||||||
quadTo(860, 205, 860, 1024),
|
|
||||||
quadTo(860, 1167, 793, 1300),
|
|
||||||
quadTo(727, 1434, 614, 1434),
|
|
||||||
// - contour #1
|
|
||||||
moveTo(614, 1638),
|
|
||||||
quadTo(1024, 1638, 1024, 819),
|
|
||||||
quadTo(1024, 0, 614, 0),
|
|
||||||
quadTo(205, 0, 205, 819),
|
|
||||||
quadTo(205, 1638, 614, 1638),
|
|
||||||
}, {
|
|
||||||
// one
|
|
||||||
// - contour #0
|
|
||||||
moveTo(205, 0),
|
|
||||||
lineTo(205, 1638),
|
|
||||||
lineTo(614, 1638),
|
|
||||||
lineTo(614, 0),
|
|
||||||
lineTo(205, 0),
|
|
||||||
}, {
|
|
||||||
// five
|
|
||||||
// - contour #0
|
|
||||||
moveTo(0, 0),
|
|
||||||
lineTo(0, 100),
|
|
||||||
lineTo(400, 100),
|
|
||||||
lineTo(400, 0),
|
|
||||||
lineTo(0, 0),
|
|
||||||
}, {
|
|
||||||
// six
|
|
||||||
// - contour #0
|
|
||||||
moveTo(0, 0),
|
|
||||||
lineTo(0, 100),
|
|
||||||
lineTo(400, 100),
|
|
||||||
lineTo(400, 0),
|
|
||||||
lineTo(0, 0),
|
|
||||||
// - contour #1
|
|
||||||
translate(111, 234, moveTo(205, 0)),
|
|
||||||
translate(111, 234, lineTo(205, 1638)),
|
|
||||||
translate(111, 234, lineTo(614, 1638)),
|
|
||||||
translate(111, 234, lineTo(614, 0)),
|
|
||||||
translate(111, 234, lineTo(205, 0)),
|
|
||||||
}, {
|
|
||||||
// seven
|
|
||||||
// - contour #0
|
|
||||||
moveTo(0, 0),
|
|
||||||
lineTo(0, 100),
|
|
||||||
lineTo(400, 100),
|
|
||||||
lineTo(400, 0),
|
|
||||||
lineTo(0, 0),
|
|
||||||
// - contour #1
|
|
||||||
transform(1<<13, 0, 0, 1<<13, 56, 117, moveTo(205, 0)),
|
|
||||||
transform(1<<13, 0, 0, 1<<13, 56, 117, lineTo(205, 1638)),
|
|
||||||
transform(1<<13, 0, 0, 1<<13, 56, 117, lineTo(614, 1638)),
|
|
||||||
transform(1<<13, 0, 0, 1<<13, 56, 117, lineTo(614, 0)),
|
|
||||||
transform(1<<13, 0, 0, 1<<13, 56, 117, lineTo(205, 0)),
|
|
||||||
}, {
|
|
||||||
// eight
|
|
||||||
// - contour #0
|
|
||||||
moveTo(0, 0),
|
|
||||||
lineTo(0, 100),
|
|
||||||
lineTo(400, 100),
|
|
||||||
lineTo(400, 0),
|
|
||||||
lineTo(0, 0),
|
|
||||||
// - contour #1
|
|
||||||
transform(3<<13, 0, 0, 1<<13, 56, 117, moveTo(205, 0)),
|
|
||||||
transform(3<<13, 0, 0, 1<<13, 56, 117, lineTo(205, 1638)),
|
|
||||||
transform(3<<13, 0, 0, 1<<13, 56, 117, lineTo(614, 1638)),
|
|
||||||
transform(3<<13, 0, 0, 1<<13, 56, 117, lineTo(614, 0)),
|
|
||||||
transform(3<<13, 0, 0, 1<<13, 56, 117, lineTo(205, 0)),
|
|
||||||
}, {
|
|
||||||
// nine
|
|
||||||
// - contour #0
|
|
||||||
moveTo(0, 0),
|
|
||||||
lineTo(0, 100),
|
|
||||||
lineTo(400, 100),
|
|
||||||
lineTo(400, 0),
|
|
||||||
lineTo(0, 0),
|
|
||||||
// - contour #1
|
|
||||||
transform(22381, 8192, 5996, 14188, 237, 258, moveTo(205, 0)),
|
|
||||||
transform(22381, 8192, 5996, 14188, 237, 258, lineTo(205, 1638)),
|
|
||||||
transform(22381, 8192, 5996, 14188, 237, 258, lineTo(614, 1638)),
|
|
||||||
transform(22381, 8192, 5996, 14188, 237, 258, lineTo(614, 0)),
|
|
||||||
transform(22381, 8192, 5996, 14188, 237, 258, lineTo(205, 0)),
|
|
||||||
}}
|
|
||||||
|
|
||||||
testSegments(t, "glyfTest.ttf", wants)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testSegments(t *testing.T, filename string, wants [][]Segment) {
|
|
||||||
data, err := ioutil.ReadFile(filepath.FromSlash("../testdata/" + filename))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadFile: %v", err)
|
|
||||||
}
|
|
||||||
f, err := Parse(data)
|
|
||||||
if err != nil {
|
|
||||||
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
|
|
||||||
for i, want := range wants {
|
|
||||||
got, err := f.LoadGlyph(&b, GlyphIndex(i), ppem, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("i=%d: LoadGlyph: %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := checkSegmentsEqual(got, want); err != nil {
|
|
||||||
t.Errorf("i=%d: %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := f.LoadGlyph(nil, 0xffff, ppem, nil); err != ErrNotFound {
|
|
||||||
t.Errorf("LoadGlyph(..., 0xffff, ...):\ngot %v\nwant %v", err, ErrNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
name, err := f.Name(nil, NameIDFamily)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Name: %v", err)
|
|
||||||
} else if want := filename[:len(filename)-len(".ttf")]; name != want {
|
|
||||||
t.Errorf("Name:\ngot %q\nwant %q", name, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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', "uni0000"},
|
|
||||||
{'!', "exclam"},
|
|
||||||
{'A', "A"},
|
|
||||||
{'{', "braceleft"},
|
|
||||||
{'\u00c4', "Adieresis"}, // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
|
|
||||||
{'\u2020', "dagger"}, // U+2020 DAGGER
|
|
||||||
{'\u2660', "spade"}, // U+2660 BLACK SPADE SUIT
|
|
||||||
{'\uf800', "gopher"}, // U+F800 <Private Use>
|
|
||||||
{'\ufffe', ".notdef"}, // Not in the Go Regular font, so GlyphIndex returns (0, nil).
|
|
||||||
}
|
|
||||||
|
|
||||||
var b Buffer
|
|
||||||
for _, tc := range testCases {
|
|
||||||
x, err := f.GlyphIndex(&b, tc.r)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("r=%q: GlyphIndex: %v", tc.r, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
got, err := f.GlyphName(&b, x)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("r=%q: GlyphName: %v", tc.r, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if got != tc.want {
|
|
||||||
t.Errorf("r=%q: got %q, want %q", tc.r, got, tc.want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuiltInPostNames(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
x GlyphIndex
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{0, ".notdef"},
|
|
||||||
{1, ".null"},
|
|
||||||
{2, "nonmarkingreturn"},
|
|
||||||
{13, "asterisk"},
|
|
||||||
{36, "A"},
|
|
||||||
{93, "z"},
|
|
||||||
{123, "ocircumflex"},
|
|
||||||
{202, "Edieresis"},
|
|
||||||
{255, "Ccaron"},
|
|
||||||
{256, "ccaron"},
|
|
||||||
{257, "dcroat"},
|
|
||||||
{258, ""},
|
|
||||||
{999, ""},
|
|
||||||
{0xffff, ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
if tc.x >= numBuiltInPostNames {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i := builtInPostNamesOffsets[tc.x+0]
|
|
||||||
j := builtInPostNamesOffsets[tc.x+1]
|
|
||||||
got := builtInPostNamesData[i:j]
|
|
||||||
if got != tc.want {
|
|
||||||
t.Errorf("x=%d: got %q, want %q", tc.x, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
572
vendor/golang.org/x/image/font/sfnt/truetype.go
generated
vendored
572
vendor/golang.org/x/image/font/sfnt/truetype.go
generated
vendored
@ -1,572 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Flags for simple (non-compound) glyphs.
|
|
||||||
//
|
|
||||||
// See https://www.microsoft.com/typography/OTSPEC/glyf.htm
|
|
||||||
const (
|
|
||||||
flagOnCurve = 1 << 0 // 0x0001
|
|
||||||
flagXShortVector = 1 << 1 // 0x0002
|
|
||||||
flagYShortVector = 1 << 2 // 0x0004
|
|
||||||
flagRepeat = 1 << 3 // 0x0008
|
|
||||||
|
|
||||||
// The same flag bits are overloaded to have two meanings, dependent on the
|
|
||||||
// value of the flag{X,Y}ShortVector bits.
|
|
||||||
flagPositiveXShortVector = 1 << 4 // 0x0010
|
|
||||||
flagThisXIsSame = 1 << 4 // 0x0010
|
|
||||||
flagPositiveYShortVector = 1 << 5 // 0x0020
|
|
||||||
flagThisYIsSame = 1 << 5 // 0x0020
|
|
||||||
)
|
|
||||||
|
|
||||||
// Flags for compound glyphs.
|
|
||||||
//
|
|
||||||
// See https://www.microsoft.com/typography/OTSPEC/glyf.htm
|
|
||||||
const (
|
|
||||||
flagArg1And2AreWords = 1 << 0 // 0x0001
|
|
||||||
flagArgsAreXYValues = 1 << 1 // 0x0002
|
|
||||||
flagRoundXYToGrid = 1 << 2 // 0x0004
|
|
||||||
flagWeHaveAScale = 1 << 3 // 0x0008
|
|
||||||
flagReserved4 = 1 << 4 // 0x0010
|
|
||||||
flagMoreComponents = 1 << 5 // 0x0020
|
|
||||||
flagWeHaveAnXAndYScale = 1 << 6 // 0x0040
|
|
||||||
flagWeHaveATwoByTwo = 1 << 7 // 0x0080
|
|
||||||
flagWeHaveInstructions = 1 << 8 // 0x0100
|
|
||||||
flagUseMyMetrics = 1 << 9 // 0x0200
|
|
||||||
flagOverlapCompound = 1 << 10 // 0x0400
|
|
||||||
flagScaledComponentOffset = 1 << 11 // 0x0800
|
|
||||||
flagUnscaledComponentOffset = 1 << 12 // 0x1000
|
|
||||||
)
|
|
||||||
|
|
||||||
func midPoint(p, q fixed.Point26_6) fixed.Point26_6 {
|
|
||||||
return fixed.Point26_6{
|
|
||||||
X: (p.X + q.X) / 2,
|
|
||||||
Y: (p.Y + q.Y) / 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseLoca(src *source, loca table, glyfOffset uint32, indexToLocFormat bool, numGlyphs int32) (locations []uint32, err error) {
|
|
||||||
if indexToLocFormat {
|
|
||||||
if loca.length != 4*uint32(numGlyphs+1) {
|
|
||||||
return nil, errInvalidLocaTable
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if loca.length != 2*uint32(numGlyphs+1) {
|
|
||||||
return nil, errInvalidLocaTable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
locations = make([]uint32, numGlyphs+1)
|
|
||||||
buf, err := src.view(nil, int(loca.offset), int(loca.length))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if indexToLocFormat {
|
|
||||||
for i := range locations {
|
|
||||||
locations[i] = 1*uint32(u32(buf[4*i:])) + glyfOffset
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i := range locations {
|
|
||||||
locations[i] = 2*uint32(u16(buf[2*i:])) + glyfOffset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return locations, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://www.microsoft.com/typography/OTSPEC/glyf.htm says that "Each
|
|
||||||
// glyph begins with the following [10 byte] header".
|
|
||||||
const glyfHeaderLen = 10
|
|
||||||
|
|
||||||
func loadGlyf(f *Font, b *Buffer, x GlyphIndex, stackBottom, recursionDepth uint32) error {
|
|
||||||
data, _, _, err := f.viewGlyphData(b, x)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(data) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if len(data) < glyfHeaderLen {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
index := glyfHeaderLen
|
|
||||||
|
|
||||||
numContours, numPoints := int16(u16(data)), 0
|
|
||||||
switch {
|
|
||||||
case numContours == -1:
|
|
||||||
// We have a compound glyph. No-op.
|
|
||||||
case numContours == 0:
|
|
||||||
return nil
|
|
||||||
case numContours > 0:
|
|
||||||
// We have a simple (non-compound) glyph.
|
|
||||||
index += 2 * int(numContours)
|
|
||||||
if index > len(data) {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
// The +1 for numPoints is because the value in the file format is
|
|
||||||
// inclusive, but Go's slice[:index] semantics are exclusive.
|
|
||||||
numPoints = 1 + int(u16(data[index-2:]))
|
|
||||||
default:
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
|
|
||||||
if numContours < 0 {
|
|
||||||
return loadCompoundGlyf(f, b, data[glyfHeaderLen:], stackBottom, recursionDepth)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the hinting instructions.
|
|
||||||
index += 2
|
|
||||||
if index > len(data) {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
hintsLength := int(u16(data[index-2:]))
|
|
||||||
index += hintsLength
|
|
||||||
if index > len(data) {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 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 coordinates and the y coordinates each start.
|
|
||||||
flagIndex := int32(index)
|
|
||||||
xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
|
|
||||||
if !ok {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
|
|
||||||
// The second pass decodes each (flags, x, y) tuple in row order.
|
|
||||||
g := glyfIter{
|
|
||||||
data: data,
|
|
||||||
flagIndex: flagIndex,
|
|
||||||
xIndex: xIndex,
|
|
||||||
yIndex: yIndex,
|
|
||||||
endIndex: glyfHeaderLen,
|
|
||||||
// The -1 is because the contour-end index in the file format is
|
|
||||||
// inclusive, but Go's slice[:index] semantics are exclusive.
|
|
||||||
prevEnd: -1,
|
|
||||||
numContours: int32(numContours),
|
|
||||||
}
|
|
||||||
for g.nextContour() {
|
|
||||||
for g.nextSegment() {
|
|
||||||
b.segments = append(b.segments, g.seg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return g.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func findXYIndexes(data []byte, index, numPoints int) (xIndex, yIndex int32, ok bool) {
|
|
||||||
xDataLen := 0
|
|
||||||
yDataLen := 0
|
|
||||||
for i := 0; ; {
|
|
||||||
if i > numPoints {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
if i == numPoints {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
repeatCount := 1
|
|
||||||
if index >= len(data) {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
flag := data[index]
|
|
||||||
index++
|
|
||||||
if flag&flagRepeat != 0 {
|
|
||||||
if index >= len(data) {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
repeatCount += int(data[index])
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
|
|
||||||
xSize := 0
|
|
||||||
if flag&flagXShortVector != 0 {
|
|
||||||
xSize = 1
|
|
||||||
} else if flag&flagThisXIsSame == 0 {
|
|
||||||
xSize = 2
|
|
||||||
}
|
|
||||||
xDataLen += xSize * repeatCount
|
|
||||||
|
|
||||||
ySize := 0
|
|
||||||
if flag&flagYShortVector != 0 {
|
|
||||||
ySize = 1
|
|
||||||
} else if flag&flagThisYIsSame == 0 {
|
|
||||||
ySize = 2
|
|
||||||
}
|
|
||||||
yDataLen += ySize * repeatCount
|
|
||||||
|
|
||||||
i += repeatCount
|
|
||||||
}
|
|
||||||
if index+xDataLen+yDataLen > len(data) {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
return int32(index), int32(index + xDataLen), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadCompoundGlyf(f *Font, b *Buffer, data []byte, stackBottom, recursionDepth uint32) error {
|
|
||||||
if recursionDepth++; recursionDepth == maxCompoundRecursionDepth {
|
|
||||||
return errUnsupportedCompoundGlyph
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and process the compound glyph's components. They are two separate
|
|
||||||
// for loops, since reading parses the elements of the data slice, and
|
|
||||||
// processing can overwrite the backing array.
|
|
||||||
|
|
||||||
stackTop := stackBottom
|
|
||||||
for {
|
|
||||||
if stackTop >= maxCompoundStackSize {
|
|
||||||
return errUnsupportedCompoundGlyph
|
|
||||||
}
|
|
||||||
elem := &b.compoundStack[stackTop]
|
|
||||||
stackTop++
|
|
||||||
|
|
||||||
if len(data) < 4 {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
flags := u16(data)
|
|
||||||
elem.glyphIndex = GlyphIndex(u16(data[2:]))
|
|
||||||
if flags&flagArg1And2AreWords == 0 {
|
|
||||||
if len(data) < 6 {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
elem.dx = int16(int8(data[4]))
|
|
||||||
elem.dy = int16(int8(data[5]))
|
|
||||||
data = data[6:]
|
|
||||||
} else {
|
|
||||||
if len(data) < 8 {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
elem.dx = int16(u16(data[4:]))
|
|
||||||
elem.dy = int16(u16(data[6:]))
|
|
||||||
data = data[8:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if flags&flagArgsAreXYValues == 0 {
|
|
||||||
return errUnsupportedCompoundGlyph
|
|
||||||
}
|
|
||||||
elem.hasTransform = flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0
|
|
||||||
if elem.hasTransform {
|
|
||||||
switch {
|
|
||||||
case flags&flagWeHaveAScale != 0:
|
|
||||||
if len(data) < 2 {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
elem.transformXX = int16(u16(data))
|
|
||||||
elem.transformXY = 0
|
|
||||||
elem.transformYX = 0
|
|
||||||
elem.transformYY = elem.transformXX
|
|
||||||
data = data[2:]
|
|
||||||
case flags&flagWeHaveAnXAndYScale != 0:
|
|
||||||
if len(data) < 4 {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
elem.transformXX = int16(u16(data[0:]))
|
|
||||||
elem.transformXY = 0
|
|
||||||
elem.transformYX = 0
|
|
||||||
elem.transformYY = int16(u16(data[2:]))
|
|
||||||
data = data[4:]
|
|
||||||
case flags&flagWeHaveATwoByTwo != 0:
|
|
||||||
if len(data) < 8 {
|
|
||||||
return errInvalidGlyphData
|
|
||||||
}
|
|
||||||
elem.transformXX = int16(u16(data[0:]))
|
|
||||||
elem.transformXY = int16(u16(data[2:]))
|
|
||||||
elem.transformYX = int16(u16(data[4:]))
|
|
||||||
elem.transformYY = int16(u16(data[6:]))
|
|
||||||
data = data[8:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if flags&flagMoreComponents == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// To support hinting, we'd have to save the remaining bytes in data here
|
|
||||||
// and interpret them after the for loop below, since that for loop's
|
|
||||||
// loadGlyf calls can overwrite the backing array.
|
|
||||||
|
|
||||||
for i := stackBottom; i < stackTop; i++ {
|
|
||||||
elem := &b.compoundStack[i]
|
|
||||||
base := len(b.segments)
|
|
||||||
if err := loadGlyf(f, b, elem.glyphIndex, stackTop, recursionDepth); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dx, dy := fixed.Int26_6(elem.dx), fixed.Int26_6(elem.dy)
|
|
||||||
segs := b.segments[base:]
|
|
||||||
if elem.hasTransform {
|
|
||||||
txx := elem.transformXX
|
|
||||||
txy := elem.transformXY
|
|
||||||
tyx := elem.transformYX
|
|
||||||
tyy := elem.transformYY
|
|
||||||
for j := range segs {
|
|
||||||
transformArgs(&segs[j].Args, txx, txy, tyx, tyy, dx, dy)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for j := range segs {
|
|
||||||
translateArgs(&segs[j].Args, dx, dy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type glyfIter struct {
|
|
||||||
data []byte
|
|
||||||
err error
|
|
||||||
|
|
||||||
// Various indices into the data slice. See the "Decoding those points in
|
|
||||||
// row order" comment above.
|
|
||||||
flagIndex int32
|
|
||||||
xIndex int32
|
|
||||||
yIndex int32
|
|
||||||
|
|
||||||
// endIndex points to the uint16 that is the inclusive point index of the
|
|
||||||
// current contour's end. prevEnd is the previous contour's end.
|
|
||||||
endIndex int32
|
|
||||||
prevEnd int32
|
|
||||||
|
|
||||||
// c and p count the current contour and point, up to numContours and
|
|
||||||
// numPoints.
|
|
||||||
c, numContours int32
|
|
||||||
p, nPoints int32
|
|
||||||
|
|
||||||
// The next two groups of fields track points and segments. Points are what
|
|
||||||
// the underlying file format provides. Bézier curve segments are what the
|
|
||||||
// rasterizer consumes.
|
|
||||||
//
|
|
||||||
// Points are either on-curve or off-curve. Two consecutive on-curve points
|
|
||||||
// define a linear curve segment between them. N off-curve points between
|
|
||||||
// on-curve points define N quadratic curve segments. The TrueType glyf
|
|
||||||
// format does not use cubic curves. If N is greater than 1, some of these
|
|
||||||
// segment end points are implicit, the midpoint of two off-curve points.
|
|
||||||
// Given the points A, B1, B2, ..., BN, C, where A and C are on-curve and
|
|
||||||
// all the Bs are off-curve, the segments are:
|
|
||||||
//
|
|
||||||
// - A, B1, midpoint(B1, B2)
|
|
||||||
// - midpoint(B1, B2), B2, midpoint(B2, B3)
|
|
||||||
// - midpoint(B2, B3), B3, midpoint(B3, B4)
|
|
||||||
// - ...
|
|
||||||
// - midpoint(BN-1, BN), BN, C
|
|
||||||
//
|
|
||||||
// Note that the sequence of Bs may wrap around from the last point in the
|
|
||||||
// glyf data to the first. A and C may also be the same point (the only
|
|
||||||
// explicit on-curve point), or there may be no explicit on-curve points at
|
|
||||||
// all (but still implicit ones between explicit off-curve points).
|
|
||||||
|
|
||||||
// Points.
|
|
||||||
x, y int16
|
|
||||||
on bool
|
|
||||||
flag uint8
|
|
||||||
repeats uint8
|
|
||||||
|
|
||||||
// Segments.
|
|
||||||
closing bool
|
|
||||||
closed bool
|
|
||||||
firstOnCurveValid bool
|
|
||||||
firstOffCurveValid bool
|
|
||||||
lastOffCurveValid bool
|
|
||||||
firstOnCurve fixed.Point26_6
|
|
||||||
firstOffCurve fixed.Point26_6
|
|
||||||
lastOffCurve fixed.Point26_6
|
|
||||||
seg Segment
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *glyfIter) nextContour() (ok bool) {
|
|
||||||
if g.c == g.numContours {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
g.c++
|
|
||||||
|
|
||||||
end := int32(u16(g.data[g.endIndex:]))
|
|
||||||
g.endIndex += 2
|
|
||||||
if end <= g.prevEnd {
|
|
||||||
g.err = errInvalidGlyphData
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
g.nPoints = end - g.prevEnd
|
|
||||||
g.p = 0
|
|
||||||
g.prevEnd = end
|
|
||||||
|
|
||||||
g.closing = false
|
|
||||||
g.closed = false
|
|
||||||
g.firstOnCurveValid = false
|
|
||||||
g.firstOffCurveValid = false
|
|
||||||
g.lastOffCurveValid = false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *glyfIter) close() {
|
|
||||||
switch {
|
|
||||||
case !g.firstOffCurveValid && !g.lastOffCurveValid:
|
|
||||||
g.closed = true
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpLineTo,
|
|
||||||
Args: [3]fixed.Point26_6{g.firstOnCurve},
|
|
||||||
}
|
|
||||||
case !g.firstOffCurveValid && g.lastOffCurveValid:
|
|
||||||
g.closed = true
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpQuadTo,
|
|
||||||
Args: [3]fixed.Point26_6{g.lastOffCurve, g.firstOnCurve},
|
|
||||||
}
|
|
||||||
case g.firstOffCurveValid && !g.lastOffCurveValid:
|
|
||||||
g.closed = true
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpQuadTo,
|
|
||||||
Args: [3]fixed.Point26_6{g.firstOffCurve, g.firstOnCurve},
|
|
||||||
}
|
|
||||||
case g.firstOffCurveValid && g.lastOffCurveValid:
|
|
||||||
g.lastOffCurveValid = false
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpQuadTo,
|
|
||||||
Args: [3]fixed.Point26_6{
|
|
||||||
g.lastOffCurve,
|
|
||||||
midPoint(g.lastOffCurve, g.firstOffCurve),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *glyfIter) nextSegment() (ok bool) {
|
|
||||||
for !g.closed {
|
|
||||||
if g.closing || !g.nextPoint() {
|
|
||||||
g.closing = true
|
|
||||||
g.close()
|
|
||||||
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),
|
|
||||||
Y: fixed.Int26_6(g.y),
|
|
||||||
}
|
|
||||||
|
|
||||||
if !g.firstOnCurveValid {
|
|
||||||
if g.on {
|
|
||||||
g.firstOnCurve = p
|
|
||||||
g.firstOnCurveValid = true
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpMoveTo,
|
|
||||||
Args: [3]fixed.Point26_6{p},
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
} else if !g.firstOffCurveValid {
|
|
||||||
g.firstOffCurve = p
|
|
||||||
g.firstOffCurveValid = true
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
g.firstOnCurve = midPoint(g.firstOffCurve, p)
|
|
||||||
g.firstOnCurveValid = true
|
|
||||||
g.lastOffCurve = p
|
|
||||||
g.lastOffCurveValid = true
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpMoveTo,
|
|
||||||
Args: [3]fixed.Point26_6{g.firstOnCurve},
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if !g.lastOffCurveValid {
|
|
||||||
if !g.on {
|
|
||||||
g.lastOffCurve = p
|
|
||||||
g.lastOffCurveValid = true
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpLineTo,
|
|
||||||
Args: [3]fixed.Point26_6{p},
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if !g.on {
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpQuadTo,
|
|
||||||
Args: [3]fixed.Point26_6{
|
|
||||||
g.lastOffCurve,
|
|
||||||
midPoint(g.lastOffCurve, p),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.lastOffCurve = p
|
|
||||||
g.lastOffCurveValid = true
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
g.seg = Segment{
|
|
||||||
Op: SegmentOpQuadTo,
|
|
||||||
Args: [3]fixed.Point26_6{g.lastOffCurve, p},
|
|
||||||
}
|
|
||||||
g.lastOffCurveValid = false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *glyfIter) nextPoint() (ok bool) {
|
|
||||||
if g.p == g.nPoints {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
g.p++
|
|
||||||
|
|
||||||
if g.repeats > 0 {
|
|
||||||
g.repeats--
|
|
||||||
} else {
|
|
||||||
g.flag = g.data[g.flagIndex]
|
|
||||||
g.flagIndex++
|
|
||||||
if g.flag&flagRepeat != 0 {
|
|
||||||
g.repeats = g.data[g.flagIndex]
|
|
||||||
g.flagIndex++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.flag&flagXShortVector != 0 {
|
|
||||||
if g.flag&flagPositiveXShortVector != 0 {
|
|
||||||
g.x += int16(g.data[g.xIndex])
|
|
||||||
} else {
|
|
||||||
g.x -= int16(g.data[g.xIndex])
|
|
||||||
}
|
|
||||||
g.xIndex += 1
|
|
||||||
} else if g.flag&flagThisXIsSame == 0 {
|
|
||||||
g.x += int16(u16(g.data[g.xIndex:]))
|
|
||||||
g.xIndex += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.flag&flagYShortVector != 0 {
|
|
||||||
if g.flag&flagPositiveYShortVector != 0 {
|
|
||||||
g.y += int16(g.data[g.yIndex])
|
|
||||||
} else {
|
|
||||||
g.y -= int16(g.data[g.yIndex])
|
|
||||||
}
|
|
||||||
g.yIndex += 1
|
|
||||||
} else if g.flag&flagThisYIsSame == 0 {
|
|
||||||
g.y += int16(u16(g.data[g.yIndex:]))
|
|
||||||
g.yIndex += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
g.on = g.flag&flagOnCurve != 0
|
|
||||||
return true
|
|
||||||
}
|
|
BIN
vendor/golang.org/x/image/font/testdata/CFFTest.otf
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/CFFTest.otf
generated
vendored
Binary file not shown.
148
vendor/golang.org/x/image/font/testdata/CFFTest.sfd
generated
vendored
148
vendor/golang.org/x/image/font/testdata/CFFTest.sfd
generated
vendored
@ -1,148 +0,0 @@
|
|||||||
SplineFontDB: 3.0
|
|
||||||
FontName: CFFTest
|
|
||||||
FullName: CFFTest
|
|
||||||
FamilyName: CFFTest
|
|
||||||
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: -100
|
|
||||||
UnderlineWidth: 50
|
|
||||||
Ascent: 800
|
|
||||||
Descent: 200
|
|
||||||
LayerCount: 2
|
|
||||||
Layer: 0 0 "Back" 1
|
|
||||||
Layer: 1 0 "Fore" 0
|
|
||||||
XUID: [1021 367 888937226 7862908]
|
|
||||||
FSType: 8
|
|
||||||
OS2Version: 0
|
|
||||||
OS2_WeightWidthSlopeOnly: 0
|
|
||||||
OS2_UseTypoMetrics: 1
|
|
||||||
CreationTime: 1479626795
|
|
||||||
ModificationTime: 1481282599
|
|
||||||
PfmFamily: 17
|
|
||||||
TTFWeight: 400
|
|
||||||
TTFWidth: 5
|
|
||||||
LineGap: 90
|
|
||||||
VLineGap: 0
|
|
||||||
OS2TypoAscent: 0
|
|
||||||
OS2TypoAOffset: 1
|
|
||||||
OS2TypoDescent: 0
|
|
||||||
OS2TypoDOffset: 1
|
|
||||||
OS2TypoLinegap: 90
|
|
||||||
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: UnicodeBmp
|
|
||||||
UnicodeInterp: none
|
|
||||||
NameList: Adobe Glyph List
|
|
||||||
DisplaySize: -24
|
|
||||||
AntiAlias: 1
|
|
||||||
FitToEm: 1
|
|
||||||
WinInfo: 64 32 11
|
|
||||||
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: 65536 4
|
|
||||||
|
|
||||||
StartChar: zero
|
|
||||||
Encoding: 48 48 0
|
|
||||||
Width: 600
|
|
||||||
VWidth: 0
|
|
||||||
HStem: 0 100<248.223 341.575> 700 100<258.425 351.777>
|
|
||||||
VStem: 100 80<243.925 531.374> 420 80<268.627 556.075>
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
300 700 m 0
|
|
||||||
210 700 180 450 180 300 c 24
|
|
||||||
180 220 220 100 300 100 c 0
|
|
||||||
390 100 420 350 420 500 c 24
|
|
||||||
420 580 380 700 300 700 c 0
|
|
||||||
300 800 m 0
|
|
||||||
400 800 500 580 500 400 c 0
|
|
||||||
500 220 400 0 300 0 c 0
|
|
||||||
200 0 100 220 100 400 c 0
|
|
||||||
100 580 200 800 300 800 c 0
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: one
|
|
||||||
Encoding: 49 49 1
|
|
||||||
Width: 400
|
|
||||||
VWidth: 0
|
|
||||||
Flags: W
|
|
||||||
HStem: 0 21G<100 300>
|
|
||||||
VStem: 100 200<0 800>
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
100 0 m 25
|
|
||||||
100 800 l 25
|
|
||||||
300 800 l 29
|
|
||||||
300 0 l 29
|
|
||||||
100 0 l 25
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: uni4E2D
|
|
||||||
Encoding: 20013 20013 2
|
|
||||||
Width: 600
|
|
||||||
VWidth: 0
|
|
||||||
Flags: W
|
|
||||||
VStem: 245 86<641.8 752>
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
141 520 m 25
|
|
||||||
235 562 l 25
|
|
||||||
243 752 l 25
|
|
||||||
331 758 l 25
|
|
||||||
341 592 l 25
|
|
||||||
453 620 l 25
|
|
||||||
463 434 l 25
|
|
||||||
355 414 l 25
|
|
||||||
331 26 l 25
|
|
||||||
245 400 l 25
|
|
||||||
137 356 l 25
|
|
||||||
141 520 l 25
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: Q
|
|
||||||
Encoding: 81 81 3
|
|
||||||
Width: 1000
|
|
||||||
VWidth: 0
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
657 237 m 0
|
|
||||||
519 615 l 0
|
|
||||||
289 387 l 0
|
|
||||||
657 237 l 0
|
|
||||||
792 169 m 1
|
|
||||||
864 83 l 25
|
|
||||||
802 3 l 21
|
|
||||||
722 93 l 1
|
|
||||||
641 18 369 -39 242 93 c 0
|
|
||||||
110 231 71 509 228 673 c 24
|
|
||||||
380 831 645 840 791 665 c 0
|
|
||||||
926 502 867 263 792 169 c 1
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 33
|
|
||||||
EndChar
|
|
||||||
EndChars
|
|
||||||
EndSplineFont
|
|
2
vendor/golang.org/x/image/font/testdata/README
generated
vendored
2
vendor/golang.org/x/image/font/testdata/README
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
CFFTest.sfd is a FontForge file for creating CFFTest.otf, a custom OpenType
|
|
||||||
font for testing the golang.org/x/image/font/sfnt package's CFF support.
|
|
265
vendor/golang.org/x/image/font/testdata/cmapTest.sfd
generated
vendored
265
vendor/golang.org/x/image/font/testdata/cmapTest.sfd
generated
vendored
@ -1,265 +0,0 @@
|
|||||||
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
|
|
BIN
vendor/golang.org/x/image/font/testdata/cmapTest.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/cmapTest.ttf
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0000
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0000
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0100
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0100
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0200
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0200
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0300
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0300
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0400
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0400
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0500
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0500
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0E00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.0E00
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1000
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1000
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1600
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1600
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1E00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1E00
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1F00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.1F00
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2000
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2000
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2100
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2100
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2200
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2200
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2300
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2300
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2400
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2400
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2500
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2500
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2600
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2600
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2700
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2700
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2800
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2800
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2A00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.2A00
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.3000
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.3000
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.FB00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.FB00
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.FE00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.FE00
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.FF00
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/fixed/7x13.FF00
generated
vendored
Binary file not shown.
9
vendor/golang.org/x/image/font/testdata/fixed/README
generated
vendored
9
vendor/golang.org/x/image/font/testdata/fixed/README
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
These font files were copied from the Plan 9 Port's font/fixed directory. The
|
|
||||||
README in that directory states that: "These fonts are converted from the BDFs
|
|
||||||
in the XFree86 distribution. They were all marked as public domain."
|
|
||||||
|
|
||||||
The Plan 9 Port is at https://github.com/9fans/plan9port and the copy was made
|
|
||||||
from commit a78b1841 (2015-08-18).
|
|
||||||
|
|
||||||
The unicode.7x13.font file also refers to a ../shinonome directory, but this
|
|
||||||
testdata does not include those subfont files.
|
|
68
vendor/golang.org/x/image/font/testdata/fixed/unicode.7x13.font
generated
vendored
68
vendor/golang.org/x/image/font/testdata/fixed/unicode.7x13.font
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
13 11
|
|
||||||
0x0000 0x001F 7x13.2400
|
|
||||||
0x0000 0x00FF 7x13.0000
|
|
||||||
0x0100 0x01FF 7x13.0100
|
|
||||||
0x0200 0x02FF 7x13.0200
|
|
||||||
0x0300 0x03FF 7x13.0300
|
|
||||||
0x0400 0x04FF 7x13.0400
|
|
||||||
0x0500 0x05FF 7x13.0500
|
|
||||||
0x0E00 0x0EFF 7x13.0E00
|
|
||||||
0x1000 0x10FF 7x13.1000
|
|
||||||
0x1600 0x16FF 7x13.1600
|
|
||||||
0x1E00 0x1EFF 7x13.1E00
|
|
||||||
0x1F00 0x1FFF 7x13.1F00
|
|
||||||
0x2000 0x20FF 7x13.2000
|
|
||||||
0x2100 0x21FF 7x13.2100
|
|
||||||
0x2200 0x22FF 7x13.2200
|
|
||||||
0x2300 0x23FF 7x13.2300
|
|
||||||
0x2400 0x24FF 7x13.2400
|
|
||||||
0x2500 0x25FF 7x13.2500
|
|
||||||
0x2600 0x26FF 7x13.2600
|
|
||||||
0x2700 0x27FF 7x13.2700
|
|
||||||
0x2800 0x28FF 7x13.2800
|
|
||||||
0x2A00 0x2AFF 7x13.2A00
|
|
||||||
0x3000 0x30fe ../shinonome/k12.3000
|
|
||||||
0x4e00 0x4ffe ../shinonome/k12.4e00
|
|
||||||
0x5005 0x51fe ../shinonome/k12.5005
|
|
||||||
0x5200 0x53fa ../shinonome/k12.5200
|
|
||||||
0x5401 0x55fe ../shinonome/k12.5401
|
|
||||||
0x5606 0x57fc ../shinonome/k12.5606
|
|
||||||
0x5800 0x59ff ../shinonome/k12.5800
|
|
||||||
0x5a01 0x5bff ../shinonome/k12.5a01
|
|
||||||
0x5c01 0x5dfe ../shinonome/k12.5c01
|
|
||||||
0x5e02 0x5fff ../shinonome/k12.5e02
|
|
||||||
0x600e 0x61ff ../shinonome/k12.600e
|
|
||||||
0x6200 0x63fa ../shinonome/k12.6200
|
|
||||||
0x6406 0x65fb ../shinonome/k12.6406
|
|
||||||
0x6602 0x67ff ../shinonome/k12.6602
|
|
||||||
0x6802 0x69ff ../shinonome/k12.6802
|
|
||||||
0x6a02 0x6bf3 ../shinonome/k12.6a02
|
|
||||||
0x6c08 0x6dfb ../shinonome/k12.6c08
|
|
||||||
0x6e05 0x6ffe ../shinonome/k12.6e05
|
|
||||||
0x7001 0x71ff ../shinonome/k12.7001
|
|
||||||
0x7206 0x73fe ../shinonome/k12.7206
|
|
||||||
0x7403 0x75ff ../shinonome/k12.7403
|
|
||||||
0x7601 0x77fc ../shinonome/k12.7601
|
|
||||||
0x7802 0x79fb ../shinonome/k12.7802
|
|
||||||
0x7a00 0x7bf7 ../shinonome/k12.7a00
|
|
||||||
0x7c00 0x7dfb ../shinonome/k12.7c00
|
|
||||||
0x7e01 0x7ffc ../shinonome/k12.7e01
|
|
||||||
0x8000 0x81fe ../shinonome/k12.8000
|
|
||||||
0x8201 0x83fd ../shinonome/k12.8201
|
|
||||||
0x8403 0x85fe ../shinonome/k12.8403
|
|
||||||
0x8602 0x87fe ../shinonome/k12.8602
|
|
||||||
0x8805 0x89f8 ../shinonome/k12.8805
|
|
||||||
0x8a00 0x8b9a ../shinonome/k12.8a00
|
|
||||||
0x8c37 0x8dff ../shinonome/k12.8c37
|
|
||||||
0x8e08 0x8ffd ../shinonome/k12.8e08
|
|
||||||
0x9000 0x91ff ../shinonome/k12.9000
|
|
||||||
0x920d 0x93e8 ../shinonome/k12.920d
|
|
||||||
0x9403 0x95e5 ../shinonome/k12.9403
|
|
||||||
0x961c 0x97ff ../shinonome/k12.961c
|
|
||||||
0x9801 0x99ff ../shinonome/k12.9801
|
|
||||||
0x9a01 0x9bf5 ../shinonome/k12.9a01
|
|
||||||
0x9c04 0x9dfd ../shinonome/k12.9c04
|
|
||||||
0x9e1a 0x9fa0 ../shinonome/k12.9e1a
|
|
||||||
0xFB00 0xFBFF 7x13.FB00
|
|
||||||
0xFE00 0xFEFF 7x13.FE00
|
|
||||||
0xFF00 0xFFFF 7x13.FF00
|
|
225
vendor/golang.org/x/image/font/testdata/glyfTest.sfd
generated
vendored
225
vendor/golang.org/x/image/font/testdata/glyfTest.sfd
generated
vendored
@ -1,225 +0,0 @@
|
|||||||
SplineFontDB: 3.0
|
|
||||||
FontName: glyfTest
|
|
||||||
FullName: glyfTest
|
|
||||||
FamilyName: glyfTest
|
|
||||||
Weight: Book
|
|
||||||
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
|
|
||||||
sfntRevision: 0x00010000
|
|
||||||
LayerCount: 2
|
|
||||||
Layer: 0 1 "Back" 1
|
|
||||||
Layer: 1 1 "Fore" 0
|
|
||||||
XUID: [1021 367 888937226 5879518]
|
|
||||||
FSType: 8
|
|
||||||
OS2Version: 4
|
|
||||||
OS2_WeightWidthSlopeOnly: 0
|
|
||||||
OS2_UseTypoMetrics: 1
|
|
||||||
CreationTime: 1484386143
|
|
||||||
ModificationTime: 1489831626
|
|
||||||
PfmFamily: 17
|
|
||||||
TTFWeight: 400
|
|
||||||
TTFWidth: 5
|
|
||||||
LineGap: 184
|
|
||||||
VLineGap: 0
|
|
||||||
Panose: 2 0 5 3 0 0 0 0 0 0
|
|
||||||
OS2TypoAscent: 1638
|
|
||||||
OS2TypoAOffset: 0
|
|
||||||
OS2TypoDescent: -410
|
|
||||||
OS2TypoDOffset: 0
|
|
||||||
OS2TypoLinegap: 184
|
|
||||||
OS2WinAscent: 1984
|
|
||||||
OS2WinAOffset: 0
|
|
||||||
OS2WinDescent: 0
|
|
||||||
OS2WinDOffset: 0
|
|
||||||
HheadAscent: 1984
|
|
||||||
HheadAOffset: 0
|
|
||||||
HheadDescent: 0
|
|
||||||
HheadDOffset: 0
|
|
||||||
OS2SubXSize: 1331
|
|
||||||
OS2SubYSize: 1433
|
|
||||||
OS2SubXOff: 55
|
|
||||||
OS2SubYOff: 286
|
|
||||||
OS2SupXSize: 1331
|
|
||||||
OS2SupYSize: 1433
|
|
||||||
OS2SupXOff: -191
|
|
||||||
OS2SupYOff: 983
|
|
||||||
OS2StrikeYSize: 102
|
|
||||||
OS2StrikeYPos: 530
|
|
||||||
OS2Vendor: 'PfEd'
|
|
||||||
OS2CodePages: 00000001.00000000
|
|
||||||
OS2UnicodeRanges: 00000001.00000000.00000000.00000000
|
|
||||||
MarkAttachClasses: 1
|
|
||||||
DEI: 91125
|
|
||||||
ShortTable: cvt 2
|
|
||||||
68
|
|
||||||
1297
|
|
||||||
EndShort
|
|
||||||
ShortTable: maxp 16
|
|
||||||
1
|
|
||||||
0
|
|
||||||
10
|
|
||||||
18
|
|
||||||
2
|
|
||||||
8
|
|
||||||
2
|
|
||||||
2
|
|
||||||
0
|
|
||||||
1
|
|
||||||
1
|
|
||||||
0
|
|
||||||
64
|
|
||||||
46
|
|
||||||
2
|
|
||||||
1
|
|
||||||
EndShort
|
|
||||||
LangName: 1033 "" "" "Regular" "FontForge : glyfTest : 18-3-2017" "" "Version 001.000"
|
|
||||||
GaspTable: 1 65535 2 0
|
|
||||||
Encoding: UnicodeBmp
|
|
||||||
UnicodeInterp: none
|
|
||||||
NameList: Adobe Glyph List
|
|
||||||
DisplaySize: -24
|
|
||||||
AntiAlias: 1
|
|
||||||
FitToEm: 1
|
|
||||||
WinInfo: 0 32 23
|
|
||||||
BeginChars: 65539 10
|
|
||||||
|
|
||||||
StartChar: .notdef
|
|
||||||
Encoding: 65536 -1 0
|
|
||||||
Width: 748
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
68 0 m 1,0,-1
|
|
||||||
68 1365 l 1,1,-1
|
|
||||||
612 1365 l 1,2,-1
|
|
||||||
612 0 l 1,3,-1
|
|
||||||
68 0 l 1,0,-1
|
|
||||||
136 68 m 1,4,-1
|
|
||||||
544 68 l 1,5,-1
|
|
||||||
544 1297 l 1,6,-1
|
|
||||||
136 1297 l 1,7,-1
|
|
||||||
136 68 l 1,4,-1
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: .null
|
|
||||||
Encoding: 65537 -1 1
|
|
||||||
Width: 0
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: nonmarkingreturn
|
|
||||||
Encoding: 65538 -1 2
|
|
||||||
Width: 682
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: zero
|
|
||||||
Encoding: 48 48 3
|
|
||||||
Width: 1228
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
614 1434 m 0,0,1
|
|
||||||
369 1434 369 1434 369 614 c 0,2,3
|
|
||||||
369 471 369 471 435 338 c 0,4,5
|
|
||||||
502 205 502 205 614 205 c 0,6,7
|
|
||||||
860 205 860 205 860 1024 c 0,8,9
|
|
||||||
860 1167 860 1167 793 1300 c 1,10,11
|
|
||||||
727 1434 727 1434 614 1434 c 0,0,1
|
|
||||||
614 1638 m 0,12,13
|
|
||||||
1024 1638 1024 1638 1024 819 c 128,-1,14
|
|
||||||
1024 0 1024 0 614 0 c 0,15,16
|
|
||||||
205 0 205 0 205 819 c 128,-1,17
|
|
||||||
205 1638 205 1638 614 1638 c 0,12,13
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: one
|
|
||||||
Encoding: 49 49 4
|
|
||||||
Width: 819
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
205 0 m 1,0,-1
|
|
||||||
205 1638 l 1,1,-1
|
|
||||||
614 1638 l 1,2,-1
|
|
||||||
614 0 l 1,3,-1
|
|
||||||
205 0 l 1,0,-1
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: five
|
|
||||||
Encoding: 53 53 5
|
|
||||||
Width: 400
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
SplineSet
|
|
||||||
0 0 m 1,0,-1
|
|
||||||
0 100 l 1,1,-1
|
|
||||||
400 100 l 1,2,-1
|
|
||||||
400 0 l 1,3,-1
|
|
||||||
0 0 l 1,0,-1
|
|
||||||
EndSplineSet
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: six
|
|
||||||
Encoding: 54 54 6
|
|
||||||
Width: 400
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
Refer: 5 53 N 1 0 0 1 0 0 2
|
|
||||||
Refer: 4 49 N 1 0 0 1 111 234 2
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: seven
|
|
||||||
Encoding: 55 55 7
|
|
||||||
Width: 400
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
Refer: 5 53 N 1 0 0 1 0 0 2
|
|
||||||
Refer: 4 49 N 0.5 0 0 0.5 56 117 2
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: eight
|
|
||||||
Encoding: 56 56 8
|
|
||||||
Width: 400
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
Refer: 5 53 N 1 0 0 1 0 0 2
|
|
||||||
Refer: 4 49 N 1.5 0 0 0.5 56 117 2
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
|
|
||||||
StartChar: nine
|
|
||||||
Encoding: 57 57 9
|
|
||||||
Width: 400
|
|
||||||
Flags: W
|
|
||||||
LayerCount: 2
|
|
||||||
Fore
|
|
||||||
Refer: 5 53 N 1 0 0 1 0 0 2
|
|
||||||
Refer: 4 49 N 1.36603 0.5 0.365967 0.865967 237 258 2
|
|
||||||
Validated: 1
|
|
||||||
EndChar
|
|
||||||
EndChars
|
|
||||||
EndSplineFont
|
|
BIN
vendor/golang.org/x/image/font/testdata/glyfTest.ttf
generated
vendored
BIN
vendor/golang.org/x/image/font/testdata/glyfTest.ttf
generated
vendored
Binary file not shown.
37
vendor/golang.org/x/image/math/f32/f32.go
generated
vendored
37
vendor/golang.org/x/image/math/f32/f32.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Package f32 implements float32 vector and matrix types.
|
|
||||||
package f32 // import "golang.org/x/image/math/f32"
|
|
||||||
|
|
||||||
// Vec2 is a 2-element vector.
|
|
||||||
type Vec2 [2]float32
|
|
||||||
|
|
||||||
// Vec3 is a 3-element vector.
|
|
||||||
type Vec3 [3]float32
|
|
||||||
|
|
||||||
// Vec4 is a 4-element vector.
|
|
||||||
type Vec4 [4]float32
|
|
||||||
|
|
||||||
// Mat3 is a 3x3 matrix in row major order.
|
|
||||||
//
|
|
||||||
// m[3*r + c] is the element in the r'th row and c'th column.
|
|
||||||
type Mat3 [9]float32
|
|
||||||
|
|
||||||
// Mat4 is a 4x4 matrix in row major order.
|
|
||||||
//
|
|
||||||
// m[4*r + c] is the element in the r'th row and c'th column.
|
|
||||||
type Mat4 [16]float32
|
|
||||||
|
|
||||||
// Aff3 is a 3x3 affine transformation matrix in row major order, where the
|
|
||||||
// bottom row is implicitly [0 0 1].
|
|
||||||
//
|
|
||||||
// m[3*r + c] is the element in the r'th row and c'th column.
|
|
||||||
type Aff3 [6]float32
|
|
||||||
|
|
||||||
// Aff4 is a 4x4 affine transformation matrix in row major order, where the
|
|
||||||
// bottom row is implicitly [0 0 0 1].
|
|
||||||
//
|
|
||||||
// m[4*r + c] is the element in the r'th row and c'th column.
|
|
||||||
type Aff4 [12]float32
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user