From 1711693a57ee77be1f0b0b0043e8fe9c99af4c51 Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Fri, 27 Mar 2020 21:39:19 +0100 Subject: [PATCH] fixed text stroke scaling --- canvas.go | 2 +- path2d.go | 2 +- paths.go | 52 +++++++++++++++++++++++----------------------- testdata/Text.png | Bin 1913 -> 1931 bytes text.go | 2 +- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/canvas.go b/canvas.go index bcc4582..997afdf 100644 --- a/canvas.go +++ b/canvas.go @@ -458,7 +458,7 @@ func (cv *Canvas) IsPointInStroke(x, y float64) bool { } var triBuf [500]backendbase.Vec - tris := cv.strokeTris(&cv.path, cv.state.transform.Invert(), true, triBuf[:0]) + tris := cv.strokeTris(&cv.path, cv.state.transform, cv.state.transform.Invert(), true, triBuf[:0]) pt := backendbase.Vec{x, y} diff --git a/path2d.go b/path2d.go index d40c1c8..4c9376e 100644 --- a/path2d.go +++ b/path2d.go @@ -480,7 +480,7 @@ func (p *Path2D) IsPointInStroke(x, y float64) bool { } var triBuf [500]backendbase.Vec - tris := p.cv.strokeTris(p, backendbase.Mat{}, false, triBuf[:0]) + tris := p.cv.strokeTris(p, p.cv.state.transform, backendbase.Mat{}, false, triBuf[:0]) pt := backendbase.Vec{x, y} diff --git a/paths.go b/paths.go index cb63c2d..9080b07 100644 --- a/paths.go +++ b/paths.go @@ -86,7 +86,7 @@ func (cv *Canvas) ClosePath() { // Stroke uses the current StrokeStyle to draw the current path func (cv *Canvas) Stroke() { - cv.strokePath(&cv.path, cv.state.transform.Invert(), true) + cv.strokePath(&cv.path, cv.state.transform, cv.state.transform.Invert(), true) } // StrokePath uses the current StrokeStyle to draw the given path @@ -96,16 +96,16 @@ func (cv *Canvas) StrokePath(path *Path2D) { p: make([]pathPoint, len(path.p)), } copy(path2.p, path.p) - cv.strokePath(&path2, backendbase.Mat{}, false) + cv.strokePath(&path2, cv.state.transform, backendbase.Mat{}, false) } -func (cv *Canvas) strokePath(path *Path2D, inv backendbase.Mat, doInv bool) { +func (cv *Canvas) strokePath(path *Path2D, tf backendbase.Mat, inv backendbase.Mat, doInv bool) { if len(path.p) == 0 { return } var triBuf [500]backendbase.Vec - tris := cv.strokeTris(path, inv, doInv, triBuf[:0]) + tris := cv.strokeTris(path, tf, inv, doInv, triBuf[:0]) cv.drawShadow(tris, nil, true) @@ -113,7 +113,7 @@ func (cv *Canvas) strokePath(path *Path2D, inv backendbase.Mat, doInv bool) { cv.b.Fill(&stl, tris, backendbase.MatIdentity, true) } -func (cv *Canvas) strokeTris(path *Path2D, inv backendbase.Mat, doInv bool, target []backendbase.Vec) []backendbase.Vec { +func (cv *Canvas) strokeTris(path *Path2D, tf backendbase.Mat, inv backendbase.Mat, doInv bool, target []backendbase.Vec) []backendbase.Vec { if len(path.p) == 0 { return target } @@ -164,7 +164,7 @@ func (cv *Canvas) strokeTris(path *Path2D, inv backendbase.Mat, doInv bool, targ lp0 = lp0.Sub(v0) lp2 = lp2.Sub(v0) case Round: - target = cv.addCircleTris(p0, cv.state.lineWidth*0.5, target) + target = cv.addCircleTris(p0, cv.state.lineWidth*0.5, tf, target) } } @@ -176,14 +176,14 @@ func (cv *Canvas) strokeTris(path *Path2D, inv backendbase.Mat, doInv bool, targ lp1 = lp1.Add(v0) lp3 = lp3.Add(v0) case Round: - target = cv.addCircleTris(p1, cv.state.lineWidth*0.5, target) + target = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tf, target) } } - target = append(target, cv.tf(lp0), cv.tf(lp1), cv.tf(lp3), cv.tf(lp0), cv.tf(lp3), cv.tf(lp2)) + target = append(target, lp0.MulMat(tf), lp1.MulMat(tf), lp3.MulMat(tf), lp0.MulMat(tf), lp3.MulMat(tf), lp2.MulMat(tf)) if p.flags&pathAttach != 0 && cv.state.lineWidth > 1 { - target = cv.lineJoint(p0, p1, p.next, lp0, lp1, lp2, lp3, target) + target = cv.lineJoint(p0, p1, p.next, lp0, lp1, lp2, lp3, tf, target) } p0 = p1 @@ -249,7 +249,7 @@ func (cv *Canvas) applyLineDash(path []pathPoint) []pathPoint { return path2 } -func (cv *Canvas) lineJoint(p0, p1, p2, l0p0, l0p1, l0p2, l0p3 backendbase.Vec, tris []backendbase.Vec) []backendbase.Vec { +func (cv *Canvas) lineJoint(p0, p1, p2, l0p0, l0p1, l0p2, l0p3 backendbase.Vec, tf backendbase.Mat, tris []backendbase.Vec) []backendbase.Vec { v2 := p1.Sub(p2).Norm() v3 := backendbase.Vec{v2[1], -v2[0]}.Mulf(cv.state.lineWidth * 0.5) @@ -275,8 +275,8 @@ func (cv *Canvas) lineJoint(p0, p1, p2, l0p0, l0p1, l0p2, l0p3 backendbase.Vec, l1p1 := p1.Sub(v3) l1p3 := p1.Add(v3) - tris = append(tris, cv.tf(p1), cv.tf(l0p1), cv.tf(l1p1), - cv.tf(p1), cv.tf(l1p3), cv.tf(l0p3)) + tris = append(tris, p1.MulMat(tf), l0p1.MulMat(tf), l1p1.MulMat(tf), + p1.MulMat(tf), l1p3.MulMat(tf), l0p3.MulMat(tf)) return tris } @@ -294,40 +294,40 @@ func (cv *Canvas) lineJoint(p0, p1, p2, l0p0, l0p1, l0p2, l0p3 backendbase.Vec, l1p1 := p1.Sub(v3) l1p3 := p1.Add(v3) - tris = append(tris, cv.tf(p1), cv.tf(l0p1), cv.tf(l1p1), - cv.tf(p1), cv.tf(l1p3), cv.tf(l0p3)) + tris = append(tris, p1.MulMat(tf), l0p1.MulMat(tf), l1p1.MulMat(tf), + p1.MulMat(tf), l1p3.MulMat(tf), l0p3.MulMat(tf)) return tris } - tris = append(tris, cv.tf(p1), cv.tf(l0p1), cv.tf(ip0), - cv.tf(p1), cv.tf(ip0), cv.tf(l1p1), - cv.tf(p1), cv.tf(l1p3), cv.tf(ip1), - cv.tf(p1), cv.tf(ip1), cv.tf(l0p3)) + tris = append(tris, p1.MulMat(tf), l0p1.MulMat(tf), ip0.MulMat(tf), + p1.MulMat(tf), ip0.MulMat(tf), l1p1.MulMat(tf), + p1.MulMat(tf), l1p3.MulMat(tf), ip1.MulMat(tf), + p1.MulMat(tf), ip1.MulMat(tf), l0p3.MulMat(tf)) case Bevel: l1p1 := p1.Sub(v3) l1p3 := p1.Add(v3) - tris = append(tris, cv.tf(p1), cv.tf(l0p1), cv.tf(l1p1), - cv.tf(p1), cv.tf(l1p3), cv.tf(l0p3)) + tris = append(tris, p1.MulMat(tf), l0p1.MulMat(tf), l1p1.MulMat(tf), + p1.MulMat(tf), l1p3.MulMat(tf), l0p3.MulMat(tf)) case Round: - tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris) + tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tf, tris) } return tris } -func (cv *Canvas) addCircleTris(center backendbase.Vec, radius float64, tris []backendbase.Vec) []backendbase.Vec { +func (cv *Canvas) addCircleTris(center backendbase.Vec, radius float64, tf backendbase.Mat, tris []backendbase.Vec) []backendbase.Vec { step := 6 / radius if step > 0.8 { step = 0.8 } else if step < 0.05 { step = 0.05 } - centertf := cv.tf(center) - p0 := cv.tf(backendbase.Vec{center[0], center[1] + radius}) + centertf := center.MulMat(tf) + p0 := backendbase.Vec{center[0], center[1] + radius}.MulMat(tf) for angle := step; angle <= math.Pi*2+step; angle += step { s, c := math.Sincos(angle) - p1 := cv.tf(backendbase.Vec{center[0] + s*radius, center[1] + c*radius}) + p1 := backendbase.Vec{center[0] + s*radius, center[1] + c*radius}.MulMat(tf) tris = append(tris, centertf, p0, p1) p0 = p1 } @@ -501,7 +501,7 @@ func (cv *Canvas) StrokeRect(x, y, w, h float64) { p[3] = pathPoint{pos: v3, next: v0, flags: pathAttach} p[4] = pathPoint{pos: v0, next: v1, flags: pathAttach} path := Path2D{p: p[:]} - cv.strokePath(&path, backendbase.Mat{}, false) + cv.strokePath(&path, cv.state.transform, backendbase.Mat{}, false) } // FillRect fills a rectangle with the active fill style diff --git a/testdata/Text.png b/testdata/Text.png index a7a1546390d885d1532e5f10fa565ece963f806d..eddca1ca631cf845714054e3fa485b25d6eee9e1 100755 GIT binary patch delta 1916 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 aSS~J{tQ;&Q$ioLLKLR&F-YdV0j{XnT{FjOV diff --git a/text.go b/text.go index 63d8fab..44f3a8b 100644 --- a/text.go +++ b/text.go @@ -307,7 +307,7 @@ func (cv *Canvas) StrokeText(str string, x, y float64) { path := cv.runePath(rn) tf := scaleMat.Mul(backendbase.MatTranslate(backendbase.Vec{x, y})).Mul(cv.state.transform) - cv.strokePath(path, tf, true) + cv.strokePath(path, tf, backendbase.Mat{}, false) x += float64(advance) / 64 }