Make DisplayListRenderer inherit from Canvas, merge JNI

Incrementally unify the upper layers for Skia and HWUI.
Remove redundant code from GLES20Canvas.java; instead
use inherited mNativeCanvasWrapper and superclass method
definitions.

Moves some unrelated SkPaint utility functions from Renderer
to new utils/PaintUtils.

bug: 15672762
Change-Id: I4ddd4214b8e9eeb95289d054ef423f2542bb5fa5
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index e42a9e4..499c113 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -34,6 +34,7 @@
 #include "RenderState.h"
 #include "UvMapper.h"
 #include "utils/LinearAllocator.h"
+#include "utils/PaintUtils.h"
 
 // Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
 #define OP_LOGS(s) OP_LOG("%s", (s))
@@ -203,7 +204,7 @@
             if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
                 return false;
             }
-            if (Renderer::isBlendedColorFilter(mPaint->getColorFilter())) {
+            if (PaintUtils::isBlendedColorFilter(mPaint->getColorFilter())) {
                 return false;
             }
         }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 1eefa89a..5a13293 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -28,6 +28,7 @@
 #include "DisplayListOp.h"
 #include "DisplayListRenderer.h"
 #include "RenderNode.h"
+#include "utils/PaintUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -63,7 +64,7 @@
 }
 
 void DisplayListRenderer::prepareDirty(float left, float top,
-        float right, float bottom, bool opaque) {
+        float right, float bottom) {
 
     LOG_ALWAYS_FATAL_IF(mDisplayListData,
             "prepareDirty called a second time during a recording!");
@@ -72,7 +73,7 @@
     mState.initializeSaveStack(0, 0, mState.getWidth(), mState.getHeight(), Vector3());
 
     mDeferredBarrierType = kBarrier_InOrder;
-    mState.setDirtyClip(opaque);
+    mState.setDirtyClip(false);
     mRestoreSaveCount = -1;
 }
 
@@ -94,9 +95,9 @@
     mDisplayListData->functors.add(functor);
 }
 
-int DisplayListRenderer::save(int flags) {
-    addStateOp(new (alloc()) SaveOp(flags));
-    return mState.save(flags);
+int DisplayListRenderer::save(SkCanvas::SaveFlags flags) {
+    addStateOp(new (alloc()) SaveOp((int) flags));
+    return mState.save((int) flags);
 }
 
 void DisplayListRenderer::restore() {
@@ -117,22 +118,21 @@
 }
 
 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
-        const SkPaint* paint, int flags) {
+        const SkPaint* paint, SkCanvas::SaveFlags flags) {
     // force matrix/clip isolation for layer
     flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
 
     paint = refPaint(paint);
-    addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
-    return mState.save(flags);
+    addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, (int) flags));
+    return mState.save((int) flags);
 }
 
-void DisplayListRenderer::translate(float dx, float dy, float dz) {
-    // ignore dz, not used at defer time
+void DisplayListRenderer::translate(float dx, float dy) {
     mHasDeferredTranslate = true;
     mTranslateX += dx;
     mTranslateY += dy;
     flushRestoreToCount();
-    mState.translate(dx, dy, dz);
+    mState.translate(dx, dy, 0.0f);
 }
 
 void DisplayListRenderer::rotate(float degrees) {
@@ -155,11 +155,27 @@
     mState.setMatrix(matrix);
 }
 
-void DisplayListRenderer::concatMatrix(const SkMatrix& matrix) {
+void DisplayListRenderer::concat(const SkMatrix& matrix) {
     addStateOp(new (alloc()) ConcatMatrixOp(matrix));
     mState.concatMatrix(matrix);
 }
 
+bool DisplayListRenderer::getClipBounds(SkRect* outRect) const {
+    Rect bounds = mState.getLocalClipBounds();
+    *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
+    return !(outRect->isEmpty());
+}
+
+bool DisplayListRenderer::quickRejectRect(float left, float top, float right, float bottom) const {
+    return mState.quickRejectConservative(left, top, right, bottom);
+}
+
+bool DisplayListRenderer::quickRejectPath(const SkPath& path) const {
+    SkRect bounds = path.getBounds();
+    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
+}
+
+
 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
         SkRegion::Op op) {
     addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
@@ -201,23 +217,50 @@
     addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint));
 }
 
-void DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
+void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float left, float top,
+        const SkPaint* paint) {
+    save(SkCanvas::kMatrix_SaveFlag);
+    translate(left, top);
+    drawBitmap(&bitmap, paint);
+    restore();
+}
+
+void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+        const SkPaint* paint) {
+    if (matrix.isIdentity()) {
+        drawBitmap(&bitmap, paint);
+    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))) {
+        // SkMatrix::isScaleTranslate() not available in L
+        SkRect src;
+        SkRect dst;
+        bitmap.getBounds(&src);
+        matrix.mapRect(&dst, src);
+        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
+                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+    } else {
+        save(SkCanvas::kMatrix_SaveFlag);
+        concat(matrix);
+        drawBitmap(&bitmap, paint);
+        restore();
+    }
+}
+
+void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop,
         float dstRight, float dstBottom, const SkPaint* paint) {
     if (srcLeft == 0 && srcTop == 0
-            && srcRight == bitmap->width() && srcBottom == bitmap->height()
+            && srcRight == bitmap.width() && srcBottom == bitmap.height()
             && (srcBottom - srcTop == dstBottom - dstTop)
             && (srcRight - srcLeft == dstRight - dstLeft)) {
         // transform simple rect to rect drawing case into position bitmap ops, since they merge
         save(SkCanvas::kMatrix_SaveFlag);
         translate(dstLeft, dstTop);
-        drawBitmap(bitmap, paint);
+        drawBitmap(&bitmap, paint);
         restore();
     } else {
-        bitmap = refBitmap(bitmap);
         paint = refPaint(paint);
 
-        addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
+        addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap),
                 srcLeft, srcTop, srcRight, srcBottom,
                 dstLeft, dstTop, dstRight, dstBottom, paint));
     }
@@ -230,16 +273,15 @@
     addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, paint));
 }
 
-void DisplayListRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+void DisplayListRenderer::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
         const float* vertices, const int* colors, const SkPaint* paint) {
     int vertexCount = (meshWidth + 1) * (meshHeight + 1);
-    bitmap = refBitmap(bitmap);
     vertices = refBuffer<float>(vertices, vertexCount * 2); // 2 floats per vertex
     paint = refPaint(paint);
     colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
 
-    addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
-                    vertices, colors, paint));
+    addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(&bitmap), meshWidth, meshHeight,
+           vertices, colors, paint));
 }
 
 void DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
@@ -255,16 +297,22 @@
     addDrawOp(new (alloc()) DrawColorOp(color, mode));
 }
 
+void DisplayListRenderer::drawPaint(const SkPaint& paint) {
+    SkRect bounds;
+    if (getClipBounds(&bounds)) {
+        drawRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, paint);
+    }
+}
+
+
 void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
-        const SkPaint* paint) {
-    paint = refPaint(paint);
-    addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
+        const SkPaint& paint) {
+    addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, refPaint(&paint)));
 }
 
 void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
-        float rx, float ry, const SkPaint* paint) {
-    paint = refPaint(paint);
-    addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
+        float rx, float ry, const SkPaint& paint) {
+    addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, refPaint(&paint)));
 }
 
 void DisplayListRenderer::drawRoundRect(
@@ -283,9 +331,8 @@
             &right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
 }
 
-void DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint* paint) {
-    paint = refPaint(paint);
-    addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
+void DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint& paint) {
+    addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, refPaint(&paint)));
 }
 
 void DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
@@ -299,65 +346,56 @@
 }
 
 void DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
-        const SkPaint* paint) {
-    paint = refPaint(paint);
-    addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
+        const SkPaint& paint) {
+    addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, refPaint(&paint)));
 }
 
 void DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
+        float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
     if (fabs(sweepAngle) >= 360.0f) {
         drawOval(left, top, right, bottom, paint);
     } else {
-        paint = refPaint(paint);
         addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
-                        startAngle, sweepAngle, useCenter, paint));
+                        startAngle, sweepAngle, useCenter, refPaint(&paint)));
     }
 }
 
-void DisplayListRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
-    path = refPath(path);
-    paint = refPaint(paint);
-
-    addDrawOp(new (alloc()) DrawPathOp(path, paint));
+void DisplayListRenderer::drawPath(const SkPath& path, const SkPaint& paint) {
+    addDrawOp(new (alloc()) DrawPathOp(refPath(&path), refPaint(&paint)));
 }
 
-void DisplayListRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
+void DisplayListRenderer::drawLines(const float* points, int count, const SkPaint& paint) {
     points = refBuffer<float>(points, count);
-    paint = refPaint(paint);
 
-    addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
+    addDrawOp(new (alloc()) DrawLinesOp(points, count, refPaint(&paint)));
 }
 
-void DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
+void DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint& paint) {
     points = refBuffer<float>(points, count);
-    paint = refPaint(paint);
 
-    addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
+    addDrawOp(new (alloc()) DrawPointsOp(points, count, refPaint(&paint)));
 }
 
-void DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
-        const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
-    if (!text || count <= 0) return;
+void DisplayListRenderer::drawTextOnPath(const uint16_t* glyphs, int count,
+        const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
+    if (!glyphs || count <= 0) return;
 
-    text = refText(text, bytesCount);
-    path = refPath(path);
-    paint = refPaint(paint);
-
-    DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
-            hOffset, vOffset, paint);
+    int bytesCount = 2 * count;
+    DrawOp* op = new (alloc()) DrawTextOnPathOp(refText((const char*) glyphs, bytesCount),
+            bytesCount, count, refPath(&path),
+            hOffset, vOffset, refPaint(&paint));
     addDrawOp(op);
 }
 
-void DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
-        const float* positions, const SkPaint* paint) {
+void DisplayListRenderer::drawPosText(const uint16_t* text, const float* positions,
+        int count, int posCount, const SkPaint& paint) {
     if (!text || count <= 0) return;
 
-    text = refText(text, bytesCount);
+    int bytesCount = 2 * count;
     positions = refBuffer<float>(positions, count * 2);
-    paint = refPaint(paint);
 
-    DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
+    DrawOp* op = new (alloc()) DrawPosTextOp(refText((const char*) text, bytesCount),
+                                             bytesCount, count, positions, refPaint(&paint));
     addDrawOp(op);
 }
 
@@ -371,40 +409,41 @@
     paint->setLooper(NULL);
 }
 
-void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, const float* positions, const SkPaint* paint,
-        float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
+void DisplayListRenderer::drawText(const uint16_t* glyphs, const float* positions,
+        int count, const SkPaint& paint, float x, float y,
+        float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
+        float totalAdvance) {
 
-    if (!text || count <= 0 || paintWillNotDrawText(*paint)) return;
+    if (!glyphs || count <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
 
-    text = refText(text, bytesCount);
+    int bytesCount = count * 2;
+    const char* text = refText((const char*) glyphs, bytesCount);
     positions = refBuffer<float>(positions, count * 2);
+    Rect bounds(boundsLeft, boundsTop, boundsRight, boundsBottom);
 
     if (CC_UNLIKELY(mHighContrastText)) {
         // high contrast draw path
-        int color = paint->getColor();
+        int color = paint.getColor();
         int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
         bool darken = channelSum < (128 * 3);
 
         // outline
-        SkPaint* outlinePaint = copyPaint(paint);
+        SkPaint* outlinePaint = copyPaint(&paint);
         simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, outlinePaint);
         outlinePaint->setStyle(SkPaint::kStrokeAndFill_Style);
         addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
                 x, y, positions, outlinePaint, totalAdvance, bounds)); // bounds?
 
         // inner
-        SkPaint* innerPaint = copyPaint(paint);
+        SkPaint* innerPaint = copyPaint(&paint);
         simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, innerPaint);
         innerPaint->setStyle(SkPaint::kFill_Style);
         addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
                 x, y, positions, innerPaint, totalAdvance, bounds));
     } else {
         // standard draw path
-        paint = refPaint(paint);
-
         DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
-                x, y, positions, paint, totalAdvance, bounds);
+                x, y, positions, refPaint(&paint), totalAdvance, bounds);
         addDrawOp(op);
     }
 }
@@ -477,7 +516,7 @@
 size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
     Rect localBounds;
     if (op->getLocalBounds(localBounds)) {
-        bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
+        bool rejected = quickRejectRect(localBounds.left, localBounds.top,
                 localBounds.right, localBounds.bottom);
         op->setQuickRejected(rejected);
     }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 34f9c38..a798329 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -25,6 +25,8 @@
 #include <SkTLazy.h>
 #include <cutils/compiler.h>
 
+#include <private/graphics/Canvas.h>
+
 #include "CanvasState.h"
 #include "DisplayList.h"
 #include "DisplayListLogBuffer.h"
@@ -62,7 +64,7 @@
 /**
  * Records drawing commands in a display list for later playback into an OpenGLRenderer.
  */
-class ANDROID_API DisplayListRenderer: public Renderer, public CanvasStateClient {
+class ANDROID_API DisplayListRenderer: public Canvas, public CanvasStateClient {
 public:
     DisplayListRenderer();
     virtual ~DisplayListRenderer();
@@ -72,126 +74,177 @@
     DisplayListData* finishRecording();
 
 // ----------------------------------------------------------------------------
-// Frame state operations
+// HWUI Frame state operations
 // ----------------------------------------------------------------------------
-    virtual void prepareDirty(float left, float top, float right,
-            float bottom, bool opaque) override;
-    virtual void prepare(bool opaque) override {
-        prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque);
-    }
-    virtual bool finish() override;
-    virtual void interrupt();
-    virtual void resume();
+
+    void prepareDirty(float left, float top, float right, float bottom);
+    void prepare() { prepareDirty(0.0f, 0.0f, width(), height()); }
+    bool finish();
+    void interrupt();
+    void resume();
 
 // ----------------------------------------------------------------------------
-// Canvas state operations
+// HWUI Canvas state operations
 // ----------------------------------------------------------------------------
-    virtual void setViewport(int width, int height) override { mState.setViewport(width, height); }
 
-    // Save (layer)
-    virtual int getSaveCount() const override { return mState.getSaveCount(); }
-    virtual int save(int flags) override;
-    virtual void restore() override;
-    virtual void restoreToCount(int saveCount) override;
-    virtual int saveLayer(float left, float top, float right, float bottom,
-            const SkPaint* paint, int flags) override;
+    void setViewport(int width, int height) { mState.setViewport(width, height); }
 
-    // Matrix
-    virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
-
-    virtual void translate(float dx, float dy, float dz = 0.0f) override;
-    virtual void rotate(float degrees) override;
-    virtual void scale(float sx, float sy) override;
-    virtual void skew(float sx, float sy) override;
-
-    virtual void setMatrix(const SkMatrix& matrix) override;
-    virtual void concatMatrix(const SkMatrix& matrix) override;
-
-    // Clip
-    virtual bool clipRect(float left, float top, float right, float bottom,
-            SkRegion::Op op) override;
-    virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
-    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
-
-    // Misc
-    virtual void setDrawFilter(SkDrawFilter* filter) override;
-    virtual const Rect& getLocalClipBounds() const override { return mState.getLocalClipBounds(); }
     const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); }
-    virtual bool quickRejectConservative(float left, float top,
-            float right, float bottom) const override {
-        return mState.quickRejectConservative(left, top, right, bottom);
-    }
 
     bool isCurrentTransformSimple() {
         return mState.currentTransform()->isSimple();
     }
 
 // ----------------------------------------------------------------------------
-// Canvas draw operations
+// HWUI Canvas draw operations
 // ----------------------------------------------------------------------------
-    virtual void drawColor(int color, SkXfermode::Mode mode) override;
 
     // Bitmap-based
-    virtual void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) override;
-    virtual void drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
-            float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, const SkPaint* paint) override;
-    virtual void drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) override;
-    virtual void drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
-            const float* vertices, const int* colors, const SkPaint* paint) override;
-    virtual void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
-            float left, float top, float right, float bottom, const SkPaint* paint) override;
+    void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
+    // TODO: move drawBitmapData() to Canvas.h
+    void drawBitmapData(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
-    virtual void drawRect(float left, float top, float right, float bottom,
-            const SkPaint* paint) override;
-    virtual void drawRects(const float* rects, int count, 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 drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
+    void drawRects(const float* rects, int count, const SkPaint* paint);
+    void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
                 CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
                 CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
                 CanvasPropertyPaint* paint);
-    virtual void drawCircle(float x, float y, float radius, const SkPaint* paint) override;
-    virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+    void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
                 CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
-    virtual void drawOval(float left, float top, float right, float bottom,
-            const SkPaint* paint) override;
-    virtual void drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) override;
-    virtual void drawPath(const SkPath* path, const SkPaint* paint) override;
-    virtual void drawLines(const float* points, int count, const SkPaint* paint) override;
-    virtual void drawPoints(const float* points, int count, const SkPaint* paint) override;
 
-    // Text
-    virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
-            const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
-            DrawOpMode drawOpMode = kDrawOpMode_Immediate) override;
-    virtual void drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path,
-            float hOffset, float vOffset, const SkPaint* paint) override;
-    virtual void drawPosText(const char* text, int bytesCount, int count,
-            const float* positions, const SkPaint* paint) override;
 
 // ----------------------------------------------------------------------------
-// Canvas draw operations - special
+// HWUI Canvas draw operations - special
 // ----------------------------------------------------------------------------
-    virtual void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
-    virtual void drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags) override;
+    void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
+    void drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags);
 
     // TODO: rename for consistency
-    virtual void callDrawGLFunction(Functor* functor, Rect& dirty) override;
+    void callDrawGLFunction(Functor* functor, Rect& dirty);
 
     void setHighContrastText(bool highContrastText) {
         mHighContrastText = highContrastText;
     }
 
 // ----------------------------------------------------------------------------
-// CanvasState callbacks
+// CanvasStateClient interface
 // ----------------------------------------------------------------------------
     virtual void onViewportInitialized() override { }
     virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override { }
     virtual GLuint onGetTargetFbo() const override { return -1; }
 
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas interface
+// ----------------------------------------------------------------------------
+    virtual SkCanvas* getSkCanvas() {
+        LOG_ALWAYS_FATAL("DisplayListRenderer has no SkCanvas");
+        return NULL;
+    }
+    virtual void setBitmap(SkBitmap* bitmap, bool copyState) {
+        LOG_ALWAYS_FATAL("DisplayListRenderer is not backed by a bitmap.");
+    }
+
+    virtual bool isOpaque() { return false; }
+    virtual int width() { return mState.getWidth(); }
+    virtual int height() { return mState.getHeight(); }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas state operations
+// ----------------------------------------------------------------------------
+    // Save (layer)
+    virtual int getSaveCount() const { return mState.getSaveCount(); }
+    virtual int save(SkCanvas::SaveFlags flags);
+    virtual void restore();
+    virtual void restoreToCount(int saveCount);
+
+    virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+        SkCanvas::SaveFlags flags);
+    virtual int saveLayerAlpha(float left, float top, float right, float bottom,
+            int alpha, SkCanvas::SaveFlags flags) {
+        SkPaint paint;
+        paint.setAlpha(alpha);
+        return saveLayer(left, top, right, bottom, &paint, flags);
+    }
+
+    // Matrix
+    virtual void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); }
+    virtual void setMatrix(const SkMatrix& matrix);
+
+    virtual void concat(const SkMatrix& matrix);
+    virtual void rotate(float degrees);
+    virtual void scale(float sx, float sy);
+    virtual void skew(float sx, float sy);
+    virtual void translate(float dx, float dy);
+
+    // Clip
+    virtual bool getClipBounds(SkRect* outRect) const;
+    virtual bool quickRejectRect(float left, float top, float right, float bottom) const;
+    virtual bool quickRejectPath(const SkPath& path) const;
+
+    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
+    virtual bool clipPath(const SkPath* path, SkRegion::Op op);
+    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
+
+    // Misc
+    virtual SkDrawFilter* getDrawFilter() { return mDrawFilter.get(); }
+    virtual void setDrawFilter(SkDrawFilter* filter);
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas draw operations
+// ----------------------------------------------------------------------------
+    virtual void drawColor(int color, SkXfermode::Mode mode);
+    virtual void drawPaint(const SkPaint& paint);
+
+    // Geometry
+    virtual void drawPoint(float x, float y, const SkPaint& paint) {
+        float points[2] = { x, y };
+        drawPoints(points, 2, paint);
+    }
+    virtual void drawPoints(const float* points, int count, const SkPaint& paint);
+    virtual void drawLine(float startX, float startY, float stopX, float stopY,
+            const SkPaint& paint) {
+        float points[4] = { startX, startY, stopX, stopY };
+        drawLines(points, 4, paint);
+    }
+    virtual void drawLines(const float* points, int count, const SkPaint& paint);
+    virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
+    virtual void drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, const SkPaint& paint);
+    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
+    virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
+    virtual void drawArc(float left, float top, float right, float bottom,
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint);
+    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+    virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
+            const float* verts, const float* tex, const int* colors,
+            const uint16_t* indices, int indexCount, const SkPaint& paint)
+        { LOG_ALWAYS_FATAL("DisplayListRenderer does not support drawVertices()"); }
+
+    // Bitmap-based
+    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+                            const SkPaint* paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+            float srcRight, float srcBottom, float dstLeft, float dstTop,
+            float dstRight, float dstBottom, const SkPaint* paint);
+    virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint);
+
+    // Text
+    virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
+            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
+            float boundsRight, float boundsBottom, float totalAdvance);
+    virtual void drawPosText(const uint16_t* text, const float* positions, int count,
+            int posCount, const SkPaint& paint);
+    virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+            float hOffset, float vOffset, const SkPaint& paint);
+    virtual bool drawTextAbsolutePos() const { return false; }
+
+
 private:
 
     CanvasState mState;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index fb3d462..3c8fb8b 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -47,6 +47,7 @@
 #include "Vector.h"
 #include "VertexBuffer.h"
 #include "utils/GLUtils.h"
+#include "utils/PaintUtils.h"
 #include "utils/TraceUtils.h"
 
 #if DEBUG_DETAILED_EVENTS
@@ -1667,8 +1668,10 @@
     // argb=1,0,0,0
     accountForClear(mode);
     // TODO: check shader blending, once we have shader drawing support for layers.
-    bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f ||
-            (mColorSet && mColorA < 1.0f) || isBlendedColorFilter(layer->getColorFilter());
+    bool blend = layer->isBlend()
+            || getLayerAlpha(layer) < 1.0f
+            || (mColorSet && mColorA < 1.0f)
+            || PaintUtils::isBlendedColorFilter(layer->getColorFilter());
     chooseBlending(blend, mode, mDescription, swapSrcDst);
 }
 
@@ -1679,7 +1682,7 @@
     accountForClear(mode);
     blend |= (mColorSet && mColorA < 1.0f) ||
             (getShader(paint) && !getShader(paint)->isOpaque()) ||
-            isBlendedColorFilter(getColorFilter(paint));
+            PaintUtils::isBlendedColorFilter(getColorFilter(paint));
     chooseBlending(blend, mode, mDescription, swapSrcDst);
 }
 
@@ -2476,7 +2479,7 @@
         float rx, float ry, const SkPaint* p) {
     if (mState.currentlyIgnored()
             || quickRejectSetupScissor(left, top, right, bottom, p)
-            || paintWillNotDraw(*p)) {
+            || PaintUtils::paintWillNotDraw(*p)) {
         return;
     }
 
@@ -2495,7 +2498,7 @@
 void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
     if (mState.currentlyIgnored()
             || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
-            || paintWillNotDraw(*p)) {
+            || PaintUtils::paintWillNotDraw(*p)) {
         return;
     }
     if (p->getPathEffect() != nullptr) {
@@ -2517,7 +2520,7 @@
         const SkPaint* p) {
     if (mState.currentlyIgnored()
             || quickRejectSetupScissor(left, top, right, bottom, p)
-            || paintWillNotDraw(*p)) {
+            || PaintUtils::paintWillNotDraw(*p)) {
         return;
     }
 
@@ -2540,7 +2543,7 @@
         float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
     if (mState.currentlyIgnored()
             || quickRejectSetupScissor(left, top, right, bottom, p)
-            || paintWillNotDraw(*p)) {
+            || PaintUtils::paintWillNotDraw(*p)) {
         return;
     }
 
@@ -2575,7 +2578,7 @@
         const SkPaint* p) {
     if (mState.currentlyIgnored()
             || quickRejectSetupScissor(left, top, right, bottom, p)
-            || paintWillNotDraw(*p)) {
+            || PaintUtils::paintWillNotDraw(*p)) {
         return;
     }
 
@@ -2657,7 +2660,8 @@
 
 bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
     float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
-    return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
+    return MathUtils::isZero(alpha)
+            && PaintUtils::getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
 }
 
 void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 9de4149..9d9b3d2 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -49,6 +49,7 @@
 #include "UvMapper.h"
 #include "Vertex.h"
 #include "Caches.h"
+#include "utils/PaintUtils.h"
 
 class SkShader;
 
@@ -274,7 +275,7 @@
 
     static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) {
         if (!paint) return SkXfermode::kSrcOver_Mode;
-        return getXfermode(paint->getXfermode());
+        return PaintUtils::getXfermode(paint->getXfermode());
     }
 
     static inline int getAlphaDirect(const SkPaint* paint) {
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index ee44d7a..3240bbc 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -57,40 +57,6 @@
 public:
     virtual ~Renderer() {}
 
-    /**
-     * Safely retrieves the mode from the specified xfermode. If the specified
-     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
-     */
-    static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
-        SkXfermode::Mode resultMode;
-        if (!SkXfermode::AsMode(mode, &resultMode)) {
-            resultMode = SkXfermode::kSrcOver_Mode;
-        }
-        return resultMode;
-    }
-
-    // TODO: move to a method on android:Paint
-    static inline bool paintWillNotDraw(const SkPaint& paint) {
-        return paint.getAlpha() == 0
-                && !paint.getColorFilter()
-                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
-    }
-
-    // TODO: move to a method on android:Paint
-    static inline bool paintWillNotDrawText(const SkPaint& paint) {
-        return paint.getAlpha() == 0
-                && paint.getLooper() == nullptr
-                && !paint.getColorFilter()
-                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
-    }
-
-    static bool isBlendedColorFilter(const SkColorFilter* filter) {
-        if (filter == nullptr) {
-            return false;
-        }
-        return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
-    }
-
 // ----------------------------------------------------------------------------
 // Frame state operations
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index ee16991..4efef6f 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -41,7 +41,7 @@
 static DisplayListRenderer* startRecording(RenderNode* node) {
     DisplayListRenderer* renderer = new DisplayListRenderer();
     renderer->setViewport(node->getWidth(), node->getHeight());
-    renderer->prepare(false);
+    renderer->prepare();
     return renderer;
 }
 
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
new file mode 100644
index 0000000..8a4034f
--- /dev/null
+++ b/libs/hwui/utils/PaintUtils.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef PAINT_UTILS_H
+#define PAINT_UTILS_H
+
+namespace android {
+namespace uirenderer {
+
+class PaintUtils {
+public:
+
+   /**
+     * Safely retrieves the mode from the specified xfermode. If the specified
+     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
+     */
+    static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
+        SkXfermode::Mode resultMode;
+        if (!SkXfermode::AsMode(mode, &resultMode)) {
+            resultMode = SkXfermode::kSrcOver_Mode;
+        }
+        return resultMode;
+    }
+
+    // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
+    static inline bool paintWillNotDraw(const SkPaint& paint) {
+        return paint.getAlpha() == 0
+                && !paint.getColorFilter()
+                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+    }
+
+    // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
+    static inline bool paintWillNotDrawText(const SkPaint& paint) {
+        return paint.getAlpha() == 0
+                && paint.getLooper() == NULL
+                && !paint.getColorFilter()
+                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+    }
+
+    static bool isBlendedColorFilter(const SkColorFilter* filter) {
+        if (filter == NULL) {
+            return false;
+        }
+        return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
+    }
+
+}; // class PaintUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* PAINT_UTILS_H */