use SkTreatAsSprite in SkDraw (with guard for chrome if needed)



git-svn-id: http://skia.googlecode.com/svn/trunk@6994 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 281c69c..0700353 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -28,6 +28,7 @@
 #include "SkAutoKern.h"
 #include "SkBitmapProcShader.h"
 #include "SkDrawProcs.h"
+#include "SkMatrixUtils.h"
 
 //#define TRACE_BITMAP_DRAWS
 
@@ -1113,6 +1114,7 @@
     go ahead and treat it as if it were, so that subsequent code can go fast.
  */
 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
+#ifdef SK_IGNORE_TREAT_AS_SPRITE
     SkMatrix::TypeMask mask = matrix.getType();
 
     if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
@@ -1129,6 +1131,9 @@
     }
     // if we got here, we're either kTranslate_Mask or identity
     return true;
+#else
+    return SkTreatAsSpriteFilter(matrix, bitmap.width(), bitmap.height());
+#endif
 }
 
 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 15d295c..1eabc78 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1807,8 +1807,9 @@
 
 #include "SkMatrixUtils.h"
 
-bool SkTreatAsSprite(const SkMatrix& mat, const SkRect& src,
+bool SkTreatAsSprite(const SkMatrix& mat, int width, int height,
                      unsigned subpixelBits) {
+    // quick reject on affine or perspective
     if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
         return false;
     }
@@ -1824,16 +1825,18 @@
     }
 
     SkRect dst;
-    SkIRect isrc, idst;
-
-    mat.mapRect(&dst, src);
-
+    SkIRect isrc = { 0, 0, width, height };
+    
     {
-        SkRect tmp = src;
-        tmp.offset(mat.getTranslateX(), mat.getTranslateY());
-        tmp.round(&isrc);
+        SkRect src;
+        src.set(isrc);
+        mat.mapRect(&dst, src);
     }
 
+    // just apply the translate to isrc
+    isrc.offset(SkScalarRoundToInt(mat.getTranslateX()),
+                SkScalarRoundToInt(mat.getTranslateY()));
+
     if (subpixelBits) {
         isrc.fLeft <<= subpixelBits;
         isrc.fTop <<= subpixelBits;
@@ -1847,6 +1850,7 @@
         dst.fBottom *= scale;
     }
 
+    SkIRect idst;
     dst.round(&idst);
     return isrc == idst;
 }
diff --git a/src/core/SkMatrixUtils.h b/src/core/SkMatrixUtils.h
index 04c0892..2074267 100644
--- a/src/core/SkMatrixUtils.h
+++ b/src/core/SkMatrixUtils.h
@@ -17,16 +17,27 @@
 #define kSkSubPixelBitsForBilerp   4
 
 /**
- *  Given a matrix and a src-rect, return true if the computed dst-rect would
+ *  Given a matrix and width/height, return true if the computed dst-rect would
  *  align such that there is a 1-to-1 coorspondence between src and dst pixels.
  *  This can be called by drawing code to see if drawBitmap can be turned into
  *  drawSprite (which is faster).
  *
+ *  The src-rect is defined to be { 0, 0, width, height }
+ *
  *  The "closeness" test is based on the subpixelBits parameter. Pass 0 for
  *  round-to-nearest behavior (e.g. nearest neighbor sampling). Pass the number
  *  of subpixel-bits to simulate filtering.
  */
-bool SkTreatAsSprite(const SkMatrix&, const SkRect& src, unsigned subpixelBits);
+bool SkTreatAsSprite(const SkMatrix&, int width, int height,
+                     unsigned subpixelBits);
 
+/**
+ *  Calls SkTreatAsSprite() with default subpixelBits value to match Skia's
+ *  filter-bitmap implementation (i.e. kSkSubPixelBitsForBilerp).
+ */
+static inline bool SkTreatAsSpriteFilter(const SkMatrix& matrix,
+                                         int width, int height) {
+    return SkTreatAsSprite(matrix, width, height, kSkSubPixelBitsForBilerp);
+}
 
 #endif
diff --git a/tests/DrawBitmapRectTest.cpp b/tests/DrawBitmapRectTest.cpp
index df5f2f5..a56396c 100644
--- a/tests/DrawBitmapRectTest.cpp
+++ b/tests/DrawBitmapRectTest.cpp
@@ -29,25 +29,28 @@
     }
 }
 
-static void rand_rect(SkRect* r, SkRandom& rand) {
-    r->set(rand.nextSScalar1() * 1000, rand.nextSScalar1() * 1000,
-           rand.nextSScalar1() * 1000, rand.nextSScalar1() * 1000);
-    r->sort();
+static void rand_size(SkISize* size, SkRandom& rand) {
+    size->set(rand.nextU() & 0xFFFF, rand.nextU() & 0xFFFF);
+}
+
+static bool treat_as_sprite(const SkMatrix& mat, const SkISize& size,
+                            unsigned bits) {
+    return SkTreatAsSprite(mat, size.width(), size.height(), bits);
 }
 
 static void test_treatAsSprite(skiatest::Reporter* reporter) {
     const unsigned bilerBits = kSkSubPixelBitsForBilerp;
 
     SkMatrix mat;
-    SkRect r;
+    SkISize  size;
     SkRandom rand;
 
     // assert: translate-only no-filter can always be treated as sprite
     for (int i = 0; i < 1000; ++i) {
         rand_matrix(&mat, rand, SkMatrix::kTranslate_Mask);
         for (int j = 0; j < 1000; ++j) {
-            rand_rect(&r, rand);
-            REPORTER_ASSERT(reporter, SkTreatAsSprite(mat, r, 0));
+            rand_size(&size, rand);
+            REPORTER_ASSERT(reporter, treat_as_sprite(mat, size, 0));
         }
     }
 
@@ -55,43 +58,43 @@
     for (int i = 0; i < 1000; ++i) {
         rand_matrix(&mat, rand, SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask);
         for (int j = 0; j < 1000; ++j) {
-            rand_rect(&r, rand);
-            REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, 0));
-            REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, bilerBits));
+            rand_size(&size, rand);
+            REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, 0));
+            REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, bilerBits));
         }
     }
 
-    r.set(10, 10, 500, 600);
+    size.set(500, 600);
 
     const SkScalar tooMuchSubpixel = SkFloatToScalar(100.1f);
     mat.setTranslate(tooMuchSubpixel, 0);
-    REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, bilerBits));
     mat.setTranslate(0, tooMuchSubpixel);
-    REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, bilerBits));
 
     const SkScalar tinySubPixel = SkFloatToScalar(100.02f);
     mat.setTranslate(tinySubPixel, 0);
-    REPORTER_ASSERT(reporter, SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, treat_as_sprite(mat, size, bilerBits));
     mat.setTranslate(0, tinySubPixel);
-    REPORTER_ASSERT(reporter, SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, treat_as_sprite(mat, size, bilerBits));
 
     const SkScalar twoThirds = SK_Scalar1 * 2 / 3;
-    const SkScalar bigScale = SkScalarDiv(r.width() + twoThirds, r.width());
+    const SkScalar bigScale = SkScalarDiv(size.width() + twoThirds, size.width());
     mat.setScale(bigScale, bigScale);
-    REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, false));
-    REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, false));
+    REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, bilerBits));
 
     const SkScalar oneThird = SK_Scalar1 / 3;
-    const SkScalar smallScale = SkScalarDiv(r.width() + oneThird, r.width());
+    const SkScalar smallScale = SkScalarDiv(size.width() + oneThird, size.width());
     mat.setScale(smallScale, smallScale);
-    REPORTER_ASSERT(reporter, SkTreatAsSprite(mat, r, false));
-    REPORTER_ASSERT(reporter, !SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, treat_as_sprite(mat, size, false));
+    REPORTER_ASSERT(reporter, !treat_as_sprite(mat, size, bilerBits));
 
     const SkScalar oneFortyth = SK_Scalar1 / 40;
-    const SkScalar tinyScale = SkScalarDiv(r.width() + oneFortyth, r.width());
+    const SkScalar tinyScale = SkScalarDiv(size.width() + oneFortyth, size.width());
     mat.setScale(tinyScale, tinyScale);
-    REPORTER_ASSERT(reporter, SkTreatAsSprite(mat, r, false));
-    REPORTER_ASSERT(reporter, SkTreatAsSprite(mat, r, bilerBits));
+    REPORTER_ASSERT(reporter, treat_as_sprite(mat, size, false));
+    REPORTER_ASSERT(reporter, treat_as_sprite(mat, size, bilerBits));
 }
 
 static void assert_ifDrawnTo(skiatest::Reporter* reporter,