undid some of the changes from the last update since it didn't work properly; added some tests
This commit is contained in:
parent
c5d148331b
commit
c1f855278d
7 changed files with 104 additions and 76 deletions
17
canvas.go
17
canvas.go
|
@ -43,7 +43,7 @@ type drawState struct {
|
||||||
lineAlpha float64
|
lineAlpha float64
|
||||||
lineWidth float64
|
lineWidth float64
|
||||||
lineJoin lineJoin
|
lineJoin lineJoin
|
||||||
lineEnd lineEnd
|
lineCap lineCap
|
||||||
miterLimitSqr float64
|
miterLimitSqr float64
|
||||||
globalAlpha float64
|
globalAlpha float64
|
||||||
|
|
||||||
|
@ -83,9 +83,9 @@ type scissor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type lineJoin uint8
|
type lineJoin uint8
|
||||||
type lineEnd uint8
|
type lineCap uint8
|
||||||
|
|
||||||
// Line join and end constants for SetLineJoin and SetLineEnd
|
// Line join and end constants for SetLineJoin and SetLineCap
|
||||||
const (
|
const (
|
||||||
Miter = iota
|
Miter = iota
|
||||||
Bevel
|
Bevel
|
||||||
|
@ -729,10 +729,15 @@ func (cv *Canvas) SetLineJoin(join lineJoin) {
|
||||||
cv.state.lineJoin = join
|
cv.state.lineJoin = join
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLineEnd sets the style of line endings for rendering a path with Stroke
|
// SetLineEnd is a synonym for SetLineCap that was misnamed by mistake. Deprecated
|
||||||
|
func (cv *Canvas) SetLineEnd(cap lineCap) {
|
||||||
|
cv.SetLineCap(cap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLineCap sets the style of line endings for rendering a path with Stroke
|
||||||
// The value can be Butt, Square, or Round
|
// The value can be Butt, Square, or Round
|
||||||
func (cv *Canvas) SetLineEnd(end lineEnd) {
|
func (cv *Canvas) SetLineCap(cap lineCap) {
|
||||||
cv.state.lineEnd = end
|
cv.state.lineCap = cap
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLineDash sets the line dash style
|
// SetLineDash sets the line dash style
|
||||||
|
|
|
@ -469,3 +469,53 @@ func TestConvexSelfIntersecting(t *testing.T) {
|
||||||
cv.Fill()
|
cv.Fill()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransform(t *testing.T) {
|
||||||
|
run(t, func(cv *canvas.Canvas) {
|
||||||
|
path := canvas.NewPath2D()
|
||||||
|
path.MoveTo(-10, -10)
|
||||||
|
path.LineTo(10, -10)
|
||||||
|
path.LineTo(0, 10)
|
||||||
|
path.ClosePath()
|
||||||
|
|
||||||
|
cv.Translate(40, 20)
|
||||||
|
cv.BeginPath()
|
||||||
|
cv.LineTo(10, 10)
|
||||||
|
cv.LineTo(30, 10)
|
||||||
|
cv.LineTo(20, 30)
|
||||||
|
cv.ClosePath()
|
||||||
|
cv.SetStrokeStyle("#F00")
|
||||||
|
cv.Stroke()
|
||||||
|
cv.SetStrokeStyle("#0F0")
|
||||||
|
cv.StrokePath(path)
|
||||||
|
cv.Translate(20, 0)
|
||||||
|
cv.SetStrokeStyle("#00F")
|
||||||
|
cv.StrokePath(path)
|
||||||
|
cv.Translate(-40, 30)
|
||||||
|
cv.BeginPath()
|
||||||
|
cv.LineTo(10, 10)
|
||||||
|
cv.LineTo(30, 10)
|
||||||
|
cv.LineTo(20, 30)
|
||||||
|
cv.ClosePath()
|
||||||
|
cv.Translate(20, 0)
|
||||||
|
cv.SetStrokeStyle("#FF0")
|
||||||
|
cv.Stroke()
|
||||||
|
cv.Translate(20, 0)
|
||||||
|
cv.SetStrokeStyle("#F0F")
|
||||||
|
cv.StrokePath(path)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransform2(t *testing.T) {
|
||||||
|
run(t, func(cv *canvas.Canvas) {
|
||||||
|
cv.SetStrokeStyle("#FFF")
|
||||||
|
cv.SetLineWidth(16)
|
||||||
|
cv.MoveTo(20, 20)
|
||||||
|
cv.LineTo(20, 50)
|
||||||
|
cv.Scale(2, 1)
|
||||||
|
cv.LineTo(45, 80)
|
||||||
|
cv.SetLineJoin(canvas.Round)
|
||||||
|
cv.SetLineCap(canvas.Round)
|
||||||
|
cv.Stroke()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ type Path2D struct {
|
||||||
|
|
||||||
type pathPoint struct {
|
type pathPoint struct {
|
||||||
pos vec
|
pos vec
|
||||||
tf vec
|
|
||||||
next vec
|
next vec
|
||||||
flags pathPointFlag
|
flags pathPointFlag
|
||||||
}
|
}
|
||||||
|
@ -39,7 +38,7 @@ func (p *Path2D) MoveTo(x, y float64) {
|
||||||
if len(p.p) > 0 && isSamePoint(p.p[len(p.p)-1].pos, vec{x, y}, 0.1) {
|
if len(p.p) > 0 && isSamePoint(p.p[len(p.p)-1].pos, vec{x, y}, 0.1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.p = append(p.p, pathPoint{pos: vec{x, y}, tf: vec{x, y}, flags: pathMove}) // todo more flags probably
|
p.p = append(p.p, pathPoint{pos: vec{x, y}, flags: pathMove}) // todo more flags probably
|
||||||
p.cwSum = 0
|
p.cwSum = 0
|
||||||
p.move = vec{x, y}
|
p.move = vec{x, y}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +60,7 @@ func (p *Path2D) lineTo(x, y float64, checkSelfIntersection bool) {
|
||||||
prev := &p.p[count-1]
|
prev := &p.p[count-1]
|
||||||
prev.next = vec{x, y}
|
prev.next = vec{x, y}
|
||||||
prev.flags |= pathAttach
|
prev.flags |= pathAttach
|
||||||
p.p = append(p.p, pathPoint{pos: vec{x, y}, tf: vec{x, y}})
|
p.p = append(p.p, pathPoint{pos: vec{x, y}})
|
||||||
newp := &p.p[count]
|
newp := &p.p[count]
|
||||||
|
|
||||||
px, py := prev.pos[0], prev.pos[1]
|
px, py := prev.pos[0], prev.pos[1]
|
||||||
|
|
103
paths.go
103
paths.go
|
@ -77,10 +77,16 @@ func (cv *Canvas) Stroke() {
|
||||||
|
|
||||||
// StrokePath uses the current StrokeStyle to draw the given path
|
// StrokePath uses the current StrokeStyle to draw the given path
|
||||||
func (cv *Canvas) StrokePath(path *Path2D) {
|
func (cv *Canvas) StrokePath(path *Path2D) {
|
||||||
for i := range path.p {
|
path2 := Path2D{
|
||||||
path.p[i].tf = cv.tf(path.p[i].pos)
|
p: make([]pathPoint, len(path.p)),
|
||||||
}
|
}
|
||||||
cv.strokePath(path)
|
// todo avoid allocation
|
||||||
|
for i, pt := range path.p {
|
||||||
|
path2.p[i].pos = cv.tf(pt.pos)
|
||||||
|
path2.p[i].next = cv.tf(pt.next)
|
||||||
|
path2.p[i].flags = pt.flags
|
||||||
|
}
|
||||||
|
cv.strokePath(&path2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cv *Canvas) strokePath(path *Path2D) {
|
func (cv *Canvas) strokePath(path *Path2D) {
|
||||||
|
@ -116,7 +122,7 @@ func (cv *Canvas) strokePath(path *Path2D) {
|
||||||
lp3 := p1.sub(v1)
|
lp3 := p1.sub(v1)
|
||||||
|
|
||||||
if start {
|
if start {
|
||||||
switch cv.state.lineEnd {
|
switch cv.state.lineCap {
|
||||||
case Butt:
|
case Butt:
|
||||||
// no need to do anything
|
// no need to do anything
|
||||||
case Square:
|
case Square:
|
||||||
|
@ -128,7 +134,7 @@ func (cv *Canvas) strokePath(path *Path2D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.flags&pathAttach == 0 {
|
if p.flags&pathAttach == 0 {
|
||||||
switch cv.state.lineEnd {
|
switch cv.state.lineCap {
|
||||||
case Butt:
|
case Butt:
|
||||||
// no need to do anything
|
// no need to do anything
|
||||||
case Square:
|
case Square:
|
||||||
|
@ -139,14 +145,9 @@ func (cv *Canvas) strokePath(path *Path2D) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lp0tf := cv.tf(lp0)
|
|
||||||
lp1tf := cv.tf(lp1)
|
|
||||||
lp2tf := cv.tf(lp2)
|
|
||||||
lp3tf := cv.tf(lp3)
|
|
||||||
|
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
float32(lp0tf[0]), float32(lp0tf[1]), float32(lp1tf[0]), float32(lp1tf[1]), float32(lp3tf[0]), float32(lp3tf[1]),
|
float32(lp0[0]), float32(lp0[1]), float32(lp1[0]), float32(lp1[1]), float32(lp3[0]), float32(lp3[1]),
|
||||||
float32(lp0tf[0]), float32(lp0tf[1]), float32(lp3tf[0]), float32(lp3tf[1]), float32(lp2tf[0]), float32(lp2tf[1]))
|
float32(lp0[0]), float32(lp0[1]), float32(lp3[0]), float32(lp3[1]), float32(lp2[0]), float32(lp2[1]))
|
||||||
|
|
||||||
if p.flags&pathAttach != 0 && cv.state.lineWidth > 1 {
|
if p.flags&pathAttach != 0 && cv.state.lineWidth > 1 {
|
||||||
tris = cv.lineJoint(p, p0, p1, p.next, lp0, lp1, lp2, lp3, tris)
|
tris = cv.lineJoint(p, p0, p1, p.next, lp0, lp1, lp2, lp3, tris)
|
||||||
|
@ -228,19 +229,17 @@ func (cv *Canvas) applyLineDash(path []pathPoint) []pathPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
v := pp.pos.sub(lp.pos)
|
v := pp.pos.sub(lp.pos)
|
||||||
vtf := pp.tf.sub(lp.tf)
|
|
||||||
vl := v.len()
|
vl := v.len()
|
||||||
prev := ldo
|
prev := ldo
|
||||||
for vl > 0 {
|
for vl > 0 {
|
||||||
draw := ldp%2 == 0
|
draw := ldp%2 == 0
|
||||||
newp := pathPoint{pos: pp.pos, tf: pp.tf}
|
newp := pathPoint{pos: pp.pos}
|
||||||
ldo += vl
|
ldo += vl
|
||||||
if ldo > cv.state.lineDash[ldp] {
|
if ldo > cv.state.lineDash[ldp] {
|
||||||
ldo = 0
|
ldo = 0
|
||||||
dl := cv.state.lineDash[ldp] - prev
|
dl := cv.state.lineDash[ldp] - prev
|
||||||
dist := dl / vl
|
dist := dl / vl
|
||||||
newp.pos = lp.pos.add(v.mulf(dist))
|
newp.pos = lp.pos.add(v.mulf(dist))
|
||||||
newp.tf = lp.tf.add(vtf.mulf(dist))
|
|
||||||
vl -= dl
|
vl -= dl
|
||||||
ldp++
|
ldp++
|
||||||
ldp %= len(cv.state.lineDash)
|
ldp %= len(cv.state.lineDash)
|
||||||
|
@ -250,7 +249,7 @@ func (cv *Canvas) applyLineDash(path []pathPoint) []pathPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
if draw {
|
if draw {
|
||||||
path2[len(path2)-1].next = newp.tf
|
path2[len(path2)-1].next = newp.pos
|
||||||
path2[len(path2)-1].flags |= pathAttach
|
path2[len(path2)-1].flags |= pathAttach
|
||||||
path2 = append(path2, newp)
|
path2 = append(path2, newp)
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,7 +259,6 @@ func (cv *Canvas) applyLineDash(path []pathPoint) []pathPoint {
|
||||||
|
|
||||||
lp = newp
|
lp = newp
|
||||||
v = pp.pos.sub(lp.pos)
|
v = pp.pos.sub(lp.pos)
|
||||||
vtf = pp.tf.sub(lp.tf)
|
|
||||||
}
|
}
|
||||||
lp = pp
|
lp = pp
|
||||||
}
|
}
|
||||||
|
@ -272,20 +270,12 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 vec,
|
||||||
v2 := p1.sub(p2).norm()
|
v2 := p1.sub(p2).norm()
|
||||||
v3 := vec{v2[1], -v2[0]}.mulf(cv.state.lineWidth * 0.5)
|
v3 := vec{v2[1], -v2[0]}.mulf(cv.state.lineWidth * 0.5)
|
||||||
|
|
||||||
p1tf := cv.tf(p1)
|
|
||||||
|
|
||||||
switch cv.state.lineJoin {
|
switch cv.state.lineJoin {
|
||||||
case Miter:
|
case Miter:
|
||||||
l1p0 := p2.sub(v3)
|
l1p0 := p2.sub(v3)
|
||||||
l1p1 := p1.sub(v3)
|
l1p1 := p1.sub(v3)
|
||||||
l1p2 := p2.add(v3)
|
l1p2 := p2.add(v3)
|
||||||
l1p3 := p1.add(v3)
|
l1p3 := p1.add(v3)
|
||||||
// l0p0tf := cv.tf(l0p0)
|
|
||||||
l0p1tf := cv.tf(l0p1)
|
|
||||||
// l0p2tf := cv.tf(l0p2)
|
|
||||||
l0p3tf := cv.tf(l0p3)
|
|
||||||
// l1p0tf := cv.tf(l1p0)
|
|
||||||
// l1p2tf := cv.tf(l1p2)
|
|
||||||
|
|
||||||
var ip0, ip1 vec
|
var ip0, ip1 vec
|
||||||
if l0p1.sub(l1p1).lenSqr() < 0.000000001 {
|
if l0p1.sub(l1p1).lenSqr() < 0.000000001 {
|
||||||
|
@ -301,12 +291,10 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 vec,
|
||||||
if dist := ip0.sub(l0p1).lenSqr(); dist > cv.state.miterLimitSqr {
|
if dist := ip0.sub(l0p1).lenSqr(); dist > cv.state.miterLimitSqr {
|
||||||
l1p1 := p1.sub(v3)
|
l1p1 := p1.sub(v3)
|
||||||
l1p3 := p1.add(v3)
|
l1p3 := p1.add(v3)
|
||||||
l1p1tf := cv.tf(l1p1)
|
|
||||||
l1p3tf := cv.tf(l1p3)
|
|
||||||
|
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l0p1tf[0]), float32(l0p1tf[1]), float32(l1p1tf[0]), float32(l1p1tf[1]),
|
float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(l1p1[0]), float32(l1p1[1]),
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l1p3tf[0]), float32(l1p3tf[1]), float32(l0p3tf[0]), float32(l0p3tf[1]))
|
float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(l0p3[0]), float32(l0p3[1]))
|
||||||
return tris
|
return tris
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,37 +311,25 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 vec,
|
||||||
if dist := ip1.sub(l1p1).lenSqr(); dist > cv.state.miterLimitSqr {
|
if dist := ip1.sub(l1p1).lenSqr(); dist > cv.state.miterLimitSqr {
|
||||||
l1p1 := p1.sub(v3)
|
l1p1 := p1.sub(v3)
|
||||||
l1p3 := p1.add(v3)
|
l1p3 := p1.add(v3)
|
||||||
l1p1tf := cv.tf(l1p1)
|
|
||||||
l1p3tf := cv.tf(l1p3)
|
|
||||||
|
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l0p1tf[0]), float32(l0p1tf[1]), float32(l1p1tf[0]), float32(l1p1tf[1]),
|
float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(l1p1[0]), float32(l1p1[1]),
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l1p3tf[0]), float32(l1p3tf[1]), float32(l0p3tf[0]), float32(l0p3tf[1]))
|
float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(l0p3[0]), float32(l0p3[1]))
|
||||||
return tris
|
return tris
|
||||||
}
|
}
|
||||||
|
|
||||||
ip0tf := cv.tf(ip0)
|
|
||||||
ip1tf := cv.tf(ip1)
|
|
||||||
l1p1tf := cv.tf(l1p1)
|
|
||||||
l1p3tf := cv.tf(l1p3)
|
|
||||||
|
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l0p1tf[0]), float32(l0p1tf[1]), float32(ip0tf[0]), float32(ip0tf[1]),
|
float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(ip0[0]), float32(ip0[1]),
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(ip0tf[0]), float32(ip0tf[1]), float32(l1p1tf[0]), float32(l1p1tf[1]),
|
float32(p1[0]), float32(p1[1]), float32(ip0[0]), float32(ip0[1]), float32(l1p1[0]), float32(l1p1[1]),
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l1p3tf[0]), float32(l1p3tf[1]), float32(ip1tf[0]), float32(ip1tf[1]),
|
float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(ip1[0]), float32(ip1[1]),
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(ip1tf[0]), float32(ip1tf[1]), float32(l0p3tf[0]), float32(l0p3tf[1]))
|
float32(p1[0]), float32(p1[1]), float32(ip1[0]), float32(ip1[1]), float32(l0p3[0]), float32(l0p3[1]))
|
||||||
case Bevel:
|
case Bevel:
|
||||||
l1p1 := p1.sub(v3)
|
l1p1 := p1.sub(v3)
|
||||||
l1p3 := p1.add(v3)
|
l1p3 := p1.add(v3)
|
||||||
|
|
||||||
l0p1tf := cv.tf(l0p1)
|
|
||||||
l0p3tf := cv.tf(l0p3)
|
|
||||||
l1p1tf := cv.tf(l1p1)
|
|
||||||
l1p3tf := cv.tf(l1p3)
|
|
||||||
|
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l0p1tf[0]), float32(l0p1tf[1]), float32(l1p1tf[0]), float32(l1p1tf[1]),
|
float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(l1p1[0]), float32(l1p1[1]),
|
||||||
float32(p1tf[0]), float32(p1tf[1]), float32(l1p3tf[0]), float32(l1p3tf[1]), float32(l0p3tf[0]), float32(l0p3tf[1]))
|
float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(l0p3[0]), float32(l0p3[1]))
|
||||||
case Round:
|
case Round:
|
||||||
tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris)
|
tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris)
|
||||||
}
|
}
|
||||||
|
@ -368,13 +344,12 @@ func (cv *Canvas) addCircleTris(center vec, radius float64, tris []float32) []fl
|
||||||
} else if step < 0.05 {
|
} else if step < 0.05 {
|
||||||
step = 0.05
|
step = 0.05
|
||||||
}
|
}
|
||||||
tfcenter := cv.tf(center)
|
p0 := vec{center[0], center[1] + radius}
|
||||||
p0 := cv.tf(vec{center[0], center[1] + radius})
|
|
||||||
for angle := step; angle <= math.Pi*2+step; angle += step {
|
for angle := step; angle <= math.Pi*2+step; angle += step {
|
||||||
s, c := math.Sincos(angle)
|
s, c := math.Sincos(angle)
|
||||||
p1 := cv.tf(vec{center[0] + s*radius, center[1] + c*radius})
|
p1 := vec{center[0] + s*radius, center[1] + c*radius}
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
float32(tfcenter[0]), float32(tfcenter[1]), float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]))
|
float32(center[0]), float32(center[1]), float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]))
|
||||||
p0 = p1
|
p0 = p1
|
||||||
}
|
}
|
||||||
return tris
|
return tris
|
||||||
|
@ -485,10 +460,10 @@ func (cv *Canvas) FillPath(path *Path2D) {
|
||||||
func (cv *Canvas) appendSubPathTriangles(tris []float32, path []pathPoint) []float32 {
|
func (cv *Canvas) appendSubPathTriangles(tris []float32, path []pathPoint) []float32 {
|
||||||
last := path[len(path)-1]
|
last := path[len(path)-1]
|
||||||
if last.flags&pathIsConvex != 0 {
|
if last.flags&pathIsConvex != 0 {
|
||||||
p0, p1 := path[0].tf, path[1].tf
|
p0, p1 := path[0].pos, path[1].pos
|
||||||
last := len(path)
|
last := len(path)
|
||||||
for i := 2; i < last; i++ {
|
for i := 2; i < last; i++ {
|
||||||
p2 := path[i].tf
|
p2 := path[i].pos
|
||||||
tris = append(tris, float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]))
|
tris = append(tris, float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]))
|
||||||
p1 = p2
|
p1 = p2
|
||||||
}
|
}
|
||||||
|
@ -580,10 +555,10 @@ func (cv *Canvas) clip(path []pathPoint) {
|
||||||
func (cv *Canvas) scissor(path []pathPoint) {
|
func (cv *Canvas) scissor(path []pathPoint) {
|
||||||
tl, br := vec{math.MaxFloat64, math.MaxFloat64}, vec{}
|
tl, br := vec{math.MaxFloat64, math.MaxFloat64}, vec{}
|
||||||
for _, p := range path {
|
for _, p := range path {
|
||||||
tl[0] = math.Min(p.tf[0], tl[0])
|
tl[0] = math.Min(p.pos[0], tl[0])
|
||||||
tl[1] = math.Min(p.tf[1], tl[1])
|
tl[1] = math.Min(p.pos[1], tl[1])
|
||||||
br[0] = math.Max(p.tf[0], br[0])
|
br[0] = math.Max(p.pos[0], br[0])
|
||||||
br[1] = math.Max(p.tf[1], br[1])
|
br[1] = math.Max(p.pos[1], br[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
if cv.state.scissor.on {
|
if cv.state.scissor.on {
|
||||||
|
@ -628,11 +603,11 @@ func (cv *Canvas) StrokeRect(x, y, w, h float64) {
|
||||||
v3 := vec{x, y + h}
|
v3 := vec{x, y + h}
|
||||||
v0t, v1t, v2t, v3t := cv.tf(v0), cv.tf(v1), cv.tf(v2), cv.tf(v3)
|
v0t, v1t, v2t, v3t := cv.tf(v0), cv.tf(v1), cv.tf(v2), cv.tf(v3)
|
||||||
var p [5]pathPoint
|
var p [5]pathPoint
|
||||||
p[0] = pathPoint{pos: v0, tf: v0t, flags: pathMove | pathAttach, next: v1t}
|
p[0] = pathPoint{pos: v0t, flags: pathMove | pathAttach, next: v1t}
|
||||||
p[1] = pathPoint{pos: v1, tf: v1t, next: v2, flags: pathAttach}
|
p[1] = pathPoint{pos: v1t, next: v2, flags: pathAttach}
|
||||||
p[2] = pathPoint{pos: v2, tf: v2t, next: v3, flags: pathAttach}
|
p[2] = pathPoint{pos: v2t, next: v3, flags: pathAttach}
|
||||||
p[3] = pathPoint{pos: v3, tf: v3t, next: v0, flags: pathAttach}
|
p[3] = pathPoint{pos: v3t, next: v0, flags: pathAttach}
|
||||||
p[4] = pathPoint{pos: v0, tf: v0t, next: v1, flags: pathAttach}
|
p[4] = pathPoint{pos: v0t, next: v1, flags: pathAttach}
|
||||||
path := Path2D{p: p[:]}
|
path := Path2D{p: p[:]}
|
||||||
cv.strokePath(&path)
|
cv.strokePath(&path)
|
||||||
}
|
}
|
||||||
|
|
BIN
testdata/Transform.png
vendored
Executable file
BIN
testdata/Transform.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 498 B |
BIN
testdata/Transform2.png
vendored
Executable file
BIN
testdata/Transform2.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 543 B |
|
@ -66,7 +66,7 @@ func triangulatePath(path []pathPoint, target []float32) []float32 {
|
||||||
var buf [500]vec
|
var buf [500]vec
|
||||||
polygon := buf[:0]
|
polygon := buf[:0]
|
||||||
for _, p := range path {
|
for _, p := range path {
|
||||||
polygon = append(polygon, p.tf)
|
polygon = append(polygon, p.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
for len(polygon) > 2 {
|
for len(polygon) > 2 {
|
||||||
|
@ -161,9 +161,8 @@ func (cv *Canvas) cutIntersections(path []pathPoint) []pathPoint {
|
||||||
|
|
||||||
for _, cut := range cuts {
|
for _, cut := range cuts {
|
||||||
copy(newPath[cut.to+1:], newPath[cut.to:])
|
copy(newPath[cut.to+1:], newPath[cut.to:])
|
||||||
newPath[cut.to].next = newPath[cut.to+1].tf
|
newPath[cut.to].next = newPath[cut.to+1].pos
|
||||||
newPath[cut.to].pos = cut.point
|
newPath[cut.to].pos = cut.point
|
||||||
newPath[cut.to].tf = cv.tf(cut.point)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPath
|
return newPath
|
||||||
|
|
Loading…
Reference in a new issue