added save and restore functions for draw state

This commit is contained in:
Thomas Friedel 2018-01-29 15:32:17 +01:00
parent 8a66ff2166
commit 6480345a60
3 changed files with 65 additions and 27 deletions

View file

@ -14,6 +14,23 @@ type Canvas struct {
x, y, w, h int x, y, w, h int
fx, fy, fw, fh float32 fx, fy, fw, fh float32
path []pathPoint
text struct {
target *image.RGBA
tex uint32
}
state drawState
stateStack []drawState
}
type pathPoint struct {
pos lm.Vec2
move bool
}
type drawState struct {
transform lm.Mat3x3
fill struct { fill struct {
r, g, b, a float32 r, g, b, a float32
} }
@ -21,18 +38,17 @@ type Canvas struct {
r, g, b, a float32 r, g, b, a float32
lineWidth float32 lineWidth float32
} }
path []pathPoint
text struct {
font *Font font *Font
size float32 fontSize float32
target *image.RGBA /*
tex uint32 The current transformation matrix.
} The current clipping region.
} The current dash list.
The current values of the following attributes: strokeStyle, fillStyle, globalAlpha,
type pathPoint struct { lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX,
pos lm.Vec2 shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font,
move bool textAlign, textBaseline, direction, imageSmoothingEnabled
*/
} }
// New creates a new canvas with the given viewport coordinates. // New creates a new canvas with the given viewport coordinates.
@ -44,8 +60,9 @@ func New(x, y, w, h int) *Canvas {
x: x, y: y, w: w, h: h, x: x, y: y, w: w, h: h,
fx: float32(x), fy: float32(y), fx: float32(x), fy: float32(y),
fw: float32(w), fh: float32(h), fw: float32(w), fh: float32(h),
stateStack: make([]drawState, 0, 20),
} }
cv.stroke.lineWidth = 1 cv.state.stroke.lineWidth = 1
return cv return cv
} }
@ -157,7 +174,8 @@ func glError() error {
func (cv *Canvas) SetFillColor(value ...interface{}) { func (cv *Canvas) SetFillColor(value ...interface{}) {
r, g, b, a, ok := parseColor(value...) r, g, b, a, ok := parseColor(value...)
if ok { if ok {
cv.fill.r, cv.fill.g, cv.fill.b, cv.fill.a = r, g, b, a f := &cv.state.fill
f.r, f.g, f.b, f.a = r, g, b, a
} }
} }
@ -165,19 +183,35 @@ func (cv *Canvas) SetFillColor(value ...interface{}) {
func (cv *Canvas) SetStrokeColor(value ...interface{}) { func (cv *Canvas) SetStrokeColor(value ...interface{}) {
r, g, b, a, ok := parseColor(value...) r, g, b, a, ok := parseColor(value...)
if ok { if ok {
cv.stroke.r, cv.stroke.g, cv.stroke.b, cv.stroke.a = r, g, b, a s := &cv.state.stroke
s.r, s.g, s.b, s.a = r, g, b, a
} }
} }
// 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.stroke.lineWidth = width cv.state.stroke.lineWidth = width
} }
// SetFont sets the font and font size // SetFont sets the font and font size
func (cv *Canvas) SetFont(font *Font, size float32) { func (cv *Canvas) SetFont(font *Font, size float32) {
cv.text.font = font cv.state.font = font
cv.text.size = size cv.state.fontSize = size
}
// Save saves the current draw state to a stack
func (cv *Canvas) Save() {
cv.stateStack = append(cv.stateStack, cv.state)
}
// Restore restores the last draw state from the stack if available
func (cv *Canvas) Restore() {
l := len(cv.stateStack)
if l <= 0 {
return
}
cv.state = cv.stateStack[l-1]
cv.stateStack = cv.stateStack[:l-1]
} }
// FillRect fills a rectangle with the active color // FillRect fills a rectangle with the active color
@ -194,7 +228,8 @@ func (cv *Canvas) FillRect(x, y, w, h float32) {
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)
gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil) gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil)
gli.Uniform4f(sr.color, cv.fill.r, cv.fill.g, cv.fill.b, cv.fill.a) f := cv.state.fill
gli.Uniform4f(sr.color, f.r, f.g, f.b, f.a)
gli.EnableVertexAttribArray(sr.vertex) gli.EnableVertexAttribArray(sr.vertex)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(sr.vertex) gli.DisableVertexAttribArray(sr.vertex)

View file

@ -69,7 +69,8 @@ func (cv *Canvas) Stroke() {
gli.Clear(gl_STENCIL_BUFFER_BIT) gli.Clear(gl_STENCIL_BUFFER_BIT)
gli.UseProgram(sr.id) gli.UseProgram(sr.id)
gli.Uniform4f(sr.color, cv.stroke.r, cv.stroke.g, cv.stroke.b, cv.stroke.a) s := cv.state.stroke
gli.Uniform4f(sr.color, s.r, s.g, s.b, s.a)
gli.EnableVertexAttribArray(sr.vertex) gli.EnableVertexAttribArray(sr.vertex)
gli.BindBuffer(gl_ARRAY_BUFFER, buf) gli.BindBuffer(gl_ARRAY_BUFFER, buf)
@ -86,8 +87,8 @@ func (cv *Canvas) Stroke() {
p1 := p.pos p1 := p.pos
v1 := p1.Sub(p0).Norm() v1 := p1.Sub(p0).Norm()
v2 := lm.Vec2{v1[1], -v1[0]}.MulF(cv.stroke.lineWidth * 0.5) v2 := lm.Vec2{v1[1], -v1[0]}.MulF(cv.state.stroke.lineWidth * 0.5)
v1 = v1.MulF(cv.stroke.lineWidth * 0.5) v1 = v1.MulF(cv.state.stroke.lineWidth * 0.5)
x0f, y0f := cv.vecToGL(p0.Sub(v1).Add(v2)) x0f, y0f := cv.vecToGL(p0.Sub(v1).Add(v2))
x1f, y1f := cv.vecToGL(p1.Add(v1).Add(v2)) x1f, y1f := cv.vecToGL(p1.Add(v1).Add(v2))
@ -122,7 +123,8 @@ func (cv *Canvas) Fill() {
cv.activate() cv.activate()
gli.UseProgram(sr.id) gli.UseProgram(sr.id)
gli.Uniform4f(sr.color, cv.fill.r, cv.fill.g, cv.fill.b, cv.fill.a) f := cv.state.fill
gli.Uniform4f(sr.color, f.r, f.g, f.b, f.a)
gli.EnableVertexAttribArray(sr.vertex) gli.EnableVertexAttribArray(sr.vertex)
gli.BindBuffer(gl_ARRAY_BUFFER, buf) gli.BindBuffer(gl_ARRAY_BUFFER, buf)

View file

@ -59,9 +59,10 @@ func (cv *Canvas) FillText(str string, x, y float32) {
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGBA, int32(cv.w), int32(cv.h), 0, gl_RGBA, gl_UNSIGNED_BYTE, nil) gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGBA, int32(cv.w), int32(cv.h), 0, gl_RGBA, gl_UNSIGNED_BYTE, nil)
} }
fontRenderingContext.setFont(cv.text.font.font) fontRenderingContext.setFont(cv.state.font.font)
fontRenderingContext.setFontSize(float64(cv.text.size)) fontRenderingContext.setFontSize(float64(cv.state.fontSize))
fontRenderingContext.setSrc(image.NewUniform(colorGLToGo(cv.fill.r, cv.fill.g, cv.fill.b, cv.fill.a))) f := cv.state.fill
fontRenderingContext.setSrc(image.NewUniform(colorGLToGo(f.r, f.g, f.b, f.a)))
fontRenderingContext.setDst(cv.text.target) fontRenderingContext.setDst(cv.text.target)
fontRenderingContext.setClip(cv.text.target.Bounds()) fontRenderingContext.setClip(cv.text.target.Bounds())
_, bounds, _ := fontRenderingContext.drawString(str, fixed.Point26_6{X: fixed.Int26_6(x*64 + 0.5), Y: fixed.Int26_6(y*64 + 0.5)}) _, bounds, _ := fontRenderingContext.drawString(str, fixed.Point26_6{X: fixed.Int26_6(x*64 + 0.5), Y: fixed.Int26_6(y*64 + 0.5)})