diff --git a/canvas.go b/canvas.go index 5e2d7c9..0925827 100644 --- a/canvas.go +++ b/canvas.go @@ -35,20 +35,13 @@ type pathPoint struct { type drawState struct { transform lm.Mat3x3 - fill struct { - color glColor - radialGradient *RadialGradient - linearGradient *LinearGradient - image *Image - } - stroke struct { - color glColor - lineWidth float32 - } - font *Font - fontSize float32 - lineJoin lineJoin - lineEnd lineEnd + fill drawStyle + stroke drawStyle + font *Font + fontSize float32 + lineWidth float32 + lineJoin lineJoin + lineEnd lineEnd lineDash []float32 lineDashPoint int @@ -66,6 +59,13 @@ type drawState struct { */ } +type drawStyle struct { + color glColor + radialGradient *RadialGradient + linearGradient *LinearGradient + image *Image +} + type lineJoin uint8 type lineEnd uint8 @@ -88,7 +88,7 @@ func New(x, y, w, h int) *Canvas { fw: float32(w), fh: float32(h), stateStack: make([]drawState, 0, 20), } - cv.state.stroke.lineWidth = 1 + cv.state.lineWidth = 1 cv.state.transform = lm.Mat3x3Identity() return cv } @@ -325,33 +325,40 @@ func glError() error { 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{}) { - cv.state.fill.color = glColor{} - cv.state.fill.linearGradient = nil - cv.state.fill.radialGradient = nil - cv.state.fill.image = nil + cv.state.fill = parseStyle(value...) +} + +// 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 { switch v := value[0].(type) { case *LinearGradient: - cv.state.fill.linearGradient = v - return + style.linearGradient = v + return style case *RadialGradient: - cv.state.fill.radialGradient = v - return + style.radialGradient = v + return style case *Image: - cv.state.fill.image = v - return + style.image = v + return style } } c, ok := parseColor(value...) if ok { - cv.state.fill.color = c + style.color = c } + return style } -func (cv *Canvas) useFillShader() (vertexLoc uint32) { - if lg := cv.state.fill.linearGradient; lg != nil { +func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { + if lg := style.linearGradient; lg != nil { lg.load() gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_1D, lg.tex) @@ -368,7 +375,7 @@ func (cv *Canvas) useFillShader() (vertexLoc uint32) { gli.Uniform1i(lgr.gradient, 0) return lgr.vertex } - if rg := cv.state.fill.radialGradient; rg != nil { + if rg := style.radialGradient; rg != nil { rg.load() gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_1D, rg.tex) @@ -388,7 +395,7 @@ func (cv *Canvas) useFillShader() (vertexLoc uint32) { gli.Uniform1i(rgr.gradient, 0) return rgr.vertex } - if img := cv.state.fill.image; img != nil { + if img := style.image; img != nil { gli.UseProgram(ipr.id) gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, img.tex) @@ -405,17 +412,9 @@ func (cv *Canvas) useFillShader() (vertexLoc uint32) { 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 func (cv *Canvas) SetLineWidth(width float32) { - cv.state.stroke.lineWidth = width + cv.state.lineWidth = width } // 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]} 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.EnableVertexAttribArray(vertex) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) diff --git a/paths.go b/paths.go index dadb78b..0c57b01 100644 --- a/paths.go +++ b/paths.go @@ -181,8 +181,8 @@ func (cv *Canvas) Stroke() { p1 := p.tf v0 := p1.Sub(p0).Norm() - v1 := lm.Vec2{v0[1], -v0[0]}.MulF(cv.state.stroke.lineWidth * 0.5) - v0 = v0.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.lineWidth * 0.5) lp0 := p0.Add(v1) lp1 := p1.Add(v1) @@ -197,7 +197,7 @@ func (cv *Canvas) Stroke() { lp0 = lp0.Sub(v0) lp2 = lp2.Sub(v0) 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) lp3 = lp3.Add(v0) 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 { 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 { 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], l1p3[0], l1p3[1], l0p3[0], l0p3[1]) 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