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/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index eaea4d4..3cb4666 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -19,19 +19,13 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
-import android.graphics.DrawFilter;
 import android.graphics.Matrix;
 import android.graphics.NinePatch;
 import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
 import android.graphics.Path;
 import android.graphics.Picture;
-import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.Shader;
-import android.graphics.TemporaryBuffer;
 import android.text.GraphicsOperations;
 import android.text.SpannableString;
 import android.text.SpannedString;
@@ -41,14 +35,6 @@
  * An implementation of Canvas on top of OpenGL ES 2.0.
  */
 class GLES20Canvas extends HardwareCanvas {
-    private final boolean mOpaque;
-    protected long mRenderer;
-
-    // The native renderer will be destroyed when this object dies.
-    // DO NOT overwrite this reference once it is set.
-    @SuppressWarnings({"unused", "FieldCanBeLocal"})
-    private CanvasFinalizer mFinalizer;
-
     private int mWidth;
     private int mHeight;
 
@@ -58,8 +44,6 @@
     private Rect mClipBounds;
     private RectF mPathBounds;
 
-    private DrawFilter mFilter;
-
     ///////////////////////////////////////////////////////////////////////////
     // JNI
     ///////////////////////////////////////////////////////////////////////////
@@ -77,39 +61,10 @@
 
     // TODO: Merge with GLES20RecordingCanvas
     protected GLES20Canvas() {
-        mOpaque = false;
-        mRenderer = nCreateDisplayListRenderer();
-        setupFinalizer();
-    }
-
-    private void setupFinalizer() {
-        if (mRenderer == 0) {
-            throw new IllegalStateException("Could not create GLES20Canvas renderer");
-        } else {
-            mFinalizer = new CanvasFinalizer(mRenderer);
-        }
+        super(nCreateDisplayListRenderer());
     }
 
     private static native long nCreateDisplayListRenderer();
-    private static native void nResetDisplayListRenderer(long renderer);
-    private static native void nDestroyRenderer(long renderer);
-
-    private static final class CanvasFinalizer {
-        private final long mRenderer;
-
-        public CanvasFinalizer(long renderer) {
-            mRenderer = renderer;
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            try {
-                nDestroyRenderer(mRenderer);
-            } finally {
-                super.finalize();
-            }
-        }
-    }
 
     public static void setProperty(String name, String value) {
         nSetProperty(name, value);
@@ -123,7 +78,7 @@
 
     @Override
     public boolean isOpaque() {
-        return mOpaque;
+        return false;
     }
 
     @Override
@@ -153,7 +108,7 @@
      * Returns the native OpenGLRenderer object.
      */
     long getRenderer() {
-        return mRenderer;
+        return mNativeCanvasWrapper;
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -165,7 +120,7 @@
         mWidth = width;
         mHeight = height;
 
-        nSetViewport(mRenderer, width, height);
+        nSetViewport(mNativeCanvasWrapper, width, height);
     }
 
     private static native void nSetViewport(long renderer,
@@ -173,19 +128,19 @@
 
     @Override
     public void setHighContrastText(boolean highContrastText) {
-        nSetHighContrastText(mRenderer, highContrastText);
+        nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
     }
 
     private static native void nSetHighContrastText(long renderer, boolean highContrastText);
 
     @Override
     public void insertReorderBarrier() {
-        nInsertReorderBarrier(mRenderer, true);
+        nInsertReorderBarrier(mNativeCanvasWrapper, true);
     }
 
     @Override
     public void insertInorderBarrier() {
-        nInsertReorderBarrier(mRenderer, false);
+        nInsertReorderBarrier(mNativeCanvasWrapper, false);
     }
 
     private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
@@ -193,20 +148,18 @@
     @Override
     public void onPreDraw(Rect dirty) {
         if (dirty != null) {
-            nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
-                    mOpaque);
+            nPrepareDirty(mNativeCanvasWrapper, dirty.left, dirty.top, dirty.right, dirty.bottom);
         } else {
-            nPrepare(mRenderer, mOpaque);
+            nPrepare(mNativeCanvasWrapper);
         }
     }
 
-    private static native void nPrepare(long renderer, boolean opaque);
-    private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom,
-            boolean opaque);
+    private static native void nPrepare(long renderer);
+    private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom);
 
     @Override
     public void onPostDraw() {
-        nFinish(mRenderer);
+        nFinish(mNativeCanvasWrapper);
     }
 
     private static native void nFinish(long renderer);
@@ -217,7 +170,7 @@
 
     @Override
     public void callDrawGLFunction2(long drawGLFunction) {
-        nCallDrawGLFunction(mRenderer, drawGLFunction);
+        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction);
     }
 
     private static native void nCallDrawGLFunction(long renderer, long drawGLFunction);
@@ -230,7 +183,7 @@
 
     @Override
     public void drawRenderNode(RenderNode renderNode, int flags) {
-        nDrawRenderNode(mRenderer, renderNode.getNativeDisplayList(), flags);
+        nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList(), flags);
     }
 
     private static native void nDrawRenderNode(long renderer, long renderNode,
@@ -242,326 +195,32 @@
 
     void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
         layer.setLayerPaint(paint);
-        nDrawLayer(mRenderer, layer.getLayerHandle(), x, y);
+        nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
     }
 
     private static native void nDrawLayer(long renderer, long layer, float x, float y);
 
     ///////////////////////////////////////////////////////////////////////////
-    // Support
-    ///////////////////////////////////////////////////////////////////////////
-
-    private Rect getInternalClipBounds() {
-        if (mClipBounds == null) mClipBounds = new Rect();
-        return mClipBounds;
-    }
-
-
-    private RectF getPathBounds() {
-        if (mPathBounds == null) mPathBounds = new RectF();
-        return mPathBounds;
-    }
-
-    private float[] getPointStorage() {
-        if (mPoint == null) mPoint = new float[2];
-        return mPoint;
-    }
-
-    private float[] getLineStorage() {
-        if (mLine == null) mLine = new float[4];
-        return mLine;
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Clipping
-    ///////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public boolean clipPath(Path path) {
-        return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
-    }
-
-    @Override
-    public boolean clipPath(Path path, Region.Op op) {
-        return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
-    }
-
-    private static native boolean nClipPath(long renderer, long path, int op);
-
-    @Override
-    public boolean clipRect(float left, float top, float right, float bottom) {
-        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
-    }
-
-    private static native boolean nClipRect(long renderer, float left, float top,
-            float right, float bottom, int op);
-
-    @Override
-    public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
-        return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
-    }
-
-    @Override
-    public boolean clipRect(int left, int top, int right, int bottom) {
-        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
-    }
-
-    private static native boolean nClipRect(long renderer, int left, int top,
-            int right, int bottom, int op);
-
-    @Override
-    public boolean clipRect(Rect rect) {
-        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
-                Region.Op.INTERSECT.nativeInt);
-    }
-
-    @Override
-    public boolean clipRect(Rect rect, Region.Op op) {
-        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
-    }
-
-    @Override
-    public boolean clipRect(RectF rect) {
-        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
-                Region.Op.INTERSECT.nativeInt);
-    }
-
-    @Override
-    public boolean clipRect(RectF rect, Region.Op op) {
-        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
-    }
-
-    @Override
-    public boolean clipRegion(Region region) {
-        return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
-    }
-
-    @Override
-    public boolean clipRegion(Region region, Region.Op op) {
-        return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
-    }
-
-    private static native boolean nClipRegion(long renderer, long region, int op);
-
-    @Override
-    public boolean getClipBounds(Rect bounds) {
-        return nGetClipBounds(mRenderer, bounds);
-    }
-
-    private static native boolean nGetClipBounds(long renderer, Rect bounds);
-
-    @Override
-    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
-        return nQuickReject(mRenderer, left, top, right, bottom);
-    }
-
-    private static native boolean nQuickReject(long renderer, float left, float top,
-            float right, float bottom);
-
-    @Override
-    public boolean quickReject(Path path, EdgeType type) {
-        RectF pathBounds = getPathBounds();
-        path.computeBounds(pathBounds, true);
-        return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
-                pathBounds.right, pathBounds.bottom);
-    }
-
-    @Override
-    public boolean quickReject(RectF rect, EdgeType type) {
-        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Transformations
-    ///////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void translate(float dx, float dy) {
-        if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
-    }
-
-    private static native void nTranslate(long renderer, float dx, float dy);
-
-    @Override
-    public void skew(float sx, float sy) {
-        nSkew(mRenderer, sx, sy);
-    }
-
-    private static native void nSkew(long renderer, float sx, float sy);
-
-    @Override
-    public void rotate(float degrees) {
-        nRotate(mRenderer, degrees);
-    }
-
-    private static native void nRotate(long renderer, float degrees);
-
-    @Override
-    public void scale(float sx, float sy) {
-        nScale(mRenderer, sx, sy);
-    }
-
-    private static native void nScale(long renderer, float sx, float sy);
-
-    @Override
-    public void setMatrix(Matrix matrix) {
-        nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
-    }
-
-    private static native void nSetMatrix(long renderer, long matrix);
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public void getMatrix(Matrix matrix) {
-        nGetMatrix(mRenderer, matrix.native_instance);
-    }
-
-    private static native void nGetMatrix(long renderer, long matrix);
-
-    @Override
-    public void concat(Matrix matrix) {
-        if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
-    }
-
-    private static native void nConcatMatrix(long renderer, long matrix);
-
-    ///////////////////////////////////////////////////////////////////////////
-    // State management
-    ///////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public int save() {
-        return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
-    }
-
-    @Override
-    public int save(int saveFlags) {
-        return nSave(mRenderer, saveFlags);
-    }
-
-    private static native int nSave(long renderer, int flags);
-
-    @Override
-    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
-        if (bounds != null) {
-            return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
-        }
-
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        return nSaveLayer(mRenderer, nativePaint, saveFlags);
-    }
-
-    private static native int nSaveLayer(long renderer, long paint, int saveFlags);
-
-    @Override
-    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
-            int saveFlags) {
-        if (left < right && top < bottom) {
-            final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-            return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
-        }
-        return save(saveFlags);
-    }
-
-    private static native int nSaveLayer(long renderer, float left, float top,
-            float right, float bottom, long paint, int saveFlags);
-
-    @Override
-    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
-        if (bounds != null) {
-            return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
-                    alpha, saveFlags);
-        }
-        return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
-    }
-
-    private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags);
-
-    @Override
-    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
-            int saveFlags) {
-        if (left < right && top < bottom) {
-            return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
-        }
-        return save(saveFlags);
-    }
-
-    private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
-            float bottom, int alpha, int saveFlags);
-
-    @Override
-    public void restore() {
-        nRestore(mRenderer);
-    }
-
-    private static native void nRestore(long renderer);
-
-    @Override
-    public void restoreToCount(int saveCount) {
-        nRestoreToCount(mRenderer, saveCount);
-    }
-
-    private static native void nRestoreToCount(long renderer, int saveCount);
-
-    @Override
-    public int getSaveCount() {
-        return nGetSaveCount(mRenderer);
-    }
-
-    private static native int nGetSaveCount(long renderer);
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Filtering
-    ///////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void setDrawFilter(DrawFilter filter) {
-        mFilter = filter;
-        nSetDrawFilter(mRenderer, (filter != null) ? filter.mNativeInt : 0);
-    }
-
-    private static native void nSetDrawFilter(long renderer, long nativeFilter);
-
-    @Override
-    public DrawFilter getDrawFilter() {
-        return mFilter;
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
     // Drawing
     ///////////////////////////////////////////////////////////////////////////
 
-    @Override
-    public void drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, boolean useCenter, Paint paint) {
-        nDrawArc(mRenderer, left, top, right, bottom,
-                startAngle, sweepAngle, useCenter, paint.getNativeInstance());
-    }
-
-    private static native void nDrawArc(long renderer, float left, float top,
-            float right, float bottom, float startAngle, float sweepAngle,
-            boolean useCenter, long paint);
-
-    @Override
-    public void drawARGB(int a, int r, int g, int b) {
-        drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
-    }
-
+    // TODO: move to Canvas.java
     @Override
     public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
         Bitmap bitmap = patch.getBitmap();
         throwIfCannotDraw(bitmap);
         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
+        nDrawPatch(mNativeCanvasWrapper, bitmap.mNativeBitmap, patch.mNativeChunk,
                 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
     }
 
+    // TODO: move to Canvas.java
     @Override
     public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
         Bitmap bitmap = patch.getBitmap();
         throwIfCannotDraw(bitmap);
         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
+        nDrawPatch(mNativeCanvasWrapper, bitmap.mNativeBitmap, patch.mNativeChunk,
                 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
     }
 
@@ -569,148 +228,9 @@
             float left, float top, float right, float bottom, long paint);
 
     @Override
-    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
-    }
-
-    private static native void nDrawBitmap(long renderer, long bitmap, float left,
-            float top, long paint);
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
-    }
-
-    private static native void nDrawBitmap(long renderer, long bitmap,
-            long matrix, long paint);
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-
-        int left, top, right, bottom;
-        if (src == null) {
-            left = top = 0;
-            right = bitmap.getWidth();
-            bottom = bitmap.getHeight();
-        } else {
-            left = src.left;
-            right = src.right;
-            top = src.top;
-            bottom = src.bottom;
-        }
-
-        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
-                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
-    }
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-
-        float left, top, right, bottom;
-        if (src == null) {
-            left = top = 0;
-            right = bitmap.getWidth();
-            bottom = bitmap.getHeight();
-        } else {
-            left = src.left;
-            right = src.right;
-            top = src.top;
-            bottom = src.bottom;
-        }
-
-        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
-                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
-    }
-
-    private static native void nDrawBitmap(long renderer, long bitmap,
-            float srcLeft, float srcTop, float srcRight, float srcBottom,
-            float left, float top, float right, float bottom, long paint);
-
-    @Override
-    public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
-            int width, int height, boolean hasAlpha, Paint paint) {
-        if (width < 0) {
-            throw new IllegalArgumentException("width must be >= 0");
-        }
-
-        if (height < 0) {
-            throw new IllegalArgumentException("height must be >= 0");
-        }
-
-        if (Math.abs(stride) < width) {
-            throw new IllegalArgumentException("abs(stride) must be >= width");
-        }
-
-        int lastScanline = offset + (height - 1) * stride;
-        int length = colors.length;
-
-        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
-                (lastScanline + width > length)) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        nDrawBitmap(mRenderer, colors, offset, stride, x, y,
-                width, height, hasAlpha, nativePaint);
-    }
-
-    private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
-            float x, float y, int width, int height, boolean hasAlpha, long nativePaint);
-
-    @Override
-    public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
-            int width, int height, boolean hasAlpha, Paint paint) {
-        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
-    }
-
-    @Override
-    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
-            int vertOffset, int[] colors, int colorOffset, Paint paint) {
-        throwIfCannotDraw(bitmap);
-        if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
-        if (meshWidth == 0 || meshHeight == 0) {
-            return;
-        }
-
-        final int count = (meshWidth + 1) * (meshHeight + 1);
-        checkRange(verts.length, vertOffset, count * 2);
-
-        if (colors != null) {
-            checkRange(colors.length, colorOffset, count);
-        }
-
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, meshWidth, meshHeight,
-                verts, vertOffset, colors, colorOffset, nativePaint);
-    }
-
-    private static native void nDrawBitmapMesh(long renderer, long bitmap,
-            int meshWidth, int meshHeight, float[] verts, int vertOffset,
-            int[] colors, int colorOffset, long paint);
-
-    @Override
-    public void drawCircle(float cx, float cy, float radius, Paint paint) {
-        nDrawCircle(mRenderer, cx, cy, radius, paint.getNativeInstance());
-    }
-
-    private static native void nDrawCircle(long renderer, float cx, float cy,
-            float radius, long paint);
-
-    @Override
     public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
             CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
-        nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
+        nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
                 radius.getNativeContainer(), paint.getNativeContainer());
     }
 
@@ -721,7 +241,7 @@
     public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
             CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
             CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
-        nDrawRoundRect(mRenderer, left.getNativeContainer(), top.getNativeContainer(),
+        nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
                 right.getNativeContainer(), bottom.getNativeContainer(),
                 rx.getNativeContainer(), ry.getNativeContainer(),
                 paint.getNativeContainer());
@@ -730,73 +250,18 @@
     private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
             long propRight, long propBottom, long propRx, long propRy, long propPaint);
 
-    @Override
-    public void drawColor(int color) {
-        drawColor(color, PorterDuff.Mode.SRC_OVER);
-    }
-
-    @Override
-    public void drawColor(int color, PorterDuff.Mode mode) {
-        nDrawColor(mRenderer, color, mode.nativeInt);
-    }
-
-    private static native void nDrawColor(long renderer, int color, int mode);
-
-    @Override
-    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
-        float[] line = getLineStorage();
-        line[0] = startX;
-        line[1] = startY;
-        line[2] = stopX;
-        line[3] = stopY;
-        drawLines(line, 0, 4, paint);
-    }
-
-    @Override
-    public void drawLines(float[] pts, int offset, int count, Paint paint) {
-        if (count < 4) return;
-
-        if ((offset | count) < 0 || offset + count > pts.length) {
-            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
-        }
-        nDrawLines(mRenderer, pts, offset, count, paint.getNativeInstance());
-    }
-
-    private static native void nDrawLines(long renderer, float[] points,
-            int offset, int count, long paint);
-
-    @Override
-    public void drawLines(float[] pts, Paint paint) {
-        drawLines(pts, 0, pts.length, paint);
-    }
-
-    @Override
-    public void drawOval(float left, float top, float right, float bottom, Paint paint) {
-        nDrawOval(mRenderer, left, top, right, bottom, paint.getNativeInstance());
-    }
-
-    private static native void nDrawOval(long renderer, float left, float top,
-            float right, float bottom, long paint);
-
-    @Override
-    public void drawPaint(Paint paint) {
-        final Rect r = getInternalClipBounds();
-        nGetClipBounds(mRenderer, r);
-        drawRect(r.left, r.top, r.right, r.bottom, paint);
-    }
-
+    // TODO: move this optimization to Canvas.java
     @Override
     public void drawPath(Path path, Paint paint) {
         if (path.isSimplePath) {
             if (path.rects != null) {
-                nDrawRects(mRenderer, path.rects.mNativeRegion, paint.getNativeInstance());
+                nDrawRects(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
             }
         } else {
-            nDrawPath(mRenderer, path.mNativePath, paint.getNativeInstance());
+            super.drawPath(path, paint);
         }
     }
 
-    private static native void nDrawPath(long renderer, long path, long paint);
     private static native void nDrawRects(long renderer, long region, long paint);
 
     @Override
@@ -804,190 +269,4 @@
         picture.endRecording();
         // TODO: Implement rendering
     }
-
-    @Override
-    public void drawPoint(float x, float y, Paint paint) {
-        float[] point = getPointStorage();
-        point[0] = x;
-        point[1] = y;
-        drawPoints(point, 0, 2, paint);
-    }
-
-    @Override
-    public void drawPoints(float[] pts, Paint paint) {
-        drawPoints(pts, 0, pts.length, paint);
-    }
-
-    @Override
-    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
-        if (count < 2) return;
-
-        nDrawPoints(mRenderer, pts, offset, count, paint.getNativeInstance());
-    }
-
-    private static native void nDrawPoints(long renderer, float[] points,
-            int offset, int count, long paint);
-
-    // Note: drawPosText just uses implementation in Canvas
-
-    @Override
-    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
-        if (left == right || top == bottom) return;
-        nDrawRect(mRenderer, left, top, right, bottom, paint.getNativeInstance());
-    }
-
-    private static native void nDrawRect(long renderer, float left, float top,
-            float right, float bottom, long paint);
-
-    @Override
-    public void drawRect(Rect r, Paint paint) {
-        drawRect(r.left, r.top, r.right, r.bottom, paint);
-    }
-
-    @Override
-    public void drawRect(RectF r, Paint paint) {
-        drawRect(r.left, r.top, r.right, r.bottom, paint);
-    }
-
-    @Override
-    public void drawRGB(int r, int g, int b) {
-        drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
-    }
-
-    @Override
-    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
-            Paint paint) {
-        nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.getNativeInstance());
-    }
-
-    private static native void nDrawRoundRect(long renderer, float left, float top,
-            float right, float bottom, float rx, float y, long paint);
-
-    @Override
-    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
-        if ((index | count | (index + count) | (text.length - index - count)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        nDrawText(mRenderer, text, index, count, x, y,
-                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    private static native void nDrawText(long renderer, char[] text, int index, int count,
-            float x, float y, int bidiFlags, long paint, long typeface);
-
-    @Override
-    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
-        if ((start | end | (end - start) | (text.length() - end)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (text instanceof String || text instanceof SpannedString ||
-                text instanceof SpannableString) {
-            nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
-                    paint.getNativeInstance(), paint.mNativeTypeface);
-        } else if (text instanceof GraphicsOperations) {
-            ((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
-        } else {
-            char[] buf = TemporaryBuffer.obtain(end - start);
-            TextUtils.getChars(text, start, end, buf, 0);
-            nDrawText(mRenderer, buf, 0, end - start, x, y,
-                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-            TemporaryBuffer.recycle(buf);
-        }
-    }
-
-    @Override
-    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
-        if ((start | end | (end - start) | (text.length() - end)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        nDrawText(mRenderer, text, start, end, x, y,
-                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    private static native void nDrawText(long renderer, String text, int start, int end,
-            float x, float y, int bidiFlags, long paint, long typeface);
-
-    @Override
-    public void drawText(String text, float x, float y, Paint paint) {
-        nDrawText(mRenderer, text, 0, text.length(), x, y,
-                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    @Override
-    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
-            float vOffset, Paint paint) {
-        if (index < 0 || index + count > text.length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
-        nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
-                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
-            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
-            long typeface);
-
-    @Override
-    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
-        if (text.length() == 0) return;
-
-        nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
-                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
-            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
-            long typeface);
-
-    @Override
-    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
-            float x, float y, boolean isRtl, Paint paint) {
-        if ((index | count | text.length - index - count) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, isRtl,
-                paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
-            int contextIndex, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
-
-    @Override
-    public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
-            float x, float y, boolean isRtl, Paint paint) {
-        if ((start | end | end - start | text.length() - end) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (text instanceof String || text instanceof SpannedString ||
-                text instanceof SpannableString) {
-            nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
-                    contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
-        } else if (text instanceof GraphicsOperations) {
-            ((GraphicsOperations) text).drawTextRun(this, start, end,
-                    contextStart, contextEnd, x, y, isRtl, paint);
-        } else {
-            int contextLen = contextEnd - contextStart;
-            int len = end - start;
-            char[] buf = TemporaryBuffer.obtain(contextLen);
-            TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-            nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
-                    x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
-            TemporaryBuffer.recycle(buf);
-        }
-    }
-
-    private static native void nDrawTextRun(long renderer, String text, int start, int end,
-            int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
-
-    @Override
-    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
-            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
-            int indexOffset, int indexCount, Paint paint) {
-        // TODO: Implement
-    }
 }
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 5e49d8e..5ca5626 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -56,7 +56,7 @@
     }
 
     long finishRecording() {
-        return nFinishRecording(mRenderer);
+        return nFinishRecording(mNativeCanvasWrapper);
     }
 
     @Override
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 98e3927..cdb350f 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -29,6 +29,14 @@
  */
 public abstract class HardwareCanvas extends Canvas {
 
+    /**
+     * Pass a reference to the native renderer to our superclass's
+     * constructor.
+     */
+    protected HardwareCanvas(long renderer) {
+        super(renderer);
+    }
+
     @Override
     public boolean isHardwareAccelerated() {
         return true;
diff --git a/core/jni/android/graphics/SkiaCanvas.cpp b/core/jni/android/graphics/SkiaCanvas.cpp
index 7de54c4..31c6514 100644
--- a/core/jni/android/graphics/SkiaCanvas.cpp
+++ b/core/jni/android/graphics/SkiaCanvas.cpp
@@ -126,7 +126,8 @@
 
     virtual void drawText(const uint16_t* text, const float* positions, int count,
             const SkPaint& paint, float x, float y,
-            float boundsLeft, float boundsTop, float boundsRight, float boundsBottom);
+            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,
@@ -686,7 +687,8 @@
 
 void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int count,
         const SkPaint& paint, float x, float y,
-        float boundsLeft, float boundsTop, float boundsRight, float boundsBottom) {
+        float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
+        float totalAdvance) {
     // Set align to left for drawing, as we don't want individual
     // glyphs centered or right-aligned; the offset above takes
     // care of all alignment.
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 265300ed..4675b49 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -411,9 +411,10 @@
 class DrawTextFunctor {
 public:
     DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
-                    const SkPaint& paint, float x, float y, MinikinRect& bounds)
+                    const SkPaint& paint, float x, float y, MinikinRect& bounds,
+                    float totalAdvance)
             : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
-              x(x), y(y), bounds(bounds) { }
+              x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
 
     void operator()(size_t start, size_t end) {
         if (canvas->drawTextAbsolutePos()) {
@@ -432,7 +433,8 @@
 
         size_t glyphCount = end - start;
         canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
-                         bounds.mLeft , bounds.mTop , bounds.mRight , bounds.mBottom);
+                         bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
+                         totalAdvance);
     }
 private:
     const Layout& layout;
@@ -443,6 +445,7 @@
     float x;
     float y;
     MinikinRect& bounds;
+    float totalAdvance;
 };
 
 // Same values used by Skia
@@ -494,8 +497,11 @@
 
     MinikinRect bounds;
     layout.getBounds(&bounds);
+    if (!canvas->drawTextAbsolutePos()) {
+        bounds.offset(x, y);
+    }
 
-    DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds);
+    DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance());
     MinikinUtils::forFontRun(layout, &paint, f);
 
     drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 084117c..8249120 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -24,19 +24,10 @@
 
 #include <androidfw/ResourceTypes.h>
 
-#include <private/hwui/DrawGlInfo.h>
-
 #include <cutils/properties.h>
 
 #include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkImageInfo.h>
-#include <SkMatrix.h>
-#include <SkPorterDuff.h>
 #include <SkRegion.h>
-#include <SkScalerContext.h>
-#include <SkTemplates.h>
-#include <SkXfermode.h>
 
 #include <DisplayListRenderer.h>
 #include <Rect.h>
@@ -45,8 +36,6 @@
 #include <Paint.h>
 #include <renderthread/RenderProxy.h>
 
-#include "MinikinUtils.h"
-
 #include "core_jni_helpers.h"
 
 namespace android {
@@ -64,19 +53,6 @@
 static const bool kDebugRenderer = false;
 
 // ----------------------------------------------------------------------------
-// Constructors
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    if (kDebugRenderer) {
-        ALOGD("Destroy DisplayListRenderer");
-    }
-    delete renderer;
-}
-
-// ----------------------------------------------------------------------------
 // Setup
 // ----------------------------------------------------------------------------
 
@@ -99,16 +75,15 @@
 }
 
 static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jboolean opaque) {
+        jlong rendererPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->prepare(opaque);
+    renderer->prepare();
 }
 
 static void android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint left, jint top, jint right, jint bottom,
-        jboolean opaque) {
+        jlong rendererPtr, jint left, jint top, jint right, jint bottom) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->prepareDirty(left, top, right, bottom, opaque);
+    renderer->prepareDirty(left, top, right, bottom);
 }
 
 static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
@@ -160,267 +135,9 @@
 }
 
 // ----------------------------------------------------------------------------
-// State
-// ----------------------------------------------------------------------------
-
-static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
-        jint flags) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    return renderer->save(flags);
-}
-
-static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    return renderer->getSaveCount();
-}
-
-static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->restore();
-}
-
-static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint saveCount) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->restoreToCount(saveCount);
-}
-
-// ----------------------------------------------------------------------------
-// Layers
-// ----------------------------------------------------------------------------
-
-static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jlong paintPtr, jint saveFlags) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
-}
-
-static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong paintPtr, jint saveFlags) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
-    return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
-            paint, saveFlags);
-}
-
-static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jint alpha, jint saveFlags) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
-}
-
-static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint alpha, jint saveFlags) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
-    return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
-            alpha, saveFlags);
-}
-
-// ----------------------------------------------------------------------------
-// Clipping
-// ----------------------------------------------------------------------------
-
-static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const bool result = renderer->quickRejectConservative(left, top, right, bottom);
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jint op) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const bool result = renderer->clipRect(left, top, right, bottom,
-                                           static_cast<SkRegion::Op>(op));
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint left, jint top, jint right, jint bottom,
-        jint op) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const bool result = renderer->clipRect(float(left), float(top), float(right),
-                                           float(bottom),
-                                           static_cast<SkRegion::Op>(op));
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong pathPtr, jint op) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong regionPtr, jint op) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
-    const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jobject rect) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
-
-    env->CallVoidMethod(rect, gRectClassInfo.set,
-            int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
-
-    return !bounds.isEmpty() ? JNI_TRUE : JNI_FALSE;
-}
-
-// ----------------------------------------------------------------------------
-// Transforms
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat dx, jfloat dy) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->translate(dx, dy);
-}
-
-static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat degrees) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->rotate(degrees);
-}
-
-static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat sx, jfloat sy) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->scale(sx, sy);
-}
-
-static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat sx, jfloat sy) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->skew(sx, sy);
-}
-
-static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong matrixPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
-}
-
-static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong matrixPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    renderer->getMatrix(matrix);
-}
-
-static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong matrixPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    renderer->concatMatrix(*matrix);
-}
-
-// ----------------------------------------------------------------------------
 // Drawing
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong bitmapPtr, jfloat left, jfloat top, jlong paintPtr) {
-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
-
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-
-    // apply transform directly to canvas, so it affects shaders correctly
-    renderer->save(SkCanvas::kMatrix_SaveFlag);
-    renderer->translate(left, top);
-    renderer->drawBitmap(bitmap, paint);
-    renderer->restore();
-}
-
-static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong bitmapPtr,
-        float srcLeft, float srcTop, float srcRight, float srcBottom,
-        float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintPtr) {
-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
-
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
-            dstLeft, dstTop, dstRight, dstBottom, paint);
-}
-
-static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong bitmapPtr, jlong matrixPtr, jlong paintPtr) {
-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
-
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-
-    // apply transform directly to canvas, so it affects shaders correctly
-    renderer->save(SkCanvas::kMatrix_SaveFlag);
-    renderer->concatMatrix(*matrix);
-    renderer->drawBitmap(bitmap, paint);
-    renderer->restore();
-}
-
-static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jintArray colors, jint offset, jint stride,
-        jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
-    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
-    // correct the alphaType to kOpaque_SkAlphaType.
-    const SkImageInfo info = SkImageInfo::Make(width, height,
-                               hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
-                               kPremul_SkAlphaType);
-    SkBitmap* bitmap = new SkBitmap;
-    if (!bitmap->tryAllocPixels(info)) {
-        delete bitmap;
-        return;
-    }
-
-    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
-        delete bitmap;
-        return;
-    }
-
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-
-    // apply transform directly to canvas, so it affects shaders correctly
-    renderer->save(SkCanvas::kMatrix_SaveFlag);
-    renderer->translate(left, top);
-    renderer->drawBitmapData(bitmap, paint);
-    renderer->restore();
-
-    // Note - bitmap isn't deleted as DisplayListRenderer owns it now
-}
-
-static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong bitmapPtr, jint meshWidth, jint meshHeight,
-        jfloatArray vertices, jint offset, jintArray colors, jint colorOffset, jlong paintPtr) {
-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
-
-    jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
-    jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
-
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
-
-    if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
-    if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
-}
-
 static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong bitmapPtr, jlong patchPtr,
         float left, float top, float right, float bottom, jlong paintPtr) {
@@ -432,29 +149,6 @@
     renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
 }
 
-static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint color, jint modeHandle) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
-    renderer->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
-}
-
-static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawRect(left, top, right, bottom, paint);
-}
-
-static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jfloat rx, jfloat ry, jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
-}
-
 static void android_view_GLES20Canvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
         jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
@@ -469,13 +163,6 @@
     renderer->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
 }
 
-static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawCircle(x, y, radius, paint);
-}
-
 static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -486,22 +173,6 @@
     renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
 }
 
-static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawOval(left, top, right, bottom, paint);
-}
-
-static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
-}
-
 static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -512,7 +183,7 @@
         SkRegion::Iterator it(*region);
         while (!it.done()) {
             const SkIRect& r = it.rect();
-            renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
+            renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, *paint);
             it.next();
         }
     } else {
@@ -532,236 +203,6 @@
     }
 }
 
-static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    jfloat* storage = env->GetFloatArrayElements(points, NULL);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawPoints(storage + offset, count, paint);
-    env->ReleaseFloatArrayElements(points, storage, 0);
-}
-
-static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawPath(path, paint);
-}
-
-static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    jfloat* storage = env->GetFloatArrayElements(points, NULL);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    renderer->drawLines(storage + offset, count, paint);
-    env->ReleaseFloatArrayElements(points, storage, 0);
-}
-
-// ----------------------------------------------------------------------------
-// Draw filters
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_setDrawFilter(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong filterPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkDrawFilter* filter = reinterpret_cast<SkDrawFilter*>(filterPtr);
-    renderer->setDrawFilter(filter);
-}
-
-// ----------------------------------------------------------------------------
-// Text
-// ----------------------------------------------------------------------------
-
-class RenderTextFunctor {
-public:
-    RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
-                Paint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
-                uirenderer::Rect& bounds)
-            : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
-            pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
-    void operator()(size_t start, size_t end) {
-        for (size_t i = start; i < end; i++) {
-            glyphs[i] = layout.getGlyphId(i);
-            pos[2 * i] = layout.getX(i);
-            pos[2 * i + 1] = layout.getY(i);
-        }
-        size_t glyphsCount = end - start;
-        int bytesCount = glyphsCount * sizeof(jchar);
-        renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
-            x, y, pos + 2 * start, paint, totalAdvance, bounds);
-    }
-private:
-    const Layout& layout;
-    DisplayListRenderer* renderer;
-    jfloat x;
-    jfloat y;
-    Paint* paint;
-    uint16_t* glyphs;
-    float* pos;
-    float totalAdvance;
-    uirenderer::Rect& bounds;
-};
-
-static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
-    jfloat x, jfloat y, Paint* paint) {
-    size_t nGlyphs = layout->nGlyphs();
-    float* pos = new float[nGlyphs * 2];
-    uint16_t* glyphs = new uint16_t[nGlyphs];
-    MinikinRect b;
-    layout->getBounds(&b);
-    android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
-    bounds.translate(x, y);
-    float totalAdvance = layout->getAdvance();
-
-    RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
-    MinikinUtils::forFontRun(*layout, paint, f);
-    delete[] glyphs;
-    delete[] pos;
-}
-
-static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
-        jfloat x, jfloat y, int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
-    Layout layout;
-    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
-    x += MinikinUtils::xOffsetForTextAlign(paint, layout);
-    renderTextLayout(renderer, &layout, x, y, paint);
-}
-
-class RenderTextOnPathFunctor {
-public:
-    RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
-                float vOffset, Paint* paint, SkPath* path)
-            : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
-                paint(paint), path(path) {
-    }
-    void operator()(size_t start, size_t end) {
-        uint16_t glyphs[1];
-        for (size_t i = start; i < end; i++) {
-            glyphs[0] = layout.getGlyphId(i);
-            float x = hOffset + layout.getX(i);
-            float y = vOffset + layout.getY(i);
-            renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
-        }
-    }
-private:
-    const Layout& layout;
-    DisplayListRenderer* renderer;
-    float hOffset;
-    float vOffset;
-    Paint* paint;
-    SkPath* path;
-};
-
-static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
-        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, Paint* paint,
-        TypefaceImpl* typeface) {
-    Layout layout;
-    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
-    hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
-    Paint::Align align = paint->getTextAlign();
-    paint->setTextAlign(Paint::kLeft_Align);
-
-    RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
-    MinikinUtils::forFontRun(layout, paint, f);
-    paint->setTextAlign(align);
-}
-
-static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
-        jint start, jint count, jint contextCount, jfloat x, jfloat y,
-        int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
-    Layout layout;
-    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount);
-    x += MinikinUtils::xOffsetForTextAlign(paint, layout);
-    renderTextLayout(renderer, &layout, x, y, paint);
-}
-
-static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jcharArray text, jint index, jint count,
-        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    jchar* textArray = env->GetCharArrayElements(text, NULL);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
-
-    renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
-    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
-}
-
-static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jstring text, jint start, jint end,
-        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const jchar* textArray = env->GetStringChars(text, NULL);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
-
-    renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
-    env->ReleaseStringChars(text, textArray);
-}
-
-static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jcharArray text, jint index, jint count,
-        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
-        jlong typefacePtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    jchar* textArray = env->GetCharArrayElements(text, NULL);
-    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
-
-    renderTextOnPath(renderer, textArray + index, count, path,
-            hOffset, vOffset, bidiFlags, paint, typeface);
-    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
-}
-
-static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jstring text, jint start, jint end,
-        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
-        jlong typefacePtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const jchar* textArray = env->GetStringChars(text, NULL);
-    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
-
-    renderTextOnPath(renderer, textArray + start, end - start, path,
-            hOffset, vOffset, bidiFlags, paint, typeface);
-    env->ReleaseStringChars(text, textArray);
-}
-
-static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jcharArray text, jint index, jint count,
-        jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
-        jlong paintPtr, jlong typefacePtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    jchar* textArray = env->GetCharArrayElements(text, NULL);
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
-
-    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
-    renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
-            count, contextCount, x, y, bidiFlags, paint, typeface);
-    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
- }
-
-static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jstring text, jint start, jint end,
-        jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
-        jlong paintPtr, jlong typefacePtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    const jchar* textArray = env->GetStringChars(text, NULL);
-    jint count = end - start;
-    jint contextCount = contextEnd - contextStart;
-    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
-    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
-
-    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
-    renderTextRun(renderer, textArray + contextStart, start - contextStart,
-            count, contextCount, x, y, bidiFlags, paint, typeface);
-    env->ReleaseStringChars(text, textArray);
-}
-
 // ----------------------------------------------------------------------------
 // Display lists
 // ----------------------------------------------------------------------------
@@ -830,88 +271,29 @@
 
 static JNINativeMethod gMethods[] = {
     { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
-    { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
     { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
     { "nSetHighContrastText","(JZ)V",          (void*) android_view_GLES20Canvas_setHighContrastText },
     { "nInsertReorderBarrier","(JZ)V",         (void*) android_view_GLES20Canvas_insertReorderBarrier },
-    { "nPrepare",           "(JZ)V",           (void*) android_view_GLES20Canvas_prepare },
-    { "nPrepareDirty",      "(JIIIIZ)V",       (void*) android_view_GLES20Canvas_prepareDirty },
+    { "nPrepare",           "(J)V",            (void*) android_view_GLES20Canvas_prepare },
+    { "nPrepareDirty",      "(JIIII)V",        (void*) android_view_GLES20Canvas_prepareDirty },
     { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
-    { "nSetProperty",           "(Ljava/lang/String;Ljava/lang/String;)V",
+    { "nSetProperty",       "(Ljava/lang/String;Ljava/lang/String;)V",
             (void*) android_view_GLES20Canvas_setProperty },
 
     { "nCallDrawGLFunction", "(JJ)V",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
 
-    { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
-    { "nRestore",           "(J)V",            (void*) android_view_GLES20Canvas_restore },
-    { "nRestoreToCount",    "(JI)V",           (void*) android_view_GLES20Canvas_restoreToCount },
-    { "nGetSaveCount",      "(J)I",            (void*) android_view_GLES20Canvas_getSaveCount },
+    { "nDrawPatch",         "(JJJFFFFJ)V",     (void*) android_view_GLES20Canvas_drawPatch },
 
-    { "nSaveLayer",         "(JFFFFJI)I",      (void*) android_view_GLES20Canvas_saveLayer },
-    { "nSaveLayer",         "(JJI)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
-    { "nSaveLayerAlpha",    "(JFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
-    { "nSaveLayerAlpha",    "(JII)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
-
-    { "nQuickReject",       "(JFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
-    { "nClipRect",          "(JFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
-    { "nClipRect",          "(JIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
-    { "nClipPath",          "(JJI)Z",          (void*) android_view_GLES20Canvas_clipPath },
-    { "nClipRegion",        "(JJI)Z",          (void*) android_view_GLES20Canvas_clipRegion },
-
-    { "nTranslate",         "(JFF)V",          (void*) android_view_GLES20Canvas_translate },
-    { "nRotate",            "(JF)V",           (void*) android_view_GLES20Canvas_rotate },
-    { "nScale",             "(JFF)V",          (void*) android_view_GLES20Canvas_scale },
-    { "nSkew",              "(JFF)V",          (void*) android_view_GLES20Canvas_skew },
-
-    { "nSetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_setMatrix },
-    { "nGetMatrix",         "(JJ)V",           (void*) android_view_GLES20Canvas_getMatrix },
-    { "nConcatMatrix",      "(JJ)V",           (void*) android_view_GLES20Canvas_concatMatrix },
-
-    { "nDrawBitmap",        "(JJFFJ)V",      (void*) android_view_GLES20Canvas_drawBitmap },
-    { "nDrawBitmap",        "(JJFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
-    { "nDrawBitmap",        "(JJJJ)V",       (void*) android_view_GLES20Canvas_drawBitmapMatrix },
-    { "nDrawBitmap",        "(J[IIIFFIIZJ)V",  (void*) android_view_GLES20Canvas_drawBitmapData },
-
-    { "nDrawBitmapMesh",    "(JJII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
-
-    { "nDrawPatch",         "(JJJFFFFJ)V",   (void*) android_view_GLES20Canvas_drawPatch },
-
-    { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
-    { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
     { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
-    { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
     { "nDrawRoundRect",     "(JJJJJJJJ)V",     (void*) android_view_GLES20Canvas_drawRoundRectProps },
-    { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
     { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
-    { "nDrawOval",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawOval },
-    { "nDrawArc",           "(JFFFFFFZJ)V",    (void*) android_view_GLES20Canvas_drawArc },
-    { "nDrawPoints",        "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawPoints },
-
-    { "nDrawPath",          "(JJJ)V",          (void*) android_view_GLES20Canvas_drawPath },
-    { "nDrawLines",         "(J[FIIJ)V",       (void*) android_view_GLES20Canvas_drawLines },
-
-    { "nSetDrawFilter",     "(JJ)V",           (void*) android_view_GLES20Canvas_setDrawFilter },
-
-    { "nDrawText",          "(J[CIIFFIJJ)V",   (void*) android_view_GLES20Canvas_drawTextArray },
-    { "nDrawText",          "(JLjava/lang/String;IIFFIJJ)V",
-            (void*) android_view_GLES20Canvas_drawText },
-
-    { "nDrawTextOnPath",    "(J[CIIJFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
-    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJJ)V",
-            (void*) android_view_GLES20Canvas_drawTextOnPath },
-
-    { "nDrawTextRun",       "(J[CIIIIFFZJJ)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
-    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFZJJ)V",
-            (void*) android_view_GLES20Canvas_drawTextRun },
-
-    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
 
     { "nFinishRecording",   "(J)J",            (void*) android_view_GLES20Canvas_finishRecording },
     { "nDrawRenderNode",    "(JJI)V",          (void*) android_view_GLES20Canvas_drawRenderNode },
 
     { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
 
-    { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
+    { "nDrawLayer",               "(JJFF)V",   (void*) android_view_GLES20Canvas_drawLayer },
 
     { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
     { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index a0267c8..2a7e177 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -44,8 +44,12 @@
  */
 public class Canvas {
 
-    // assigned in constructors or setBitmap, freed in finalizer
-    private long mNativeCanvasWrapper;
+    /**
+     * Should only be assigned in constructors (or setBitmap if software canvas),
+     * freed in finalizer.
+     * @hide
+     */
+    protected long mNativeCanvasWrapper;
 
     /** @hide */
     public long getNativeCanvasWrapper() {
@@ -1619,6 +1623,9 @@
             int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
             @NonNull Paint paint) {
         checkRange(verts.length, vertOffset, vertexCount);
+        if (isHardwareAccelerated()) {
+            return;
+        }
         if (texs != null) {
             checkRange(texs.length, texOffset, vertexCount);
         }
diff --git a/include/private/graphics/Canvas.h b/include/private/graphics/Canvas.h
index 2eda6a4..ae79907 100644
--- a/include/private/graphics/Canvas.h
+++ b/include/private/graphics/Canvas.h
@@ -131,15 +131,23 @@
             const float* vertices, const int* colors, const SkPaint* paint) = 0;
 
     // Text
-    virtual void drawText(const uint16_t* text, const float* positions, int count,
+    /**
+     * drawText: count is of glyphs
+     * totalAdvance is ignored in software renderering, used by hardware renderer for
+     * text decorations (underlines, strikethroughs).
+     */
+    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) = 0;
+            float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
+            float totalAdvance) = 0;
+    /** drawPosText: count is of UTF16 characters, posCount is floats (2 * glyphs) */
     virtual void drawPosText(const uint16_t* text, const float* positions, int count,
             int posCount, const SkPaint& paint) = 0;
+    /** drawTextOnPath: count is of glyphs */
     virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
             float hOffset, float vOffset, const SkPaint& paint) = 0;
 
-    /*
+    /**
      * Specifies if the positions passed to ::drawText are absolute or relative
      * to the (x,y) value provided.
      *
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 */