Tweak SkPictureShader's tile semantics.
authorfmalita <fmalita@chromium.org>
Mon, 8 Dec 2014 19:13:27 +0000 (11:13 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 8 Dec 2014 19:13:27 +0000 (11:13 -0800)
Currently, the tile offset is added when drawing the picture. This might
have made a tiny bit of sense when the picture was always positioned at
origin, but with a picture cull rect offset things looks really strange.

For example, to specify a tile == the picture cull rect we have to pass
in [-cullrect.x, -cullrect.y, cullrect.width, cullrect.height]. Yikes.

(there's also a bug when not passing a tile, as we use a default tile
== cullrect but don't compensate for the above oddity)

This changes the semantics of the tile offset: it is now subtracted when
drawing the picture tile. As a consequence, one can pass in a tile equal
to the cull rect and get the expected behavior (same when not passing
a tile).

This will require a minor Blink change with the roll, as one client
works around the current behavior:
https://codereview.chromium.org/789503003

R=reed@google.com,robertphillips@google.com
BUG=440046

Review URL: https://codereview.chromium.org/733203005

gm/pictureshadertile.cpp
src/core/SkPictureShader.cpp

index ecea553..ae87a55 100644 (file)
@@ -21,50 +21,69 @@ static const struct {
     SkScalar offsetX, offsetY;
 } tiles[] = {
     {      0,      0,    1,    1,      0,    0 },
-    {   0.5f,   0.5f,    1,    1,      0,    0 },
     {  -0.5f,  -0.5f,    1,    1,      0,    0 },
+    {   0.5f,   0.5f,    1,    1,      0,    0 },
 
     {      0,      0, 1.5f, 1.5f,      0,    0 },
-    {   0.5f,   0.5f, 1.5f, 1.5f,      0,    0 },
     {  -0.5f,  -0.5f, 1.5f, 1.5f,      0,    0 },
+    {   0.5f,   0.5f, 1.5f, 1.5f,      0,    0 },
 
     {      0,      0, 0.5f, 0.5f,      0,    0 },
-    { -0.25f, -0.25f, 0.5f, 0.5f,      0,    0 },
     {  0.25f,  0.25f, 0.5f, 0.5f,      0,    0 },
+    { -0.25f, -0.25f, 0.5f, 0.5f,      0,    0 },
 
     {      0,      0,    1,    1,   0.5f, 0.5f },
-    {   0.5f,   0.5f,    1,    1,   0.5f, 0.5f },
     {  -0.5f,  -0.5f,    1,    1,   0.5f, 0.5f },
+    {   0.5f,   0.5f,    1,    1,   0.5f, 0.5f },
 
     {      0,      0, 1.5f, 1.5f,   0.5f, 0.5f },
-    {   0.5f,   0.5f, 1.5f, 1.5f,   0.5f, 0.5f },
     {  -0.5f,  -0.5f, 1.5f, 1.5f,   0.5f, 0.5f },
+    {   0.5f,   0.5f, 1.5f, 1.5f,   0.5f, 0.5f },
 
     {      0,      0, 1.5f,    1,      0,    0 },
-    {   0.5f,   0.5f, 1.5f,    1,      0,    0 },
     {  -0.5f,  -0.5f, 1.5f,    1,      0,    0 },
+    {   0.5f,   0.5f, 1.5f,    1,      0,    0 },
 
     {      0,      0, 0.5f,    1,      0,    0 },
-    { -0.25f, -0.25f, 0.5f,    1,      0,    0 },
     {  0.25f,  0.25f, 0.5f,    1,      0,    0 },
+    { -0.25f, -0.25f, 0.5f,    1,      0,    0 },
 
     {      0,      0,    1, 1.5f,      0,    0 },
-    {   0.5f,   0.5f,    1, 1.5f,      0,    0 },
     {  -0.5f,  -0.5f,    1, 1.5f,      0,    0 },
+    {   0.5f,   0.5f,    1, 1.5f,      0,    0 },
 
     {      0,      0,    1, 0.5f,      0,    0 },
-    { -0.25f, -0.25f,    1, 0.5f,      0,    0 },
     {  0.25f,  0.25f,    1, 0.5f,      0,    0 },
+    { -0.25f, -0.25f,    1, 0.5f,      0,    0 },
 };
 
 class PictureShaderTileGM : public skiagm::GM {
-public:
-    PictureShaderTileGM() {
+protected:
+    virtual uint32_t onGetFlags() const SK_OVERRIDE {
+        return kSkipTiled_Flag;
+    }
+
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("pictureshadertile");
+    }
+
+    virtual SkISize onISize() SK_OVERRIDE {
+        return SkISize::Make(800, 600);
+    }
+
+    virtual void onOnceBeforeDraw() SK_OVERRIDE {
         SkPictureRecorder recorder;
-        SkCanvas* pictureCanvas = recorder.beginRecording(kPictureSize, kPictureSize, NULL, 0);
+        SkCanvas* pictureCanvas = recorder.beginRecording(kPictureSize, kPictureSize);
         drawScene(pictureCanvas, kPictureSize);
         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
+        SkPoint offset = SkPoint::Make(100, 100);
+        pictureCanvas = recorder.beginRecording(SkRect::MakeXYWH(offset.x(), offset.y(),
+                                                                 kPictureSize, kPictureSize));
+        pictureCanvas->translate(offset.x(), offset.y());
+        drawScene(pictureCanvas, kPictureSize);
+        SkAutoTUnref<SkPicture> offsetPicture(recorder.endRecording());
+
         for (unsigned i = 0; i < SK_ARRAY_COUNT(tiles); ++i) {
             SkRect tile = SkRect::MakeXYWH(tiles[i].x * kPictureSize,
                                            tiles[i].y * kPictureSize,
@@ -75,27 +94,24 @@ public:
                                      tiles[i].offsetY * kPictureSize);
             localMatrix.postScale(kFillSize / (2 * kPictureSize),
                                   kFillSize / (2 * kPictureSize));
-            fShaders[i].reset(SkShader::CreatePictureShader(picture,
+
+            SkPicture* picturePtr = picture.get();
+            SkRect* tilePtr = &tile;
+
+            if (tile == SkRect::MakeWH(kPictureSize, kPictureSize)) {
+                // When the tile == picture bounds, exercise the picture + offset path.
+                picturePtr = offsetPicture.get();
+                tilePtr = NULL;
+            }
+
+            fShaders[i].reset(SkShader::CreatePictureShader(picturePtr,
                               SkShader::kRepeat_TileMode,
                               SkShader::kRepeat_TileMode,
                               &localMatrix,
-                              &tile));
+                              tilePtr));
         }
     }
 
-protected:
-    virtual uint32_t onGetFlags() const SK_OVERRIDE {
-        return kSkipTiled_Flag;
-    }
-
-    virtual SkString onShortName() SK_OVERRIDE {
-        return SkString("pictureshadertile");
-    }
-
-    virtual SkISize onISize() SK_OVERRIDE {
-        return SkISize::Make(800, 600);
-    }
-
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         canvas->clear(SK_ColorBLACK);
 
index 5fded93..198a2a9 100644 (file)
@@ -185,7 +185,7 @@ SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatri
 
         SkCanvas canvas(bm);
         canvas.scale(tileScale.width(), tileScale.height());
-        canvas.translate(fTile.x(), fTile.y());
+        canvas.translate(-fTile.x(), -fTile.y());
         canvas.drawPicture(fPicture);
 
         SkMatrix shaderMatrix = this->getLocalMatrix();