From ff4c73b6b7929766b86d0bd72fd898c3ff7ad09e Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Wed, 17 Apr 2019 11:50:33 +0200 Subject: [PATCH] fixed a transformation issue --- canvas.go | 22 ++++++++++++++++++++-- canvas_test.go | 2 +- paths.go | 25 +++++++++++++++---------- triangulation.go | 4 ++-- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/canvas.go b/canvas.go index 94cf189..4bd68b2 100644 --- a/canvas.go +++ b/canvas.go @@ -142,6 +142,7 @@ func New(backend backendbase.Backend) *Canvas { cv.state.fill.color = color.RGBA{A: 255} cv.state.stroke.color = color.RGBA{A: 255} cv.state.transform = matIdentity() + cv.path.cv = cv return cv } @@ -393,7 +394,7 @@ func (cv *Canvas) Restore() { cv.b.ClearClip() for _, st := range cv.stateStack { if len(st.clip.p) > 0 { - cv.clip(&st.clip) + cv.clip(&st.clip, matIdentity()) } } cv.state = cv.stateStack[l-1] @@ -464,5 +465,22 @@ func (cv *Canvas) IsPointInPath(x, y float64, rule pathRule) bool { // IsPointInStroke returns true if the point is in the current // path stroke func (cv *Canvas) IsPointInStroke(x, y float64) bool { - return cv.path.IsPointInStroke(x, y) + if len(cv.path.p) == 0 { + return false + } + + var triBuf [500][2]float64 + tris := cv.strokeTris(&cv.path, cv.state.transform.invert(), true, triBuf[:0]) + + pt := vec{x, y} + + for i := 0; i < len(tris); i += 3 { + a := vec{tris[i][0], tris[i][1]} + b := vec{tris[i+1][0], tris[i+1][1]} + c := vec{tris[i+2][0], tris[i+2][1]} + if triangleContainsPoint(a, b, c, pt) { + return true + } + } + return false } diff --git a/canvas_test.go b/canvas_test.go index 6c3219f..82323f1 100644 --- a/canvas_test.go +++ b/canvas_test.go @@ -473,7 +473,7 @@ func TestConvexSelfIntersecting(t *testing.T) { func TestTransform(t *testing.T) { run(t, func(cv *canvas.Canvas) { - path := canvas.NewPath2D() + path := cv.NewPath2D() path.MoveTo(-10, -10) path.LineTo(10, -10) path.LineTo(0, 10) diff --git a/paths.go b/paths.go index 7570951..a411027 100644 --- a/paths.go +++ b/paths.go @@ -336,11 +336,16 @@ func lineIntersection(a0, a1, b0, b1 vec) (vec, float64, float64) { // Fill fills the current path with the current FillStyle func (cv *Canvas) Fill() { - cv.FillPath(&cv.path) + cv.fillPath(&cv.path, matIdentity()) } // FillPath fills the given path with the current FillStyle func (cv *Canvas) FillPath(path *Path2D) { + cv.fillPath(path, cv.state.transform) +} + +// FillPath fills the given path with the current FillStyle +func (cv *Canvas) fillPath(path *Path2D, tf mat) { if len(path.p) < 3 { return } @@ -348,7 +353,7 @@ func (cv *Canvas) FillPath(path *Path2D) { var triBuf [500][2]float64 tris := triBuf[:0] runSubPaths(path.p, func(sp []pathPoint) bool { - tris = appendSubPathTriangles(tris, sp) + tris = appendSubPathTriangles(tris, tf, sp) return false }) if len(tris) == 0 { @@ -361,23 +366,23 @@ func (cv *Canvas) FillPath(path *Path2D) { cv.b.Fill(&stl, tris) } -func appendSubPathTriangles(tris [][2]float64, path []pathPoint) [][2]float64 { +func appendSubPathTriangles(tris [][2]float64, mat mat, path []pathPoint) [][2]float64 { last := path[len(path)-1] if last.flags&pathIsConvex != 0 { - p0, p1 := path[0].pos, path[1].pos + p0, p1 := path[0].pos.mulMat(mat), path[1].pos.mulMat(mat) last := len(path) for i := 2; i < last; i++ { - p2 := path[i].pos + p2 := path[i].pos.mulMat(mat) tris = append(tris, p0, p1, p2) p1 = p2 } } else if last.flags&pathSelfIntersects != 0 { selfIntersectingPathParts(path, func(sp []pathPoint) bool { - tris = triangulatePath(sp, tris) + tris = triangulatePath(sp, mat, tris) return false }) } else { - tris = triangulatePath(path, tris) + tris = triangulatePath(path, mat, tris) } return tris } @@ -385,10 +390,10 @@ func appendSubPathTriangles(tris [][2]float64, path []pathPoint) [][2]float64 { // Clip uses the current path to clip any further drawing. Use Save/Restore to // remove the clipping again func (cv *Canvas) Clip() { - cv.clip(&cv.path) + cv.clip(&cv.path, matIdentity()) } -func (cv *Canvas) clip(path *Path2D) { +func (cv *Canvas) clip(path *Path2D, tf mat) { if len(path.p) < 3 { return } @@ -396,7 +401,7 @@ func (cv *Canvas) clip(path *Path2D) { var triBuf [500][2]float64 tris := triBuf[:0] runSubPaths(path.p, func(sp []pathPoint) bool { - tris = appendSubPathTriangles(tris, sp) + tris = appendSubPathTriangles(tris, tf, sp) return false }) if len(tris) == 0 { diff --git a/triangulation.go b/triangulation.go index f3ae316..7c1763b 100644 --- a/triangulation.go +++ b/triangulation.go @@ -84,11 +84,11 @@ func polygonContainsPoint(polygon []vec, p vec) bool { return count%2 == 1 } -func triangulatePath(path []pathPoint, target [][2]float64) [][2]float64 { +func triangulatePath(path []pathPoint, mat mat, target [][2]float64) [][2]float64 { var buf [500]vec polygon := buf[:0] for _, p := range path { - polygon = append(polygon, p.pos) + polygon = append(polygon, p.pos.mulMat(mat)) } for len(polygon) > 2 {