Modifying SkTileGrid to support arbitrary query rectangles.
Exposing SkTileGrid functionality in the public API through SkTileGridPicture.
This patch also makes TileGrid and Rtree testable in gm, which revealed errors.

TEST=gm with '--tileGrid'
BUG=http://code.google.com/p/chromium/issues/detail?id=164636
Review URL: https://codereview.appspot.com/6933044

git-svn-id: http://skia.googlecode.com/svn/trunk@6783 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/TileGridTest.cpp b/tests/TileGridTest.cpp
index e0c855c..d5ca52b4 100644
--- a/tests/TileGridTest.cpp
+++ b/tests/TileGridTest.cpp
@@ -8,6 +8,9 @@
 
 #include "Test.h"
 #include "SkTileGrid.h"
+#include "SkTileGridPicture.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
 
 enum Tile {
     kTopLeft_Tile = 0x1,
@@ -18,10 +21,26 @@
     kAll_Tile = kTopLeft_Tile | kTopRight_Tile | kBottomLeft_Tile | kBottomRight_Tile,
 };
 
+namespace {
+class MockCanvas : public SkCanvas {
+public:
+    MockCanvas(SkDevice* device) : SkCanvas(device)
+    {}
+
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint)
+    {
+        // This capture occurs before quick reject.
+        fRects.push(rect);
+    }
+
+    SkTDArray<SkRect> fRects;
+};
+}
+
 class TileGridTest {
 public:
     static void verifyTileHits(skiatest::Reporter* reporter, SkIRect rect, uint32_t tileMask) {
-        SkTileGrid grid(10, 10, 2, 2);
+        SkTileGrid grid(10, 10, 2, 2, NULL);
         grid.insert(NULL, rect, false);
         REPORTER_ASSERT(reporter, grid.tile(0,0).count() ==
             ((tileMask & kTopLeft_Tile)? 1 : 0));
@@ -33,6 +52,60 @@
             ((tileMask & kBottomRight_Tile)? 1 : 0));
     }
 
+    static void TestUnalignedQuery(skiatest::Reporter* reporter) {
+        // Use SkTileGridPicture to generate a SkTileGrid with a helper
+        SkTileGridPicture picture(10, 10, 20, 20);
+        SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 
+            SkIntToScalar(8), SkIntToScalar(8));
+        SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(11), SkIntToScalar(11),
+            SkIntToScalar(1), SkIntToScalar(1));
+        SkCanvas* canvas = picture.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
+        SkPaint paint;
+        canvas->drawRect(rect1, paint);
+        canvas->drawRect(rect2, paint);
+        picture.endRecording();
+
+        SkBitmap store;
+        store.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+        store.allocPixels();
+
+        // Test parts of top-left tile
+        {
+            SkDevice device(store);
+            MockCanvas mockCanvas(&device);
+            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(-7.99f), SkFloatToScalar(-7.99f));
+            picture.draw(&mockCanvas);
+            REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
+            REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
+        }
+        // Corner overlap
+        {
+            SkDevice device(store);
+            MockCanvas mockCanvas(&device);
+            mockCanvas.translate(SkFloatToScalar(-9.5f), SkFloatToScalar(-9.5f));
+            picture.draw(&mockCanvas);
+            REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
+            REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
+            REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
+        }
+        // Intersect bottom right tile, but does not overlap rect 2
+        {
+            SkDevice device(store);
+            MockCanvas mockCanvas(&device);
+            mockCanvas.translate(SkFloatToScalar(-16.0f), SkFloatToScalar(-16.0f));
+            picture.draw(&mockCanvas);
+            REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
+            REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
+        }
+    }
+
     static void Test(skiatest::Reporter* reporter) {
         // Out of bounds
         verifyTileHits(reporter, SkIRect::MakeXYWH(30, 0, 1, 1),  0);
@@ -52,6 +125,8 @@
                        kBottomLeft_Tile);
         verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 10),  kAll_Tile);
         verifyTileHits(reporter, SkIRect::MakeXYWH(-10, -10, 40, 40),  kAll_Tile);
+
+        TestUnalignedQuery(reporter);
     }
 };