diff --git a/README.md b/README.md index f79e919..474a119 100644 --- a/README.md +++ b/README.md @@ -115,12 +115,12 @@ These features *should* work just like their HTML5 counterparts, but there are l - clearRect - shadowColor - shadowOffset(X/Y) +- miterLimit # Missing features - globalCompositeOperation - lineDashOffset -- miterLimit - shadowBlur - textBaseline - getLineDash diff --git a/canvas.go b/canvas.go index 1d49450..b411255 100644 --- a/canvas.go +++ b/canvas.go @@ -27,17 +27,18 @@ type Canvas struct { } type drawState struct { - transform mat - fill drawStyle - stroke drawStyle - font *Font - fontSize float64 - textAlign textAlign - lineAlpha float64 - lineWidth float64 - lineJoin lineJoin - lineEnd lineEnd - globalAlpha float64 + transform mat + fill drawStyle + stroke drawStyle + font *Font + fontSize float64 + textAlign textAlign + lineAlpha float64 + lineWidth float64 + lineJoin lineJoin + lineEnd lineEnd + miterLimitSqr float64 + globalAlpha float64 lineDash []float64 lineDashPoint int @@ -105,6 +106,7 @@ func New(x, y, w, h int) *Canvas { cv.SetBounds(x, y, w, h) cv.state.lineWidth = 1 cv.state.lineAlpha = 1 + cv.state.miterLimitSqr = 100 cv.state.globalAlpha = 1 cv.state.fill.color = glColor{a: 1} cv.state.stroke.color = glColor{a: 1} @@ -583,6 +585,12 @@ func (cv *Canvas) SetLineDash(dash []float64) { cv.state.lineDashOffset = 0 } +// SetMiterLimit sets the limit for how far a miter line join can be extend. +// The fallback is a bevel join +func (cv *Canvas) SetMiterLimit(limit float64) { + cv.state.miterLimitSqr = limit * limit +} + // SetGlobalAlpha sets the global alpha value func (cv *Canvas) SetGlobalAlpha(alpha float64) { cv.state.globalAlpha = alpha diff --git a/paths.go b/paths.go index 49ca4d7..ed6dbbf 100644 --- a/paths.go +++ b/paths.go @@ -431,6 +431,17 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 vec, ip0 = l0p1.add(l1p1).mulf(0.5) } } + + if dist := ip0.sub(l0p1).lenSqr(); dist > cv.state.miterLimitSqr { + l1p1 := p1.sub(v3) + l1p3 := p1.add(v3) + + tris = append(tris, + float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(l1p1[0]), float32(l1p1[1]), + float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(l0p3[0]), float32(l0p3[1])) + return tris + } + if l0p3.sub(l1p3).lenSqr() < 0.000000001 { ip1 = l0p3.sub(l1p3).mulf(0.5).add(l1p3) } else { @@ -441,6 +452,16 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 vec, } } + if dist := ip1.sub(l1p1).lenSqr(); dist > cv.state.miterLimitSqr { + l1p1 := p1.sub(v3) + l1p3 := p1.add(v3) + + tris = append(tris, + float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(l1p1[0]), float32(l1p1[1]), + float32(p1[0]), float32(p1[1]), float32(l1p3[0]), float32(l1p3[1]), float32(l0p3[0]), float32(l0p3[1])) + return tris + } + tris = append(tris, float32(p1[0]), float32(p1[1]), float32(l0p1[0]), float32(l0p1[1]), float32(ip0[0]), float32(ip0[1]), float32(p1[0]), float32(p1[1]), float32(ip0[0]), float32(ip0[1]), float32(l1p1[0]), float32(l1p1[1]),