Move drawRegion from DisplayList to Canvas

Change-Id: I9f401dc5b24732938ac2ca7ed829796e2d7ef3e8
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index a68a193..ac98fa9 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -278,18 +278,4 @@
 
     private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
             long propRight, long propBottom, long propRx, long propRy, long propPaint);
-
-    // TODO: move this optimization to Canvas.java
-    @Override
-    public void drawPath(Path path, Paint paint) {
-        if (path.isSimplePath) {
-            if (path.rects != null) {
-                nDrawRects(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
-            }
-        } else {
-            super.drawPath(path, paint);
-        }
-    }
-
-    private static native void nDrawRects(long renderer, long region, long paint);
 }
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 2116da0..1f01453 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -255,6 +255,13 @@
     get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
 }
 
+static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle,
+                       jlong paintHandle) {
+    const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+    get_canvas(canvasHandle)->drawRegion(*region, *paint);
+}
+
 static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
                           jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
     const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
@@ -698,6 +705,7 @@
     {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
     {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
     {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
+    {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
     {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
     {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
     {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 71d509c..2c0e790 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -124,36 +124,6 @@
     renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
 }
 
-static void android_view_DisplayListCanvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
-    SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    if (paint->getStyle() != Paint::kFill_Style ||
-            (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) {
-        SkRegion::Iterator it(*region);
-        while (!it.done()) {
-            const SkIRect& r = it.rect();
-            renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, *paint);
-            it.next();
-        }
-    } else {
-        int count = 0;
-        Vector<float> rects;
-        SkRegion::Iterator it(*region);
-        while (!it.done()) {
-            const SkIRect& r = it.rect();
-            rects.push(r.fLeft);
-            rects.push(r.fTop);
-            rects.push(r.fRight);
-            rects.push(r.fBottom);
-            count += 4;
-            it.next();
-        }
-        renderer->drawRects(rects.array(), count, paint);
-    }
-}
-
 // ----------------------------------------------------------------------------
 // Display lists
 // ----------------------------------------------------------------------------
@@ -235,7 +205,6 @@
 
     { "nDrawPatch",         "(JLandroid/graphics/Bitmap;JFFFFJ)V",     (void*) android_view_DisplayListCanvas_drawPatch },
 
-    { "nDrawRects",         "(JJJ)V",          (void*) android_view_DisplayListCanvas_drawRegionAsRects },
     { "nDrawRoundRect",     "(JJJJJJJJ)V",     (void*) android_view_DisplayListCanvas_drawRoundRectProps },
     { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_DisplayListCanvas_drawCircleProps },
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 30627bb..73caf68 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1248,7 +1248,11 @@
      * @param paint The paint used to draw the path
      */
     public void drawPath(@NonNull Path path, @NonNull Paint paint) {
-        native_drawPath(mNativeCanvasWrapper, path.ni(), paint.getNativeInstance());
+        if (path.isSimplePath && path.rects != null) {
+            native_drawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
+        } else {
+            native_drawPath(mNativeCanvasWrapper, path.ni(), paint.getNativeInstance());
+        }
     }
 
     /**
@@ -2053,6 +2057,8 @@
     private static native void native_drawPath(long nativeCanvas,
                                                long nativePath,
                                                long nativePaint);
+    private static native void native_drawRegion(long nativeCanvas,
+            long nativeRegion, long nativePaint);
     private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
                                                  float left, float top,
                                                  long nativePaintOrZero,
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index 160d9a8..116bc56 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -118,6 +118,7 @@
     virtual void drawLines(const float* points, int count, const SkPaint& paint) = 0;
     virtual void drawRect(float left, float top, float right, float bottom,
             const SkPaint& paint) = 0;
+    virtual void drawRegion(const SkRegion& region, const SkPaint& paint) = 0;
     virtual void drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint& paint) = 0;
     virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) = 0;
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index b96e555..af18e03 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -486,6 +486,32 @@
     }
 }
 
+void DisplayListCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
+    if (paint.getStyle() != SkPaint::kFill_Style ||
+            (paint.isAntiAlias() && !mState.currentTransform()->isSimple())) {
+        SkRegion::Iterator it(region);
+        while (!it.done()) {
+            const SkIRect& r = it.rect();
+            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
+            it.next();
+        }
+    } else {
+        int count = 0;
+        Vector<float> rects;
+        SkRegion::Iterator it(region);
+        while (!it.done()) {
+            const SkIRect& r = it.rect();
+            rects.push(r.fLeft);
+            rects.push(r.fTop);
+            rects.push(r.fRight);
+            rects.push(r.fBottom);
+            count += 4;
+            it.next();
+        }
+        drawRects(rects.array(), count, &paint);
+    }
+}
+
 void DisplayListCanvas::drawRects(const float* rects, int count, const SkPaint* paint) {
     if (count <= 0) return;
 
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index 04a65e3..6f2e2b5 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -75,24 +75,15 @@
 
     void insertReorderBarrier(bool enableReorder);
 
-    const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); }
-
-    bool isCurrentTransformSimple() {
-        return mState.currentTransform()->isSimple();
-    }
-
 // ----------------------------------------------------------------------------
 // HWUI Canvas draw operations
 // ----------------------------------------------------------------------------
 
-    // Bitmap-based
-    void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
     // TODO: move drawPatch() to Canvas.h
     void drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch,
             float left, float top, float right, float bottom, const SkPaint* paint);
 
     // Shapes
-    void drawRects(const float* rects, int count, const SkPaint* paint);
     void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
                 CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
                 CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
@@ -195,6 +186,7 @@
     }
     virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
     virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
+    virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
     virtual void drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint& paint) override;
     virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
@@ -239,6 +231,9 @@
         kBarrier_OutOfOrder,
     };
 
+    void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
+    void drawRects(const float* rects, int count, const SkPaint* paint);
+
     void flushRestoreToCount();
     void flushTranslate();
     void flushReorderBarrier();
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 644a4f3..971b53a 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -95,6 +95,7 @@
     virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
     virtual void drawRect(float left, float top, float right, float bottom,
             const SkPaint& paint) override;
+    virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
     virtual void drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint& paint) override;
     virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
@@ -507,6 +508,14 @@
 
 }
 
+void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
+    SkRegion::Iterator it(region);
+    while (!it.done()) {
+        mCanvas->drawRect(SkRect::Make(it.rect()), paint);
+        it.next();
+    }
+}
+
 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
         float rx, float ry, const SkPaint& paint) {
     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 64d9037..a224376 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -230,21 +230,19 @@
         DisplayListCanvas* renderer = startRecording(node.get());
         renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
 
+        SkRegion region;
         float rects[width * height];
         int index = 0;
         for (int xOffset = 0; xOffset < width; xOffset+=2) {
             for (int yOffset = 0; yOffset < height; yOffset+=2) {
-                rects[index++] = xOffset;
-                rects[index++] = yOffset;
-                rects[index++] = xOffset + 1;
-                rects[index++] = yOffset + 1;
+                region.op(xOffset, yOffset, xOffset + 1, yOffset + 1, SkRegion::kUnion_Op);
             }
         }
         int count = width * height;
 
         SkPaint paint;
         paint.setColor(0xff00ffff);
-        renderer->drawRects(rects, count, &paint);
+        renderer->drawRegion(region, paint);
 
         endRecording(renderer, node.get());
         return node;