added save and restore functions for draw state
This commit is contained in:
parent
8a66ff2166
commit
6480345a60
3 changed files with 65 additions and 27 deletions
75
canvas.go
75
canvas.go
|
@ -14,25 +14,41 @@ type Canvas struct {
|
||||||
x, y, w, h int
|
x, y, w, h int
|
||||||
fx, fy, fw, fh float32
|
fx, fy, fw, fh float32
|
||||||
|
|
||||||
fill struct {
|
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 {
|
||||||
r, g, b, a float32
|
r, g, b, a float32
|
||||||
}
|
}
|
||||||
stroke struct {
|
stroke struct {
|
||||||
r, g, b, a float32
|
r, g, b, a float32
|
||||||
lineWidth float32
|
lineWidth float32
|
||||||
}
|
}
|
||||||
path []pathPoint
|
font *Font
|
||||||
text struct {
|
fontSize float32
|
||||||
font *Font
|
/*
|
||||||
size float32
|
The current transformation matrix.
|
||||||
target *image.RGBA
|
The current clipping region.
|
||||||
tex uint32
|
The current dash list.
|
||||||
}
|
The current values of the following attributes: strokeStyle, fillStyle, globalAlpha,
|
||||||
}
|
lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX,
|
||||||
|
shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font,
|
||||||
type pathPoint struct {
|
textAlign, textBaseline, direction, imageSmoothingEnabled
|
||||||
pos lm.Vec2
|
*/
|
||||||
move bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
|
|
10
paths.go
10
paths.go
|
@ -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)
|
||||||
|
|
7
text.go
7
text.go
|
@ -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)})
|
||||||
|
|
Loading…
Reference in a new issue