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