fixed Arc and ArcTo scaling
This commit is contained in:
parent
50c77477c9
commit
259bb9e598
4 changed files with 42 additions and 20 deletions
|
@ -141,7 +141,7 @@ func New(backend backendbase.Backend) *Canvas {
|
|||
cv.state.globalAlpha = 1
|
||||
cv.state.fill.color = color.RGBA{A: 255}
|
||||
cv.state.stroke.color = color.RGBA{A: 255}
|
||||
cv.state.transform = matIdentity()
|
||||
cv.state.transform = matIdentity
|
||||
cv.path.cv = cv
|
||||
return cv
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ func (cv *Canvas) Restore() {
|
|||
cv.b.ClearClip()
|
||||
for _, st := range cv.stateStack {
|
||||
if len(st.clip.p) > 0 {
|
||||
cv.clip(&st.clip, matIdentity())
|
||||
cv.clip(&st.clip, matIdentity)
|
||||
}
|
||||
}
|
||||
cv.state = cv.stateStack[l-1]
|
||||
|
|
4
math.go
4
math.go
|
@ -79,12 +79,10 @@ func (m *mat) String() string {
|
|||
return fmt.Sprintf("[%f,%f,0,\n %f,%f,0,\n %f,%f,1,]", m[0], m[2], m[4], m[1], m[3], m[5])
|
||||
}
|
||||
|
||||
func matIdentity() mat {
|
||||
return mat{
|
||||
var matIdentity = mat{
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 0}
|
||||
}
|
||||
|
||||
func matTranslate(v vec) mat {
|
||||
return mat{
|
||||
|
|
37
path2d.go
37
path2d.go
|
@ -114,13 +114,21 @@ func (p *Path2D) lineTo(x, y float64, checkSelfIntersection bool) {
|
|||
|
||||
// Arc (see equivalent function on canvas type)
|
||||
func (p *Path2D) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise bool) {
|
||||
p.arc(x, y, radius, startAngle, endAngle, anticlockwise, matIdentity, true)
|
||||
}
|
||||
|
||||
func (p *Path2D) arc(x, y, radius, startAngle, endAngle float64, anticlockwise bool, m mat, ident bool) {
|
||||
checkSelfIntersection := len(p.p) > 0
|
||||
|
||||
lastWasMove := len(p.p) == 0 || p.p[len(p.p)-1].flags&pathMove != 0
|
||||
|
||||
if endAngle == startAngle {
|
||||
s, c := math.Sincos(endAngle)
|
||||
p.lineTo(x+radius*c, y+radius*s, checkSelfIntersection)
|
||||
pt := vec{x + radius*c, y + radius*s}
|
||||
if !ident {
|
||||
pt = pt.mulMat(m)
|
||||
}
|
||||
p.lineTo(pt[0], pt[1], checkSelfIntersection)
|
||||
|
||||
if lastWasMove {
|
||||
p.p[len(p.p)-1].flags |= pathIsConvex
|
||||
|
@ -153,16 +161,28 @@ func (p *Path2D) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise b
|
|||
if !anticlockwise {
|
||||
for a := startAngle; a < endAngle; a += step {
|
||||
s, c := math.Sincos(a)
|
||||
p.lineTo(x+radius*c, y+radius*s, checkSelfIntersection)
|
||||
pt := vec{x + radius*c, y + radius*s}
|
||||
if !ident {
|
||||
pt = pt.mulMat(m)
|
||||
}
|
||||
p.lineTo(pt[0], pt[1], checkSelfIntersection)
|
||||
}
|
||||
} else {
|
||||
for a := startAngle; a > endAngle; a -= step {
|
||||
s, c := math.Sincos(a)
|
||||
p.lineTo(x+radius*c, y+radius*s, checkSelfIntersection)
|
||||
pt := vec{x + radius*c, y + radius*s}
|
||||
if !ident {
|
||||
pt = pt.mulMat(m)
|
||||
}
|
||||
p.lineTo(pt[0], pt[1], checkSelfIntersection)
|
||||
}
|
||||
}
|
||||
s, c := math.Sincos(endAngle)
|
||||
p.lineTo(x+radius*c, y+radius*s, checkSelfIntersection)
|
||||
pt := vec{x + radius*c, y + radius*s}
|
||||
if !ident {
|
||||
pt = pt.mulMat(m)
|
||||
}
|
||||
p.lineTo(pt[0], pt[1], checkSelfIntersection)
|
||||
|
||||
if lastWasMove {
|
||||
p.p[len(p.p)-1].flags |= pathIsConvex
|
||||
|
@ -171,10 +191,17 @@ func (p *Path2D) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise b
|
|||
|
||||
// ArcTo (see equivalent function on canvas type)
|
||||
func (p *Path2D) ArcTo(x1, y1, x2, y2, radius float64) {
|
||||
p.arcTo(x1, y1, x2, y2, radius, matIdentity, true)
|
||||
}
|
||||
|
||||
func (p *Path2D) arcTo(x1, y1, x2, y2, radius float64, m mat, ident bool) {
|
||||
if len(p.p) == 0 {
|
||||
return
|
||||
}
|
||||
p0, p1, p2 := p.p[len(p.p)-1].pos, vec{x1, y1}, vec{x2, y2}
|
||||
if !ident {
|
||||
p0 = p0.mulMat(m.invert())
|
||||
}
|
||||
v0, v1 := p0.sub(p1).norm(), p2.sub(p1).norm()
|
||||
angle := math.Acos(v0.dot(v1))
|
||||
// should be in the range [0-pi]. if parallel, use a straight line
|
||||
|
@ -201,7 +228,7 @@ func (p *Path2D) ArcTo(x1, y1, x2, y2, radius float64) {
|
|||
a1 += math.Pi * 2
|
||||
}
|
||||
}
|
||||
p.Arc(center[0], center[1], radius, a0, a1, x > 0)
|
||||
p.arc(center[0], center[1], radius, a0, a1, x > 0, m, ident)
|
||||
}
|
||||
|
||||
// QuadraticCurveTo (see equivalent function on canvas type)
|
||||
|
|
11
paths.go
11
paths.go
|
@ -32,11 +32,10 @@ func (cv *Canvas) LineTo(x, y float64) {
|
|||
// is the radius, startAngle and endAngle are angles in radians, anticlockwise
|
||||
// means that the line is added anticlockwise
|
||||
func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise bool) {
|
||||
tf := cv.tf(vec{x, y})
|
||||
ax, ay := math.Sincos(startAngle)
|
||||
startAngle2 := vec{ay, ax}.mulMat2(cv.state.transform.mat2()).atan2()
|
||||
endAngle2 := startAngle2 + (endAngle - startAngle)
|
||||
cv.path.Arc(tf[0], tf[1], radius, startAngle2, endAngle2, anticlockwise)
|
||||
cv.path.arc(x, y, radius, startAngle2, endAngle2, anticlockwise, cv.state.transform, false)
|
||||
}
|
||||
|
||||
// ArcTo adds to the current path by drawing a line toward x1/y1 and a circle
|
||||
|
@ -44,9 +43,7 @@ func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise
|
|||
// lines from the end of the path to x1/y1, and from x1/y1 to x2/y2. The line
|
||||
// will only go to where the circle segment would touch the latter line
|
||||
func (cv *Canvas) ArcTo(x1, y1, x2, y2, radius float64) {
|
||||
tf1 := cv.tf(vec{x1, y1})
|
||||
tf2 := cv.tf(vec{x2, y2})
|
||||
cv.path.ArcTo(tf1[0], tf1[1], tf2[0], tf2[1], radius)
|
||||
cv.path.arcTo(x1, y1, x2, y2, radius, cv.state.transform, false)
|
||||
}
|
||||
|
||||
// QuadraticCurveTo adds a quadratic curve to the path. It uses the current end
|
||||
|
@ -368,7 +365,7 @@ func linePointDistSqr(a, b, p vec) float64 {
|
|||
|
||||
// Fill fills the current path with the current FillStyle
|
||||
func (cv *Canvas) Fill() {
|
||||
cv.fillPath(&cv.path, matIdentity())
|
||||
cv.fillPath(&cv.path, matIdentity)
|
||||
}
|
||||
|
||||
// FillPath fills the given path with the current FillStyle
|
||||
|
@ -426,7 +423,7 @@ func appendSubPathTriangles(tris [][2]float64, mat mat, path []pathPoint) [][2]f
|
|||
// 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, matIdentity())
|
||||
cv.clip(&cv.path, matIdentity)
|
||||
}
|
||||
|
||||
func (cv *Canvas) clip(path *Path2D, tf mat) {
|
||||
|
|
Loading…
Reference in a new issue