added dashed lines
This commit is contained in:
parent
d9854d540e
commit
46c68ca5ad
2 changed files with 92 additions and 20 deletions
26
canvas.go
26
canvas.go
|
@ -14,8 +14,9 @@ type Canvas struct {
|
|||
x, y, w, h int
|
||||
fx, fy, fw, fh float32
|
||||
|
||||
path []pathPoint
|
||||
text struct {
|
||||
polyPath []pathPoint
|
||||
linePath []pathPoint
|
||||
text struct {
|
||||
target *image.RGBA
|
||||
tex uint32
|
||||
}
|
||||
|
@ -44,6 +45,10 @@ type drawState struct {
|
|||
fontSize float32
|
||||
lineJoin lineJoin
|
||||
lineEnd lineEnd
|
||||
|
||||
lineDash []float32
|
||||
lineDashPoint int
|
||||
lineDashOffset float32
|
||||
/*
|
||||
The current transformation matrix.
|
||||
The current clipping region.
|
||||
|
@ -231,6 +236,23 @@ func (cv *Canvas) SetLineEnd(end lineEnd) {
|
|||
cv.state.lineEnd = end
|
||||
}
|
||||
|
||||
// SetLineDash sets the line dash style
|
||||
func (cv *Canvas) SetLineDash(dash []float32) {
|
||||
l := len(dash)
|
||||
if l%2 == 0 {
|
||||
d2 := make([]float32, l)
|
||||
copy(d2, dash)
|
||||
cv.state.lineDash = d2
|
||||
} else {
|
||||
d2 := make([]float32, l*2)
|
||||
copy(d2[:l], dash)
|
||||
copy(d2[l:], dash)
|
||||
cv.state.lineDash = d2
|
||||
}
|
||||
cv.state.lineDashPoint = 0
|
||||
cv.state.lineDashOffset = 0
|
||||
}
|
||||
|
||||
// Save saves the current draw state to a stack
|
||||
func (cv *Canvas) Save() {
|
||||
cv.stateStack = append(cv.stateStack, cv.state)
|
||||
|
|
86
paths.go
86
paths.go
|
@ -9,24 +9,67 @@ import (
|
|||
)
|
||||
|
||||
func (cv *Canvas) BeginPath() {
|
||||
if cv.path == nil {
|
||||
cv.path = make([]pathPoint, 0, 100)
|
||||
if cv.linePath == nil {
|
||||
cv.linePath = make([]pathPoint, 0, 100)
|
||||
}
|
||||
cv.path = cv.path[:0]
|
||||
if cv.polyPath == nil {
|
||||
cv.polyPath = make([]pathPoint, 0, 100)
|
||||
}
|
||||
cv.linePath = cv.linePath[:0]
|
||||
cv.polyPath = cv.polyPath[:0]
|
||||
}
|
||||
|
||||
func (cv *Canvas) MoveTo(x, y float32) {
|
||||
cv.path = append(cv.path, pathPoint{pos: lm.Vec2{x, y}, move: true})
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: lm.Vec2{x, y}, move: true})
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: lm.Vec2{x, y}, move: true})
|
||||
}
|
||||
|
||||
func (cv *Canvas) LineTo(x, y float32) {
|
||||
if len(cv.path) == 0 {
|
||||
if len(cv.linePath) == 0 {
|
||||
cv.MoveTo(x, y)
|
||||
return
|
||||
}
|
||||
cv.path[len(cv.path)-1].next = lm.Vec2{x, y}
|
||||
cv.path[len(cv.path)-1].attach = true
|
||||
cv.path = append(cv.path, pathPoint{pos: lm.Vec2{x, y}, move: false})
|
||||
if len(cv.state.lineDash) > 0 {
|
||||
lp := cv.linePath[len(cv.linePath)-1].pos
|
||||
tp := lm.Vec2{x, y}
|
||||
v := tp.Sub(lp)
|
||||
vl := v.Len()
|
||||
prev := cv.state.lineDashOffset
|
||||
for vl > 0 {
|
||||
draw := cv.state.lineDashPoint%2 == 0
|
||||
p := tp
|
||||
cv.state.lineDashOffset += vl
|
||||
if cv.state.lineDashOffset > cv.state.lineDash[cv.state.lineDashPoint] {
|
||||
cv.state.lineDashOffset = 0
|
||||
dl := cv.state.lineDash[cv.state.lineDashPoint] - prev
|
||||
p = lp.Add(v.MulF(dl / vl))
|
||||
vl -= dl
|
||||
cv.state.lineDashPoint++
|
||||
cv.state.lineDashPoint %= len(cv.state.lineDash)
|
||||
prev = 0
|
||||
} else {
|
||||
vl = 0
|
||||
}
|
||||
|
||||
if draw {
|
||||
cv.linePath[len(cv.linePath)-1].next = p
|
||||
cv.linePath[len(cv.linePath)-1].attach = true
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: p, move: false})
|
||||
} else {
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: p, move: true})
|
||||
}
|
||||
|
||||
lp = p
|
||||
v = tp.Sub(lp)
|
||||
}
|
||||
} else {
|
||||
cv.linePath[len(cv.linePath)-1].next = lm.Vec2{x, y}
|
||||
cv.linePath[len(cv.linePath)-1].attach = true
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: lm.Vec2{x, y}, move: false})
|
||||
}
|
||||
cv.polyPath[len(cv.polyPath)-1].next = lm.Vec2{x, y}
|
||||
cv.polyPath[len(cv.polyPath)-1].attach = true
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: lm.Vec2{x, y}, move: false})
|
||||
}
|
||||
|
||||
func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float32, anticlockwise bool) {
|
||||
|
@ -53,16 +96,23 @@ func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float32, anticlockwise
|
|||
}
|
||||
|
||||
func (cv *Canvas) ClosePath() {
|
||||
if len(cv.path) < 2 {
|
||||
if len(cv.linePath) < 2 {
|
||||
return
|
||||
}
|
||||
cv.path[len(cv.path)-1].next = cv.path[0].pos
|
||||
cv.path[len(cv.path)-1].attach = true
|
||||
cv.path = append(cv.path, pathPoint{pos: cv.path[0].pos, move: false, next: cv.path[1].pos, attach: true})
|
||||
if len(cv.state.lineDash) > 0 {
|
||||
cv.LineTo(cv.linePath[0].pos[0], cv.linePath[0].pos[1])
|
||||
return
|
||||
}
|
||||
cv.linePath[len(cv.linePath)-1].next = cv.linePath[0].pos
|
||||
cv.linePath[len(cv.linePath)-1].attach = true
|
||||
cv.linePath = append(cv.linePath, pathPoint{pos: cv.linePath[0].pos, move: false, next: cv.linePath[1].pos, attach: true})
|
||||
cv.polyPath[len(cv.polyPath)-1].next = cv.polyPath[0].pos
|
||||
cv.polyPath[len(cv.polyPath)-1].attach = true
|
||||
cv.polyPath = append(cv.polyPath, pathPoint{pos: cv.polyPath[0].pos, move: false, next: cv.polyPath[1].pos, attach: true})
|
||||
}
|
||||
|
||||
func (cv *Canvas) Stroke() {
|
||||
if len(cv.path) == 0 {
|
||||
if len(cv.linePath) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -87,7 +137,7 @@ func (cv *Canvas) Stroke() {
|
|||
|
||||
start := true
|
||||
var p0 lm.Vec2
|
||||
for _, p := range cv.path {
|
||||
for _, p := range cv.linePath {
|
||||
if p.move {
|
||||
p0 = p.pos
|
||||
start = true
|
||||
|
@ -238,13 +288,13 @@ func lineIntersection(a0, a1, b0, b1 lm.Vec2) lm.Vec2 {
|
|||
|
||||
func (cv *Canvas) Fill() {
|
||||
lastMove := 0
|
||||
for i, p := range cv.path {
|
||||
for i, p := range cv.polyPath {
|
||||
if p.move {
|
||||
lastMove = i
|
||||
}
|
||||
}
|
||||
|
||||
path := cv.path[lastMove:]
|
||||
path := cv.polyPath[lastMove:]
|
||||
|
||||
if len(path) < 3 {
|
||||
return
|
||||
|
@ -278,7 +328,7 @@ func (cv *Canvas) Fill() {
|
|||
}
|
||||
|
||||
func (cv *Canvas) Clip() {
|
||||
if len(cv.path) < 3 {
|
||||
if len(cv.polyPath) < 3 {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -301,7 +351,7 @@ func (cv *Canvas) Clip() {
|
|||
tris := buf[:0]
|
||||
tris = append(tris, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1)
|
||||
|
||||
tris = triangulatePath(cv.path, tris)
|
||||
tris = triangulatePath(cv.polyPath, tris)
|
||||
total := len(tris)
|
||||
for i := 12; i < total; i += 2 {
|
||||
x, y := tris[i], tris[i+1]
|
||||
|
|
Loading…
Reference in a new issue