vector: make args float32 pairs instead of f32.Vec2.
The f32.Vec2 type doesn't seem worth it. Change-Id: I021c7e13d7e2dd261334f4aa7e867df4fd8f1c3e Reviewed-on: https://go-review.googlesource.com/32772 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
c78039e8ce
commit
98f3e4e74d
|
@ -481,11 +481,11 @@ func makeInXxx(height int, useFloatingPointMath bool) *Rasterizer {
|
|||
for _, d := range data {
|
||||
switch d.n {
|
||||
case 0:
|
||||
z.MoveTo(d.p)
|
||||
z.MoveTo(d.px, d.py)
|
||||
case 1:
|
||||
z.LineTo(d.p)
|
||||
z.LineTo(d.px, d.py)
|
||||
case 2:
|
||||
z.QuadTo(d.p, d.q)
|
||||
z.QuadTo(d.px, d.py, d.qx, d.qy)
|
||||
}
|
||||
}
|
||||
return z
|
||||
|
|
|
@ -7,10 +7,6 @@ package vector
|
|||
// This file contains a fixed point math implementation of the vector
|
||||
// graphics rasterizer.
|
||||
|
||||
import (
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
const (
|
||||
// ϕ is the number of binary digits after the fixed point.
|
||||
//
|
||||
|
@ -58,35 +54,35 @@ func fixedMin(x, y int1ϕ) int1ϕ {
|
|||
func fixedFloor(x int1ϕ) int32 { return int32(x >> ϕ) }
|
||||
func fixedCeil(x int1ϕ) int32 { return int32((x + fxOneMinusIota) >> ϕ) }
|
||||
|
||||
func (z *Rasterizer) fixedLineTo(b f32.Vec2) {
|
||||
a := z.pen
|
||||
z.pen = b
|
||||
func (z *Rasterizer) fixedLineTo(bx, by float32) {
|
||||
ax, ay := z.penX, z.penY
|
||||
z.penX, z.penY = bx, by
|
||||
dir := int1ϕ(1)
|
||||
if a[1] > b[1] {
|
||||
dir, a, b = -1, b, a
|
||||
if ay > by {
|
||||
dir, ax, ay, bx, by = -1, bx, by, ax, ay
|
||||
}
|
||||
// Horizontal line segments yield no change in coverage. Almost horizontal
|
||||
// segments would yield some change, in ideal math, but the computation
|
||||
// further below, involving 1 / (b[1] - a[1]), is unstable in fixed point
|
||||
// math, so we treat the segment as if it was perfectly horizontal.
|
||||
if b[1]-a[1] <= 0.000001 {
|
||||
// further below, involving 1 / (by - ay), is unstable in fixed point math,
|
||||
// so we treat the segment as if it was perfectly horizontal.
|
||||
if by-ay <= 0.000001 {
|
||||
return
|
||||
}
|
||||
dxdy := (b[0] - a[0]) / (b[1] - a[1])
|
||||
dxdy := (bx - ax) / (by - ay)
|
||||
|
||||
ay := int1ϕ(a[1] * float32(fxOne))
|
||||
by := int1ϕ(b[1] * float32(fxOne))
|
||||
ayϕ := int1ϕ(ay * float32(fxOne))
|
||||
byϕ := int1ϕ(by * float32(fxOne))
|
||||
|
||||
x := int1ϕ(a[0] * float32(fxOne))
|
||||
y := fixedFloor(ay)
|
||||
yMax := fixedCeil(by)
|
||||
x := int1ϕ(ax * float32(fxOne))
|
||||
y := fixedFloor(ayϕ)
|
||||
yMax := fixedCeil(byϕ)
|
||||
if yMax > int32(z.size.Y) {
|
||||
yMax = int32(z.size.Y)
|
||||
}
|
||||
width := int32(z.size.X)
|
||||
|
||||
for ; y < yMax; y++ {
|
||||
dy := fixedMin(int1ϕ(y+1)<<ϕ, by) - fixedMax(int1ϕ(y)<<ϕ, ay)
|
||||
dy := fixedMin(int1ϕ(y+1)<<ϕ, byϕ) - fixedMax(int1ϕ(y)<<ϕ, ayϕ)
|
||||
xNext := x + int1ϕ(float32(dy)*dxdy)
|
||||
if y < 0 {
|
||||
x = xNext
|
||||
|
|
|
@ -9,8 +9,6 @@ package vector
|
|||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
func floatingMax(x, y float32) float32 {
|
||||
|
@ -30,32 +28,32 @@ func floatingMin(x, y float32) float32 {
|
|||
func floatingFloor(x float32) int32 { return int32(math.Floor(float64(x))) }
|
||||
func floatingCeil(x float32) int32 { return int32(math.Ceil(float64(x))) }
|
||||
|
||||
func (z *Rasterizer) floatingLineTo(b f32.Vec2) {
|
||||
a := z.pen
|
||||
z.pen = b
|
||||
func (z *Rasterizer) floatingLineTo(bx, by float32) {
|
||||
ax, ay := z.penX, z.penY
|
||||
z.penX, z.penY = bx, by
|
||||
dir := float32(1)
|
||||
if a[1] > b[1] {
|
||||
dir, a, b = -1, b, a
|
||||
if ay > by {
|
||||
dir, ax, ay, bx, by = -1, bx, by, ax, ay
|
||||
}
|
||||
// Horizontal line segments yield no change in coverage. Almost horizontal
|
||||
// segments would yield some change, in ideal math, but the computation
|
||||
// further below, involving 1 / (b[1] - a[1]), is unstable in floating
|
||||
// point math, so we treat the segment as if it was perfectly horizontal.
|
||||
if b[1]-a[1] <= 0.000001 {
|
||||
// further below, involving 1 / (by - ay), is unstable in floating point
|
||||
// math, so we treat the segment as if it was perfectly horizontal.
|
||||
if by-ay <= 0.000001 {
|
||||
return
|
||||
}
|
||||
dxdy := (b[0] - a[0]) / (b[1] - a[1])
|
||||
dxdy := (bx - ax) / (by - ay)
|
||||
|
||||
x := a[0]
|
||||
y := floatingFloor(a[1])
|
||||
yMax := floatingCeil(b[1])
|
||||
x := ax
|
||||
y := floatingFloor(ay)
|
||||
yMax := floatingCeil(by)
|
||||
if yMax > int32(z.size.Y) {
|
||||
yMax = int32(z.size.Y)
|
||||
}
|
||||
width := int32(z.size.X)
|
||||
|
||||
for ; y < yMax; y++ {
|
||||
dy := floatingMin(float32(y+1), b[1]) - floatingMax(float32(y), a[1])
|
||||
dy := floatingMin(float32(y+1), by) - floatingMax(float32(y), ay)
|
||||
xNext := x + dy*dxdy
|
||||
if y < 0 {
|
||||
x = xNext
|
||||
|
|
110
vector/vector.go
110
vector/vector.go
|
@ -26,8 +26,6 @@ import (
|
|||
"image/color"
|
||||
"image/draw"
|
||||
"math"
|
||||
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
// floatingPointMathThreshold is the width or height above which the rasterizer
|
||||
|
@ -50,18 +48,8 @@ import (
|
|||
// would still produce acceptable quality, but 512 seems to work.
|
||||
const floatingPointMathThreshold = 512
|
||||
|
||||
func midPoint(p, q f32.Vec2) f32.Vec2 {
|
||||
return f32.Vec2{
|
||||
(p[0] + q[0]) * 0.5,
|
||||
(p[1] + q[1]) * 0.5,
|
||||
}
|
||||
}
|
||||
|
||||
func lerp(t float32, p, q f32.Vec2) f32.Vec2 {
|
||||
return f32.Vec2{
|
||||
p[0] + t*(q[0]-p[0]),
|
||||
p[1] + t*(q[1]-p[1]),
|
||||
}
|
||||
func lerp(t, px, py, qx, qy float32) (x, y float32) {
|
||||
return px + t*(qx-px), py + t*(qy-py)
|
||||
}
|
||||
|
||||
func clamp(i, width int32) uint {
|
||||
|
@ -106,9 +94,11 @@ type Rasterizer struct {
|
|||
|
||||
useFloatingPointMath bool
|
||||
|
||||
size image.Point
|
||||
first f32.Vec2
|
||||
pen f32.Vec2
|
||||
size image.Point
|
||||
firstX float32
|
||||
firstY float32
|
||||
penX float32
|
||||
penY float32
|
||||
|
||||
// DrawOp is the operator used for the Draw method.
|
||||
//
|
||||
|
@ -124,8 +114,10 @@ type Rasterizer struct {
|
|||
// This includes setting z.DrawOp to draw.Over.
|
||||
func (z *Rasterizer) Reset(w, h int) {
|
||||
z.size = image.Point{w, h}
|
||||
z.first = f32.Vec2{}
|
||||
z.pen = f32.Vec2{}
|
||||
z.firstX = 0
|
||||
z.firstY = 0
|
||||
z.penX = 0
|
||||
z.penY = 0
|
||||
z.DrawOp = draw.Over
|
||||
|
||||
z.setUseFloatingPointMath(w > floatingPointMathThreshold || h > floatingPointMathThreshold)
|
||||
|
@ -169,63 +161,66 @@ func (z *Rasterizer) Bounds() image.Rectangle {
|
|||
|
||||
// Pen returns the location of the path-drawing pen: the last argument to the
|
||||
// most recent XxxTo call.
|
||||
func (z *Rasterizer) Pen() f32.Vec2 {
|
||||
return z.pen
|
||||
func (z *Rasterizer) Pen() (x, y float32) {
|
||||
return z.penX, z.penY
|
||||
}
|
||||
|
||||
// ClosePath closes the current path.
|
||||
func (z *Rasterizer) ClosePath() {
|
||||
z.LineTo(z.first)
|
||||
z.LineTo(z.firstX, z.firstY)
|
||||
}
|
||||
|
||||
// MoveTo starts a new path and moves the pen to a.
|
||||
// MoveTo starts a new path and moves the pen to (ax, ay).
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) MoveTo(a f32.Vec2) {
|
||||
z.first = a
|
||||
z.pen = a
|
||||
func (z *Rasterizer) MoveTo(ax, ay float32) {
|
||||
z.firstX = ax
|
||||
z.firstY = ay
|
||||
z.penX = ax
|
||||
z.penY = ay
|
||||
}
|
||||
|
||||
// LineTo adds a line segment, from the pen to b, and moves the pen to b.
|
||||
// LineTo adds a line segment, from the pen to (bx, by), and moves the pen to
|
||||
// (bx, by).
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) LineTo(b f32.Vec2) {
|
||||
func (z *Rasterizer) LineTo(bx, by float32) {
|
||||
if z.useFloatingPointMath {
|
||||
z.floatingLineTo(b)
|
||||
z.floatingLineTo(bx, by)
|
||||
} else {
|
||||
z.fixedLineTo(b)
|
||||
z.fixedLineTo(bx, by)
|
||||
}
|
||||
}
|
||||
|
||||
// QuadTo adds a quadratic Bézier segment, from the pen via b to c, and moves
|
||||
// the pen to c.
|
||||
// QuadTo adds a quadratic Bézier segment, from the pen via (bx, by) to (cx,
|
||||
// cy), and moves the pen to (cx, cy).
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) QuadTo(b, c f32.Vec2) {
|
||||
a := z.pen
|
||||
devsq := devSquared(a, b, c)
|
||||
func (z *Rasterizer) QuadTo(bx, by, cx, cy float32) {
|
||||
ax, ay := z.penX, z.penY
|
||||
devsq := devSquared(ax, ay, bx, by, cx, cy)
|
||||
if devsq >= 0.333 {
|
||||
const tol = 3
|
||||
n := 1 + int(math.Sqrt(math.Sqrt(tol*float64(devsq))))
|
||||
t, nInv := float32(0), 1/float32(n)
|
||||
for i := 0; i < n-1; i++ {
|
||||
t += nInv
|
||||
ab := lerp(t, a, b)
|
||||
bc := lerp(t, b, c)
|
||||
z.LineTo(lerp(t, ab, bc))
|
||||
abx, aby := lerp(t, ax, ay, bx, by)
|
||||
bcx, bcy := lerp(t, bx, by, cx, cy)
|
||||
z.LineTo(lerp(t, abx, aby, bcx, bcy))
|
||||
}
|
||||
}
|
||||
z.LineTo(c)
|
||||
z.LineTo(cx, cy)
|
||||
}
|
||||
|
||||
// CubeTo adds a cubic Bézier segment, from the pen via b and c to d, and moves
|
||||
// the pen to d.
|
||||
// CubeTo adds a cubic Bézier segment, from the pen via (bx, by) and (cx, cy)
|
||||
// to (dx, dy), and moves the pen to (dx, dy).
|
||||
//
|
||||
// The coordinates are allowed to be out of the Rasterizer's bounds.
|
||||
func (z *Rasterizer) CubeTo(b, c, d f32.Vec2) {
|
||||
a := z.pen
|
||||
devsq := devSquared(a, b, d)
|
||||
if devsqAlt := devSquared(a, c, d); devsq < devsqAlt {
|
||||
func (z *Rasterizer) CubeTo(bx, by, cx, cy, dx, dy float32) {
|
||||
ax, ay := z.penX, z.penY
|
||||
devsq := devSquared(ax, ay, bx, by, dx, dy)
|
||||
if devsqAlt := devSquared(ax, ay, cx, cy, dx, dy); devsq < devsqAlt {
|
||||
devsq = devsqAlt
|
||||
}
|
||||
if devsq >= 0.333 {
|
||||
|
@ -234,19 +229,20 @@ func (z *Rasterizer) CubeTo(b, c, d f32.Vec2) {
|
|||
t, nInv := float32(0), 1/float32(n)
|
||||
for i := 0; i < n-1; i++ {
|
||||
t += nInv
|
||||
ab := lerp(t, a, b)
|
||||
bc := lerp(t, b, c)
|
||||
cd := lerp(t, c, d)
|
||||
abc := lerp(t, ab, bc)
|
||||
bcd := lerp(t, bc, cd)
|
||||
z.LineTo(lerp(t, abc, bcd))
|
||||
abx, aby := lerp(t, ax, ay, bx, by)
|
||||
bcx, bcy := lerp(t, bx, by, cx, cy)
|
||||
cdx, cdy := lerp(t, cx, cy, dx, dy)
|
||||
abcx, abcy := lerp(t, abx, aby, bcx, bcy)
|
||||
bcdx, bcdy := lerp(t, bcx, bcy, cdx, cdy)
|
||||
z.LineTo(lerp(t, abcx, abcy, bcdx, bcdy))
|
||||
}
|
||||
}
|
||||
z.LineTo(d)
|
||||
z.LineTo(dx, dy)
|
||||
}
|
||||
|
||||
// devSquared returns a measure of how curvy the sequnce a to b to c is. It
|
||||
// determines how many line segments will approximate a Bézier curve segment.
|
||||
// devSquared returns a measure of how curvy the sequence (ax, ay) to (bx, by)
|
||||
// to (cx, cy) is. It determines how many line segments will approximate a
|
||||
// Bézier curve segment.
|
||||
//
|
||||
// http://lists.nongnu.org/archive/html/freetype-devel/2016-08/msg00080.html
|
||||
// gives the rationale for this evenly spaced heuristic instead of a recursive
|
||||
|
@ -258,9 +254,9 @@ func (z *Rasterizer) CubeTo(b, c, d f32.Vec2) {
|
|||
// Taking a circular arc as a simplifying assumption (ie a spherical cow),
|
||||
// where I get n, a recursive approach would get 2^⌈lg n⌉, which, if I haven't
|
||||
// made any horrible mistakes, is expected to be 33% more in the limit.
|
||||
func devSquared(a, b, c f32.Vec2) float32 {
|
||||
devx := a[0] - 2*b[0] + c[0]
|
||||
devy := a[1] - 2*b[1] + c[1]
|
||||
func devSquared(ax, ay, bx, by, cx, cy float32) float32 {
|
||||
devx := ax - 2*bx + cx
|
||||
devy := ay - 2*by + cy
|
||||
return devx*devx + devy*devy
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/image/math/f32"
|
||||
)
|
||||
|
||||
// encodePNG is useful for manually debugging the tests.
|
||||
|
@ -35,15 +33,13 @@ func encodePNG(dstFilename string, src image.Image) error {
|
|||
return closeErr
|
||||
}
|
||||
|
||||
func pointOnCircle(center, radius, index, number int) f32.Vec2 {
|
||||
func pointOnCircle(center, radius, index, number int) (x, y float32) {
|
||||
c := float64(center)
|
||||
r := float64(radius)
|
||||
i := float64(index)
|
||||
n := float64(number)
|
||||
return f32.Vec2{
|
||||
float32(c + r*(math.Cos(2*math.Pi*i/n))),
|
||||
float32(c + r*(math.Sin(2*math.Pi*i/n))),
|
||||
}
|
||||
return float32(c + r*(math.Cos(2*math.Pi*i/n))),
|
||||
float32(c + r*(math.Sin(2*math.Pi*i/n)))
|
||||
}
|
||||
|
||||
func TestRasterizeOutOfBounds(t *testing.T) {
|
||||
|
@ -59,15 +55,15 @@ func TestRasterizeOutOfBounds(t *testing.T) {
|
|||
for i := 0; i < n; i++ {
|
||||
for j := 1; j < n/2; j++ {
|
||||
z.Reset(2*center, 2*center)
|
||||
z.MoveTo(f32.Vec2{1 * center, 1 * center})
|
||||
z.MoveTo(1*center, 1*center)
|
||||
z.LineTo(pointOnCircle(center, radius, i+0, n))
|
||||
z.LineTo(pointOnCircle(center, radius, i+j, n))
|
||||
z.ClosePath()
|
||||
|
||||
z.MoveTo(f32.Vec2{0 * center, 0 * center})
|
||||
z.LineTo(f32.Vec2{0 * center, 2 * center})
|
||||
z.LineTo(f32.Vec2{2 * center, 2 * center})
|
||||
z.LineTo(f32.Vec2{2 * center, 0 * center})
|
||||
z.MoveTo(0*center, 0*center)
|
||||
z.LineTo(0*center, 2*center)
|
||||
z.LineTo(2*center, 2*center)
|
||||
z.LineTo(2*center, 0*center)
|
||||
z.ClosePath()
|
||||
|
||||
dst := image.NewAlpha(z.Bounds())
|
||||
|
@ -91,10 +87,7 @@ func TestRasterizePolygon(t *testing.T) {
|
|||
for radius := 4; radius <= 256; radius *= 2 {
|
||||
for n := 3; n <= 19; n += 4 {
|
||||
z.Reset(2*radius, 2*radius)
|
||||
z.MoveTo(f32.Vec2{
|
||||
float32(2 * radius),
|
||||
float32(1 * radius),
|
||||
})
|
||||
z.MoveTo(float32(2*radius), float32(1*radius))
|
||||
for i := 1; i < n; i++ {
|
||||
z.LineTo(pointOnCircle(radius, radius, i, n))
|
||||
}
|
||||
|
@ -112,10 +105,10 @@ func TestRasterizePolygon(t *testing.T) {
|
|||
|
||||
func TestRasterizeAlmostAxisAligned(t *testing.T) {
|
||||
z := NewRasterizer(8, 8)
|
||||
z.MoveTo(f32.Vec2{2, 2})
|
||||
z.LineTo(f32.Vec2{6, math.Nextafter32(2, 0)})
|
||||
z.LineTo(f32.Vec2{6, 6})
|
||||
z.LineTo(f32.Vec2{math.Nextafter32(2, 0), 6})
|
||||
z.MoveTo(2, 2)
|
||||
z.LineTo(6, math.Nextafter32(2, 0))
|
||||
z.LineTo(6, 6)
|
||||
z.LineTo(math.Nextafter32(2, 0), 6)
|
||||
z.ClosePath()
|
||||
|
||||
dst := image.NewAlpha(z.Bounds())
|
||||
|
@ -132,10 +125,10 @@ func TestRasterizeWideAlmostHorizontalLines(t *testing.T) {
|
|||
x := float32(int(1 << i))
|
||||
|
||||
z.Reset(8, 8)
|
||||
z.MoveTo(f32.Vec2{-x, 3})
|
||||
z.LineTo(f32.Vec2{+x, 4})
|
||||
z.LineTo(f32.Vec2{+x, 6})
|
||||
z.LineTo(f32.Vec2{-x, 6})
|
||||
z.MoveTo(-x, 3)
|
||||
z.LineTo(+x, 4)
|
||||
z.LineTo(+x, 6)
|
||||
z.LineTo(-x, 6)
|
||||
z.ClosePath()
|
||||
|
||||
dst := image.NewAlpha(z.Bounds())
|
||||
|
@ -149,9 +142,9 @@ func TestRasterizeWideAlmostHorizontalLines(t *testing.T) {
|
|||
|
||||
func TestRasterize30Degrees(t *testing.T) {
|
||||
z := NewRasterizer(8, 8)
|
||||
z.MoveTo(f32.Vec2{4, 4})
|
||||
z.LineTo(f32.Vec2{8, 4})
|
||||
z.LineTo(f32.Vec2{4, 6})
|
||||
z.MoveTo(4, 4)
|
||||
z.LineTo(8, 4)
|
||||
z.LineTo(4, 6)
|
||||
z.ClosePath()
|
||||
|
||||
dst := image.NewAlpha(z.Bounds())
|
||||
|
@ -168,11 +161,11 @@ func TestRasterizeRandomLineTos(t *testing.T) {
|
|||
n, rng := 0, rand.New(rand.NewSource(int64(i)))
|
||||
|
||||
z.Reset(i+2, i+2)
|
||||
z.MoveTo(f32.Vec2{float32(i / 2), float32(i / 2)})
|
||||
z.MoveTo(float32(i/2), float32(i/2))
|
||||
for ; rng.Intn(16) != 0; n++ {
|
||||
x := 1 + rng.Intn(i)
|
||||
y := 1 + rng.Intn(i)
|
||||
z.LineTo(f32.Vec2{float32(x), float32(y)})
|
||||
z.LineTo(float32(x), float32(y))
|
||||
}
|
||||
z.ClosePath()
|
||||
|
||||
|
@ -235,10 +228,10 @@ var basicMask = []byte{
|
|||
|
||||
func testBasicPath(t *testing.T, prefix string, dst draw.Image, src image.Image, op draw.Op, want []byte) {
|
||||
z := NewRasterizer(16, 16)
|
||||
z.MoveTo(f32.Vec2{2, 2})
|
||||
z.LineTo(f32.Vec2{8, 2})
|
||||
z.QuadTo(f32.Vec2{14, 2}, f32.Vec2{14, 14})
|
||||
z.CubeTo(f32.Vec2{8, 2}, f32.Vec2{5, 20}, f32.Vec2{2, 8})
|
||||
z.MoveTo(2, 2)
|
||||
z.LineTo(8, 2)
|
||||
z.QuadTo(14, 2, 14, 14)
|
||||
z.CubeTo(8, 2, 5, 20, 2, 8)
|
||||
z.ClosePath()
|
||||
|
||||
z.DrawOp = op
|
||||
|
@ -365,45 +358,47 @@ const (
|
|||
|
||||
type benchmarkGlyphDatum struct {
|
||||
// n being 0, 1 or 2 means moveTo, lineTo or quadTo.
|
||||
n uint32
|
||||
p f32.Vec2
|
||||
q f32.Vec2
|
||||
n uint32
|
||||
px float32
|
||||
py float32
|
||||
qx float32
|
||||
qy float32
|
||||
}
|
||||
|
||||
// benchmarkGlyphData is the 'a' glyph from the Roboto Regular font, translated
|
||||
// so that its top left corner is (0, 0).
|
||||
var benchmarkGlyphData = []benchmarkGlyphDatum{
|
||||
{0, f32.Vec2{699, 1102}, f32.Vec2{0, 0}},
|
||||
{2, f32.Vec2{683, 1070}, f32.Vec2{673, 988}},
|
||||
{2, f32.Vec2{544, 1122}, f32.Vec2{365, 1122}},
|
||||
{2, f32.Vec2{205, 1122}, f32.Vec2{102.5, 1031.5}},
|
||||
{2, f32.Vec2{0, 941}, f32.Vec2{0, 802}},
|
||||
{2, f32.Vec2{0, 633}, f32.Vec2{128.5, 539.5}},
|
||||
{2, f32.Vec2{257, 446}, f32.Vec2{490, 446}},
|
||||
{1, f32.Vec2{670, 446}, f32.Vec2{0, 0}},
|
||||
{1, f32.Vec2{670, 361}, f32.Vec2{0, 0}},
|
||||
{2, f32.Vec2{670, 264}, f32.Vec2{612, 206.5}},
|
||||
{2, f32.Vec2{554, 149}, f32.Vec2{441, 149}},
|
||||
{2, f32.Vec2{342, 149}, f32.Vec2{275, 199}},
|
||||
{2, f32.Vec2{208, 249}, f32.Vec2{208, 320}},
|
||||
{1, f32.Vec2{22, 320}, f32.Vec2{0, 0}},
|
||||
{2, f32.Vec2{22, 239}, f32.Vec2{79.5, 163.5}},
|
||||
{2, f32.Vec2{137, 88}, f32.Vec2{235.5, 44}},
|
||||
{2, f32.Vec2{334, 0}, f32.Vec2{452, 0}},
|
||||
{2, f32.Vec2{639, 0}, f32.Vec2{745, 93.5}},
|
||||
{2, f32.Vec2{851, 187}, f32.Vec2{855, 351}},
|
||||
{1, f32.Vec2{855, 849}, f32.Vec2{0, 0}},
|
||||
{2, f32.Vec2{855, 998}, f32.Vec2{893, 1086}},
|
||||
{1, f32.Vec2{893, 1102}, f32.Vec2{0, 0}},
|
||||
{1, f32.Vec2{699, 1102}, f32.Vec2{0, 0}},
|
||||
{0, f32.Vec2{392, 961}, f32.Vec2{0, 0}},
|
||||
{2, f32.Vec2{479, 961}, f32.Vec2{557, 916}},
|
||||
{2, f32.Vec2{635, 871}, f32.Vec2{670, 799}},
|
||||
{1, f32.Vec2{670, 577}, f32.Vec2{0, 0}},
|
||||
{1, f32.Vec2{525, 577}, f32.Vec2{0, 0}},
|
||||
{2, f32.Vec2{185, 577}, f32.Vec2{185, 776}},
|
||||
{2, f32.Vec2{185, 863}, f32.Vec2{243, 912}},
|
||||
{2, f32.Vec2{301, 961}, f32.Vec2{392, 961}},
|
||||
{0, 699, 1102, 0, 0},
|
||||
{2, 683, 1070, 673, 988},
|
||||
{2, 544, 1122, 365, 1122},
|
||||
{2, 205, 1122, 102.5, 1031.5},
|
||||
{2, 0, 941, 0, 802},
|
||||
{2, 0, 633, 128.5, 539.5},
|
||||
{2, 257, 446, 490, 446},
|
||||
{1, 670, 446, 0, 0},
|
||||
{1, 670, 361, 0, 0},
|
||||
{2, 670, 264, 612, 206.5},
|
||||
{2, 554, 149, 441, 149},
|
||||
{2, 342, 149, 275, 199},
|
||||
{2, 208, 249, 208, 320},
|
||||
{1, 22, 320, 0, 0},
|
||||
{2, 22, 239, 79.5, 163.5},
|
||||
{2, 137, 88, 235.5, 44},
|
||||
{2, 334, 0, 452, 0},
|
||||
{2, 639, 0, 745, 93.5},
|
||||
{2, 851, 187, 855, 351},
|
||||
{1, 855, 849, 0, 0},
|
||||
{2, 855, 998, 893, 1086},
|
||||
{1, 893, 1102, 0, 0},
|
||||
{1, 699, 1102, 0, 0},
|
||||
{0, 392, 961, 0, 0},
|
||||
{2, 479, 961, 557, 916},
|
||||
{2, 635, 871, 670, 799},
|
||||
{1, 670, 577, 0, 0},
|
||||
{1, 525, 577, 0, 0},
|
||||
{2, 185, 577, 185, 776},
|
||||
{2, 185, 863, 243, 912},
|
||||
{2, 301, 961, 392, 961},
|
||||
}
|
||||
|
||||
func scaledBenchmarkGlyphData(height int) (width int, data []benchmarkGlyphDatum) {
|
||||
|
@ -412,10 +407,10 @@ func scaledBenchmarkGlyphData(height int) (width int, data []benchmarkGlyphDatum
|
|||
// Clone the benchmarkGlyphData slice and scale its coordinates.
|
||||
data = append(data, benchmarkGlyphData...)
|
||||
for i := range data {
|
||||
data[i].p[0] *= scale
|
||||
data[i].p[1] *= scale
|
||||
data[i].q[0] *= scale
|
||||
data[i].q[1] *= scale
|
||||
data[i].px *= scale
|
||||
data[i].py *= scale
|
||||
data[i].qx *= scale
|
||||
data[i].qy *= scale
|
||||
}
|
||||
|
||||
return int(math.Ceil(float64(benchmarkGlyphWidth * scale))), data
|
||||
|
@ -457,11 +452,11 @@ func benchGlyph(b *testing.B, colorModel byte, loose bool, height int, op draw.O
|
|||
for _, d := range data {
|
||||
switch d.n {
|
||||
case 0:
|
||||
z.MoveTo(d.p)
|
||||
z.MoveTo(d.px, d.py)
|
||||
case 1:
|
||||
z.LineTo(d.p)
|
||||
z.LineTo(d.px, d.py)
|
||||
case 2:
|
||||
z.QuadTo(d.p, d.q)
|
||||
z.QuadTo(d.px, d.py, d.qx, d.qy)
|
||||
}
|
||||
}
|
||||
z.Draw(dst, bounds, src, image.Point{})
|
||||
|
|
Loading…
Reference in New Issue
Block a user