Clamp SkPictureShader's tile size.

Blink used to clamp the max size for its pattern bitmaps (several SVG
pattern tests rely on/verify this behavior).

This CL clamps the maximum tile area to a reasonable value (16M pixels),
and scales beyond that.

R=bsalomon@google.com, reed@google.com, robertphillips@google.com

Author: fmalita@chromium.org

Review URL: https://codereview.chromium.org/446243002
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 2a6aae5..65a2cd3 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -76,12 +76,21 @@
     }
     SkSize scaledSize = SkSize::Make(scale.x() * fTile.width(), scale.y() * fTile.height());
 
+    // Clamp the tile size to about 16M pixels
+    static const SkScalar kMaxTileArea = 4096 * 4096;
+    SkScalar tileArea = SkScalarMul(scaledSize.width(), scaledSize.height());
+    if (tileArea > kMaxTileArea) {
+        SkScalar clampScale = SkScalarSqrt(SkScalarDiv(kMaxTileArea, tileArea));
+        scaledSize.set(SkScalarMul(scaledSize.width(), clampScale),
+                       SkScalarMul(scaledSize.height(), clampScale));
+    }
+
     SkISize tileSize = scaledSize.toRound();
     if (tileSize.isEmpty()) {
         return NULL;
     }
 
-    // The actual scale, compensating for rounding.
+    // The actual scale, compensating for rounding & clamping.
     SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fTile.width(),
                                     SkIntToScalar(tileSize.height()) / fTile.height());