use bit flags instead of booleans for more compact storage

This commit is contained in:
Thomas Friedel 2018-04-04 16:21:24 +02:00
parent f0d9b83afb
commit d5a4c0b4bb
2 changed files with 36 additions and 28 deletions

View file

@ -17,19 +17,13 @@ type Canvas struct {
polyPath []pathPoint polyPath []pathPoint
linePath []pathPoint linePath []pathPoint
convex bool
rect bool
state drawState state drawState
stateStack []drawState stateStack []drawState
} }
type pathPoint struct {
pos vec
tf vec
move bool
next vec
attach bool
}
type drawState struct { type drawState struct {
transform mat transform mat
fill drawStyle fill drawStyle

View file

@ -5,6 +5,20 @@ import (
"unsafe" "unsafe"
) )
type pathPoint struct {
pos vec
tf vec
next vec
flags pathPointFlag
}
type pathPointFlag uint8
const (
pathMove pathPointFlag = 1 << iota
pathAttach
)
func (cv *Canvas) BeginPath() { func (cv *Canvas) BeginPath() {
if cv.linePath == nil { if cv.linePath == nil {
cv.linePath = make([]pathPoint, 0, 100) cv.linePath = make([]pathPoint, 0, 100)
@ -25,8 +39,8 @@ func (cv *Canvas) MoveTo(x, y float64) {
if len(cv.linePath) > 0 && isSamePoint(cv.linePath[len(cv.linePath)-1].tf, tf, 0.1) { if len(cv.linePath) > 0 && isSamePoint(cv.linePath[len(cv.linePath)-1].tf, tf, 0.1) {
return return
} }
cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf, move: true}) 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, move: true}) cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf, flags: pathMove})
} }
func (cv *Canvas) LineTo(x, y float64) { func (cv *Canvas) LineTo(x, y float64) {
@ -39,7 +53,7 @@ func (cv *Canvas) strokeLineTo(x, y float64) {
return return
} }
if len(cv.linePath) == 0 { if len(cv.linePath) == 0 {
cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: cv.tf(vec{x, y}), move: true}) cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: cv.tf(vec{x, y}), flags: pathMove})
return return
} }
if len(cv.state.lineDash) > 0 { if len(cv.state.lineDash) > 0 {
@ -66,10 +80,10 @@ func (cv *Canvas) strokeLineTo(x, y float64) {
if draw { if draw {
cv.linePath[len(cv.linePath)-1].next = cv.tf(p) cv.linePath[len(cv.linePath)-1].next = cv.tf(p)
cv.linePath[len(cv.linePath)-1].attach = true cv.linePath[len(cv.linePath)-1].flags |= pathAttach
cv.linePath = append(cv.linePath, pathPoint{pos: p, tf: cv.tf(p), move: false}) cv.linePath = append(cv.linePath, pathPoint{pos: p, tf: cv.tf(p)})
} else { } else {
cv.linePath = append(cv.linePath, pathPoint{pos: p, tf: cv.tf(p), move: true}) cv.linePath = append(cv.linePath, pathPoint{pos: p, tf: cv.tf(p), flags: pathMove})
} }
lp = p lp = p
@ -78,8 +92,8 @@ func (cv *Canvas) strokeLineTo(x, y float64) {
} else { } else {
tf := cv.tf(vec{x, y}) tf := cv.tf(vec{x, y})
cv.linePath[len(cv.linePath)-1].next = tf cv.linePath[len(cv.linePath)-1].next = tf
cv.linePath[len(cv.linePath)-1].attach = true cv.linePath[len(cv.linePath)-1].flags |= pathAttach
cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf, move: false}) cv.linePath = append(cv.linePath, pathPoint{pos: vec{x, y}, tf: tf})
} }
} }
@ -88,13 +102,13 @@ func (cv *Canvas) fillLineTo(x, y float64) {
return return
} }
if len(cv.polyPath) == 0 { if len(cv.polyPath) == 0 {
cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: cv.tf(vec{x, y}), move: true}) cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: cv.tf(vec{x, y}), flags: pathMove})
return return
} }
tf := cv.tf(vec{x, y}) tf := cv.tf(vec{x, y})
cv.polyPath[len(cv.polyPath)-1].next = tf cv.polyPath[len(cv.polyPath)-1].next = tf
cv.polyPath[len(cv.polyPath)-1].attach = true cv.polyPath[len(cv.polyPath)-1].flags |= pathAttach
cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf, move: false}) cv.polyPath = append(cv.polyPath, pathPoint{pos: vec{x, y}, tf: tf})
} }
func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise bool) { func (cv *Canvas) Arc(x, y, radius, startAngle, endAngle float64, anticlockwise bool) {
@ -233,7 +247,7 @@ func (cv *Canvas) ClosePath() {
} }
closeIdx := 0 closeIdx := 0
for i := len(cv.linePath) - 1; i >= 0; i-- { for i := len(cv.linePath) - 1; i >= 0; i-- {
if cv.linePath[i].move { if cv.linePath[i].flags&pathMove != 0 {
closeIdx = i closeIdx = i
break break
} }
@ -261,7 +275,7 @@ func (cv *Canvas) stroke(path []pathPoint) {
start := true start := true
var p0 vec var p0 vec
for _, p := range path { for _, p := range path {
if p.move { if p.flags&pathMove != 0 {
p0 = p.tf p0 = p.tf
start = true start = true
continue continue
@ -289,7 +303,7 @@ func (cv *Canvas) stroke(path []pathPoint) {
} }
} }
if !p.attach { if p.flags&pathAttach == 0 {
switch cv.state.lineEnd { switch cv.state.lineEnd {
case Butt: case Butt:
// no need to do anything // no need to do anything
@ -305,7 +319,7 @@ func (cv *Canvas) stroke(path []pathPoint) {
float32(lp0[0]), float32(lp0[1]), float32(lp1[0]), float32(lp1[1]), float32(lp3[0]), float32(lp3[1]), float32(lp0[0]), float32(lp0[1]), float32(lp1[0]), float32(lp1[1]), float32(lp3[0]), float32(lp3[1]),
float32(lp0[0]), float32(lp0[1]), float32(lp3[0]), float32(lp3[1]), float32(lp2[0]), float32(lp2[1])) float32(lp0[0]), float32(lp0[1]), float32(lp3[0]), float32(lp3[1]), float32(lp2[0]), float32(lp2[1]))
if p.attach { if p.flags&pathAttach != 0 {
tris = cv.lineJoint(p, p0, p1, p.next, lp0, lp1, lp2, lp3, tris) tris = cv.lineJoint(p, p0, p1, p.next, lp0, lp1, lp2, lp3, tris)
} }
@ -441,7 +455,7 @@ func (cv *Canvas) Fill() {
cv.activate() cv.activate()
start := 0 start := 0
for i, p := range cv.polyPath { for i, p := range cv.polyPath {
if !p.move { if p.flags&pathMove == 0 {
continue continue
} }
if i >= start+3 { if i >= start+3 {
@ -552,10 +566,10 @@ func (cv *Canvas) StrokeRect(x, y, w, h float64) {
v3 := vec{x, y + h} v3 := vec{x, y + h}
v0t, v1t, v2t, v3t := cv.tf(v0), cv.tf(v1), cv.tf(v2), cv.tf(v3) v0t, v1t, v2t, v3t := cv.tf(v0), cv.tf(v1), cv.tf(v2), cv.tf(v3)
var path [5]pathPoint var path [5]pathPoint
path[0] = pathPoint{pos: v0, tf: v0t, move: true, next: v1t, attach: true} path[0] = pathPoint{pos: v0, tf: v0t, flags: pathMove | pathAttach, next: v1t}
path[1] = pathPoint{pos: v1, tf: v1t, next: v2t, attach: true} path[1] = pathPoint{pos: v1, tf: v1t, next: v2t, flags: pathAttach}
path[2] = pathPoint{pos: v2, tf: v2t, next: v3t, attach: true} path[2] = pathPoint{pos: v2, tf: v2t, next: v3t, flags: pathAttach}
path[3] = pathPoint{pos: v3, tf: v3t, next: v0t, attach: true} path[3] = pathPoint{pos: v3, tf: v3t, next: v0t, flags: pathAttach}
path[4] = pathPoint{pos: v0, tf: v0t} path[4] = pathPoint{pos: v0, tf: v0t}
cv.stroke(path[:]) cv.stroke(path[:])
} }