diff --git a/README.md b/README.md index ba53863..bf43298 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,9 @@ These features *should* work just like their HTML5 counterparts, but there are l - lineWidth - lineEnd (square, butt, round) - lineJoin (bevel, miter, round) +- miterLimit - lineDash +- getLineDash - global alpha - drawImage - getImageData @@ -115,7 +117,6 @@ These features *should* work just like their HTML5 counterparts, but there are l - clearRect - shadowColor - shadowOffset(X/Y) -- miterLimit - shadowBlur # Missing features @@ -123,7 +124,6 @@ These features *should* work just like their HTML5 counterparts, but there are l - globalCompositeOperation - lineDashOffset - textBaseline -- getLineDash - isPointInPath - isPointInStroke - strokeText diff --git a/canvas.go b/canvas.go index 7885450..42a2792 100644 --- a/canvas.go +++ b/canvas.go @@ -682,6 +682,13 @@ func (cv *Canvas) SetLineDash(dash []float64) { cv.state.lineDashOffset = 0 } +// GetLineDash gets the line dash style +func (cv *Canvas) GetLineDash() []float64 { + result := make([]float64, len(cv.state.lineDash)) + copy(result, cv.state.lineDash) + return result +} + // 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) { diff --git a/canvas_test.go b/canvas_test.go index 9dee506..a7680c9 100644 --- a/canvas_test.go +++ b/canvas_test.go @@ -206,3 +206,31 @@ func TestMiterLimit(t *testing.T) { cv.Stroke() }) } + +func TestLineDash(t *testing.T) { + run(t, func(cv *canvas.Canvas) { + cv.SetStrokeStyle("#0F0") + cv.SetLineWidth(2.5) + cv.SetLineDash([]float64{4, 6, 8}) + cv.BeginPath() + cv.MoveTo(20, 20) + cv.LineTo(80, 20) + cv.LineTo(80, 80) + cv.LineTo(50, 80) + cv.LineTo(50, 50) + cv.LineTo(20, 50) + cv.ClosePath() + cv.MoveTo(30, 30) + cv.LineTo(70, 30) + cv.LineTo(70, 70) + cv.LineTo(60, 70) + cv.LineTo(60, 40) + cv.LineTo(30, 40) + cv.ClosePath() + cv.Stroke() + ld := cv.GetLineDash() + if ld[0] != 4 || ld[1] != 6 || ld[2] != 8 || ld[3] != 4 || ld[4] != 6 || ld[5] != 8 { + t.Fail() + } + }) +} diff --git a/paths.go b/paths.go index ed6dbbf..f7eaf7f 100644 --- a/paths.go +++ b/paths.go @@ -19,6 +19,7 @@ const ( pathAttach pathIsRect pathIsConvex + pathExplicitMove ) // BeginPath clears the current path and starts a new one @@ -43,8 +44,8 @@ func (cv *Canvas) MoveTo(x, y float64) { if len(cv.linePath) > 0 && isSamePoint(cv.linePath[len(cv.linePath)-1].tf, tf, 0.1) { return } - cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf, flags: pathMove}) - cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf, flags: pathMove}) + cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf, flags: pathMove | pathExplicitMove}) + cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf, flags: pathMove | pathExplicitMove}) } // LineTo adds a line to the end of the path @@ -273,17 +274,24 @@ func (cv *Canvas) ClosePath() { if isSamePoint(cv.linePath[len(cv.linePath)-1].tf, cv.linePath[0].tf, 0.1) { return } - closeIdx := 0 + lineCloseIdx := 0 for i := len(cv.linePath) - 1; i >= 0; i-- { - if cv.linePath[i].flags&pathMove != 0 { - closeIdx = i + if cv.linePath[i].flags&pathExplicitMove != 0 { + lineCloseIdx = i break } } - cv.LineTo(cv.linePath[closeIdx].pos[0], cv.linePath[closeIdx].pos[1]) - cv.linePath[len(cv.linePath)-1].next = cv.linePath[closeIdx].next + polyCloseIdx := 0 + for i := len(cv.polyPath) - 1; i >= 0; i-- { + if cv.polyPath[i].flags&pathExplicitMove != 0 { + polyCloseIdx = i + break + } + } + cv.LineTo(cv.linePath[lineCloseIdx].pos[0], cv.linePath[lineCloseIdx].pos[1]) + cv.linePath[len(cv.linePath)-1].next = cv.linePath[lineCloseIdx].next cv.linePath[len(cv.linePath)-1].flags |= pathAttach - cv.polyPath[len(cv.polyPath)-1].next = cv.polyPath[closeIdx].next + cv.polyPath[len(cv.polyPath)-1].next = cv.polyPath[polyCloseIdx].next } // Stroke uses the current StrokeStyle to draw the path diff --git a/testimages/LineDash.png b/testimages/LineDash.png new file mode 100755 index 0000000..e9c5f2a Binary files /dev/null and b/testimages/LineDash.png differ