Make drawImage a virtual on SkDevice

This reverts commit 06dad4b92f1fcb593bc686f9537d3e0d866b2241.

BUG=485243

Review URL: https://codereview.chromium.org/1129843003
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 3e3f714..34d6aaa 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1734,12 +1734,15 @@
     this->onDrawPath(path, paint);
 }
 
-void SkCanvas::drawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
-    this->onDrawImage(image, dx, dy, paint);
+void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
+    this->onDrawImage(image, x, y, paint);
 }
 
 void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
                              const SkPaint* paint) {
+    if (dst.isEmpty()) {
+        return;
+    }
     this->onDrawImageRect(image, src, dst, paint);
 }
 
@@ -1959,15 +1962,58 @@
     LOOPER_END
 }
 
-void SkCanvas::onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
+void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
-    image->draw(this, dx, dy, paint);
+    SkRect bounds = SkRect::MakeXYWH(x, y,
+                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
+    if (NULL == paint || paint->canComputeFastBounds()) {
+        if (paint) {
+            paint->computeFastBounds(bounds, &bounds);
+        }
+        if (this->quickReject(bounds)) {
+            return;
+        }
+    }
+    
+    SkLazyPaint lazy;
+    if (NULL == paint) {
+        paint = lazy.init();
+    }
+    
+    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
+    
+    while (iter.next()) {
+        iter.fDevice->drawImage(iter, image, x, y, looper.paint());
+    }
+    
+    LOOPER_END
 }
 
 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
                                const SkPaint* paint) {
     TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
-    image->drawRect(this, src, dst, paint);
+    SkRect storage;
+    const SkRect* bounds = &dst;
+    if (NULL == paint || paint->canComputeFastBounds()) {
+        if (paint) {
+            bounds = &paint->computeFastBounds(dst, &storage);
+        }
+        if (this->quickReject(*bounds)) {
+            return;
+        }
+    }
+    SkLazyPaint lazy;
+    if (NULL == paint) {
+        paint = lazy.init();
+    }
+    
+    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
+    
+    while (iter.next()) {
+        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint());
+    }
+    
+    LOOPER_END
 }
 
 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 6be9178..37fafd8 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -9,6 +9,7 @@
 #include "SkDeviceProperties.h"
 #include "SkDraw.h"
 #include "SkDrawFilter.h"
+#include "SkImage_Base.h"
 #include "SkMetaData.h"
 #include "SkPatchUtils.h"
 #include "SkPathMeasure.h"
@@ -165,6 +166,24 @@
     }
 }
 
+void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
+                             const SkPaint& paint) {
+    // Default impl : turns everything into raster bitmap
+    SkBitmap bm;
+    if (as_IB(image)->getROPixels(&bm)) {
+        this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
+    }
+}
+
+void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
+                                 const SkRect& dst, const SkPaint& paint) {
+    // Default impl : turns everything into raster bitmap
+    SkBitmap bm;
+    if (as_IB(image)->getROPixels(&bm)) {
+        this->drawBitmapRect(draw, bm, src, dst, paint, SkCanvas::kNone_DrawBitmapRectFlag);
+    }
+}
+
 bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
 #ifdef SK_DEBUG
     SkASSERT(info.width() > 0 && info.height() > 0);
diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp
index c6957cd..3ced573 100644
--- a/src/core/SkPaintPriv.cpp
+++ b/src/core/SkPaintPriv.cpp
@@ -9,6 +9,7 @@
 
 #include "SkBitmap.h"
 #include "SkColorFilter.h"
+#include "SkImage.h"
 #include "SkPaint.h"
 #include "SkShader.h"
 
@@ -49,3 +50,8 @@
 
     return isPaintOpaque(paint, contentType);
 }
+
+bool isPaintOpaque(const SkPaint* paint, const SkImage* image) {
+    return isPaintOpaque(paint, image->isOpaque() ?
+                         kOpaque_SkPaintBitmapOpacity : kUnknown_SkPaintBitmapOpacity);
+}
diff --git a/src/core/SkPaintPriv.h b/src/core/SkPaintPriv.h
index 88fc4fc..be441b8 100644
--- a/src/core/SkPaintPriv.h
+++ b/src/core/SkPaintPriv.h
@@ -8,11 +8,12 @@
 #ifndef SkPaintPriv_DEFINED
 #define SkPaintPriv_DEFINED
 
-class SkBitmap;
-class SkPaint;
-
 #include "SkTypes.h"
 
+class SkBitmap;
+class SkImage;
+class SkPaint;
+
 enum SkPaintBitmapOpacity {
     // No content replaces the paint's color
     kNoBitmap_SkPaintBitmapOpacity = 0,
@@ -40,6 +41,7 @@
         shader.
     @return true if paint is opaque
 */
-bool isPaintOpaque(const SkPaint* paint,
-                   const SkBitmap* bmpReplacesShader = NULL);
+bool isPaintOpaque(const SkPaint* paint, const SkBitmap* bmpReplacesShader = NULL);
+bool isPaintOpaque(const SkPaint* paint, const SkImage* image);
+
 #endif
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 53ecdd0..07811fb 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -7,6 +7,7 @@
 
 #include "SkPictureRecord.h"
 #include "SkDevice.h"
+#include "SkImage_Base.h"
 #include "SkPatchUtils.h"
 #include "SkPixelRef.h"
 #include "SkRRect.h"
@@ -563,6 +564,22 @@
     this->validate(initialOffset, size);
 }
 
+void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
+                                  const SkPaint* paint) {
+    SkBitmap bm;
+    if (as_IB(image)->getROPixels(&bm)) {
+        this->SkPictureRecord::onDrawBitmap(bm, x, y, paint);
+    }
+}
+
+void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+                                      const SkPaint* paint) {
+    SkBitmap bm;
+    if (as_IB(image)->getROPixels(&bm)) {
+        this->SkPictureRecord::onDrawBitmapRect(bm, src, dst, paint, kNone_DrawBitmapRectFlag);
+    }
+}
+
 void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                        const SkRect& dst, const SkPaint* paint) {
     // op + paint index + bitmap id + center + dst rect
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 5e2d5a1..7a6fc81 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -184,12 +184,9 @@
     void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
     void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
                           DrawBitmapRectFlags flags) override;
-#if 0
-    // rely on conversion to bitmap (for now)
     void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
     void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
                          const SkPaint*) override;
-#endif
     void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
                           const SkPaint*) override;
     void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;