diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go index fcb4d11..224bc5f 100644 --- a/backend/backendbase/base.go +++ b/backend/backendbase/base.go @@ -89,15 +89,11 @@ type GradientStop struct { type LinearGradient interface { Delete() - IsDeleted() bool - IsOpaque() bool Replace(data Gradient) } type RadialGradient interface { Delete() - IsDeleted() bool - IsOpaque() bool Replace(data Gradient) } @@ -106,7 +102,5 @@ type Image interface { Height() int Size() (w, h int) Delete() - IsDeleted() bool Replace(src image.Image) error - IsOpaque() bool } diff --git a/backend/gogl/gradients.go b/backend/gogl/gradients.go index b103253..49dee06 100644 --- a/backend/gogl/gradients.go +++ b/backend/gogl/gradients.go @@ -24,18 +24,16 @@ type RadialGradient struct { } type gradient struct { - b *GoGLBackend - tex uint32 - loaded bool - deleted bool - opaque bool + b *GoGLBackend + tex uint32 + loaded bool } func (b *GoGLBackend) LoadLinearGradient(data backendbase.Gradient) backendbase.LinearGradient { b.activate() lg := &LinearGradient{ - gradient: gradient{b: b, opaque: true}, + gradient: gradient{b: b}, } gl.GenTextures(1, &lg.tex) gl.ActiveTexture(gl.TEXTURE0) @@ -57,7 +55,7 @@ func (b *GoGLBackend) LoadRadialGradient(data backendbase.Gradient) backendbase. b.activate() rg := &RadialGradient{ - gradient: gradient{b: b, opaque: true}, + gradient: gradient{b: b}, } gl.GenTextures(1, &rg.tex) gl.ActiveTexture(gl.TEXTURE0) @@ -80,12 +78,8 @@ func (g *gradient) Delete() { g.b.activate() gl.DeleteTextures(1, &g.tex) - g.deleted = true } -func (g *gradient) IsDeleted() bool { return g.deleted } -func (g *gradient) IsOpaque() bool { return g.opaque } - func (lg *LinearGradient) Replace(data backendbase.Gradient) { lg.load(data) } func (rg *RadialGradient) Replace(data backendbase.Gradient) { rg.load(data) } diff --git a/backend/gogl/images.go b/backend/gogl/images.go index 33beec6..e83846f 100644 --- a/backend/gogl/images.go +++ b/backend/gogl/images.go @@ -12,12 +12,10 @@ 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 - opaque bool - flip bool + b *GoGLBackend + w, h int + tex uint32 + flip bool } func (b *GoGLBackend) LoadImage(src image.Image) (backendbase.Image, error) { @@ -38,10 +36,8 @@ func (b *GoGLBackend) LoadImage(src image.Image) (backendbase.Image, error) { img.b = b runtime.SetFinalizer(img, func(img *Image) { - if !img.deleted { - b.glChan <- func() { - gl.DeleteTextures(1, &img.tex) - } + b.glChan <- func() { + gl.DeleteTextures(1, &img.tex) } }) @@ -74,19 +70,7 @@ func loadImage(src image.Image, tex uint32) (*Image, error) { } func loadImageRGBA(src *image.RGBA, tex uint32) (*Image, error) { - img := &Image{tex: tex, w: src.Bounds().Dx(), h: src.Bounds().Dy(), opaque: true} - -checkOpaque: - for y := 0; y < img.h; y++ { - off := src.PixOffset(0, y) + 3 - for x := 0; x < img.w; x++ { - if src.Pix[off] < 255 { - img.opaque = false - break checkOpaque - } - off += 4 - } - } + img := &Image{tex: tex, w: src.Bounds().Dx(), h: src.Bounds().Dy()} gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) @@ -147,7 +131,7 @@ func loadImageGray(src *image.Gray, tex uint32) (*Image, error) { } func loadImageConverted(src image.Image, tex uint32) (*Image, error) { - img := &Image{tex: tex, w: src.Bounds().Dx(), h: src.Bounds().Dy(), opaque: true} + img := &Image{tex: tex, w: src.Bounds().Dx(), h: src.Bounds().Dy()} gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) @@ -161,9 +145,6 @@ func loadImageConverted(src image.Image, tex uint32) (*Image, error) { ir, ig, ib, ia := src.At(x, y).RGBA() r, g, b, a := uint8(ir>>8), uint8(ig>>8), uint8(ib>>8), uint8(ia>>8) data = append(data, r, g, b, a) - if a < 255 { - img.opaque = false - } } } gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(img.w), int32(img.h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) @@ -192,13 +173,8 @@ func (img *Image) Delete() { img.b.activate() gl.DeleteTextures(1, &img.tex) - img.deleted = true } -// IsDeleted returns true if the Delete function has been -// called on this image -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() @@ -214,10 +190,6 @@ func (img *Image) Replace(src image.Image) error { return nil } -// IsOpaque returns true if all pixels in the image -// have a full alpha value -func (img *Image) IsOpaque() bool { return img.opaque } - func (b *GoGLBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float64, pts [4][2]float64, alpha float64) { b.activate() diff --git a/canvas.go b/canvas.go index e1cef59..c08a2c9 100644 --- a/canvas.go +++ b/canvas.go @@ -226,19 +226,6 @@ func (cv *Canvas) parseStyle(value ...interface{}) drawStyle { return style } -func (s *drawStyle) isOpaque() bool { - if lg := s.linearGradient; lg != nil { - return lg.opaque - } - if rg := s.radialGradient; rg != nil { - return rg.opaque - } - if img := s.image; img != nil { - return img.img.IsOpaque() - } - return s.color.A >= 255 -} - func (cv *Canvas) backendFillStyle(s *drawStyle, alpha float64) backendbase.FillStyle { stl := backendbase.FillStyle{Color: s.color} alpha *= cv.state.globalAlpha diff --git a/gradients.go b/gradients.go index 0af8d44..ac8b088 100644 --- a/gradients.go +++ b/gradients.go @@ -68,13 +68,27 @@ func (cv *Canvas) CreateRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGr } // Delete explicitly deletes the gradient -func (lg *LinearGradient) Delete() { lg.grad.Delete() } +func (lg *LinearGradient) Delete() { + if lg.deleted { + return + } + lg.grad.Delete() + lg.grad = nil + lg.deleted = true +} // Delete explicitly deletes the gradient -func (rg *RadialGradient) Delete() { rg.grad.Delete() } +func (rg *RadialGradient) Delete() { + if rg.deleted { + return + } + rg.grad.Delete() + rg.grad = nil + rg.deleted = true +} func (lg *LinearGradient) load() { - if lg.loaded || len(lg.data) < 1 { + if lg.loaded || len(lg.data) < 1 || lg.deleted { return } @@ -88,7 +102,7 @@ func (lg *LinearGradient) load() { } func (rg *RadialGradient) load() { - if rg.loaded || len(rg.data) < 1 { + if rg.loaded || len(rg.data) < 1 || rg.deleted { return } diff --git a/images.go b/images.go index 33398b9..0d46156 100644 --- a/images.go +++ b/images.go @@ -13,8 +13,9 @@ import ( ) type Image struct { - cv *Canvas - img backendbase.Image + cv *Canvas + img backendbase.Image + deleted bool } // LoadImage loads an image. The src parameter can be either an image from the @@ -113,7 +114,11 @@ func (img *Image) Size() (int, int) { return img.img.Size() } // Delete deletes the image from memory. Any draw calls with a deleted image // will not do anything -func (img *Image) Delete() { img.img.Delete() } +func (img *Image) Delete() { + img.img.Delete() + img.img = nil + img.deleted = true +} // Replace replaces the image with the new one func (img *Image) Replace(src interface{}) error { @@ -137,20 +142,9 @@ func (img *Image) Replace(src interface{}) error { // Where dx/dy/dw/dh are the destination coordinates and sx/sy/sw/sh are the // 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 { - img = cv.getImage(image) - // } + img := cv.getImage(image) - if img == nil { - return - } - - if img.img.IsDeleted() { + if img == nil || img.deleted { return } @@ -169,11 +163,6 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) { dw, dh = coords[6], coords[7] } - // if flip { - // dy += dh - // dh = -dh - // } - var data [4][2]float64 data[0] = cv.tf(vec{dx, dy}) data[1] = cv.tf(vec{dx, dy + dh})