migrating to new curve package
This commit is contained in:
parent
216d3f60dd
commit
4b3ba53f4c
16 changed files with 192 additions and 178 deletions
2
arc.go
2
arc.go
|
@ -33,7 +33,7 @@ func arc(t VertexConverter, x, y, rx, ry, start, angle, scale float64) (lastX, l
|
||||||
curY = y + math.Sin(angle)*ry
|
curY = y + math.Sin(angle)*ry
|
||||||
|
|
||||||
angle += da
|
angle += da
|
||||||
t.Vertex(curX, curY)
|
t.AddPoint(curX, curY)
|
||||||
}
|
}
|
||||||
return curX, curY
|
return curX, curY
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func TraceArc(t LineTracer, x, y, rx, ry, start, angle, scale float64) {
|
||||||
curY = y + math.Sin(angle)*ry
|
curY = y + math.Sin(angle)*ry
|
||||||
|
|
||||||
angle += da
|
angle += da
|
||||||
t.LineTo(curX, curY)
|
t.AddPoint(curX, curY)
|
||||||
}
|
}
|
||||||
t.LineTo(curX, curY)
|
t.AddPoint(curX, curY)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@ const (
|
||||||
CurveRecursionLimit = 32
|
CurveRecursionLimit = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// x1, y1, cpx1, cpx2, cpx2, cpy2, x2, y2 float64
|
// x1, y1, cpx1, cpy1, cpx2, cpy2, x2, y2 float64
|
||||||
type CubicCurveFloat64 [8]float64
|
// type Cubic []float64
|
||||||
|
|
||||||
// Subdivide a Bezier cubic curve in 2 equivalents Bezier cubic curves.
|
// Subdivide a Bezier cubic curve in 2 equivalents Bezier cubic curves.
|
||||||
// c1 and c2 parameters are the resulting curves
|
// c1 and c2 parameters are the resulting curves
|
||||||
func (c *CubicCurveFloat64) Subdivide(c1, c2 *CubicCurveFloat64) {
|
func SubdivideCubic(c, c1, c2 []float64) {
|
||||||
// First point of c is the first point of c1
|
// First point of c is the first point of c1
|
||||||
c1[0], c1[1] = c[0], c[1]
|
c1[0], c1[1] = c[0], c[1]
|
||||||
// Last point of c is the last point of c2
|
// Last point of c is the last point of c2
|
||||||
|
@ -46,21 +46,21 @@ func (c *CubicCurveFloat64) Subdivide(c1, c2 *CubicCurveFloat64) {
|
||||||
c2[0], c2[1] = c1[6], c1[7]
|
c2[0], c2[1] = c1[6], c1[7]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace generate lines subdividing the curve using a LineTracer
|
// TraceCubic generate lines subdividing the cubic curve using a LineTracer
|
||||||
// flattening_threshold helps determines the flattening expectation of the curve
|
// flattening_threshold helps determines the flattening expectation of the curve
|
||||||
func (curve *CubicCurveFloat64) Trace(t LineTracer, flattening_threshold float64) {
|
func TraceCubic(t LineTracer, cubic []float64, flattening_threshold float64) {
|
||||||
// Allocation curves
|
// Allocation curves
|
||||||
var curves [CurveRecursionLimit]CubicCurveFloat64
|
var curves [CurveRecursionLimit * 8]float64
|
||||||
curves[0] = *curve
|
copy(curves[0:8], cubic[0:8])
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
// current curve
|
// current curve
|
||||||
var c *CubicCurveFloat64
|
var c []float64
|
||||||
|
|
||||||
var dx, dy, d2, d3 float64
|
var dx, dy, d2, d3 float64
|
||||||
|
|
||||||
for i >= 0 {
|
for i >= 0 {
|
||||||
c = &curves[i]
|
c = curves[i*8:]
|
||||||
dx = c[6] - c[0]
|
dx = c[6] - c[0]
|
||||||
dy = c[7] - c[1]
|
dy = c[7] - c[1]
|
||||||
|
|
||||||
|
@ -69,11 +69,11 @@ func (curve *CubicCurveFloat64) Trace(t LineTracer, flattening_threshold float64
|
||||||
|
|
||||||
// if it's flat then trace a line
|
// if it's flat then trace a line
|
||||||
if (d2+d3)*(d2+d3) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 {
|
if (d2+d3)*(d2+d3) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 {
|
||||||
t.LineTo(c[6], c[7])
|
t.AddPoint(c[6], c[7])
|
||||||
i--
|
i--
|
||||||
} else {
|
} else {
|
||||||
// second half of bezier go lower onto the stack
|
// second half of bezier go lower onto the stack
|
||||||
c.Subdivide(&curves[i+1], &curves[i])
|
SubdivideCubic(c, curves[(i+1)*8:], curves[i*8:])
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,35 +1,36 @@
|
||||||
package curve
|
package curve
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
"image/png"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/llgcode/draw2d"
|
|
||||||
"github.com/llgcode/draw2d/raster"
|
"github.com/llgcode/draw2d/raster"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
flattening_threshold float64 = 0.5
|
flattening_threshold float64 = 0.5
|
||||||
testsCubicFloat64 = []CubicCurveFloat64{
|
testsCubicFloat64 = []float64{
|
||||||
CubicCurveFloat64{100, 100, 200, 100, 100, 200, 200, 200},
|
100, 100, 200, 100, 100, 200, 200, 200,
|
||||||
CubicCurveFloat64{100, 100, 300, 200, 200, 200, 300, 100},
|
100, 100, 300, 200, 200, 200, 300, 100,
|
||||||
CubicCurveFloat64{100, 100, 0, 300, 200, 0, 300, 300},
|
100, 100, 0, 300, 200, 0, 300, 300,
|
||||||
CubicCurveFloat64{150, 290, 10, 10, 290, 10, 150, 290},
|
150, 290, 10, 10, 290, 10, 150, 290,
|
||||||
CubicCurveFloat64{10, 290, 10, 10, 290, 10, 290, 290},
|
10, 290, 10, 10, 290, 10, 290, 290,
|
||||||
CubicCurveFloat64{100, 290, 290, 10, 10, 10, 200, 290},
|
100, 290, 290, 10, 10, 10, 200, 290,
|
||||||
}
|
}
|
||||||
testsQuadFloat64 = []QuadCurveFloat64{
|
testsQuadFloat64 = []float64{
|
||||||
QuadCurveFloat64{100, 100, 200, 100, 200, 200},
|
100, 100, 200, 100, 200, 200,
|
||||||
QuadCurveFloat64{100, 100, 290, 200, 290, 100},
|
100, 100, 290, 200, 290, 100,
|
||||||
QuadCurveFloat64{100, 100, 0, 290, 200, 290},
|
100, 100, 0, 290, 200, 290,
|
||||||
QuadCurveFloat64{150, 290, 10, 10, 290, 290},
|
150, 290, 10, 10, 290, 290,
|
||||||
QuadCurveFloat64{10, 290, 10, 10, 290, 290},
|
10, 290, 10, 10, 290, 290,
|
||||||
QuadCurveFloat64{100, 290, 290, 10, 120, 290},
|
100, 290, 290, 10, 120, 290,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,16 +38,8 @@ type Path struct {
|
||||||
points []float64
|
points []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Path) LineTo(x, y float64) {
|
func (p *Path) AddPoint(x, y float64) {
|
||||||
if len(p.points)+2 > cap(p.points) {
|
p.points = append(p.points, x, y)
|
||||||
points := make([]float64, len(p.points)+2, len(p.points)+32)
|
|
||||||
copy(points, p.points)
|
|
||||||
p.points = points
|
|
||||||
} else {
|
|
||||||
p.points = p.points[0 : len(p.points)+2]
|
|
||||||
}
|
|
||||||
p.points[len(p.points)-2] = x
|
|
||||||
p.points[len(p.points)-1] = y
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -59,7 +52,7 @@ func init() {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
log.Printf("Create html viewer")
|
log.Printf("Create html viewer")
|
||||||
f.Write([]byte("<html><body>"))
|
f.Write([]byte("<html><body>"))
|
||||||
for i := 0; i < len(testsCubicFloat64); i++ {
|
for i := 0; i < len(testsCubicFloat64)/8; i++ {
|
||||||
f.Write([]byte(fmt.Sprintf("<div><img src='_test%d.png'/></div>\n", i)))
|
f.Write([]byte(fmt.Sprintf("<div><img src='_test%d.png'/></div>\n", i)))
|
||||||
}
|
}
|
||||||
for i := 0; i < len(testsQuadFloat64); i++ {
|
for i := 0; i < len(testsQuadFloat64); i++ {
|
||||||
|
@ -87,32 +80,32 @@ func drawPoints(img draw.Image, c color.Color, s ...float64) image.Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCubicCurve(t *testing.T) {
|
func TestCubicCurve(t *testing.T) {
|
||||||
for i, curve := range testsCubicFloat64 {
|
for i := 0; i < len(testsCubicFloat64); i += 8 {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(curve[0], curve[1])
|
p.AddPoint(testsCubicFloat64[i], testsCubicFloat64[i+1])
|
||||||
curve.Trace(&p, flattening_threshold)
|
TraceCubic(&p, testsCubicFloat64[i:], flattening_threshold)
|
||||||
img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
|
img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
|
||||||
raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
|
raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, testsCubicFloat64[i:i+8]...)
|
||||||
raster.PolylineBresenham(img, image.Black, p.points...)
|
raster.PolylineBresenham(img, image.Black, p.points...)
|
||||||
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
|
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
|
||||||
drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
|
drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
|
||||||
draw2d.SaveToPngFile(fmt.Sprintf("test_results/_test%d.png", i), img)
|
SaveToPngFile(fmt.Sprintf("test_results/_test%d.png", i/8), img)
|
||||||
log.Printf("Num of points: %d\n", len(p.points))
|
log.Printf("Num of points: %d\n", len(p.points))
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuadCurve(t *testing.T) {
|
func TestQuadCurve(t *testing.T) {
|
||||||
for i, curve := range testsQuadFloat64 {
|
for i := 0; i < len(testsQuadFloat64); i += 6 {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(curve[0], curve[1])
|
p.AddPoint(testsQuadFloat64[i], testsQuadFloat64[i+1])
|
||||||
curve.Trace(&p, flattening_threshold)
|
TraceQuad(&p, testsQuadFloat64[i:], flattening_threshold)
|
||||||
img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
|
img := image.NewNRGBA(image.Rect(0, 0, 300, 300))
|
||||||
raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, curve[:]...)
|
raster.PolylineBresenham(img, color.NRGBA{0xff, 0, 0, 0xff}, testsQuadFloat64[i:i+6]...)
|
||||||
raster.PolylineBresenham(img, image.Black, p.points...)
|
raster.PolylineBresenham(img, image.Black, p.points...)
|
||||||
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
|
//drawPoints(img, image.NRGBAColor{0, 0, 0, 0xff}, curve[:]...)
|
||||||
drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
|
drawPoints(img, color.NRGBA{0, 0, 0, 0xff}, p.points...)
|
||||||
draw2d.SaveToPngFile(fmt.Sprintf("test_results/_testQuad%d.png", i), img)
|
SaveToPngFile(fmt.Sprintf("test_results/_testQuad%d.png", i), img)
|
||||||
log.Printf("Num of points: %d\n", len(p.points))
|
log.Printf("Num of points: %d\n", len(p.points))
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
@ -120,10 +113,32 @@ func TestQuadCurve(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkCubicCurve(b *testing.B) {
|
func BenchmarkCubicCurve(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
for _, curve := range testsCubicFloat64 {
|
for i := 0; i < len(testsCubicFloat64); i += 8 {
|
||||||
p := Path{make([]float64, 0, 32)}
|
var p Path
|
||||||
p.LineTo(curve[0], curve[1])
|
p.AddPoint(testsCubicFloat64[i], testsCubicFloat64[i+1])
|
||||||
curve.Trace(&p, flattening_threshold)
|
TraceCubic(&p, testsCubicFloat64[i:], flattening_threshold)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveToPngFile create and save an image to a file using PNG format
|
||||||
|
func SaveToPngFile(filePath string, m image.Image) error {
|
||||||
|
// Create the file
|
||||||
|
f, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
// Create Writer from file
|
||||||
|
b := bufio.NewWriter(f)
|
||||||
|
// Write the image into the buffer
|
||||||
|
err = png.Encode(b, m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = b.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -8,12 +8,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// x1, y1, cpx1, cpy2, x2, y2 float64
|
// x1, y1, cpx1, cpy2, x2, y2 float64
|
||||||
type QuadCurveFloat64 [6]float64
|
// type Quad [6]float64
|
||||||
|
|
||||||
// Subdivide a Bezier quad curve in 2 equivalents Bezier quad curves.
|
// Subdivide a Bezier quad curve in 2 equivalents Bezier quad curves.
|
||||||
// c1 and c2 parameters are the resulting curves
|
// c1 and c2 parameters are the resulting curves
|
||||||
func (c *QuadCurveFloat64) Subdivide(c1, c2 *QuadCurveFloat64) {
|
func SubdivideQuad(c, c1, c2 []float64) {
|
||||||
|
|
||||||
// First point of c is the first point of c1
|
// First point of c is the first point of c1
|
||||||
c1[0], c1[1] = c[0], c[1]
|
c1[0], c1[1] = c[0], c[1]
|
||||||
// Last point of c is the last point of c2
|
// Last point of c is the last point of c2
|
||||||
|
@ -32,17 +31,17 @@ func (c *QuadCurveFloat64) Subdivide(c1, c2 *QuadCurveFloat64) {
|
||||||
|
|
||||||
// Trace generate lines subdividing the curve using a LineTracer
|
// Trace generate lines subdividing the curve using a LineTracer
|
||||||
// flattening_threshold helps determines the flattening expectation of the curve
|
// flattening_threshold helps determines the flattening expectation of the curve
|
||||||
func (curve *QuadCurveFloat64) Trace(t LineTracer, flattening_threshold float64) {
|
func TraceQuad(t LineTracer, quad []float64, flattening_threshold float64) {
|
||||||
// Allocates curves stack
|
// Allocates curves stack
|
||||||
var curves [CurveRecursionLimit]QuadCurveFloat64
|
var curves [CurveRecursionLimit * 6]float64
|
||||||
curves[0] = *curve
|
copy(curves[0:6], quad[0:6])
|
||||||
i := 0
|
i := 0
|
||||||
// current curve
|
// current curve
|
||||||
var c *QuadCurveFloat64
|
var c []float64
|
||||||
var dx, dy, d float64
|
var dx, dy, d float64
|
||||||
|
|
||||||
for i >= 0 {
|
for i >= 0 {
|
||||||
c = &curves[i]
|
c = curves[i*6:]
|
||||||
dx = c[4] - c[0]
|
dx = c[4] - c[0]
|
||||||
dy = c[5] - c[1]
|
dy = c[5] - c[1]
|
||||||
|
|
||||||
|
@ -50,11 +49,11 @@ func (curve *QuadCurveFloat64) Trace(t LineTracer, flattening_threshold float64)
|
||||||
|
|
||||||
// if it's flat then trace a line
|
// if it's flat then trace a line
|
||||||
if (d*d) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 {
|
if (d*d) < flattening_threshold*(dx*dx+dy*dy) || i == len(curves)-1 {
|
||||||
t.LineTo(c[4], c[5])
|
t.AddPoint(c[4], c[5])
|
||||||
i--
|
i--
|
||||||
} else {
|
} else {
|
||||||
// second half of bezier go lower onto the stack
|
// second half of bezier go lower onto the stack
|
||||||
c.Subdivide(&curves[i+1], &curves[i])
|
SubdivideQuad(c, curves[(i+1)*6:], curves[i*6:])
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,5 +2,6 @@ package curve
|
||||||
|
|
||||||
// LineTracer is an interface that help segmenting curve into small lines
|
// LineTracer is an interface that help segmenting curve into small lines
|
||||||
type LineTracer interface {
|
type LineTracer interface {
|
||||||
LineTo(x, y float64)
|
// AddPoint a point
|
||||||
|
AddPoint(x, y float64)
|
||||||
}
|
}
|
||||||
|
|
34
curves.go
34
curves.go
|
@ -88,7 +88,7 @@ func recursiveQuadraticBezierBezier(v VertexConverter, x1, y1, x2, y2, x3, y3 fl
|
||||||
// we tend to finish subdivisions.
|
// we tend to finish subdivisions.
|
||||||
//----------------------
|
//----------------------
|
||||||
if angleTolerance < CurveAngleToleranceEpsilon {
|
if angleTolerance < CurveAngleToleranceEpsilon {
|
||||||
v.Vertex(x123, y123)
|
v.AddPoint(x123, y123)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ func recursiveQuadraticBezierBezier(v VertexConverter, x1, y1, x2, y2, x3, y3 fl
|
||||||
if da < angleTolerance {
|
if da < angleTolerance {
|
||||||
// Finally we can stop the recursion
|
// Finally we can stop the recursion
|
||||||
//----------------------
|
//----------------------
|
||||||
v.Vertex(x123, y123)
|
v.AddPoint(x123, y123)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ func recursiveQuadraticBezierBezier(v VertexConverter, x1, y1, x2, y2, x3, y3 fl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if d < distanceToleranceSquare {
|
if d < distanceToleranceSquare {
|
||||||
v.Vertex(x2, y2)
|
v.AddPoint(x2, y2)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,12 +209,12 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
}
|
}
|
||||||
if d2 > d3 {
|
if d2 > d3 {
|
||||||
if d2 < distanceToleranceSquare {
|
if d2 < distanceToleranceSquare {
|
||||||
v.Vertex(x2, y2)
|
v.AddPoint(x2, y2)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if d3 < distanceToleranceSquare {
|
if d3 < distanceToleranceSquare {
|
||||||
v.Vertex(x3, y3)
|
v.AddPoint(x3, y3)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
//----------------------
|
//----------------------
|
||||||
if d3*d3 <= distanceToleranceSquare*(dx*dx+dy*dy) {
|
if d3*d3 <= distanceToleranceSquare*(dx*dx+dy*dy) {
|
||||||
if angleTolerance < CurveAngleToleranceEpsilon {
|
if angleTolerance < CurveAngleToleranceEpsilon {
|
||||||
v.Vertex(x23, y23)
|
v.AddPoint(x23, y23)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,14 +237,14 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
}
|
}
|
||||||
|
|
||||||
if da1 < angleTolerance {
|
if da1 < angleTolerance {
|
||||||
v.Vertex(x2, y2)
|
v.AddPoint(x2, y2)
|
||||||
v.Vertex(x3, y3)
|
v.AddPoint(x3, y3)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cuspLimit != 0.0 {
|
if cuspLimit != 0.0 {
|
||||||
if da1 > cuspLimit {
|
if da1 > cuspLimit {
|
||||||
v.Vertex(x3, y3)
|
v.AddPoint(x3, y3)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
//----------------------
|
//----------------------
|
||||||
if d2*d2 <= distanceToleranceSquare*(dx*dx+dy*dy) {
|
if d2*d2 <= distanceToleranceSquare*(dx*dx+dy*dy) {
|
||||||
if angleTolerance < CurveAngleToleranceEpsilon {
|
if angleTolerance < CurveAngleToleranceEpsilon {
|
||||||
v.Vertex(x23, y23)
|
v.AddPoint(x23, y23)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,14 +268,14 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
}
|
}
|
||||||
|
|
||||||
if da1 < angleTolerance {
|
if da1 < angleTolerance {
|
||||||
v.Vertex(x2, y2)
|
v.AddPoint(x2, y2)
|
||||||
v.Vertex(x3, y3)
|
v.AddPoint(x3, y3)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cuspLimit != 0.0 {
|
if cuspLimit != 0.0 {
|
||||||
if da1 > cuspLimit {
|
if da1 > cuspLimit {
|
||||||
v.Vertex(x2, y2)
|
v.AddPoint(x2, y2)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
// we tend to finish subdivisions.
|
// we tend to finish subdivisions.
|
||||||
//----------------------
|
//----------------------
|
||||||
if angleTolerance < CurveAngleToleranceEpsilon {
|
if angleTolerance < CurveAngleToleranceEpsilon {
|
||||||
v.Vertex(x23, y23)
|
v.AddPoint(x23, y23)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,18 +309,18 @@ func recursiveCubicBezier(v VertexConverter, x1, y1, x2, y2, x3, y3, x4, y4 floa
|
||||||
if da1+da2 < angleTolerance {
|
if da1+da2 < angleTolerance {
|
||||||
// Finally we can stop the recursion
|
// Finally we can stop the recursion
|
||||||
//----------------------
|
//----------------------
|
||||||
v.Vertex(x23, y23)
|
v.AddPoint(x23, y23)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cuspLimit != 0.0 {
|
if cuspLimit != 0.0 {
|
||||||
if da1 > cuspLimit {
|
if da1 > cuspLimit {
|
||||||
v.Vertex(x2, y2)
|
v.AddPoint(x2, y2)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if da2 > cuspLimit {
|
if da2 > cuspLimit {
|
||||||
v.Vertex(x3, y3)
|
v.AddPoint(x3, y3)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
dasher.go
12
dasher.go
|
@ -28,7 +28,7 @@ func (dasher *DashVertexConverter) NextCommand(cmd VertexCommand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dasher *DashVertexConverter) Vertex(x, y float64) {
|
func (dasher *DashVertexConverter) AddPoint(x, y float64) {
|
||||||
switch dasher.command {
|
switch dasher.command {
|
||||||
case VertexStartCommand:
|
case VertexStartCommand:
|
||||||
dasher.start(x, y)
|
dasher.start(x, y)
|
||||||
|
@ -40,7 +40,7 @@ func (dasher *DashVertexConverter) Vertex(x, y float64) {
|
||||||
|
|
||||||
func (dasher *DashVertexConverter) start(x, y float64) {
|
func (dasher *DashVertexConverter) start(x, y float64) {
|
||||||
dasher.next.NextCommand(VertexStartCommand)
|
dasher.next.NextCommand(VertexStartCommand)
|
||||||
dasher.next.Vertex(x, y)
|
dasher.next.AddPoint(x, y)
|
||||||
dasher.x, dasher.y = x, y
|
dasher.x, dasher.y = x, y
|
||||||
dasher.distance = dasher.dashOffset
|
dasher.distance = dasher.dashOffset
|
||||||
dasher.currentDash = 0
|
dasher.currentDash = 0
|
||||||
|
@ -60,12 +60,12 @@ func (dasher *DashVertexConverter) lineTo(x, y float64) {
|
||||||
ly := dasher.y + k*(y-dasher.y)
|
ly := dasher.y + k*(y-dasher.y)
|
||||||
if dasher.currentDash%2 == 0 {
|
if dasher.currentDash%2 == 0 {
|
||||||
// line
|
// line
|
||||||
dasher.next.Vertex(lx, ly)
|
dasher.next.AddPoint(lx, ly)
|
||||||
} else {
|
} else {
|
||||||
// gap
|
// gap
|
||||||
dasher.next.NextCommand(VertexStopCommand)
|
dasher.next.NextCommand(VertexStopCommand)
|
||||||
dasher.next.NextCommand(VertexStartCommand)
|
dasher.next.NextCommand(VertexStartCommand)
|
||||||
dasher.next.Vertex(lx, ly)
|
dasher.next.AddPoint(lx, ly)
|
||||||
}
|
}
|
||||||
d = d - rest
|
d = d - rest
|
||||||
dasher.x, dasher.y = lx, ly
|
dasher.x, dasher.y = lx, ly
|
||||||
|
@ -75,12 +75,12 @@ func (dasher *DashVertexConverter) lineTo(x, y float64) {
|
||||||
dasher.distance = d
|
dasher.distance = d
|
||||||
if dasher.currentDash%2 == 0 {
|
if dasher.currentDash%2 == 0 {
|
||||||
// line
|
// line
|
||||||
dasher.next.Vertex(x, y)
|
dasher.next.AddPoint(x, y)
|
||||||
} else {
|
} else {
|
||||||
// gap
|
// gap
|
||||||
dasher.next.NextCommand(VertexStopCommand)
|
dasher.next.NextCommand(VertexStopCommand)
|
||||||
dasher.next.NextCommand(VertexStartCommand)
|
dasher.next.NextCommand(VertexStartCommand)
|
||||||
dasher.next.Vertex(x, y)
|
dasher.next.AddPoint(x, y)
|
||||||
}
|
}
|
||||||
if dasher.distance >= dasher.dash[dasher.currentDash] {
|
if dasher.distance >= dasher.dash[dasher.currentDash] {
|
||||||
dasher.distance = dasher.distance - dasher.dash[dasher.currentDash]
|
dasher.distance = dasher.distance - dasher.dash[dasher.currentDash]
|
||||||
|
|
|
@ -16,8 +16,8 @@ func (dc *DemuxConverter) NextCommand(cmd VertexCommand) {
|
||||||
converter.NextCommand(cmd)
|
converter.NextCommand(cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (dc *DemuxConverter) Vertex(x, y float64) {
|
func (dc *DemuxConverter) AddPoint(x, y float64) {
|
||||||
for _, converter := range dc.converters {
|
for _, converter := range dc.converters {
|
||||||
converter.Vertex(x, y)
|
converter.AddPoint(x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ func (vertexAdder *VertexAdder) NextCommand(cmd VertexCommand) {
|
||||||
vertexAdder.command = cmd
|
vertexAdder.command = cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vertexAdder *VertexAdder) Vertex(x, y float64) {
|
func (vertexAdder *VertexAdder) AddPoint(x, y float64) {
|
||||||
switch vertexAdder.command {
|
switch vertexAdder.command {
|
||||||
case VertexStartCommand:
|
case VertexStartCommand:
|
||||||
vertexAdder.adder.Start(raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)})
|
vertexAdder.adder.Start(raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)})
|
||||||
|
|
|
@ -4,74 +4,73 @@
|
||||||
package draw2d
|
package draw2d
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/llgcode/draw2d/curve"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PathConverter struct {
|
type PathConverter struct {
|
||||||
converter VertexConverter
|
converter VertexConverter
|
||||||
ApproximationScale, AngleTolerance, CuspLimit float64
|
ApproximationScale float64
|
||||||
startX, startY, x, y float64
|
startX, startY, x, y float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPathConverter(converter VertexConverter) *PathConverter {
|
func NewPathConverter(converter VertexConverter) *PathConverter {
|
||||||
return &PathConverter{converter, 1, 0, 0, 0, 0, 0, 0}
|
return &PathConverter{converter, 1, 0, 0, 0, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PathConverter) Convert(paths ...*PathStorage) {
|
func (c *PathConverter) Convert(paths ...*PathStorage) {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
j := 0
|
i := 0
|
||||||
for _, cmd := range path.commands {
|
for _, cmd := range path.commands {
|
||||||
j = j + c.ConvertCommand(cmd, path.vertices[j:]...)
|
switch cmd {
|
||||||
|
case MoveTo:
|
||||||
|
c.x, c.y = path.vertices[i], path.vertices[i+1]
|
||||||
|
c.startX, c.startY = c.x, c.y
|
||||||
|
c.converter.NextCommand(VertexStopCommand)
|
||||||
|
c.converter.NextCommand(VertexStartCommand)
|
||||||
|
c.converter.AddPoint(c.x, c.y)
|
||||||
|
i += 2
|
||||||
|
case LineTo:
|
||||||
|
c.x, c.y = path.vertices[i], path.vertices[i+1]
|
||||||
|
if c.startX == c.x && c.startY == c.y {
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
}
|
||||||
|
c.converter.AddPoint(c.x, c.y)
|
||||||
|
c.converter.NextCommand(VertexJoinCommand)
|
||||||
|
i += 2
|
||||||
|
case QuadCurveTo:
|
||||||
|
curve.TraceQuad(c.converter, path.vertices[i-2:], 0.5)
|
||||||
|
c.x, c.y = path.vertices[i+2], path.vertices[i+3]
|
||||||
|
if c.startX == c.x && c.startY == c.y {
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
}
|
||||||
|
c.converter.AddPoint(c.x, c.y)
|
||||||
|
i += 4
|
||||||
|
case CubicCurveTo:
|
||||||
|
curve.TraceCubic(c.converter, path.vertices[i-2:], 0.5)
|
||||||
|
c.x, c.y = path.vertices[i+4], path.vertices[i+5]
|
||||||
|
if c.startX == c.x && c.startY == c.y {
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
}
|
||||||
|
c.converter.AddPoint(c.x, c.y)
|
||||||
|
i += 6
|
||||||
|
case ArcTo:
|
||||||
|
c.x, c.y = arc(c.converter, path.vertices[i], path.vertices[i+1], path.vertices[i+2], path.vertices[i+3], path.vertices[i+4], path.vertices[i+5], c.ApproximationScale)
|
||||||
|
if c.startX == c.x && c.startY == c.y {
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
}
|
||||||
|
c.converter.AddPoint(c.x, c.y)
|
||||||
|
i += 6
|
||||||
|
case Close:
|
||||||
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
|
c.converter.AddPoint(c.startX, c.startY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c.converter.NextCommand(VertexStopCommand)
|
c.converter.NextCommand(VertexStopCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PathConverter) ConvertCommand(cmd PathCmd, vertices ...float64) int {
|
func (c *PathConverter) convertCommand(cmd PathCmd, vertices ...float64) int {
|
||||||
switch cmd {
|
|
||||||
case MoveTo:
|
|
||||||
c.x, c.y = vertices[0], vertices[1]
|
|
||||||
c.startX, c.startY = c.x, c.y
|
|
||||||
c.converter.NextCommand(VertexStopCommand)
|
|
||||||
c.converter.NextCommand(VertexStartCommand)
|
|
||||||
c.converter.Vertex(c.x, c.y)
|
|
||||||
return 2
|
|
||||||
case LineTo:
|
|
||||||
c.x, c.y = vertices[0], vertices[1]
|
|
||||||
if c.startX == c.x && c.startY == c.y {
|
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
|
||||||
}
|
|
||||||
c.converter.Vertex(c.x, c.y)
|
|
||||||
c.converter.NextCommand(VertexJoinCommand)
|
|
||||||
return 2
|
|
||||||
case QuadCurveTo:
|
|
||||||
quadraticBezier(c.converter, c.x, c.y, vertices[0], vertices[1], vertices[2], vertices[3], c.ApproximationScale, c.AngleTolerance)
|
|
||||||
c.x, c.y = vertices[2], vertices[3]
|
|
||||||
if c.startX == c.x && c.startY == c.y {
|
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
|
||||||
}
|
|
||||||
c.converter.Vertex(c.x, c.y)
|
|
||||||
return 4
|
|
||||||
case CubicCurveTo:
|
|
||||||
cubicBezier(c.converter, c.x, c.y, vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5], c.ApproximationScale, c.AngleTolerance, c.CuspLimit)
|
|
||||||
c.x, c.y = vertices[4], vertices[5]
|
|
||||||
if c.startX == c.x && c.startY == c.y {
|
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
|
||||||
}
|
|
||||||
c.converter.Vertex(c.x, c.y)
|
|
||||||
return 6
|
|
||||||
case ArcTo:
|
|
||||||
c.x, c.y = arc(c.converter, vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5], c.ApproximationScale)
|
|
||||||
if c.startX == c.x && c.startY == c.y {
|
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
|
||||||
}
|
|
||||||
c.converter.Vertex(c.x, c.y)
|
|
||||||
return 6
|
|
||||||
case Close:
|
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
|
||||||
c.converter.Vertex(c.startX, c.startY)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ func (c *PathConverter) MoveTo(x, y float64) *PathConverter {
|
||||||
c.startX, c.startY = c.x, c.y
|
c.startX, c.startY = c.x, c.y
|
||||||
c.converter.NextCommand(VertexStopCommand)
|
c.converter.NextCommand(VertexStopCommand)
|
||||||
c.converter.NextCommand(VertexStartCommand)
|
c.converter.NextCommand(VertexStartCommand)
|
||||||
c.converter.Vertex(c.x, c.y)
|
c.converter.AddPoint(c.x, c.y)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ func (c *PathConverter) LineTo(x, y float64) *PathConverter {
|
||||||
if c.startX == c.x && c.startY == c.y {
|
if c.startX == c.x && c.startY == c.y {
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
}
|
}
|
||||||
c.converter.Vertex(c.x, c.y)
|
c.converter.AddPoint(c.x, c.y)
|
||||||
c.converter.NextCommand(VertexJoinCommand)
|
c.converter.NextCommand(VertexJoinCommand)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -105,12 +104,12 @@ func (c *PathConverter) RLineTo(dx, dy float64) *PathConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PathConverter) QuadCurveTo(cx, cy, x, y float64) *PathConverter {
|
func (c *PathConverter) QuadCurveTo(cx, cy, x, y float64) *PathConverter {
|
||||||
quadraticBezier(c.converter, c.x, c.y, cx, cy, x, y, c.ApproximationScale, c.AngleTolerance)
|
curve.TraceQuad(c.converter, []float64{c.x, c.y, cx, cy, x, y}, 0.5)
|
||||||
c.x, c.y = x, y
|
c.x, c.y = x, y
|
||||||
if c.startX == c.x && c.startY == c.y {
|
if c.startX == c.x && c.startY == c.y {
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
}
|
}
|
||||||
c.converter.Vertex(c.x, c.y)
|
c.converter.AddPoint(c.x, c.y)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,12 +119,12 @@ func (c *PathConverter) RQuadCurveTo(dcx, dcy, dx, dy float64) *PathConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PathConverter) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) *PathConverter {
|
func (c *PathConverter) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) *PathConverter {
|
||||||
cubicBezier(c.converter, c.x, c.y, cx1, cy1, cx2, cy2, x, y, c.ApproximationScale, c.AngleTolerance, c.CuspLimit)
|
curve.TraceCubic(c.converter, []float64{c.x, c.y, cx1, cy1, cx2, cy2, x, y}, 0.5)
|
||||||
c.x, c.y = x, y
|
c.x, c.y = x, y
|
||||||
if c.startX == c.x && c.startY == c.y {
|
if c.startX == c.x && c.startY == c.y {
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
}
|
}
|
||||||
c.converter.Vertex(c.x, c.y)
|
c.converter.AddPoint(c.x, c.y)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +156,7 @@ func (c *PathConverter) ArcTo(cx, cy, rx, ry, startAngle, angle float64) *PathCo
|
||||||
if c.startX == c.x && c.startY == c.y {
|
if c.startX == c.x && c.startY == c.y {
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
}
|
}
|
||||||
c.converter.Vertex(c.x, c.y)
|
c.converter.AddPoint(c.x, c.y)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +167,6 @@ func (c *PathConverter) RArcTo(dcx, dcy, rx, ry, startAngle, angle float64) *Pat
|
||||||
|
|
||||||
func (c *PathConverter) Close() *PathConverter {
|
func (c *PathConverter) Close() *PathConverter {
|
||||||
c.converter.NextCommand(VertexCloseCommand)
|
c.converter.NextCommand(VertexCloseCommand)
|
||||||
c.converter.Vertex(c.startX, c.startY)
|
c.converter.AddPoint(c.startX, c.startY)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,18 +39,8 @@ func (p *PathStorage) Clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathStorage) appendToPath(cmd PathCmd, vertices ...float64) {
|
func (p *PathStorage) appendToPath(cmd PathCmd, vertices ...float64) {
|
||||||
if cap(p.vertices) <= len(p.vertices)+6 {
|
p.commands = append(p.commands, cmd)
|
||||||
a := make([]PathCmd, len(p.commands), cap(p.commands)+256)
|
p.vertices = append(p.vertices, vertices...)
|
||||||
b := make([]float64, len(p.vertices), cap(p.vertices)+256)
|
|
||||||
copy(a, p.commands)
|
|
||||||
p.commands = a
|
|
||||||
copy(b, p.vertices)
|
|
||||||
p.vertices = b
|
|
||||||
}
|
|
||||||
p.commands = p.commands[0 : len(p.commands)+1]
|
|
||||||
p.commands[len(p.commands)-1] = cmd
|
|
||||||
copy(p.vertices[len(p.vertices):len(p.vertices)+len(vertices)], vertices)
|
|
||||||
p.vertices = p.vertices[0 : len(p.vertices)+len(vertices)]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (src *PathStorage) Copy() (dest *PathStorage) {
|
func (src *PathStorage) Copy() (dest *PathStorage) {
|
||||||
|
@ -77,6 +67,7 @@ func (p *PathStorage) Close() *PathStorage {
|
||||||
|
|
||||||
func (p *PathStorage) MoveTo(x, y float64) *PathStorage {
|
func (p *PathStorage) MoveTo(x, y float64) *PathStorage {
|
||||||
p.appendToPath(MoveTo, x, y)
|
p.appendToPath(MoveTo, x, y)
|
||||||
|
|
||||||
p.x = x
|
p.x = x
|
||||||
p.y = y
|
p.y = y
|
||||||
return p
|
return p
|
||||||
|
@ -89,6 +80,9 @@ func (p *PathStorage) RMoveTo(dx, dy float64) *PathStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathStorage) LineTo(x, y float64) *PathStorage {
|
func (p *PathStorage) LineTo(x, y float64) *PathStorage {
|
||||||
|
if len(p.commands) == 0 { //special case when no move has been done
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
}
|
||||||
p.appendToPath(LineTo, x, y)
|
p.appendToPath(LineTo, x, y)
|
||||||
p.x = x
|
p.x = x
|
||||||
p.y = y
|
p.y = y
|
||||||
|
@ -102,6 +96,9 @@ func (p *PathStorage) RLineTo(dx, dy float64) *PathStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathStorage) QuadCurveTo(cx, cy, x, y float64) *PathStorage {
|
func (p *PathStorage) QuadCurveTo(cx, cy, x, y float64) *PathStorage {
|
||||||
|
if len(p.commands) == 0 { //special case when no move has been done
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
}
|
||||||
p.appendToPath(QuadCurveTo, cx, cy, x, y)
|
p.appendToPath(QuadCurveTo, cx, cy, x, y)
|
||||||
p.x = x
|
p.x = x
|
||||||
p.y = y
|
p.y = y
|
||||||
|
@ -115,6 +112,9 @@ func (p *PathStorage) RQuadCurveTo(dcx, dcy, dx, dy float64) *PathStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathStorage) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) *PathStorage {
|
func (p *PathStorage) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) *PathStorage {
|
||||||
|
if len(p.commands) == 0 { //special case when no move has been done
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
}
|
||||||
p.appendToPath(CubicCurveTo, cx1, cy1, cx2, cy2, x, y)
|
p.appendToPath(CubicCurveTo, cx1, cy1, cx2, cy2, x, y)
|
||||||
p.x = x
|
p.x = x
|
||||||
p.y = y
|
p.y = y
|
||||||
|
|
|
@ -55,7 +55,7 @@ func TestFreetype(t *testing.T) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ func TestFreetypeNonZeroWinding(t *testing.T) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ func TestRasterizer(t *testing.T) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
||||||
|
@ -116,7 +116,7 @@ func TestRasterizerNonZeroWinding(t *testing.T) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
||||||
|
@ -131,7 +131,7 @@ func BenchmarkFreetype(b *testing.B) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ func BenchmarkFreetypeNonZeroWinding(b *testing.B) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ func BenchmarkRasterizerNonZeroWinding(b *testing.B) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
||||||
|
@ -189,7 +189,7 @@ func BenchmarkRasterizer(b *testing.B) {
|
||||||
var p Path
|
var p Path
|
||||||
p.LineTo(10, 190)
|
p.LineTo(10, 190)
|
||||||
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
c := curve.CubicCurveFloat64{10, 190, 10, 10, 190, 10, 190, 190}
|
||||||
c.Segment(&p, flattening_threshold)
|
c.Trace(&p, flattening_threshold)
|
||||||
poly := Polygon(p.points)
|
poly := Polygon(p.points)
|
||||||
color := color.RGBA{0, 0, 0, 0xff}
|
color := color.RGBA{0, 0, 0, 0xff}
|
||||||
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
tr := [6]float64{1, 0, 0, 1, 0, 0}
|
||||||
|
|
|
@ -47,16 +47,16 @@ func (l *LineStroker) NextCommand(command VertexCommand) {
|
||||||
if command == VertexStopCommand {
|
if command == VertexStopCommand {
|
||||||
l.Next.NextCommand(VertexStartCommand)
|
l.Next.NextCommand(VertexStartCommand)
|
||||||
for i, j := 0, 1; j < len(l.vertices); i, j = i+2, j+2 {
|
for i, j := 0, 1; j < len(l.vertices); i, j = i+2, j+2 {
|
||||||
l.Next.Vertex(l.vertices[i], l.vertices[j])
|
l.Next.AddPoint(l.vertices[i], l.vertices[j])
|
||||||
l.Next.NextCommand(VertexNoCommand)
|
l.Next.NextCommand(VertexNoCommand)
|
||||||
}
|
}
|
||||||
for i, j := len(l.rewind)-2, len(l.rewind)-1; j > 0; i, j = i-2, j-2 {
|
for i, j := len(l.rewind)-2, len(l.rewind)-1; j > 0; i, j = i-2, j-2 {
|
||||||
l.Next.NextCommand(VertexNoCommand)
|
l.Next.NextCommand(VertexNoCommand)
|
||||||
l.Next.Vertex(l.rewind[i], l.rewind[j])
|
l.Next.AddPoint(l.rewind[i], l.rewind[j])
|
||||||
}
|
}
|
||||||
if len(l.vertices) > 1 {
|
if len(l.vertices) > 1 {
|
||||||
l.Next.NextCommand(VertexNoCommand)
|
l.Next.NextCommand(VertexNoCommand)
|
||||||
l.Next.Vertex(l.vertices[0], l.vertices[1])
|
l.Next.AddPoint(l.vertices[0], l.vertices[1])
|
||||||
}
|
}
|
||||||
l.Next.NextCommand(VertexStopCommand)
|
l.Next.NextCommand(VertexStopCommand)
|
||||||
// reinit vertices
|
// reinit vertices
|
||||||
|
@ -66,7 +66,7 @@ func (l *LineStroker) NextCommand(command VertexCommand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LineStroker) Vertex(x, y float64) {
|
func (l *LineStroker) AddPoint(x, y float64) {
|
||||||
switch l.command {
|
switch l.command {
|
||||||
case VertexNoCommand:
|
case VertexNoCommand:
|
||||||
l.line(l.x, l.y, x, y)
|
l.line(l.x, l.y, x, y)
|
||||||
|
|
|
@ -266,10 +266,10 @@ func (vmt *VertexMatrixTransform) NextCommand(command VertexCommand) {
|
||||||
vmt.Next.NextCommand(command)
|
vmt.Next.NextCommand(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vmt *VertexMatrixTransform) Vertex(x, y float64) {
|
func (vmt *VertexMatrixTransform) AddPoint(x, y float64) {
|
||||||
u := x*vmt.tr[0] + y*vmt.tr[2] + vmt.tr[4]
|
u := x*vmt.tr[0] + y*vmt.tr[2] + vmt.tr[4]
|
||||||
v := x*vmt.tr[1] + y*vmt.tr[3] + vmt.tr[5]
|
v := x*vmt.tr[1] + y*vmt.tr[3] + vmt.tr[5]
|
||||||
vmt.Next.Vertex(u, v)
|
vmt.Next.AddPoint(u, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this adder apply a Matrix transformation to points
|
// this adder apply a Matrix transformation to points
|
||||||
|
|
|
@ -15,5 +15,5 @@ const (
|
||||||
|
|
||||||
type VertexConverter interface {
|
type VertexConverter interface {
|
||||||
NextCommand(cmd VertexCommand)
|
NextCommand(cmd VertexCommand)
|
||||||
Vertex(x, y float64)
|
AddPoint(x, y float64)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue