diff --git a/devtools/internal/inspector/spr.go b/devtools/internal/inspector/spr.go index 7aa0bedd..46c299b1 100644 --- a/devtools/internal/inspector/spr.go +++ b/devtools/internal/inspector/spr.go @@ -65,7 +65,7 @@ func (m *sprSelectionMode) update(spr *Spr) { } func (m *sprSelectionMode) draw() { - pi.SprSheet().Copy(0, 0, pi.SprSheet().Width(), pi.SprSheet().Height(), pi.Scr(), m.camera.X, m.camera.Y) + pi.SprSheet().Copy(pi.Scr(), m.camera.X, m.camera.Y) mouseX, mouseY := pi.MousePos.X, pi.MousePos.Y diff --git a/examples/pixmap/main.go b/examples/pixmap/main.go index a964e426..f4aeba7a 100644 --- a/examples/pixmap/main.go +++ b/examples/pixmap/main.go @@ -16,20 +16,23 @@ func main() { pi.Load(resources) // copy from sprite-sheet to sprite-sheet: - pi.SprSheet().Copy(10, 0, 100, 100, pi.SprSheet(), 0, 0) + src := pi.SprSheet().WithClip(10, 0, 100, 100) + src.Copy(pi.SprSheet(), 0, 0) // draw a filled rectangle directly to sprite-sheet: pi.SprSheet().RectFill(60, 30, 70, 40, 7) // merge from sprite-sheet to screen using custom merge function, which merges two lines - pi.SprSheet().Merge(-1, -1, 103, 70, pi.Scr(), -1, -1, func(dst, src []byte) { + src = pi.SprSheet().WithClip(-1, -1, 103, 70) + src.Merge(pi.Scr(), -1, -1, func(dst, src []byte) { for x := 0; x < len(dst); x++ { dst[x] += pi.Pal[src[x]] + 1 } }) // update each line in a loop: - pi.Scr().Foreach(10, 10, 16, 16, func(x, y int, line []byte) { + src = pi.Scr().WithClip(10, 10, 16, 16) + src.Foreach(func(x, y int, line []byte) { for i := 0; i < len(line); i++ { line[i] = byte(i) } diff --git a/pixmap.go b/pixmap.go index 50aa122a..44ed8fa4 100644 --- a/pixmap.go +++ b/pixmap.go @@ -226,9 +226,9 @@ type Pointer struct { RemainingLines int } -// Copy copies the region specified by x, y, w, h into dst PixMap at dstX,dstY position. -func (p PixMap) Copy(x, y, w, h int, dst PixMap, dstX, dstY int) { - dstPtr, srcPtr := p.pointersForCopy(x, y, w, h, dst, dstX, dstY) +// Copy copies the clipped pixmap into dst PixMap at dstX,dstY position. +func (p PixMap) Copy(dst PixMap, dstX, dstY int) { + dstPtr, srcPtr := p.pointersForCopy(dst, dstX, dstY) remainingLines := MinInt(dstPtr.RemainingLines, srcPtr.RemainingLines) @@ -247,8 +247,8 @@ func (p PixMap) Copy(x, y, w, h int, dst PixMap, dstX, dstY int) { } // Merge merges destination with source by running merge operation for each destination line. -func (p PixMap) Merge(x, y, w, h int, dst PixMap, dstX, dstY int, merge func(dst, src []byte)) { - dstPtr, srcPtr := p.pointersForCopy(x, y, w, h, dst, dstX, dstY) +func (p PixMap) Merge(dst PixMap, dstX, dstY int, merge func(dst, src []byte)) { + dstPtr, srcPtr := p.pointersForCopy(dst, dstX, dstY) remainingLines := MinInt(dstPtr.RemainingLines, srcPtr.RemainingLines) @@ -266,14 +266,19 @@ func (p PixMap) Merge(x, y, w, h int, dst PixMap, dstX, dstY int, merge func(dst } } -// Foreach runs the update function on PixMap fragment specified by x, y, w and h. +// Foreach runs the update function on clipped PixMap. // // The update function accepts entire line to increase the performance. -func (p PixMap) Foreach(x, y, w, h int, update func(x, y int, dst []byte)) { +func (p PixMap) Foreach(update func(x, y int, dst []byte)) { if update == nil { return } + x := p.clip.X + y := p.clip.Y + w := p.clip.W + h := p.clip.H + ptr, ok := p.Pointer(x, y, w, h) if !ok { return @@ -334,9 +339,9 @@ func (p PixMap) lineOfColor(col byte, length int) []byte { return line } -func (p PixMap) pointersForCopy(srcX int, srcY int, w int, h int, dst PixMap, dstX int, dstY int) (Pointer, Pointer) { - dstPtr, _ := dst.Pointer(dstX, dstY, w, h) - srcPtr, _ := p.Pointer(srcX, srcY, w, h) +func (p PixMap) pointersForCopy(dst PixMap, dstX int, dstY int) (Pointer, Pointer) { + dstPtr, _ := dst.Pointer(dstX, dstY, p.clip.W, p.clip.H) + srcPtr, _ := p.Pointer(p.clip.X, p.clip.Y, p.clip.W, p.clip.H) // both maps must be moved by the same DeltaX and DeltaY if srcPtr.DeltaX > dstPtr.DeltaX { diff --git a/pixmap_test.go b/pixmap_test.go index cf5cb389..a1cfe385 100644 --- a/pixmap_test.go +++ b/pixmap_test.go @@ -351,14 +351,15 @@ func TestPixMap_Pointer(t *testing.T) { func TestPixMap_Foreach(t *testing.T) { t.Run("should not do anything when update function is nil", func(t *testing.T) { pixMap := pi.NewPixMap(2, 2) - pixMap.Foreach(0, 0, 2, 2, nil) + pixMap.Foreach(nil) }) t.Run("should run update line number of times", func(t *testing.T) { t.Run("inside clipping range", func(t *testing.T) { pixMap := pi.NewPixMap(1, 3) timesRun := 0 - pixMap.Foreach(0, 0, 1, 2, func(x, y int, dst []byte) { + src := pixMap.WithClip(0, 0, 1, 2) + src.Foreach(func(x, y int, dst []byte) { timesRun++ }) assert.Equal(t, 2, timesRun) @@ -367,7 +368,8 @@ func TestPixMap_Foreach(t *testing.T) { t.Run("outside clipping range", func(t *testing.T) { pixMap := pi.NewPixMap(1, 3) timesRun := 0 - pixMap.Foreach(0, 0, 1, 4, func(x, y int, dst []byte) { + src := pixMap.WithClip(0, 0, 1, 4) + src.Foreach(func(x, y int, dst []byte) { timesRun++ }) assert.Equal(t, 3, timesRun) @@ -380,7 +382,8 @@ func TestPixMap_Foreach(t *testing.T) { t.Run("x=0", func(t *testing.T) { var lines [][]byte - pixMap.Foreach(0, 0, 2, 3, func(x, y int, dst []byte) { + src := pixMap.WithClip(0, 0, 2, 3) + src.Foreach(func(x, y int, dst []byte) { lines = append(lines, dst) }) assert.Equal(t, [][]byte{{0, 1}, {3, 4}, {6, 7}}, lines) @@ -388,7 +391,8 @@ func TestPixMap_Foreach(t *testing.T) { t.Run("x=1", func(t *testing.T) { var lines [][]byte - pixMap.Foreach(1, 0, 2, 3, func(x, y int, dst []byte) { + src := pixMap.WithClip(1, 0, 2, 3) + src.Foreach(func(x, y int, dst []byte) { lines = append(lines, dst) }) assert.Equal(t, [][]byte{{1, 2}, {4, 5}, {7, 8}}, lines) @@ -401,7 +405,8 @@ func TestPixMap_Foreach(t *testing.T) { t.Run("inside clipping range", func(t *testing.T) { var coords []pi.Position - pixMap.Foreach(1, 1, 2, 2, func(x, y int, dst []byte) { + src := pixMap.WithClip(1, 1, 2, 2) + src.Foreach(func(x, y int, dst []byte) { coords = append(coords, pi.Position{X: x, Y: y}) }) assert.Equal(t, []pi.Position{{X: 1, Y: 1}, {X: 1, Y: 2}}, coords) @@ -409,7 +414,8 @@ func TestPixMap_Foreach(t *testing.T) { t.Run("outside clipping range", func(t *testing.T) { var coords []pi.Position - pixMap.Foreach(-1, -1, 3, 3, func(x, y int, dst []byte) { + src := pixMap.WithClip(-1, -1, 3, 3) + src.Foreach(func(x, y int, dst []byte) { coords = append(coords, pi.Position{X: x, Y: y}) }) assert.Equal(t, []pi.Position{{X: 0, Y: 0}, {X: 0, Y: 1}}, coords) @@ -422,14 +428,16 @@ func TestPixMap_Foreach(t *testing.T) { update := func(x, y int, dst []byte) { executed = true } - pixMap.Foreach(0, 0, 0, 1, update) // width = 0 + src := pixMap.WithClip(0, 0, 0, 1) // width = 0 + src.Foreach(update) assert.False(t, executed) }) t.Run("should update pixels", func(t *testing.T) { pixMap := pi.NewPixMap(2, 3) i := byte(1) - pixMap.Foreach(0, 0, 2, 3, func(x, y int, dst []byte) { + src := pixMap.WithClip(0, 0, 2, 3) + src.Foreach(func(x, y int, dst []byte) { dst[0] = i dst[1] = i + 1 i += 2 @@ -442,7 +450,7 @@ func TestPixMap_Copy(t *testing.T) { testPixMapCopy(t, pi.PixMap.Copy) } -func testPixMapCopy(t *testing.T, merge func(pi.PixMap, int, int, int, int, pi.PixMap, int, int)) { +func testPixMapCopy(t *testing.T, merge func(pi.PixMap, pi.PixMap, int, int)) { t.Run("src bigger than dst", func(t *testing.T) { src := pi.NewPixMapWithPix([]byte{ 1, 2, 3, @@ -488,7 +496,8 @@ func testPixMapCopy(t *testing.T, merge func(pi.PixMap, int, int, int, int, pi.P for name, test := range tests { t.Run(name, func(t *testing.T) { dst := pi.NewPixMap(dstWidth, dstHeight) - merge(src, test.x, test.y, test.w, test.h, dst, test.dstX, test.dstY) + source := src.WithClip(test.x, test.y, test.w, test.h) + merge(source, dst, test.dstX, test.dstY) assert.Equal(t, test.expected, dst.Pix()) }) } @@ -517,7 +526,8 @@ func testPixMapCopy(t *testing.T, merge func(pi.PixMap, int, int, int, int, pi.P for name, test := range tests { t.Run(name, func(t *testing.T) { dst := pi.NewPixMap(dstWidth, dstHeight) - merge(src, test.x, test.y, test.w, test.h, dst, test.dstX, test.dstY) + source := src.WithClip(test.x, test.y, test.w, test.h) + merge(source, dst, test.dstX, test.dstY) assert.Equal(t, test.expected, dst.Pix()) }) } @@ -525,8 +535,8 @@ func testPixMapCopy(t *testing.T, merge func(pi.PixMap, int, int, int, int, pi.P } func TestPixMap_Merge(t *testing.T) { - testPixMapCopy(t, func(src pi.PixMap, x int, y int, w int, h int, dst pi.PixMap, dstX int, dstY int) { - src.Merge(x, y, w, h, dst, dstX, dstY, func(dst, src []byte) { + testPixMapCopy(t, func(src pi.PixMap, dst pi.PixMap, dstX int, dstY int) { + src.Merge(dst, dstX, dstY, func(dst, src []byte) { copy(dst, src) }) })