From d2c991b774b395f2763f97cfb75b8ab26277c38c Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 28 Apr 2023 00:55:10 +0900 Subject: [PATCH] all: refactoring: use image.Rectangle --- image.go | 10 +++--- internal/atlas/image.go | 10 +++--- internal/atlas/image_test.go | 63 ++++++++++++++++++----------------- internal/atlas/shader_test.go | 9 ++--- internal/buffered/image.go | 27 +++++++-------- internal/mipmap/mipmap.go | 9 ++--- internal/ui/image.go | 39 +++++++++++----------- internal/ui/ui.go | 5 +-- 8 files changed, 88 insertions(+), 84 deletions(-) diff --git a/image.go b/image.go index dbb50f386..f2cbb653d 100644 --- a/image.go +++ b/image.go @@ -94,7 +94,7 @@ func (i *Image) Fill(clr color.Color) { caf = float32(ca) / 0xffff b := i.Bounds() x, y := i.adjustPosition(b.Min.X, b.Min.Y) - i.image.Fill(crf, cgf, cbf, caf, x, y, b.Dx(), b.Dy()) + i.image.Fill(crf, cgf, cbf, caf, image.Rect(x, y, x+b.Dx(), y+b.Dy())) } func canSkipMipmap(geom GeoM, filter builtinshader.Filter) bool { @@ -881,7 +881,7 @@ func (i *Image) ReadPixels(pixels []byte) { } x, y := i.adjustPosition(b.Min.X, b.Min.Y) - i.image.ReadPixels(pixels, x, y, b.Dx(), b.Dy()) + i.image.ReadPixels(pixels, image.Rect(x, y, x+b.Dx(), y+b.Dy())) } // At returns the color of the image at (x, y). @@ -927,7 +927,7 @@ func (i *Image) at(x, y int) (r, g, b, a byte) { x, y = i.adjustPosition(x, y) var pix [4]byte - i.image.ReadPixels(pix[:], x, y, 1, 1) + i.image.ReadPixels(pix[:], image.Rect(x, y, x+1, y+1)) return pix[0], pix[1], pix[2], pix[3] } @@ -950,7 +950,7 @@ func (i *Image) Set(x, y int, clr color.Color) { dx, dy := i.adjustPosition(x, y) cr, cg, cb, ca := clr.RGBA() - i.image.WritePixels([]byte{byte(cr / 0x101), byte(cg / 0x101), byte(cb / 0x101), byte(ca / 0x101)}, dx, dy, 1, 1) + i.image.WritePixels([]byte{byte(cr / 0x101), byte(cg / 0x101), byte(cb / 0x101), byte(ca / 0x101)}, image.Rect(dx, dy, dx+1, dy+1)) } // Dispose disposes the image data. @@ -997,7 +997,7 @@ func (i *Image) WritePixels(pixels []byte) { // Do not need to copy pixels here. // * In internal/mipmap, pixels are copied when necessary. // * In internal/atlas, pixels are copied to make its paddings. - i.image.WritePixels(pixels, x, y, r.Dx(), r.Dy()) + i.image.WritePixels(pixels, image.Rect(x, y, x+r.Dx(), y+r.Dy())) } // ReplacePixels replaces the pixels of the image. diff --git a/internal/atlas/image.go b/internal/atlas/image.go index f6aaed907..7967ab94d 100644 --- a/internal/atlas/image.go +++ b/internal/atlas/image.go @@ -515,10 +515,10 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [ } // WritePixels replaces the pixels on the image. -func (i *Image) WritePixels(pix []byte, x, y, width, height int) { +func (i *Image) WritePixels(pix []byte, region image.Rectangle) { backendsM.Lock() defer backendsM.Unlock() - i.writePixels(pix, image.Rect(x, y, x+width, y+height)) + i.writePixels(pix, region) } func (i *Image) writePixels(pix []byte, region image.Rectangle) { @@ -585,7 +585,7 @@ func (i *Image) writePixels(pix []byte, region image.Rectangle) { i.backend.restorable.WritePixels(pixb, r) } -func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, x, y, width, height int) error { +func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, region image.Rectangle) error { backendsM.Lock() defer backendsM.Unlock() @@ -601,9 +601,7 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte } r := i.regionWithPadding() - x += r.Min.X - y += r.Min.Y - return i.backend.restorable.ReadPixels(graphicsDriver, pixels, image.Rect(x, y, x+width, y+height)) + return i.backend.restorable.ReadPixels(graphicsDriver, pixels, region.Add(r.Min)) } // MarkDisposed marks the image as disposed. The actual operation is deferred. diff --git a/internal/atlas/image_test.go b/internal/atlas/image_test.go index 6980ce374..0db55e0da 100644 --- a/internal/atlas/image_test.go +++ b/internal/atlas/image_test.go @@ -15,6 +15,7 @@ package atlas_test import ( + "image" "image/color" "runtime" "testing" @@ -63,17 +64,17 @@ func TestEnsureIsolatedFromSourceBackend(t *testing.T) { img1 := atlas.NewImage(bigSize, 100, atlas.ImageTypeRegular) defer img1.MarkDisposed() // Ensure img1's region is allocated. - img1.WritePixels(make([]byte, 4*bigSize*100), 0, 0, bigSize, 100) + img1.WritePixels(make([]byte, 4*bigSize*100), image.Rect(0, 0, bigSize, 100)) img2 := atlas.NewImage(100, bigSize, atlas.ImageTypeRegular) defer img2.MarkDisposed() - img2.WritePixels(make([]byte, 4*100*bigSize), 0, 0, 100, bigSize) + img2.WritePixels(make([]byte, 4*100*bigSize), image.Rect(0, 0, 100, bigSize)) const size = 32 img3 := atlas.NewImage(size/2, size/2, atlas.ImageTypeRegular) defer img3.MarkDisposed() - img3.WritePixels(make([]byte, (size/2)*(size/2)*4), 0, 0, size/2, size/2) + img3.WritePixels(make([]byte, (size/2)*(size/2)*4), image.Rect(0, 0, size/2, size/2)) img4 := atlas.NewImage(size, size, atlas.ImageTypeRegular) defer img4.MarkDisposed() @@ -90,7 +91,7 @@ func TestEnsureIsolatedFromSourceBackend(t *testing.T) { pix[4*(i+j*size)+3] = byte(i + j) } } - img4.WritePixels(pix, 0, 0, size, size) + img4.WritePixels(pix, image.Rect(0, 0, size, size)) const ( dx0 = size / 4 @@ -126,7 +127,7 @@ func TestEnsureIsolatedFromSourceBackend(t *testing.T) { } pix = make([]byte, 4*size*size) - if err := img4.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil { + if err := img4.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil { t.Fatal(err) } for j := 0; j < size; j++ { @@ -158,11 +159,11 @@ func TestReputOnSourceBackend(t *testing.T) { img0 := atlas.NewImage(size, size, atlas.ImageTypeRegular) defer img0.MarkDisposed() - img0.WritePixels(make([]byte, 4*size*size), 0, 0, size, size) + img0.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size)) img1 := atlas.NewImage(size, size, atlas.ImageTypeRegular) defer img1.MarkDisposed() - img1.WritePixels(make([]byte, 4*size*size), 0, 0, size, size) + img1.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size)) if got, want := img1.IsOnSourceBackendForTesting(), true; got != want { t.Errorf("got: %v, want: %v", got, want) } @@ -178,12 +179,12 @@ func TestReputOnSourceBackend(t *testing.T) { pix[4*(i+j*size)+3] = byte(i + j) } } - img2.WritePixels(pix, 0, 0, size, size) + img2.WritePixels(pix, image.Rect(0, 0, size, size)) // Create a volatile image. This should always be on a non-source backend. img3 := atlas.NewImage(size, size, atlas.ImageTypeVolatile) defer img3.MarkDisposed() - img3.WritePixels(make([]byte, 4*size*size), 0, 0, size, size) + img3.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size)) if got, want := img3.IsOnSourceBackendForTesting(), false; got != want { t.Errorf("got: %v, want: %v", got, want) } @@ -232,7 +233,7 @@ func TestReputOnSourceBackend(t *testing.T) { } pix = make([]byte, 4*size*size) - if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil { + if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil { t.Fatal(err) } for j := 0; j < size; j++ { @@ -256,7 +257,7 @@ func TestReputOnSourceBackend(t *testing.T) { } pix = make([]byte, 4*size*size) - if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil { + if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil { t.Fatal(err) } for j := 0; j < size; j++ { @@ -288,7 +289,7 @@ func TestReputOnSourceBackend(t *testing.T) { if err := atlas.PutImagesOnSourceBackendForTesting(ui.GraphicsDriverForTesting()); err != nil { t.Fatal(err) } - img1.WritePixels(make([]byte, 4*size*size), 0, 0, size, size) + img1.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size)) vs := quadVertices(size, size, 0, 0, 1) img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false) if got, want := img1.IsOnSourceBackendForTesting(), false; got != want { @@ -333,7 +334,7 @@ func TestExtend(t *testing.T) { p0[4*i+2] = byte(i) p0[4*i+3] = byte(i) } - img0.WritePixels(p0, 0, 0, w0, h0) + img0.WritePixels(p0, image.Rect(0, 0, w0, h0)) const w1, h1 = minSourceImageSizeForTesting + 1, 100 img1 := atlas.NewImage(w1, h1, atlas.ImageTypeRegular) @@ -347,10 +348,10 @@ func TestExtend(t *testing.T) { p1[4*i+3] = byte(i) } // Ensure to allocate - img1.WritePixels(p1, 0, 0, w1, h1) + img1.WritePixels(p1, image.Rect(0, 0, w1, h1)) pix0 := make([]byte, 4*w0*h0) - if err := img0.ReadPixels(ui.GraphicsDriverForTesting(), pix0, 0, 0, w0, h0); err != nil { + if err := img0.ReadPixels(ui.GraphicsDriverForTesting(), pix0, image.Rect(0, 0, w0, h0)); err != nil { t.Fatal(err) } for j := 0; j < h0; j++ { @@ -369,7 +370,7 @@ func TestExtend(t *testing.T) { } pix1 := make([]byte, 4*w1*h1) - if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix1, 0, 0, w1, h1); err != nil { + if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix1, image.Rect(0, 0, w1, h1)); err != nil { t.Fatal(err) } for j := 0; j < h1; j++ { @@ -402,7 +403,7 @@ func TestWritePixelsAfterDrawTriangles(t *testing.T) { pix[4*i+2] = byte(i) pix[4*i+3] = byte(i) } - src.WritePixels(pix, 0, 0, w, h) + src.WritePixels(pix, image.Rect(0, 0, w, h)) vs := quadVertices(w, h, 0, 0, 1) is := graphics.QuadIndices() @@ -413,10 +414,10 @@ func TestWritePixelsAfterDrawTriangles(t *testing.T) { Height: h, } dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false) - dst.WritePixels(pix, 0, 0, w, h) + dst.WritePixels(pix, image.Rect(0, 0, w, h)) pix = make([]byte, 4*w*h) - if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil { + if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, w, h)); err != nil { t.Fatal(err) } for j := 0; j < h; j++ { @@ -450,7 +451,7 @@ func TestSmallImages(t *testing.T) { pix[4*i+2] = 0xff pix[4*i+3] = 0xff } - src.WritePixels(pix, 0, 0, w, h) + src.WritePixels(pix, image.Rect(0, 0, w, h)) vs := quadVertices(w, h, 0, 0, 1) is := graphics.QuadIndices() @@ -463,7 +464,7 @@ func TestSmallImages(t *testing.T) { dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false) pix = make([]byte, 4*w*h) - if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil { + if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, w, h)); err != nil { t.Fatal(err) } for j := 0; j < h; j++ { @@ -497,7 +498,7 @@ func TestLongImages(t *testing.T) { pix[4*i+2] = 0xff pix[4*i+3] = 0xff } - src.WritePixels(pix, 0, 0, w, h) + src.WritePixels(pix, image.Rect(0, 0, w, h)) const scale = 120 vs := quadVertices(w, h, 0, 0, scale) @@ -511,7 +512,7 @@ func TestLongImages(t *testing.T) { dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false) pix = make([]byte, 4*dstW*dstH) - if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, dstW, dstH); err != nil { + if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, dstW, dstH)); err != nil { t.Fatal(err) } for j := 0; j < h; j++ { @@ -547,12 +548,12 @@ func TestExtendWithBigImage(t *testing.T) { img0 := atlas.NewImage(1, 1, atlas.ImageTypeRegular) defer img0.MarkDisposed() - img0.WritePixels(make([]byte, 4*1*1), 0, 0, 1, 1) + img0.WritePixels(make([]byte, 4*1*1), image.Rect(0, 0, 1, 1)) img1 := atlas.NewImage(minSourceImageSizeForTesting+1, minSourceImageSizeForTesting+1, atlas.ImageTypeRegular) defer img1.MarkDisposed() - img1.WritePixels(make([]byte, 4*(minSourceImageSizeForTesting+1)*(minSourceImageSizeForTesting+1)), 0, 0, minSourceImageSizeForTesting+1, minSourceImageSizeForTesting+1) + img1.WritePixels(make([]byte, 4*(minSourceImageSizeForTesting+1)*(minSourceImageSizeForTesting+1)), image.Rect(0, 0, minSourceImageSizeForTesting+1, minSourceImageSizeForTesting+1)) } // Issue #1217 @@ -565,7 +566,7 @@ func TestMaxImageSize(t *testing.T) { s := maxImageSizeForTesting - 2*paddingSize img1 := atlas.NewImage(s, s, atlas.ImageTypeRegular) defer img1.MarkDisposed() - img1.WritePixels(make([]byte, 4*s*s), 0, 0, s, s) + img1.WritePixels(make([]byte, 4*s*s), image.Rect(0, 0, s, s)) } // Issue #1217 (disabled) @@ -578,7 +579,7 @@ func Disable_TestMinImageSize(t *testing.T) { s := minSourceImageSizeForTesting img := atlas.NewImage(s, s, atlas.ImageTypeRegular) defer img.MarkDisposed() - img.WritePixels(make([]byte, 4*s*s), 0, 0, s, s) + img.WritePixels(make([]byte, 4*s*s), image.Rect(0, 0, s, s)) } func TestMaxImageSizeJust(t *testing.T) { @@ -587,7 +588,7 @@ func TestMaxImageSizeJust(t *testing.T) { // TODO: Should we allow such this size for ImageTypeRegular? img := atlas.NewImage(s, s, atlas.ImageTypeUnmanaged) defer img.MarkDisposed() - img.WritePixels(make([]byte, 4*s*s), 0, 0, s, s) + img.WritePixels(make([]byte, 4*s*s), image.Rect(0, 0, s, s)) } func TestMaxImageSizeExceeded(t *testing.T) { @@ -602,7 +603,7 @@ func TestMaxImageSizeExceeded(t *testing.T) { } }() - img.WritePixels(make([]byte, 4*(s+1)*s), 0, 0, s+1, s) + img.WritePixels(make([]byte, 4*(s+1)*s), image.Rect(0, 0, s+1, s)) } // Issue #1421 @@ -726,7 +727,7 @@ func TestImageWritePixelsModify(t *testing.T) { pix[4*(i+j*size)+3] = byte(i + j) } } - img.WritePixels(pix, 0, 0, size, size) + img.WritePixels(pix, image.Rect(0, 0, size, size)) // Modify pix after WritePixels. for j := 0; j < size; j++ { @@ -740,7 +741,7 @@ func TestImageWritePixelsModify(t *testing.T) { // Check the pixels are the original ones. pix = make([]byte, 4*size*size) - if err := img.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil { + if err := img.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil { t.Fatal(err) } for j := 0; j < size; j++ { diff --git a/internal/atlas/shader_test.go b/internal/atlas/shader_test.go index 88e160398..218d1c838 100644 --- a/internal/atlas/shader_test.go +++ b/internal/atlas/shader_test.go @@ -15,6 +15,7 @@ package atlas_test import ( + "image" "image/color" "testing" @@ -48,7 +49,7 @@ func TestShaderFillTwice(t *testing.T) { dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, s1, nil, false) pix := make([]byte, 4*w*h) - if err := dst.ReadPixels(g, pix, 0, 0, w, h); err != nil { + if err := dst.ReadPixels(g, pix, image.Rect(0, 0, w, h)); err != nil { t.Error(err) } if got, want := (color.RGBA{R: pix[0], G: pix[1], B: pix[2], A: pix[3]}), (color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xff}); got != want { @@ -61,9 +62,9 @@ func TestImageDrawTwice(t *testing.T) { dst := atlas.NewImage(w, h, atlas.ImageTypeRegular) src0 := atlas.NewImage(w, h, atlas.ImageTypeRegular) - src0.WritePixels([]byte{0xff, 0xff, 0xff, 0xff}, 0, 0, w, h) + src0.WritePixels([]byte{0xff, 0xff, 0xff, 0xff}, image.Rect(0, 0, w, h)) src1 := atlas.NewImage(w, h, atlas.ImageTypeRegular) - src1.WritePixels([]byte{0x80, 0x80, 0x80, 0xff}, 0, 0, w, h) + src1.WritePixels([]byte{0x80, 0x80, 0x80, 0xff}, image.Rect(0, 0, w, h)) vs := quadVertices(w, h, 0, 0, 1) is := graphics.QuadIndices() @@ -80,7 +81,7 @@ func TestImageDrawTwice(t *testing.T) { dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false) pix := make([]byte, 4*w*h) - if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil { + if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, w, h)); err != nil { t.Error(err) } if got, want := (color.RGBA{R: pix[0], G: pix[1], B: pix[2], A: pix[3]}), (color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xff}); got != want { diff --git a/internal/buffered/image.go b/internal/buffered/image.go index c6e81b787..afba1b6d8 100644 --- a/internal/buffered/image.go +++ b/internal/buffered/image.go @@ -16,6 +16,7 @@ package buffered import ( "fmt" + "image" "github.com/hajimehoshi/ebiten/v2/internal/atlas" "github.com/hajimehoshi/ebiten/v2/internal/graphics" @@ -89,12 +90,12 @@ func (i *Image) markDisposedImpl() { i.img.MarkDisposed() } -func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, x, y, width, height int) error { +func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, region image.Rectangle) error { checkDelayedCommandsFlushed("ReadPixels") // If restorable.AlwaysReadPixelsFromGPU() returns false, the pixel data is cached in the restorable package. if !restorable.AlwaysReadPixelsFromGPU() { - if err := i.img.ReadPixels(graphicsDriver, pixels, x, y, width, height); err != nil { + if err := i.img.ReadPixels(graphicsDriver, pixels, region); err != nil { return err } return nil @@ -102,16 +103,16 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte if i.pixels == nil { pix := make([]byte, 4*i.width*i.height) - if err := i.img.ReadPixels(graphicsDriver, pix, 0, 0, i.width, i.height); err != nil { + if err := i.img.ReadPixels(graphicsDriver, pix, image.Rect(0, 0, i.width, i.height)); err != nil { return err } i.pixels = pix } - lineWidth := 4 * width - for j := 0; j < height; j++ { - dstX := 4 * j * width - srcX := 4 * ((y+j)*i.width + x) + lineWidth := 4 * region.Dx() + for j := 0; j < region.Dy(); j++ { + dstX := 4 * j * region.Dx() + srcX := 4 * ((region.Min.Y+j)*i.width + region.Min.X) copy(pixels[dstX:dstX+lineWidth], i.pixels[srcX:srcX+lineWidth]) } return nil @@ -123,8 +124,8 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name stri } // WritePixels replaces the pixels at the specified region. -func (i *Image) WritePixels(pix []byte, x, y, width, height int) { - if l := 4 * width * height; len(pix) != l { +func (i *Image) WritePixels(pix []byte, region image.Rectangle) { + if l := 4 * region.Dx() * region.Dy(); len(pix) != l { panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", len(pix), l)) } @@ -132,17 +133,17 @@ func (i *Image) WritePixels(pix []byte, x, y, width, height int) { copied := make([]byte, len(pix)) copy(copied, pix) if tryAddDelayedCommand(func() { - i.writePixelsImpl(copied, x, y, width, height) + i.writePixelsImpl(copied, region) }) { return } } - i.writePixelsImpl(pix, x, y, width, height) + i.writePixelsImpl(pix, region) } -func (i *Image) writePixelsImpl(pix []byte, x, y, width, height int) { +func (i *Image) writePixelsImpl(pix []byte, region image.Rectangle) { i.invalidatePixels() - i.img.WritePixels(pix, x, y, width, height) + i.img.WritePixels(pix, region) } // DrawTriangles draws the src image with the given vertices. diff --git a/internal/mipmap/mipmap.go b/internal/mipmap/mipmap.go index 490c09bc0..ffcfd05a8 100644 --- a/internal/mipmap/mipmap.go +++ b/internal/mipmap/mipmap.go @@ -16,6 +16,7 @@ package mipmap import ( "fmt" + "image" "math" "github.com/hajimehoshi/ebiten/v2/internal/atlas" @@ -56,13 +57,13 @@ func (m *Mipmap) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name str return m.orig.DumpScreenshot(graphicsDriver, name, blackbg) } -func (m *Mipmap) WritePixels(pix []byte, x, y, width, height int) { - m.orig.WritePixels(pix, x, y, width, height) +func (m *Mipmap) WritePixels(pix []byte, region image.Rectangle) { + m.orig.WritePixels(pix, region) m.disposeMipmaps() } -func (m *Mipmap) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, x, y, width, height int) error { - return m.orig.ReadPixels(graphicsDriver, pixels, x, y, width, height) +func (m *Mipmap) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, region image.Rectangle) error { + return m.orig.ReadPixels(graphicsDriver, pixels, region) } func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageCount]*Mipmap, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms []uint32, evenOdd bool, canSkipMipmap bool) { diff --git a/internal/ui/image.go b/internal/ui/image.go index 3f5a53826..03e2dc6ea 100644 --- a/internal/ui/image.go +++ b/internal/ui/image.go @@ -16,6 +16,7 @@ package ui import ( "fmt" + "image" "math" "github.com/hajimehoshi/ebiten/v2/internal/atlas" @@ -40,7 +41,7 @@ type Image struct { height int imageType atlas.ImageType - dotsBuffer map[[2]int][4]byte + dotsBuffer map[image.Point][4]byte // bigOffscreenBuffer is a double-sized offscreen for anti-alias rendering. bigOffscreenBuffer *bigOffscreenImage @@ -115,22 +116,22 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [ i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd, canSkipMipmap) } -func (i *Image) WritePixels(pix []byte, x, y, width, height int) { +func (i *Image) WritePixels(pix []byte, region image.Rectangle) { if i.modifyCallback != nil { i.modifyCallback() } - if width == 1 && height == 1 { + if region.Dx() == 1 && region.Dy() == 1 { // Flush the other buffer to make the buffers exclusive. i.flushBigOffscreenBufferIfNeeded() if i.dotsBuffer == nil { - i.dotsBuffer = map[[2]int][4]byte{} + i.dotsBuffer = map[image.Point][4]byte{} } var clr [4]byte copy(clr[:], pix) - i.dotsBuffer[[2]int{x, y}] = clr + i.dotsBuffer[region.Min] = clr // One square requires 6 indices (= 2 triangles). if len(i.dotsBuffer) >= graphics.MaxVerticesCount/6 { @@ -140,10 +141,10 @@ func (i *Image) WritePixels(pix []byte, x, y, width, height int) { } i.flushBufferIfNeeded() - i.mipmap.WritePixels(pix, x, y, width, height) + i.mipmap.WritePixels(pix, region) } -func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) { +func (i *Image) ReadPixels(pixels []byte, region image.Rectangle) { // Check the error existence and avoid unnecessary calls. if theGlobalState.error() != nil { return @@ -151,8 +152,8 @@ func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) { i.flushBigOffscreenBufferIfNeeded() - if width == 1 && height == 1 { - if c, ok := i.dotsBuffer[[2]int{x, y}]; ok { + if region.Dx() == 1 && region.Dy() == 1 { + if c, ok := i.dotsBuffer[region.Min]; ok { copy(pixels, c[:]) return } @@ -162,7 +163,7 @@ func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) { i.flushDotsBufferIfNeeded() } - if err := theUI.readPixels(i.mipmap, pixels, x, y, width, height); err != nil { + if err := theUI.readPixels(i.mipmap, pixels, region); err != nil { if panicOnErrorOnReadingPixels { panic(err) } @@ -192,8 +193,8 @@ func (i *Image) flushDotsBufferIfNeeded() { sx, sy := float32(1), float32(1) var idx int for p, c := range i.dotsBuffer { - dx := float32(p[0]) - dy := float32(p[1]) + dx := float32(p.X) + dy := float32(p.Y) crf := float32(c[0]) / 0xff cgf := float32(c[1]) / 0xff cbf := float32(c[2]) / 0xff @@ -273,19 +274,19 @@ func init() { pix[i] = 0xff } // As whiteImage is used at Fill, use WritePixels instead. - whiteImage.WritePixels(pix, 0, 0, whiteImage.width, whiteImage.height) + whiteImage.WritePixels(pix, image.Rect(0, 0, whiteImage.width, whiteImage.height)) } func (i *Image) clear() { - i.Fill(0, 0, 0, 0, 0, 0, i.width, i.height) + i.Fill(0, 0, 0, 0, image.Rect(0, 0, i.width, i.height)) } -func (i *Image) Fill(r, g, b, a float32, x, y, width, height int) { +func (i *Image) Fill(r, g, b, a float32, region image.Rectangle) { dstRegion := graphicsdriver.Region{ - X: float32(x), - Y: float32(y), - Width: float32(width), - Height: float32(height), + X: float32(region.Min.X), + Y: float32(region.Min.Y), + Width: float32(region.Dx()), + Height: float32(region.Dy()), } if len(i.tmpVerticesForFill) < 4*graphics.VertexFloatCount { diff --git a/internal/ui/ui.go b/internal/ui/ui.go index ed2e66ea4..d00e548a9 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -16,6 +16,7 @@ package ui import ( "errors" + "image" "github.com/hajimehoshi/ebiten/v2/internal/atlas" "github.com/hajimehoshi/ebiten/v2/internal/mipmap" @@ -72,8 +73,8 @@ func Get() *UserInterface { return theUI } -func (u *UserInterface) readPixels(mipmap *mipmap.Mipmap, pixels []byte, x, y, width, height int) error { - return mipmap.ReadPixels(u.graphicsDriver, pixels, x, y, width, height) +func (u *UserInterface) readPixels(mipmap *mipmap.Mipmap, pixels []byte, region image.Rectangle) error { + return mipmap.ReadPixels(u.graphicsDriver, pixels, region) } func (u *UserInterface) dumpScreenshot(mipmap *mipmap.Mipmap, name string, blackbg bool) (string, error) {