GLES20Canvas.java revision cce47eb580d666ead1f6095d1e3b65233592bbaa
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/*
2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2010 The Android Open Source Project
3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * you may not use this file except in compliance with the License.
6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * You may obtain a copy of the License at
7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software
11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * See the License for the specific language governing permissions and
14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * limitations under the License.
15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
17e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guypackage android.view;
18e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Bitmap;
20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Canvas;
2152244fff29042926e21fa897ef5ab11148e35299John Reckimport android.graphics.CanvasProperty;
22e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.DrawFilter;
23e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Matrix;
243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyimport android.graphics.NinePatch;
25e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Paint;
265ff9df658230d49e42c43586997a02d8e4dd417eRomain Guyimport android.graphics.PaintFlagsDrawFilter;
27e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Path;
28e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Picture;
29e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.PorterDuff;
30e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Rect;
31e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.RectF;
32e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Region;
33d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guyimport android.graphics.Shader;
34a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.graphics.TemporaryBuffer;
35a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.GraphicsOperations;
36a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.SpannableString;
37a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.SpannedString;
38a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.TextUtils;
39e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
40e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/**
41e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * An implementation of Canvas on top of OpenGL ES 2.0.
42e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
43b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guyclass GLES20Canvas extends HardwareCanvas {
44e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private final boolean mOpaque;
4544fd8d24f761f82d21e9b00932648a1b6bf91449John Reck    protected long mRenderer;
46f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy
47f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    // The native renderer will be destroyed when this object dies.
48f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    // DO NOT overwrite this reference once it is set.
49eea60692b060737faeaa02bb30f5b79e2202b482Romain Guy    @SuppressWarnings({"unused", "FieldCanBeLocal"})
50f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    private CanvasFinalizer mFinalizer;
51f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy
52e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private int mWidth;
53e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private int mHeight;
54051910b9f998030dacb8a0722588cc715813fde1Raph Levien
556410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] mPoint;
566410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] mLine;
57051910b9f998030dacb8a0722588cc715813fde1Raph Levien
586410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private Rect mClipBounds;
596410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private RectF mPathBounds;
606926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy
616926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    private DrawFilter mFilter;
62da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
63163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    ///////////////////////////////////////////////////////////////////////////
64163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    // JNI
65163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    ///////////////////////////////////////////////////////////////////////////
66163935113919a184122b8b3bd672ef08c8df65dcRomain Guy
67163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    private static native boolean nIsAvailable();
68163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    private static boolean sIsAvailable = nIsAvailable();
69163935113919a184122b8b3bd672ef08c8df65dcRomain Guy
70163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    static boolean isAvailable() {
71163935113919a184122b8b3bd672ef08c8df65dcRomain Guy        return sIsAvailable;
72163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    }
73e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
74e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
75e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Constructors
76e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
77b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
7884a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    // TODO: Merge with GLES20RecordingCanvas
7984a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck    protected GLES20Canvas() {
8084a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck        mOpaque = false;
8184a4c887a07c1c2939443f4e0587d7f1ac109e4bJohn Reck        mRenderer = nCreateDisplayListRenderer();
826c319ca1275c8db892c39b48fc54864c949f9171Romain Guy        setupFinalizer();
836c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
846c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
856c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    private void setupFinalizer() {
86fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        if (mRenderer == 0) {
87fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            throw new IllegalStateException("Could not create GLES20Canvas renderer");
885c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        } else {
89162a0217563f4665da6eb183dfce0fef740f641fJeff Brown            mFinalizer = new CanvasFinalizer(mRenderer);
90fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        }
91e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
92b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
9336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native long nCreateDisplayListRenderer();
9436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResetDisplayListRenderer(long renderer);
9536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDestroyRenderer(long renderer);
965c13d89c1332fcc499379b9064b891187b75ca32Chet Haase
97162a0217563f4665da6eb183dfce0fef740f641fJeff Brown    private static final class CanvasFinalizer {
9836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        private final long mRenderer;
995977baa1fa24125c148a72699b53e62abaf08960Chet Haase
10036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        public CanvasFinalizer(long renderer) {
101f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy            mRenderer = renderer;
1025c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        }
1035c13d89c1332fcc499379b9064b891187b75ca32Chet Haase
1045c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        @Override
105f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy        protected void finalize() throws Throwable {
106171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy            try {
107162a0217563f4665da6eb183dfce0fef740f641fJeff Brown                nDestroyRenderer(mRenderer);
108171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy            } finally {
109171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy                super.finalize();
110171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy            }
111e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        }
112e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
113ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
114ba9b613437c34873fa95800a25fc51720638267cChris Craik    public static void setProperty(String name, String value) {
115ba9b613437c34873fa95800a25fc51720638267cChris Craik        nSetProperty(name, value);
116ba9b613437c34873fa95800a25fc51720638267cChris Craik    }
117ba9b613437c34873fa95800a25fc51720638267cChris Craik
118ba9b613437c34873fa95800a25fc51720638267cChris Craik    private static native void nSetProperty(String name, String value);
119ba9b613437c34873fa95800a25fc51720638267cChris Craik
120e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
121e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Canvas management
122e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
123e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
124e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
125e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean isOpaque() {
126e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mOpaque;
127e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
128e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
129e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
130e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getWidth() {
131e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mWidth;
132e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
133e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
134e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
135e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getHeight() {
136e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mHeight;
137e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
138e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
139f61970fc79e9c5cf340fa942597628242361864aRomain Guy    @Override
140f61970fc79e9c5cf340fa942597628242361864aRomain Guy    public int getMaximumBitmapWidth() {
141f61970fc79e9c5cf340fa942597628242361864aRomain Guy        return nGetMaximumTextureWidth();
142f61970fc79e9c5cf340fa942597628242361864aRomain Guy    }
143f61970fc79e9c5cf340fa942597628242361864aRomain Guy
144f61970fc79e9c5cf340fa942597628242361864aRomain Guy    @Override
145f61970fc79e9c5cf340fa942597628242361864aRomain Guy    public int getMaximumBitmapHeight() {
146f61970fc79e9c5cf340fa942597628242361864aRomain Guy        return nGetMaximumTextureHeight();
147f61970fc79e9c5cf340fa942597628242361864aRomain Guy    }
148f61970fc79e9c5cf340fa942597628242361864aRomain Guy
149f61970fc79e9c5cf340fa942597628242361864aRomain Guy    private static native int nGetMaximumTextureWidth();
150530041d3191ce817832a0108514617768e43cda6Romain Guy    private static native int nGetMaximumTextureHeight();
151f61970fc79e9c5cf340fa942597628242361864aRomain Guy
1522bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy    /**
1532bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy     * Returns the native OpenGLRenderer object.
1542bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy     */
15536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    long getRenderer() {
1562bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy        return mRenderer;
1572bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy    }
1582bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy
159e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
160e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Setup
161e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
162e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
163e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
164e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setViewport(int width, int height) {
165e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mWidth = width;
166e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mHeight = height;
167e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
168e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        nSetViewport(mRenderer, width, height);
169e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
170051910b9f998030dacb8a0722588cc715813fde1Raph Levien
171cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik    private static native void nSetViewport(long renderer,
172cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik            int width, int height);
173cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik
174cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik    @Override
175cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik    public void setHighContrastText(boolean highContrastText) {
176cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik        nSetHighContrastText(mRenderer, highContrastText);
177cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik    }
178cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik
179cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik    private static native void nSetHighContrastText(long renderer, boolean highContrastText);
180e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
181b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
18244b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase    public int onPreDraw(Rect dirty) {
1837d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        if (dirty != null) {
18444b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
18544b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase                    mOpaque);
1867d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        } else {
18744b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return nPrepare(mRenderer, mOpaque);
1887d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        }
189e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
190b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
19136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nPrepare(long renderer, boolean opaque);
19236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nPrepareDirty(long renderer, int left, int top, int right, int bottom,
1937d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            boolean opaque);
194e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
195b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
196b35ab7b72967adcfd01cec483a705dafe8b951d1Gilles Debunne    public void onPostDraw() {
197b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        nFinish(mRenderer);
198b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
1999ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy
20036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nFinish(long renderer);
201b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
202530041d3191ce817832a0108514617768e43cda6Romain Guy    ///////////////////////////////////////////////////////////////////////////
203530041d3191ce817832a0108514617768e43cda6Romain Guy    // Functor
204530041d3191ce817832a0108514617768e43cda6Romain Guy    ///////////////////////////////////////////////////////////////////////////
205530041d3191ce817832a0108514617768e43cda6Romain Guy
206da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    @Override
20736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    public int callDrawGLFunction(long drawGLFunction) {
208daf98e941e140e8739458126640183b9f296a2abChet Haase        return nCallDrawGLFunction(mRenderer, drawGLFunction);
209daf98e941e140e8739458126640183b9f296a2abChet Haase    }
210daf98e941e140e8739458126640183b9f296a2abChet Haase
21136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nCallDrawGLFunction(long renderer, long drawGLFunction);
212daf98e941e140e8739458126640183b9f296a2abChet Haase
213bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    ///////////////////////////////////////////////////////////////////////////
214b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    // Display list
215b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    ///////////////////////////////////////////////////////////////////////////
216b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
21744fd8d24f761f82d21e9b00932648a1b6bf91449John Reck    protected static native long nFinishRecording(long renderer);
21865b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy
21952036b19a5f82bc4d75cfcbff99c65df8d25a99bRomain Guy    @Override
220a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    public int drawRenderNode(RenderNode renderNode, Rect dirty, int flags) {
221a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik        return nDrawRenderNode(mRenderer, renderNode.getNativeDisplayList(), dirty, flags);
222b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
223b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
224a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    private static native int nDrawRenderNode(long renderer, long renderNode,
2251271e2cc80b01d577e9db339459ef0222bb9320dChet Haase            Rect dirty, int flags);
226da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
227e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
2286c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    // Hardware layer
2296c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
230051910b9f998030dacb8a0722588cc715813fde1Raph Levien
231ada830f639591b99c3e40de22b07296c7932a33fRomain Guy    void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
232a4e16c58c9e3c983251e0475125a2a6f5bec2dbfChris Craik        layer.setLayerPaint(paint);
23304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        nDrawLayer(mRenderer, layer.getLayer(), x, y);
2346c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
2356c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
23636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawLayer(long renderer, long layer, float x, float y);
237aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
2386c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
2396410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    // Support
2406410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    ///////////////////////////////////////////////////////////////////////////
2416410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2426410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private Rect getInternalClipBounds() {
2436410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mClipBounds == null) mClipBounds = new Rect();
2446410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mClipBounds;
2456410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2466410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2476410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2486410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private RectF getPathBounds() {
2496410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mPathBounds == null) mPathBounds = new RectF();
2506410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mPathBounds;
2516410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2526410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2536410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] getPointStorage() {
2546410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mPoint == null) mPoint = new float[2];
2556410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mPoint;
2566410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2576410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2586410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] getLineStorage() {
2596410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mLine == null) mLine = new float[4];
2606410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mLine;
2616410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2626410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2636410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    ///////////////////////////////////////////////////////////////////////////
264e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Clipping
265e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
266e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
267e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
268e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path) {
269735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
270e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
271e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
272e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
273e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path, Region.Op op) {
274735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
275e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
276e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
27736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipPath(long renderer, long path, int op);
278735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy
279e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
280e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom) {
281079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
282e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
283051910b9f998030dacb8a0722588cc715813fde1Raph Levien
28436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRect(long renderer, float left, float top,
285079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            float right, float bottom, int op);
286e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
287e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
288e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
289079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
290e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
291e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
292e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
293e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(int left, int top, int right, int bottom) {
294daf98e941e140e8739458126640183b9f296a2abChet Haase        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
295e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
296051910b9f998030dacb8a0722588cc715813fde1Raph Levien
29736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRect(long renderer, int left, int top,
298735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy            int right, int bottom, int op);
299e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
300e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
301e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect) {
302079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
303051910b9f998030dacb8a0722588cc715813fde1Raph Levien                Region.Op.INTERSECT.nativeInt);
304e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
305e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
306e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
307e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect, Region.Op op) {
308079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
309e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
310e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
311e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
312e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect) {
313079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
314079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                Region.Op.INTERSECT.nativeInt);
315e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
316e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
317e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
318e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect, Region.Op op) {
319079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
320e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
321e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
322e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
323e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region) {
324735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
325e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
326e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
327e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
328e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region, Region.Op op) {
329735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
330e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
331e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
33236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRegion(long renderer, long region, int op);
333735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy
334e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
335e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean getClipBounds(Rect bounds) {
3369d5316e3f56d138504565ff311145ac01621dff4Romain Guy        return nGetClipBounds(mRenderer, bounds);
337e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
338e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
33936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nGetClipBounds(long renderer, Rect bounds);
3409d5316e3f56d138504565ff311145ac01621dff4Romain Guy
341e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
342e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
343ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger        return nQuickReject(mRenderer, left, top, right, bottom);
344e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
345051910b9f998030dacb8a0722588cc715813fde1Raph Levien
34636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nQuickReject(long renderer, float left, float top,
347ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger            float right, float bottom);
348e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
349e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
350e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(Path path, EdgeType type) {
3516410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        RectF pathBounds = getPathBounds();
3526410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        path.computeBounds(pathBounds, true);
3536410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
3546410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy                pathBounds.right, pathBounds.bottom);
355e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
356e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
357e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
358e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(RectF rect, EdgeType type) {
359ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
360e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
361e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
362e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
363e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Transformations
364e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
365e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
366e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
367e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void translate(float dx, float dy) {
368807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy        if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
369e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
370051910b9f998030dacb8a0722588cc715813fde1Raph Levien
37136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nTranslate(long renderer, float dx, float dy);
372e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
373e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
374e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void skew(float sx, float sy) {
375807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy        nSkew(mRenderer, sx, sy);
376e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
377e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
37836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSkew(long renderer, float sx, float sy);
379807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy
380e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
381e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void rotate(float degrees) {
382f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nRotate(mRenderer, degrees);
383e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
384051910b9f998030dacb8a0722588cc715813fde1Raph Levien
38536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRotate(long renderer, float degrees);
386e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
387e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
388e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void scale(float sx, float sy) {
389fe02b4b344c37200486d8afc972560fb550cb17eChris Craik        // TODO: remove
390fe02b4b344c37200486d8afc972560fb550cb17eChris Craik        if (sx > 1000000 || sy > 1000000) throw new IllegalArgumentException("invalid scales passed " + sx + ", " + sy);
391fe02b4b344c37200486d8afc972560fb550cb17eChris Craik
392f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nScale(mRenderer, sx, sy);
393e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
394051910b9f998030dacb8a0722588cc715813fde1Raph Levien
39536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nScale(long renderer, float sx, float sy);
396f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
397e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
398e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setMatrix(Matrix matrix) {
399e707859415f4c8e1c01228dfaa58fb0a690d442eRomain Guy        nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
400e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
401051910b9f998030dacb8a0722588cc715813fde1Raph Levien
40236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetMatrix(long renderer, long matrix);
403e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
4045ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    @SuppressWarnings("deprecation")
405e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
406f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    public void getMatrix(Matrix matrix) {
407f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nGetMatrix(mRenderer, matrix.native_instance);
408e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
409051910b9f998030dacb8a0722588cc715813fde1Raph Levien
41036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nGetMatrix(long renderer, long matrix);
411e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
412e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
413e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void concat(Matrix matrix) {
4144e7b772b733593fbe25c733e95b8dcea293234b6Romain Guy        if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
415e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
416051910b9f998030dacb8a0722588cc715813fde1Raph Levien
41736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nConcatMatrix(long renderer, long matrix);
418051910b9f998030dacb8a0722588cc715813fde1Raph Levien
419e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
420e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // State management
421e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
422e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
423e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
424e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save() {
4258aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
426e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
427051910b9f998030dacb8a0722588cc715813fde1Raph Levien
428e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
429e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save(int saveFlags) {
430bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nSave(mRenderer, saveFlags);
431e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
432e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
43336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSave(long renderer, int flags);
434051910b9f998030dacb8a0722588cc715813fde1Raph Levien
435e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
436e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
437189887e0ae171c1b7601991442104a30e56c50abRomain Guy        if (bounds != null) {
438189887e0ae171c1b7601991442104a30e56c50abRomain Guy            return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
439189887e0ae171c1b7601991442104a30e56c50abRomain Guy        }
440189887e0ae171c1b7601991442104a30e56c50abRomain Guy
44176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
44276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        return nSaveLayer(mRenderer, nativePaint, saveFlags);
443e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
444e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
44536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayer(long renderer, long paint, int saveFlags);
446189887e0ae171c1b7601991442104a30e56c50abRomain Guy
447e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
448e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
449e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
45001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (left < right && top < bottom) {
45176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
45276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger            return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
45301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
45401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return save(saveFlags);
455e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
456e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
45736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayer(long renderer, float left, float top,
45836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint, int saveFlags);
459bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
460e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
461e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
462189887e0ae171c1b7601991442104a30e56c50abRomain Guy        if (bounds != null) {
463189887e0ae171c1b7601991442104a30e56c50abRomain Guy            return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
464189887e0ae171c1b7601991442104a30e56c50abRomain Guy                    alpha, saveFlags);
465189887e0ae171c1b7601991442104a30e56c50abRomain Guy        }
466189887e0ae171c1b7601991442104a30e56c50abRomain Guy        return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
467e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
468e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
46936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags);
470189887e0ae171c1b7601991442104a30e56c50abRomain Guy
471e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
472e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
473e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
47401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (left < right && top < bottom) {
47501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
47601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
47701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return save(saveFlags);
478e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
479e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
48036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
481bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            float bottom, int alpha, int saveFlags);
482051910b9f998030dacb8a0722588cc715813fde1Raph Levien
483e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
484e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restore() {
485bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestore(mRenderer);
486e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
487051910b9f998030dacb8a0722588cc715813fde1Raph Levien
48836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRestore(long renderer);
489e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
490e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
491e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restoreToCount(int saveCount) {
492bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestoreToCount(mRenderer, saveCount);
493e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
494e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
49536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRestoreToCount(long renderer, int saveCount);
496051910b9f998030dacb8a0722588cc715813fde1Raph Levien
497e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
498e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getSaveCount() {
499bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nGetSaveCount(mRenderer);
500e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
501051910b9f998030dacb8a0722588cc715813fde1Raph Levien
50236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nGetSaveCount(long renderer);
503e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
504e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
505e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Filtering
506e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
507e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
508e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
509e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setDrawFilter(DrawFilter filter) {
5106926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        mFilter = filter;
5115ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        if (filter == null) {
5125ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            nResetPaintFilter(mRenderer);
5135ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        } else if (filter instanceof PaintFlagsDrawFilter) {
5145ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
5155ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
5165ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        }
517e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
518e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
51936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResetPaintFilter(long renderer);
52036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetupPaintFilter(long renderer, int clearBits, int setBits);
5215ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
522e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
523e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public DrawFilter getDrawFilter() {
5246926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        return mFilter;
525e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
526e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
527e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
528e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Drawing
529e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
530e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
531e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
53224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese    public void drawArc(float left, float top, float right, float bottom,
53324609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese            float startAngle, float sweepAngle, boolean useCenter, Paint paint) {
53424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese        nDrawArc(mRenderer, left, top, right, bottom,
535d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                startAngle, sweepAngle, useCenter, paint.mNativePaint);
536e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
537e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
53836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawArc(long renderer, float left, float top,
5397d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            float right, float bottom, float startAngle, float sweepAngle,
54036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            boolean useCenter, long paint);
5418b2f5267f16c295f12faab810527cd6311997e34Romain Guy
542e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
543e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawARGB(int a, int r, int g, int b) {
54485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
545e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
546e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
547e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
548f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
549f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        Bitmap bitmap = patch.getBitmap();
5501abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
55176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
55276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
55376d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
554f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    }
555f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy
556f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    @Override
5573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
5583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        Bitmap bitmap = patch.getBitmap();
5591abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
56076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
56176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
56276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
563deba785f122a47915756ffd991f5540d952cf937Romain Guy    }
564deba785f122a47915756ffd991f5540d952cf937Romain Guy
56536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPatch(long renderer, long bitmap, byte[] buffer, long chunk,
56636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, float right, float bottom, long paint);
567deba785f122a47915756ffd991f5540d952cf937Romain Guy
568deba785f122a47915756ffd991f5540d952cf937Romain Guy    @Override
569e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
5701abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
571d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
572d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
573e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
574e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
57536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
57636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, long paint);
577dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy
578e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
579e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
5801abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
581d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
582d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
583d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                matrix.native_instance, nativePaint);
584e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
585e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
58636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
58736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            long matrix, long paint);
588f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
589e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
590e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
5911abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
592d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
593694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy
594d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        int left, top, right, bottom;
595d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (src == null) {
596d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = top = 0;
597d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = bitmap.getWidth();
598d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = bitmap.getHeight();
599d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
600d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = src.left;
601d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = src.right;
602d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            top = src.top;
603d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = src.bottom;
604445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
605d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
606d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
607d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
608e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
609e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
610e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
611e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
6121abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
613d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
614d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
615d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        float left, top, right, bottom;
616d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (src == null) {
617d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = top = 0;
618d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = bitmap.getWidth();
619d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = bitmap.getHeight();
620d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
621d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = src.left;
622d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = src.right;
623d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            top = src.top;
624d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = src.bottom;
625ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy        }
626d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
627d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
628d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
629e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
630e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
63136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
632ce0537b80087a6225273040a987414b1dd081aa0Romain Guy            float srcLeft, float srcTop, float srcRight, float srcBottom,
63336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, float right, float bottom, long paint);
634ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
635e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
636e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
637e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
638e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (width < 0) {
639e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("width must be >= 0");
640e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
641e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
642e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (height < 0) {
643e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("height must be >= 0");
644e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
645e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
646e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (Math.abs(stride) < width) {
647e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("abs(stride) must be >= width");
648e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
649e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
650e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        int lastScanline = offset + (height - 1) * stride;
651e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        int length = colors.length;
652e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
653e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
654e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy                (lastScanline + width > length)) {
655e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new ArrayIndexOutOfBoundsException();
656e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
657e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
65876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
65976d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawBitmap(mRenderer, colors, offset, stride, x, y,
66076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                width, height, hasAlpha, nativePaint);
661e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
662e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
66336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
66436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float x, float y, int width, int height, boolean hasAlpha, long nativePaint);
665e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
666e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
667e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
668e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
669ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
670e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
671e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
672e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
673e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
674e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int vertOffset, int[] colors, int colorOffset, Paint paint) {
6751abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
6765a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
6775a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            throw new ArrayIndexOutOfBoundsException();
6785a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        }
6795a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
6805a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        if (meshWidth == 0 || meshHeight == 0) {
6815a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            return;
6825a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        }
6835a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
6845a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        final int count = (meshWidth + 1) * (meshHeight + 1);
6855a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        checkRange(verts.length, vertOffset, count * 2);
6865a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
687ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        if (colors != null) {
688ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy            checkRange(colors.length, colorOffset, count);
689ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        }
6905a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
691d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
692d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
693d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                verts, vertOffset, colors, colorOffset, nativePaint);
694e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
695e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
69636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer,
6975a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            int meshWidth, int meshHeight, float[] verts, int vertOffset,
69836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int[] colors, int colorOffset, long paint);
6995a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
700e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
701e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawCircle(float cx, float cy, float radius, Paint paint) {
702d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
703e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
704e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
70536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawCircle(long renderer, float cx, float cy,
70636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float radius, long paint);
70701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
708e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
70952244fff29042926e21fa897ef5ab11148e35299John Reck    public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
71052244fff29042926e21fa897ef5ab11148e35299John Reck            CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
71152244fff29042926e21fa897ef5ab11148e35299John Reck        nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
71252244fff29042926e21fa897ef5ab11148e35299John Reck                radius.getNativeContainer(), paint.getNativeContainer());
71352244fff29042926e21fa897ef5ab11148e35299John Reck    }
71452244fff29042926e21fa897ef5ab11148e35299John Reck
71552244fff29042926e21fa897ef5ab11148e35299John Reck    private static native void nDrawCircle(long renderer, long propCx,
71652244fff29042926e21fa897ef5ab11148e35299John Reck            long propCy, long propRadius, long propPaint);
71752244fff29042926e21fa897ef5ab11148e35299John Reck
71852244fff29042926e21fa897ef5ab11148e35299John Reck    @Override
719e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color) {
72085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(color, PorterDuff.Mode.SRC_OVER);
721e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
722e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
723e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
724e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color, PorterDuff.Mode mode) {
72585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        nDrawColor(mRenderer, color, mode.nativeInt);
726e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
727051910b9f998030dacb8a0722588cc715813fde1Raph Levien
72836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawColor(long renderer, int color, int mode);
729e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
730e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
731e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
7326410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        float[] line = getLineStorage();
7336410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[0] = startX;
7346410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[1] = startY;
7356410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[2] = stopX;
7366410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[3] = stopY;
7376410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        drawLines(line, 0, 4, paint);
738e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
739e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
740e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
741e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, int offset, int count, Paint paint) {
7425d11676414b3606792e23c269cf75b44faa1a2afChris Craik        if (count < 4) return;
7435d11676414b3606792e23c269cf75b44faa1a2afChris Craik
744759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        if ((offset | count) < 0 || offset + count > pts.length) {
745759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
746759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        }
747d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
748e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
749e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
75036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawLines(long renderer, float[] points,
75136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int offset, int count, long paint);
752759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
753e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
754e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, Paint paint) {
755759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        drawLines(pts, 0, pts.length, paint);
756e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
757e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
758e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
75924609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese    public void drawOval(float left, float top, float right, float bottom, Paint paint) {
76024609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese        nDrawOval(mRenderer, left, top, right, bottom, paint.mNativePaint);
761e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
762e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
76336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawOval(long renderer, float left, float top,
76436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint);
765c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
766e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
767e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPaint(Paint paint) {
7686410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        final Rect r = getInternalClipBounds();
7696926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        nGetClipBounds(mRenderer, r);
7706926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
771e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
772e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
773e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
774e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPath(Path path, Paint paint) {
775d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (path.isSimplePath) {
776d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            if (path.rects != null) {
777d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
778a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy            }
779d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
780d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
781a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy        }
782e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
783e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
78436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPath(long renderer, long path, long paint);
78536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRects(long renderer, long region, long paint);
7867fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy
787e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
788e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture) {
78975582e889d4895483309e38364266073be6d46b8Romain Guy        picture.endRecording();
79075582e889d4895483309e38364266073be6d46b8Romain Guy        // TODO: Implement rendering
791e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
792e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
793e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
794e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture, Rect dst) {
79575582e889d4895483309e38364266073be6d46b8Romain Guy        save();
79675582e889d4895483309e38364266073be6d46b8Romain Guy        translate(dst.left, dst.top);
79775582e889d4895483309e38364266073be6d46b8Romain Guy        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
79875582e889d4895483309e38364266073be6d46b8Romain Guy            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
79975582e889d4895483309e38364266073be6d46b8Romain Guy        }
80075582e889d4895483309e38364266073be6d46b8Romain Guy        drawPicture(picture);
80175582e889d4895483309e38364266073be6d46b8Romain Guy        restore();
802e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
803e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
804e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
805e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture, RectF dst) {
80675582e889d4895483309e38364266073be6d46b8Romain Guy        save();
80775582e889d4895483309e38364266073be6d46b8Romain Guy        translate(dst.left, dst.top);
80875582e889d4895483309e38364266073be6d46b8Romain Guy        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
80975582e889d4895483309e38364266073be6d46b8Romain Guy            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
81075582e889d4895483309e38364266073be6d46b8Romain Guy        }
81175582e889d4895483309e38364266073be6d46b8Romain Guy        drawPicture(picture);
81275582e889d4895483309e38364266073be6d46b8Romain Guy        restore();
813e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
814e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
815e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
816e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPoint(float x, float y, Paint paint) {
8176410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        float[] point = getPointStorage();
8186410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        point[0] = x;
8196410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        point[1] = y;
8206410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        drawPoints(point, 0, 2, paint);
821e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
822e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
823e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
824ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy    public void drawPoints(float[] pts, Paint paint) {
825ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy        drawPoints(pts, 0, pts.length, paint);
826e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
827e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
828e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
829ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
8305d11676414b3606792e23c269cf75b44faa1a2afChris Craik        if (count < 2) return;
8315d11676414b3606792e23c269cf75b44faa1a2afChris Craik
832d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
833e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
834e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
83536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPoints(long renderer, float[] points,
83636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int offset, int count, long paint);
837ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy
8383f0d6167227d6d2cdd85f7718d92db859b443e92Raph Levien    // Note: drawPosText just uses implementation in Canvas
839eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
840e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
841e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
842765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        if (left == right || top == bottom) return;
843d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
844e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
845e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
84636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRect(long renderer, float left, float top,
84736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint);
848c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
849e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
850e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(Rect r, Paint paint) {
851c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
852e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
853e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
854e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
855c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    public void drawRect(RectF r, Paint paint) {
856c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
857e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
858e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
859e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
860e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRGB(int r, int g, int b) {
86185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
862e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
863e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
864e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
8654d1c1538e2422d0a5b19ad1cd2fb353ed6279a88Chris Craik    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
8664d1c1538e2422d0a5b19ad1cd2fb353ed6279a88Chris Craik            Paint paint) {
867d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
868e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
869e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
87036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRoundRect(long renderer, float left, float top,
87136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, float rx, float y, long paint);
87201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
873e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
874e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
875a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((index | count | (index + count) | (text.length - index - count)) < 0) {
876a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
877a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
87861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
879d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawText(mRenderer, text, index, count, x, y,
880d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
881e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
882051910b9f998030dacb8a0722588cc715813fde1Raph Levien
88336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawText(long renderer, char[] text, int index, int count,
8841a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien            float x, float y, int bidiFlags, long paint, long typeface);
885e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
886e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
887e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
888d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (text instanceof String || text instanceof SpannedString ||
889d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                text instanceof SpannableString) {
890d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
891d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                    paint.mNativePaint, paint.mNativeTypeface);
892d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else if (text instanceof GraphicsOperations) {
893d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            ((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
894d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
895d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            char[] buf = TemporaryBuffer.obtain(end - start);
896d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TextUtils.getChars(text, start, end, buf, 0);
897d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawText(mRenderer, buf, 0, end - start, x, y,
898d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                    paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
899d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TemporaryBuffer.recycle(buf);
900a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
901e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
902e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
903e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
904e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
905a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((start | end | (end - start) | (text.length() - end)) < 0) {
906a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
907a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
90861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
909d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawText(mRenderer, text, start, end, x, y,
910d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
911e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
912e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
91336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawText(long renderer, String text, int start, int end,
9141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien            float x, float y, int bidiFlags, long paint, long typeface);
915a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
916e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
917e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, float x, float y, Paint paint) {
918d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawText(mRenderer, text, 0, text.length(), x, y,
919d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
920e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
921e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
922e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
923e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
924e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float vOffset, Paint paint) {
925325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        if (index < 0 || index + count > text.length) {
926325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            throw new ArrayIndexOutOfBoundsException();
927325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        }
928325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
929d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
9309d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
931e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
932e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
93336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
9349d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
9359d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long typeface);
936325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
937e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
938e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
939325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        if (text.length() == 0) return;
940325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
941d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
9429d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
943e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
944e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
94536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
9469d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
9479d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long typeface);
948325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
949e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
950e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
951051910b9f998030dacb8a0722588cc715813fde1Raph Levien            float x, float y, boolean isRtl, Paint paint) {
95261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((index | count | text.length - index - count) < 0) {
95361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
95461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
95561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
956051910b9f998030dacb8a0722588cc715813fde1Raph Levien        nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, isRtl,
957d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mNativePaint, paint.mNativeTypeface);
958e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
959e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
96036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
961051910b9f998030dacb8a0722588cc715813fde1Raph Levien            int contextIndex, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
96261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
963e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
964e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
965051910b9f998030dacb8a0722588cc715813fde1Raph Levien            float x, float y, boolean isRtl, Paint paint) {
96661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((start | end | end - start | text.length() - end) < 0) {
96761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
96861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
96961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
970d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (text instanceof String || text instanceof SpannedString ||
971d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                text instanceof SpannableString) {
972d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
973051910b9f998030dacb8a0722588cc715813fde1Raph Levien                    contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
974d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else if (text instanceof GraphicsOperations) {
975d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            ((GraphicsOperations) text).drawTextRun(this, start, end,
976051910b9f998030dacb8a0722588cc715813fde1Raph Levien                    contextStart, contextEnd, x, y, isRtl, paint);
977d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
978d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            int contextLen = contextEnd - contextStart;
979d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            int len = end - start;
980d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            char[] buf = TemporaryBuffer.obtain(contextLen);
981d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
982d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
983051910b9f998030dacb8a0722588cc715813fde1Raph Levien                    x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
984d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TemporaryBuffer.recycle(buf);
98561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
986e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
987e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
98836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextRun(long renderer, String text, int start, int end,
989051910b9f998030dacb8a0722588cc715813fde1Raph Levien            int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
99061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
991e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
992e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
993e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
994e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int indexOffset, int indexCount, Paint paint) {
9956926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        // TODO: Implement
996e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
997e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
998