mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
graphics: Forbid copying Image objects
This commit is contained in:
parent
b88b86e0e7
commit
94c4cc35ab
49
image.go
49
image.go
@ -47,8 +47,25 @@ func init() {
|
||||
//
|
||||
// Functions of Image never returns error as of 1.5.0-alpha, and error values are always nil.
|
||||
type Image struct {
|
||||
// addr holds self to check copying.
|
||||
// See strings.Builder for similar examples.
|
||||
addr *Image
|
||||
|
||||
restorable *restorable.Image
|
||||
filter Filter
|
||||
|
||||
filter Filter
|
||||
}
|
||||
|
||||
func (i *Image) copyCheck() {
|
||||
if i.addr == nil {
|
||||
// As it is OK that an image is allocated at heap,
|
||||
// 'noespace' function like strings.noescape is not needed.
|
||||
i.addr = i
|
||||
return
|
||||
}
|
||||
if i.addr != i {
|
||||
panic("ebiten: illegal use of non-zero Image copied by value")
|
||||
}
|
||||
}
|
||||
|
||||
// Size returns the size of the image.
|
||||
@ -62,6 +79,7 @@ func (i *Image) Size() (width, height int) {
|
||||
//
|
||||
// Clear always returns nil as of 1.5.0-alpha.
|
||||
func (i *Image) Clear() error {
|
||||
i.copyCheck()
|
||||
i.fill(0, 0, 0, 0)
|
||||
return nil
|
||||
}
|
||||
@ -72,6 +90,7 @@ func (i *Image) Clear() error {
|
||||
//
|
||||
// Fill always returns nil as of 1.5.0-alpha.
|
||||
func (i *Image) Fill(clr color.Color) error {
|
||||
i.copyCheck()
|
||||
r, g, b, a := clr.RGBA()
|
||||
i.fill(uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
|
||||
return nil
|
||||
@ -123,6 +142,7 @@ func (i *Image) fill(r, g, b, a uint8) {
|
||||
//
|
||||
// DrawImage always returns nil as of 1.5.0-alpha.
|
||||
func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
|
||||
i.copyCheck()
|
||||
if i == img {
|
||||
panic("ebiten: Image.DrawImage: img must be different from the receiver")
|
||||
}
|
||||
@ -230,6 +250,7 @@ func (i *Image) At(x, y int) color.Color {
|
||||
//
|
||||
// Dipose always return nil as of 1.5.0-alpha.
|
||||
func (i *Image) Dispose() error {
|
||||
i.copyCheck()
|
||||
if i.restorable == nil {
|
||||
return nil
|
||||
}
|
||||
@ -251,6 +272,7 @@ func (i *Image) Dispose() error {
|
||||
//
|
||||
// ReplacePixels always returns nil as of 1.5.0-alpha.
|
||||
func (i *Image) ReplacePixels(p []byte) error {
|
||||
i.copyCheck()
|
||||
if i.restorable == nil {
|
||||
return nil
|
||||
}
|
||||
@ -317,7 +339,10 @@ type DrawImageOptions struct {
|
||||
func NewImage(width, height int, filter Filter) (*Image, error) {
|
||||
checkSize(width, height)
|
||||
r := restorable.NewImage(width, height, false)
|
||||
i := &Image{r, filter}
|
||||
i := &Image{
|
||||
restorable: r,
|
||||
filter: filter,
|
||||
}
|
||||
i.fill(0, 0, 0, 0)
|
||||
runtime.SetFinalizer(i, (*Image).Dispose)
|
||||
return i, nil
|
||||
@ -327,7 +352,10 @@ func NewImage(width, height int, filter Filter) (*Image, error) {
|
||||
func newImageWithoutInit(width, height int) *Image {
|
||||
checkSize(width, height)
|
||||
r := restorable.NewImage(width, height, false)
|
||||
i := &Image{r, FilterDefault}
|
||||
i := &Image{
|
||||
restorable: r,
|
||||
filter: FilterDefault,
|
||||
}
|
||||
runtime.SetFinalizer(i, (*Image).Dispose)
|
||||
return i
|
||||
}
|
||||
@ -350,7 +378,10 @@ func newImageWithoutInit(width, height int) *Image {
|
||||
func newVolatileImage(width, height int, filter Filter) *Image {
|
||||
checkSize(width, height)
|
||||
r := restorable.NewImage(width, height, true)
|
||||
i := &Image{r, filter}
|
||||
i := &Image{
|
||||
restorable: r,
|
||||
filter: filter,
|
||||
}
|
||||
i.fill(0, 0, 0, 0)
|
||||
runtime.SetFinalizer(i, (*Image).Dispose)
|
||||
return i
|
||||
@ -368,7 +399,10 @@ func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
|
||||
size := source.Bounds().Size()
|
||||
checkSize(size.X, size.Y)
|
||||
r := restorable.NewImageFromImage(source)
|
||||
i := &Image{r, filter}
|
||||
i := &Image{
|
||||
restorable: r,
|
||||
filter: filter,
|
||||
}
|
||||
runtime.SetFinalizer(i, (*Image).Dispose)
|
||||
return i, nil
|
||||
}
|
||||
@ -376,7 +410,10 @@ func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
|
||||
func newImageWithScreenFramebuffer(width, height, framebufferWidth, framebufferHeight int) *Image {
|
||||
checkSize(width, height)
|
||||
r := restorable.NewScreenFramebufferImage(width, height, framebufferWidth, framebufferHeight)
|
||||
i := &Image{r, FilterDefault}
|
||||
i := &Image{
|
||||
restorable: r,
|
||||
filter: FilterDefault,
|
||||
}
|
||||
runtime.SetFinalizer(i, (*Image).Dispose)
|
||||
return i
|
||||
}
|
||||
|
@ -744,3 +744,15 @@ func TestImageSize4096(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageCopy(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("copying image and using it should panic")
|
||||
}
|
||||
}()
|
||||
|
||||
img0, _ := NewImage(256, 256, FilterDefault)
|
||||
img1 := *img0
|
||||
img1.Fill(color.Transparent)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user