From a7d1a06c0e74ce19a350d240243f82a141d122fc Mon Sep 17 00:00:00 2001 From: shindonghwi Date: Sun, 21 Dec 2025 13:23:33 +0900 Subject: [PATCH 1/2] fix: correct coordinate calculation in _retainChildren recursion --- lib/src/layer/tile_layer/tile_image_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/layer/tile_layer/tile_image_view.dart b/lib/src/layer/tile_layer/tile_image_view.dart index 1537e6a29..5a67e07cd 100644 --- a/lib/src/layer/tile_layer/tile_image_view.dart +++ b/lib/src/layer/tile_layer/tile_image_view.dart @@ -183,7 +183,7 @@ final class TileImageView { } if (z + 1 < maxZoom) { - _retainChildren(retain, i, j, z + 1, maxZoom); + _retainChildren(retain, 2 * x + i, 2 * y + j, z + 1, maxZoom); } } } From 1deb02b455ec4c5ec2fee4b5b068bd86c81fb7e8 Mon Sep 17 00:00:00 2001 From: shindonghwi Date: Sun, 21 Dec 2025 13:26:59 +0900 Subject: [PATCH 2/2] test: add test for _retainChildren z+2 coordinate calculation --- .../tile_layer/tile_image_view_test.dart | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/layer/tile_layer/tile_image_view_test.dart b/test/layer/tile_layer/tile_image_view_test.dart index 99801dfd6..0261ccc38 100644 --- a/test/layer/tile_layer/tile_image_view_test.dart +++ b/test/layer/tile_layer/tile_image_view_test.dart @@ -138,6 +138,37 @@ void main() { } }); + group('renderTiles', () { + test('%.retainChildren uses correct coordinates for z+2 fallback', () { + // This test verifies that _retainChildren correctly calculates + // descendant coordinates when recursing to z+2 level. + // Using large coordinates (100, 200) to catch the bug where + // i,j (0-1) was passed instead of 2*x+i, 2*y+j. + const baseZoom = 10; + final tileImages = tileImagesMappingFrom([ + // z=10 tile not ready + MockTileImage(100, 200, baseZoom, + loadFinished: false, readyToDisplay: false), + // z=11 tiles don't exist + // z=12 tile exists and is ready (this is what we want to fall back to) + MockTileImage(400, 800, baseZoom + 2), + ]); + + final tileImageView = TileImageView( + tileImages: tileImages, + positionCoordinates: Set.from(tileImages.keys), + visibleRange: discreteTileRange(100, 200, 100, 200, zoom: baseZoom), + keepRange: discreteTileRange(100, 200, 100, 200, zoom: baseZoom), + ); + + final renderTiles = tileImageView.renderTiles.toList(); + expect( + renderTiles, + contains(const TileCoordinates(400, 800, baseZoom + 2)), + ); + }); + }); + test('errorTilesNotVisible', () { const zoom = 10; final tileImages = tileImagesMappingFrom([