aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-09 16:13:09 +0000
committerGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-09 16:13:09 +0000
commitef5b81142600510b89184fd6f69202ecb92be724 (patch)
tree4e5cc64b307581f317fda880e7d2ddbc301d532f
parent54c69147f96eedb10e430df72d71419795e81d3a (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.cpp18
-rw-r--r--tests/TileGridTest.cpp34
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);