made stroke and fill style code more generic

This commit is contained in:
Thomas Friedel 2018-02-09 11:41:57 +01:00
parent 91e8935866
commit ac8adda421
2 changed files with 46 additions and 47 deletions

View file

@ -35,18 +35,11 @@ type pathPoint struct {
type drawState struct { type drawState struct {
transform lm.Mat3x3 transform lm.Mat3x3
fill struct { fill drawStyle
color glColor stroke drawStyle
radialGradient *RadialGradient
linearGradient *LinearGradient
image *Image
}
stroke struct {
color glColor
lineWidth float32
}
font *Font font *Font
fontSize float32 fontSize float32
lineWidth float32
lineJoin lineJoin lineJoin lineJoin
lineEnd lineEnd lineEnd lineEnd
@ -66,6 +59,13 @@ type drawState struct {
*/ */
} }
type drawStyle struct {
color glColor
radialGradient *RadialGradient
linearGradient *LinearGradient
image *Image
}
type lineJoin uint8 type lineJoin uint8
type lineEnd uint8 type lineEnd uint8
@ -88,7 +88,7 @@ func New(x, y, w, h int) *Canvas {
fw: float32(w), fh: float32(h), fw: float32(w), fh: float32(h),
stateStack: make([]drawState, 0, 20), stateStack: make([]drawState, 0, 20),
} }
cv.state.stroke.lineWidth = 1 cv.state.lineWidth = 1
cv.state.transform = lm.Mat3x3Identity() cv.state.transform = lm.Mat3x3Identity()
return cv return cv
} }
@ -325,33 +325,40 @@ func glError() error {
return nil return nil
} }
// SetFillStyle sets the color or gradient for any fill calls // SetFillStyle sets the color, gradient, or image for any fill calls
func (cv *Canvas) SetFillStyle(value ...interface{}) { func (cv *Canvas) SetFillStyle(value ...interface{}) {
cv.state.fill.color = glColor{} cv.state.fill = parseStyle(value...)
cv.state.fill.linearGradient = nil }
cv.state.fill.radialGradient = nil
cv.state.fill.image = nil // SetStrokeStyle sets the color, gradient, or image for any line drawing calls
func (cv *Canvas) SetStrokeStyle(value ...interface{}) {
cv.state.stroke = parseStyle(value...)
}
func parseStyle(value ...interface{}) drawStyle {
var style drawStyle
if len(value) == 1 { if len(value) == 1 {
switch v := value[0].(type) { switch v := value[0].(type) {
case *LinearGradient: case *LinearGradient:
cv.state.fill.linearGradient = v style.linearGradient = v
return return style
case *RadialGradient: case *RadialGradient:
cv.state.fill.radialGradient = v style.radialGradient = v
return return style
case *Image: case *Image:
cv.state.fill.image = v style.image = v
return return style
} }
} }
c, ok := parseColor(value...) c, ok := parseColor(value...)
if ok { if ok {
cv.state.fill.color = c style.color = c
} }
return style
} }
func (cv *Canvas) useFillShader() (vertexLoc uint32) { func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
if lg := cv.state.fill.linearGradient; lg != nil { if lg := style.linearGradient; lg != nil {
lg.load() lg.load()
gli.ActiveTexture(gl_TEXTURE0) gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_1D, lg.tex) gli.BindTexture(gl_TEXTURE_1D, lg.tex)
@ -368,7 +375,7 @@ func (cv *Canvas) useFillShader() (vertexLoc uint32) {
gli.Uniform1i(lgr.gradient, 0) gli.Uniform1i(lgr.gradient, 0)
return lgr.vertex return lgr.vertex
} }
if rg := cv.state.fill.radialGradient; rg != nil { if rg := style.radialGradient; rg != nil {
rg.load() rg.load()
gli.ActiveTexture(gl_TEXTURE0) gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_1D, rg.tex) gli.BindTexture(gl_TEXTURE_1D, rg.tex)
@ -388,7 +395,7 @@ func (cv *Canvas) useFillShader() (vertexLoc uint32) {
gli.Uniform1i(rgr.gradient, 0) gli.Uniform1i(rgr.gradient, 0)
return rgr.vertex return rgr.vertex
} }
if img := cv.state.fill.image; img != nil { if img := style.image; img != nil {
gli.UseProgram(ipr.id) gli.UseProgram(ipr.id)
gli.ActiveTexture(gl_TEXTURE0) gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_2D, img.tex) gli.BindTexture(gl_TEXTURE_2D, img.tex)
@ -405,17 +412,9 @@ func (cv *Canvas) useFillShader() (vertexLoc uint32) {
return sr.vertex return sr.vertex
} }
// SetStrokeColor sets the color for any line drawing calls
func (cv *Canvas) SetStrokeColor(value ...interface{}) {
c, ok := parseColor(value...)
if ok {
cv.state.stroke.color = c
}
}
// SetLineWidth sets the line width for any line drawing calls // SetLineWidth sets the line width for any line drawing calls
func (cv *Canvas) SetLineWidth(width float32) { func (cv *Canvas) SetLineWidth(width float32) {
cv.state.stroke.lineWidth = width cv.state.lineWidth = width
} }
// SetFont sets the font and font size // SetFont sets the font and font size
@ -507,7 +506,7 @@ func (cv *Canvas) FillRect(x, y, w, h float32) {
data := [8]float32{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]} data := [8]float32{p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]}
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW) gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
vertex := cv.useFillShader() vertex := cv.useShader(&cv.state.fill)
gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, nil) gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, nil)
gli.EnableVertexAttribArray(vertex) gli.EnableVertexAttribArray(vertex)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)

View file

@ -181,8 +181,8 @@ func (cv *Canvas) Stroke() {
p1 := p.tf p1 := p.tf
v0 := p1.Sub(p0).Norm() v0 := p1.Sub(p0).Norm()
v1 := lm.Vec2{v0[1], -v0[0]}.MulF(cv.state.stroke.lineWidth * 0.5) v1 := lm.Vec2{v0[1], -v0[0]}.MulF(cv.state.lineWidth * 0.5)
v0 = v0.MulF(cv.state.stroke.lineWidth * 0.5) v0 = v0.MulF(cv.state.lineWidth * 0.5)
lp0 := p0.Add(v1) lp0 := p0.Add(v1)
lp1 := p1.Add(v1) lp1 := p1.Add(v1)
@ -197,7 +197,7 @@ func (cv *Canvas) Stroke() {
lp0 = lp0.Sub(v0) lp0 = lp0.Sub(v0)
lp2 = lp2.Sub(v0) lp2 = lp2.Sub(v0)
case Round: case Round:
tris = cv.addCircleTris(p0, cv.state.stroke.lineWidth*0.5, tris) tris = cv.addCircleTris(p0, cv.state.lineWidth*0.5, tris)
} }
} }
@ -209,7 +209,7 @@ func (cv *Canvas) Stroke() {
lp1 = lp1.Add(v0) lp1 = lp1.Add(v0)
lp3 = lp3.Add(v0) lp3 = lp3.Add(v0)
case Round: case Round:
tris = cv.addCircleTris(p1, cv.state.stroke.lineWidth*0.5, tris) tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris)
} }
} }
@ -257,7 +257,7 @@ func (cv *Canvas) Stroke() {
func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 lm.Vec2, tris []float32) []float32 { func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 lm.Vec2, tris []float32) []float32 {
v2 := p1.Sub(p2).Norm() v2 := p1.Sub(p2).Norm()
v3 := lm.Vec2{v2[1], -v2[0]}.MulF(cv.state.stroke.lineWidth * 0.5) v3 := lm.Vec2{v2[1], -v2[0]}.MulF(cv.state.lineWidth * 0.5)
switch cv.state.lineJoin { switch cv.state.lineJoin {
case Miter: case Miter:
@ -282,7 +282,7 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 lm.V
p1[0], p1[1], l0p1[0], l0p1[1], l1p1[0], l1p1[1], p1[0], p1[1], l0p1[0], l0p1[1], l1p1[0], l1p1[1],
p1[0], p1[1], l1p3[0], l1p3[1], l0p3[0], l0p3[1]) p1[0], p1[1], l1p3[0], l1p3[1], l0p3[0], l0p3[1])
case Round: case Round:
tris = cv.addCircleTris(p1, cv.state.stroke.lineWidth*0.5, tris) tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris)
} }
return tris return tris