moved offscreen canvas to backend
This commit is contained in:
parent
a0dfb6f530
commit
8dc91b34f5
12 changed files with 122 additions and 211 deletions
|
@ -10,6 +10,8 @@ import (
|
|||
// drawing. This enables the backend to be implemented by
|
||||
// various methods (OpenGL, but also other APIs or software)
|
||||
type Backend interface {
|
||||
Size() (int, int)
|
||||
|
||||
LoadImage(img image.Image) (Image, error)
|
||||
LoadLinearGradient(data *LinearGradientData) LinearGradient
|
||||
LoadRadialGradient(data *RadialGradientData) RadialGradient
|
||||
|
|
|
@ -7,11 +7,15 @@ import (
|
|||
)
|
||||
|
||||
func (b *GoGLBackend) ClearClip() {
|
||||
b.activate()
|
||||
|
||||
gl.StencilMask(0xFF)
|
||||
gl.Clear(gl.STENCIL_BUFFER_BIT)
|
||||
}
|
||||
|
||||
func (b *GoGLBackend) Clip(pts [][2]float64) {
|
||||
b.activate()
|
||||
|
||||
b.ptsBuf = b.ptsBuf[:0]
|
||||
b.ptsBuf = append(b.ptsBuf,
|
||||
0, 0,
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
)
|
||||
|
||||
func (b *GoGLBackend) Clear(pts [4][2]float64) {
|
||||
b.activate()
|
||||
|
||||
// first check if the four points are aligned to form a nice rectangle, which can be more easily
|
||||
// cleared using glScissor and glClear
|
||||
aligned := pts[0][0] == pts[1][0] && pts[2][0] == pts[3][0] && pts[0][1] == pts[3][1] && pts[1][1] == pts[2][1]
|
||||
|
@ -68,6 +70,8 @@ func (b *GoGLBackend) clearRect(x, y, w, h int) {
|
|||
}
|
||||
|
||||
func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
|
||||
b.activate()
|
||||
|
||||
if style.Blur > 0 {
|
||||
b.offscr1.alpha = true
|
||||
b.enableTextureRenderTarget(&b.offscr1)
|
||||
|
@ -140,6 +144,8 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
|
|||
}
|
||||
|
||||
func (b *GoGLBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [][2]float64) {
|
||||
b.activate()
|
||||
|
||||
w, h := mask.Rect.Dx(), mask.Rect.Dy()
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE1)
|
||||
|
|
|
@ -42,6 +42,10 @@ type GoGLBackend struct {
|
|||
|
||||
ptsBuf []float32
|
||||
|
||||
offscreen bool
|
||||
offscrBuf offscreenBuffer
|
||||
offscrImg Image
|
||||
|
||||
glChan chan func()
|
||||
}
|
||||
|
||||
|
@ -54,7 +58,7 @@ type offscreenBuffer struct {
|
|||
alpha bool
|
||||
}
|
||||
|
||||
func New(x, y, w, h int) (backendbase.Backend, error) {
|
||||
func New(x, y, w, h int) (*GoGLBackend, error) {
|
||||
err := gl.Init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -210,15 +214,31 @@ func New(x, y, w, h int) (backendbase.Backend, error) {
|
|||
return b, nil
|
||||
}
|
||||
|
||||
func NewOffscreen(w, h int, alpha bool) (*GoGLBackend, error) {
|
||||
b, err := New(0, 0, w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.offscreen = true
|
||||
b.offscrBuf.alpha = alpha
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// SetBounds updates the bounds of the canvas. This would
|
||||
// usually be called for example when the window is resized
|
||||
func (b *GoGLBackend) SetBounds(x, y, w, h int) {
|
||||
if !b.offscreen {
|
||||
b.x, b.y = x, y
|
||||
b.fx, b.fy = float64(x), float64(y)
|
||||
}
|
||||
b.w, b.h = w, h
|
||||
b.fw, b.fh = float64(w), float64(h)
|
||||
}
|
||||
|
||||
func (b *GoGLBackend) Size() (int, int) {
|
||||
return b.w, b.h
|
||||
}
|
||||
|
||||
func glError() error {
|
||||
glErr := gl.GetError()
|
||||
if glErr != gl.NO_ERROR {
|
||||
|
@ -227,21 +247,44 @@ func glError() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Activate makes this GL backend active and sets the viewport. Only
|
||||
// needs to be called if any other GL code changes the viewport
|
||||
func (b *GoGLBackend) Activate() {
|
||||
// if b.offscreen {
|
||||
// gl.Viewport(0, 0, int32(cv.w), int32(cv.h))
|
||||
// cv.enableTextureRenderTarget(&cv.offscrBuf)
|
||||
// cv.offscrImg.w = cv.offscrBuf.w
|
||||
// cv.offscrImg.h = cv.offscrBuf.h
|
||||
// cv.offscrImg.tex = cv.offscrBuf.tex
|
||||
// } else {
|
||||
var activeContext *GoGLBackend
|
||||
|
||||
func (b *GoGLBackend) activate() {
|
||||
if activeContext != b {
|
||||
activeContext = b
|
||||
if b.offscreen {
|
||||
gl.Viewport(0, 0, int32(b.w), int32(b.h))
|
||||
b.enableTextureRenderTarget(&b.offscrBuf)
|
||||
b.offscrImg.w = b.offscrBuf.w
|
||||
b.offscrImg.h = b.offscrBuf.h
|
||||
b.offscrImg.tex = b.offscrBuf.tex
|
||||
} else {
|
||||
gl.Viewport(int32(b.x), int32(b.y), int32(b.w), int32(b.h))
|
||||
b.disableTextureRenderTarget()
|
||||
// }
|
||||
// b.applyScissor()
|
||||
gl.Clear(gl.STENCIL_BUFFER_BIT)
|
||||
}
|
||||
}
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case f := <-b.glChan:
|
||||
f()
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *GoGLBackend) DeleteOffscreen() {
|
||||
if !b.offscreen {
|
||||
return
|
||||
}
|
||||
gl.DeleteTextures(1, &b.offscrBuf.tex)
|
||||
gl.DeleteFramebuffers(1, &b.offscrBuf.frameBuf)
|
||||
gl.DeleteRenderbuffers(1, &b.offscrBuf.renderStencilBuf)
|
||||
b.offscreen = false
|
||||
|
||||
b.activate()
|
||||
}
|
||||
|
||||
type glColor struct {
|
||||
|
@ -439,11 +482,11 @@ func (b *GoGLBackend) enableTextureRenderTarget(offscr *offscreenBuffer) {
|
|||
}
|
||||
|
||||
func (b *GoGLBackend) disableTextureRenderTarget() {
|
||||
// if b.offscreen {
|
||||
// b.enableTextureRenderTarget(&b.offscrBuf)
|
||||
// } else {
|
||||
if b.offscreen {
|
||||
b.enableTextureRenderTarget(&b.offscrBuf)
|
||||
} else {
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
type mat [9]float64
|
||||
|
|
|
@ -25,6 +25,7 @@ type RadialGradient struct {
|
|||
}
|
||||
|
||||
type gradient struct {
|
||||
b *GoGLBackend
|
||||
from, to vec
|
||||
tex uint32
|
||||
loaded bool
|
||||
|
@ -33,8 +34,10 @@ type gradient struct {
|
|||
}
|
||||
|
||||
func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) backendbase.LinearGradient {
|
||||
b.activate()
|
||||
|
||||
lg := &LinearGradient{
|
||||
gradient: gradient{from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true},
|
||||
gradient: gradient{b: b, from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true},
|
||||
}
|
||||
gl.GenTextures(1, &lg.tex)
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
|
@ -53,8 +56,10 @@ func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) b
|
|||
}
|
||||
|
||||
func (b *GoGLBackend) LoadRadialGradient(data *backendbase.RadialGradientData) backendbase.RadialGradient {
|
||||
b.activate()
|
||||
|
||||
rg := &RadialGradient{
|
||||
gradient: gradient{from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true},
|
||||
gradient: gradient{b: b, from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true},
|
||||
radFrom: data.RadFrom,
|
||||
radTo: data.RadTo,
|
||||
}
|
||||
|
@ -76,6 +81,8 @@ func (b *GoGLBackend) LoadRadialGradient(data *backendbase.RadialGradientData) b
|
|||
|
||||
// Delete explicitly deletes the gradient
|
||||
func (g *gradient) Delete() {
|
||||
g.b.activate()
|
||||
|
||||
gl.DeleteTextures(1, &g.tex)
|
||||
g.deleted = true
|
||||
}
|
||||
|
@ -91,6 +98,8 @@ func (g *gradient) load(stops backendbase.Gradient) {
|
|||
return
|
||||
}
|
||||
|
||||
g.b.activate()
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
gl.BindTexture(gl.TEXTURE_2D, g.tex)
|
||||
var pixels [2048 * 4]byte
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
// GetImageData returns an RGBA image of the current image
|
||||
func (b *GoGLBackend) GetImageData(x, y, w, h int) *image.RGBA {
|
||||
// cv.activate()
|
||||
b.activate()
|
||||
|
||||
if x < 0 {
|
||||
w += x
|
||||
|
@ -44,7 +44,7 @@ func (b *GoGLBackend) GetImageData(x, y, w, h int) *image.RGBA {
|
|||
|
||||
// PutImageData puts the given image at the given x/y coordinates
|
||||
func (b *GoGLBackend) PutImageData(img *image.RGBA, x, y int) {
|
||||
// cv.activate()
|
||||
b.activate()
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
if b.imageBufTex == 0 {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
// Image represents a loaded image that can be used in various drawing functions
|
||||
type Image struct {
|
||||
b *GoGLBackend
|
||||
w, h int
|
||||
tex uint32
|
||||
deleted bool
|
||||
|
@ -19,6 +20,8 @@ type Image struct {
|
|||
}
|
||||
|
||||
func (b *GoGLBackend) LoadImage(src image.Image) (backendbase.Image, error) {
|
||||
b.activate()
|
||||
|
||||
var tex uint32
|
||||
gl.GenTextures(1, &tex)
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
|
@ -184,6 +187,8 @@ func (img *Image) Size() (int, int) { return img.w, img.h }
|
|||
// Delete deletes the image from memory. Any draw calls
|
||||
// with a deleted image will not do anything
|
||||
func (img *Image) Delete() {
|
||||
img.b.activate()
|
||||
|
||||
gl.DeleteTextures(1, &img.tex)
|
||||
img.deleted = true
|
||||
}
|
||||
|
@ -194,6 +199,8 @@ func (img *Image) IsDeleted() bool { return img.deleted }
|
|||
|
||||
// Replace replaces the image with the new one
|
||||
func (img *Image) Replace(src image.Image) error {
|
||||
img.b.activate()
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
gl.BindTexture(gl.TEXTURE_2D, img.tex)
|
||||
newImg, err := loadImage(src, img.tex)
|
||||
|
@ -209,6 +216,8 @@ func (img *Image) Replace(src image.Image) error {
|
|||
func (img *Image) IsOpaque() bool { return img.opaque }
|
||||
|
||||
func (b *GoGLBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh, dx, dy, dw, dh float64, alpha float64) {
|
||||
b.activate()
|
||||
|
||||
img := dimg.(*Image)
|
||||
|
||||
sx /= float64(img.w)
|
||||
|
|
153
canvas.go
153
canvas.go
|
@ -20,8 +20,8 @@ import (
|
|||
type Canvas struct {
|
||||
b backendbase.Backend
|
||||
|
||||
x, y, w, h int
|
||||
fx, fy, fw, fh float64
|
||||
w, h int
|
||||
fw, fh float64
|
||||
|
||||
path Path2D
|
||||
convex bool
|
||||
|
@ -30,10 +30,6 @@ type Canvas struct {
|
|||
state drawState
|
||||
stateStack []drawState
|
||||
|
||||
offscreen bool
|
||||
offscrBuf offscreenBuffer
|
||||
offscrImg Image
|
||||
|
||||
images map[interface{}]*Image
|
||||
|
||||
shadowBuf [][2]float64
|
||||
|
@ -136,16 +132,14 @@ var Performance = struct {
|
|||
// While all functions on the canvas use the top left point as
|
||||
// the origin, since GL uses the bottom left coordinate, the
|
||||
// coordinates given here also use the bottom left as origin
|
||||
func New(backend backendbase.Backend, x, y, w, h int) *Canvas {
|
||||
if gli == nil {
|
||||
panic("LoadGL must be called before a canvas can be created")
|
||||
}
|
||||
func New(backend backendbase.Backend) *Canvas {
|
||||
cv := &Canvas{
|
||||
b: backend,
|
||||
stateStack: make([]drawState, 0, 20),
|
||||
images: make(map[interface{}]*Image),
|
||||
}
|
||||
cv.SetBounds(x, y, w, h)
|
||||
w, h := backend.Size()
|
||||
cv.setBounds(w, h)
|
||||
cv.state.lineWidth = 1
|
||||
cv.state.lineAlpha = 1
|
||||
cv.state.miterLimitSqr = 100
|
||||
|
@ -156,36 +150,9 @@ func New(backend backendbase.Backend, x, y, w, h int) *Canvas {
|
|||
return cv
|
||||
}
|
||||
|
||||
// NewOffscreen creates a new canvas with the given size. It
|
||||
// does not render directly to the screen but renders to a
|
||||
// texture instead. If alpha is set to true, the offscreen
|
||||
// canvas will have an alpha channel
|
||||
func NewOffscreen(backend backendbase.Backend, w, h int, alpha bool) *Canvas {
|
||||
cv := New(backend, 0, 0, w, h)
|
||||
cv.offscreen = true
|
||||
cv.offscrBuf.alpha = alpha
|
||||
return cv
|
||||
}
|
||||
|
||||
func DeleteOffscreen(cv *Canvas) {
|
||||
if !cv.offscreen {
|
||||
return
|
||||
}
|
||||
gli.DeleteTextures(1, &cv.offscrBuf.tex)
|
||||
gli.DeleteFramebuffers(1, &cv.offscrBuf.frameBuf)
|
||||
gli.DeleteRenderbuffers(1, &cv.offscrBuf.renderStencilBuf)
|
||||
}
|
||||
|
||||
// SetBounds updates the bounds of the canvas. This would
|
||||
// usually be called for example when the window is resized
|
||||
func (cv *Canvas) SetBounds(x, y, w, h int) {
|
||||
if !cv.offscreen {
|
||||
cv.x, cv.y = x, y
|
||||
cv.fx, cv.fy = float64(x), float64(y)
|
||||
}
|
||||
func (cv *Canvas) setBounds(w, h int) {
|
||||
cv.w, cv.h = w, h
|
||||
cv.fw, cv.fh = float64(w), float64(h)
|
||||
activeCanvas = nil
|
||||
}
|
||||
|
||||
// Width returns the internal width of the canvas
|
||||
|
@ -202,46 +169,8 @@ func (cv *Canvas) tf(v vec) vec {
|
|||
return v
|
||||
}
|
||||
|
||||
// Activate makes the canvas active and sets the viewport. Only needs
|
||||
// to be called if any other GL code changes the viewport
|
||||
func (cv *Canvas) Activate() {
|
||||
if cv.offscreen {
|
||||
gli.Viewport(0, 0, int32(cv.w), int32(cv.h))
|
||||
cv.enableTextureRenderTarget(&cv.offscrBuf)
|
||||
// cv.offscrImg.w = cv.offscrBuf.w
|
||||
// cv.offscrImg.h = cv.offscrBuf.h
|
||||
// cv.offscrImg.tex = cv.offscrBuf.tex
|
||||
} else {
|
||||
gli.Viewport(int32(cv.x), int32(cv.y), int32(cv.w), int32(cv.h))
|
||||
cv.disableTextureRenderTarget()
|
||||
}
|
||||
}
|
||||
|
||||
var activeCanvas *Canvas
|
||||
|
||||
func (cv *Canvas) activate() {
|
||||
if activeCanvas != cv {
|
||||
activeCanvas = cv
|
||||
cv.Activate()
|
||||
}
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case f := <-glChan:
|
||||
f()
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const alphaTexSize = 2048
|
||||
|
||||
var (
|
||||
gli GL
|
||||
glChan = make(chan func())
|
||||
)
|
||||
|
||||
type offscreenBuffer struct {
|
||||
tex uint32
|
||||
w int
|
||||
|
@ -261,23 +190,6 @@ type gaussianShader struct {
|
|||
kernel int32
|
||||
}
|
||||
|
||||
// LoadGL needs to be called once per GL context to load the GL assets
|
||||
// that canvas needs. The parameter is an implementation of the GL interface
|
||||
// in this package that should make this package neutral to GL implementations.
|
||||
// The goglimpl subpackage contains an implementation based on Go-GL v3.2
|
||||
func LoadGL(glimpl GL) (err error) {
|
||||
gli = glimpl
|
||||
return
|
||||
}
|
||||
|
||||
func glError() error {
|
||||
glErr := gli.GetError()
|
||||
if glErr != gl_NO_ERROR {
|
||||
return fmt.Errorf("GL Error: %x", glErr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFillStyle sets the color, gradient, or image for any fill calls. To set a
|
||||
// color, there are several acceptable formats: 3 or 4 int values for RGB(A) in
|
||||
// the range 0-255, 3 or 4 float values for RGB(A) in the range 0-1, hex strings
|
||||
|
@ -349,57 +261,6 @@ func (cv *Canvas) backendFillStyle(s *drawStyle, alpha float64) backendbase.Fill
|
|||
return stl
|
||||
}
|
||||
|
||||
func (cv *Canvas) enableTextureRenderTarget(offscr *offscreenBuffer) {
|
||||
if offscr.w != cv.w || offscr.h != cv.h {
|
||||
if offscr.w != 0 && offscr.h != 0 {
|
||||
gli.DeleteTextures(1, &offscr.tex)
|
||||
gli.DeleteFramebuffers(1, &offscr.frameBuf)
|
||||
gli.DeleteRenderbuffers(1, &offscr.renderStencilBuf)
|
||||
}
|
||||
offscr.w = cv.w
|
||||
offscr.h = cv.h
|
||||
|
||||
gli.ActiveTexture(gl_TEXTURE0)
|
||||
gli.GenTextures(1, &offscr.tex)
|
||||
gli.BindTexture(gl_TEXTURE_2D, offscr.tex)
|
||||
// todo do non-power-of-two textures work everywhere?
|
||||
if offscr.alpha {
|
||||
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGBA, int32(cv.w), int32(cv.h), 0, gl_RGBA, gl_UNSIGNED_BYTE, nil)
|
||||
} else {
|
||||
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGB, int32(cv.w), int32(cv.h), 0, gl_RGB, gl_UNSIGNED_BYTE, nil)
|
||||
}
|
||||
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, gl_NEAREST)
|
||||
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_NEAREST)
|
||||
|
||||
gli.GenFramebuffers(1, &offscr.frameBuf)
|
||||
gli.BindFramebuffer(gl_FRAMEBUFFER, offscr.frameBuf)
|
||||
|
||||
gli.GenRenderbuffers(1, &offscr.renderStencilBuf)
|
||||
gli.BindRenderbuffer(gl_RENDERBUFFER, offscr.renderStencilBuf)
|
||||
gli.RenderbufferStorage(gl_RENDERBUFFER, gl_DEPTH24_STENCIL8, int32(cv.w), int32(cv.h))
|
||||
gli.FramebufferRenderbuffer(gl_FRAMEBUFFER, gl_DEPTH_STENCIL_ATTACHMENT, gl_RENDERBUFFER, offscr.renderStencilBuf)
|
||||
|
||||
gli.FramebufferTexture(gl_FRAMEBUFFER, gl_COLOR_ATTACHMENT0, offscr.tex, 0)
|
||||
|
||||
if err := gli.CheckFramebufferStatus(gl_FRAMEBUFFER); err != gl_FRAMEBUFFER_COMPLETE {
|
||||
// todo this should maybe not panic
|
||||
panic(fmt.Sprintf("Failed to set up framebuffer for offscreen texture: %x", err))
|
||||
}
|
||||
|
||||
gli.Clear(gl_COLOR_BUFFER_BIT | gl_STENCIL_BUFFER_BIT)
|
||||
} else {
|
||||
gli.BindFramebuffer(gl_FRAMEBUFFER, offscr.frameBuf)
|
||||
}
|
||||
}
|
||||
|
||||
func (cv *Canvas) disableTextureRenderTarget() {
|
||||
if cv.offscreen {
|
||||
cv.enableTextureRenderTarget(&cv.offscrBuf)
|
||||
} else {
|
||||
gli.BindFramebuffer(gl_FRAMEBUFFER, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// SetLineWidth sets the line width for any line drawing calls
|
||||
func (cv *Canvas) SetLineWidth(width float64) {
|
||||
if width < 0 {
|
||||
|
@ -430,7 +291,7 @@ func (cv *Canvas) SetFont(src interface{}, size float64) {
|
|||
if f, ok := fonts[v]; ok {
|
||||
cv.state.font = f
|
||||
} else {
|
||||
f, err := LoadFont(v)
|
||||
f, err := cv.LoadFont(v)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error loading font %s: %v\n", v, err)
|
||||
fonts[v] = nil
|
||||
|
|
22
images.go
22
images.go
|
@ -124,13 +124,13 @@ func (img *Image) Replace(src interface{}) error {
|
|||
// source coordinates
|
||||
func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
|
||||
var img *Image
|
||||
var flip bool
|
||||
if cv2, ok := image.(*Canvas); ok && cv2.offscreen {
|
||||
img = &cv2.offscrImg
|
||||
flip = true
|
||||
} else {
|
||||
// var flip bool
|
||||
// if cv2, ok := image.(*Canvas); ok && cv2.offscreen {
|
||||
// img = &cv2.offscrImg
|
||||
// flip = true
|
||||
// } else {
|
||||
img = cv.getImage(image)
|
||||
}
|
||||
// }
|
||||
|
||||
if img == nil {
|
||||
return
|
||||
|
@ -140,8 +140,6 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
|
|||
return
|
||||
}
|
||||
|
||||
cv.activate()
|
||||
|
||||
var sx, sy, sw, sh, dx, dy, dw, dh float64
|
||||
sw, sh = float64(img.Width()), float64(img.Height())
|
||||
dw, dh = float64(img.Width()), float64(img.Height())
|
||||
|
@ -157,10 +155,10 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
|
|||
dw, dh = coords[6], coords[7]
|
||||
}
|
||||
|
||||
if flip {
|
||||
dy += dh
|
||||
dh = -dh
|
||||
}
|
||||
// if flip {
|
||||
// dy += dh
|
||||
// dh = -dh
|
||||
// }
|
||||
|
||||
var data [4][2]float64
|
||||
data[0] = cv.tf(vec{dx, dy})
|
||||
|
|
7
paths.go
7
paths.go
|
@ -96,8 +96,6 @@ func (cv *Canvas) strokePath(path *Path2D) {
|
|||
return
|
||||
}
|
||||
|
||||
cv.activate()
|
||||
|
||||
dashedPath := cv.applyLineDash(path.p)
|
||||
|
||||
var triBuf [500][2]float64
|
||||
|
@ -328,7 +326,6 @@ func (cv *Canvas) FillPath(path *Path2D) {
|
|||
if len(path.p) < 3 {
|
||||
return
|
||||
}
|
||||
cv.activate()
|
||||
|
||||
var triBuf [500][2]float64
|
||||
tris := buildFillTriangles(path, triBuf[:0])
|
||||
|
@ -431,8 +428,6 @@ func (cv *Canvas) StrokeRect(x, y, w, h float64) {
|
|||
|
||||
// FillRect fills a rectangle with the active fill style
|
||||
func (cv *Canvas) FillRect(x, y, w, h float64) {
|
||||
cv.activate()
|
||||
|
||||
p0 := cv.tf(vec{x, y})
|
||||
p1 := cv.tf(vec{x, y + h})
|
||||
p2 := cv.tf(vec{x + w, y + h})
|
||||
|
@ -448,8 +443,6 @@ func (cv *Canvas) FillRect(x, y, w, h float64) {
|
|||
|
||||
// ClearRect sets the color of the rectangle to transparent black
|
||||
func (cv *Canvas) ClearRect(x, y, w, h float64) {
|
||||
cv.activate()
|
||||
|
||||
p0 := cv.tf(vec{x, y})
|
||||
p1 := cv.tf(vec{x, y + h})
|
||||
p2 := cv.tf(vec{x + w, y + h})
|
||||
|
|
|
@ -12,9 +12,7 @@ import (
|
|||
|
||||
"github.com/go-gl/gl/v3.2-core/gl"
|
||||
"github.com/tfriedel6/canvas"
|
||||
"github.com/tfriedel6/canvas/backend/backendbase"
|
||||
"github.com/tfriedel6/canvas/backend/gogl"
|
||||
"github.com/tfriedel6/canvas/glimpl/gogl"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
|
@ -24,7 +22,7 @@ type Window struct {
|
|||
Window *sdl.Window
|
||||
WindowID uint32
|
||||
GLContext sdl.GLContext
|
||||
Backend backendbase.Backend
|
||||
Backend *goglbackend.GoGLBackend
|
||||
canvas *canvas.Canvas
|
||||
frameTimes [10]time.Time
|
||||
frameIndex int
|
||||
|
@ -98,12 +96,7 @@ func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) {
|
|||
sdl.GLSetSwapInterval(1)
|
||||
gl.Enable(gl.MULTISAMPLE)
|
||||
|
||||
err = canvas.LoadGL(glimplgogl.GLImpl{})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error loading canvas GL assets: %v", err)
|
||||
}
|
||||
|
||||
cv := canvas.New(backend, 0, 0, w, h)
|
||||
cv := canvas.New(backend)
|
||||
wnd := &Window{
|
||||
Window: window,
|
||||
WindowID: windowID,
|
||||
|
@ -195,7 +188,7 @@ func (wnd *Window) StartFrame() error {
|
|||
wnd.SizeChange(int(e.Data1), int(e.Data2))
|
||||
handled = true
|
||||
} else {
|
||||
wnd.canvas.SetBounds(0, 0, int(e.Data1), int(e.Data2))
|
||||
wnd.Backend.SetBounds(0, 0, int(e.Data1), int(e.Data2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
text.go
9
text.go
|
@ -28,10 +28,7 @@ var defaultFont *Font
|
|||
|
||||
// LoadFont loads a font and returns the result. The font
|
||||
// can be a file name or a byte slice in TTF format
|
||||
func LoadFont(src interface{}) (*Font, error) {
|
||||
if gli == nil {
|
||||
panic("LoadGL must be called before fonts can be loaded")
|
||||
}
|
||||
func (cv *Canvas) LoadFont(src interface{}) (*Font, error) {
|
||||
var f *Font
|
||||
switch v := src.(type) {
|
||||
case *truetype.Font:
|
||||
|
@ -64,8 +61,6 @@ func LoadFont(src interface{}) (*Font, error) {
|
|||
// FillText draws the given string at the given coordinates
|
||||
// using the currently set font and font height
|
||||
func (cv *Canvas) FillText(str string, x, y float64) {
|
||||
cv.activate()
|
||||
|
||||
if cv.state.font == nil {
|
||||
return
|
||||
}
|
||||
|
@ -227,8 +222,6 @@ func (cv *Canvas) FillText(str string, x, y float64) {
|
|||
// using the currently set font and font height and using the
|
||||
// current stroke style
|
||||
func (cv *Canvas) StrokeText(str string, x, y float64) {
|
||||
cv.activate()
|
||||
|
||||
if cv.state.font == nil {
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue