diff options
author | junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-09 16:13:09 +0000 |
---|---|---|
committer | junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-09 16:13:09 +0000 |
commit | ef5b81142600510b89184fd6f69202ecb92be724 (patch) | |
tree | 4e5cc64b307581f317fda880e7d2ddbc301d532f | |
parent | 54c69147f96eedb10e430df72d71419795e81d3a (diff) |
Fixing SkTileGrid to clamp rather than clip content and querries that are outside the bounds of the grid
This fix prevents border padding and offsets on the tile grid structure from resulting in bad clipping. The job of clipping contents is left to the playback canvas.
BUG=https://code.google.com/p/skia/issues/detail?id=1209
TEST=TileGrid unit test,
Review URL: https://codereview.chromium.org/13493016
git-svn-id: http://skia.googlecode.com/svn/trunk@8576 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | src/core/SkTileGrid.cpp | 18 | ||||
-rw-r--r-- | tests/TileGridTest.cpp | 34 |
2 files changed, 43 insertions, 9 deletions
diff --git a/src/core/SkTileGrid.cpp b/src/core/SkTileGrid.cpp index 641a03179c..7a9c8eec6b 100644 --- a/src/core/SkTileGrid.cpp +++ b/src/core/SkTileGrid.cpp @@ -64,8 +64,12 @@ void SkTileGrid::insert(void* data, const SkIRect& bounds, bool) { void SkTileGrid::search(const SkIRect& query, SkTDArray<void*>* results) { SkIRect adjustedQuery = query; + // The inset is to counteract the outset that was applied in 'insert' + // The outset/inset is to optimize for lookups of size + // 'tileInterval + 2 * margin' that are aligned with the tile grid. adjustedQuery.inset(fInfo.fMargin.width(), fInfo.fMargin.height()); adjustedQuery.offset(fInfo.fOffset); + adjustedQuery.sort(); // in case the inset inverted the rectangle // Convert the query rectangle from device coordinates to tile coordinates // by rounding outwards to the nearest tile boundary so that the resulting tile // region includes the query rectangle. (using truncating division to "floor") @@ -75,16 +79,14 @@ void SkTileGrid::search(const SkIRect& query, SkTDArray<void*>* results) { int tileStartY = adjustedQuery.top() / fInfo.fTileInterval.height(); int tileEndY = (adjustedQuery.bottom() + fInfo.fTileInterval.height() - 1) / fInfo.fTileInterval.height(); - if (tileStartX >= fXTileCount || tileStartY >= fYTileCount || tileEndX <= 0 || tileEndY <= 0) { - return; // query does not intersect the grid - } - // clamp to grid - if (tileStartX < 0) tileStartX = 0; - if (tileStartY < 0) tileStartY = 0; - if (tileEndX > fXTileCount) tileEndX = fXTileCount; - if (tileEndY > fYTileCount) tileEndY = fYTileCount; + + tileStartX = SkPin32(tileStartX, 0, fXTileCount - 1); + tileEndX = SkPin32(tileEndX, 1, fXTileCount); + tileStartY = SkPin32(tileStartY, 0, fYTileCount - 1); + tileEndY = SkPin32(tileEndY, 1, fYTileCount); int queryTileCount = (tileEndX - tileStartX) * (tileEndY - tileStartY); + SkASSERT(queryTileCount); if (queryTileCount == 1) { *results = this->tile(tileStartX, tileStartY); } else { diff --git a/tests/TileGridTest.cpp b/tests/TileGridTest.cpp index 11407634c5..78620b48aa 100644 --- a/tests/TileGridTest.cpp +++ b/tests/TileGridTest.cpp @@ -113,6 +113,39 @@ public: REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]); } + // Out of bounds queries, snap to border tiles + { + SkDevice device(store); + MockCanvas mockCanvas(&device); + mockCanvas.translate(SkFloatToScalar(2.0f), SkFloatToScalar(0.0f)); + picture.draw(&mockCanvas); + REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); + REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]); + } + { + SkDevice device(store); + MockCanvas mockCanvas(&device); + mockCanvas.translate(SkFloatToScalar(0.0f), SkFloatToScalar(2.0f)); + picture.draw(&mockCanvas); + REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); + REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]); + } + { + SkDevice device(store); + MockCanvas mockCanvas(&device); + mockCanvas.translate(SkFloatToScalar(-22.0f), SkFloatToScalar(-16.0f)); + picture.draw(&mockCanvas); + REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); + REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]); + } + { + SkDevice device(store); + MockCanvas mockCanvas(&device); + mockCanvas.translate(SkFloatToScalar(-16.0f), SkFloatToScalar(-22.0f)); + picture.draw(&mockCanvas); + REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); + REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]); + } } static void TestOverlapOffsetQueryAlignment(skiatest::Reporter* reporter) { @@ -215,7 +248,6 @@ public: verifyTileHits(reporter, SkIRect::MakeXYWH(9, 9, 1, 1), kAll_Tile, 1); verifyTileHits(reporter, SkIRect::MakeXYWH(10, 10, 1, 1), kBottomRight_Tile, 1); verifyTileHits(reporter, SkIRect::MakeXYWH(17, 17, 1, 1), kBottomRight_Tile, 1); - verifyTileHits(reporter, SkIRect::MakeXYWH(18, 18, 1, 1), 0, 1); // BBoxes that overlap tiles verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 1), kTopLeft_Tile | kTopRight_Tile); |