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
1828afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    public void insertReorderBarrier() {
1838afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik        nInsertReorderBarrier(mRenderer, true);
1848afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    }
1858afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik
1868afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    @Override
1878afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    public void insertInorderBarrier() {
1888afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik        nInsertReorderBarrier(mRenderer, false);
1898afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    }
1908afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik
1918afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
1928afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik
1938afd0f245cc0c4a0366f39f41b5f78e47ee83be3Chris Craik    @Override
19444b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase    public int onPreDraw(Rect dirty) {
1957d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        if (dirty != null) {
19644b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
19744b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase                    mOpaque);
1987d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        } else {
19944b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return nPrepare(mRenderer, mOpaque);
2007d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        }
201e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
202b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
20336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nPrepare(long renderer, boolean opaque);
20436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nPrepareDirty(long renderer, int left, int top, int right, int bottom,
2057d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            boolean opaque);
206e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
207b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
208b35ab7b72967adcfd01cec483a705dafe8b951d1Gilles Debunne    public void onPostDraw() {
209b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        nFinish(mRenderer);
210b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
2119ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy
21236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nFinish(long renderer);
213b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
214530041d3191ce817832a0108514617768e43cda6Romain Guy    ///////////////////////////////////////////////////////////////////////////
215530041d3191ce817832a0108514617768e43cda6Romain Guy    // Functor
216530041d3191ce817832a0108514617768e43cda6Romain Guy    ///////////////////////////////////////////////////////////////////////////
217530041d3191ce817832a0108514617768e43cda6Romain Guy
218da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    @Override
219680df8d60e3445bd14df902796079d730c283c46John Reck    public int callDrawGLFunction2(long drawGLFunction) {
220daf98e941e140e8739458126640183b9f296a2abChet Haase        return nCallDrawGLFunction(mRenderer, drawGLFunction);
221daf98e941e140e8739458126640183b9f296a2abChet Haase    }
222daf98e941e140e8739458126640183b9f296a2abChet Haase
22336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nCallDrawGLFunction(long renderer, long drawGLFunction);
224daf98e941e140e8739458126640183b9f296a2abChet Haase
225bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    ///////////////////////////////////////////////////////////////////////////
226b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    // Display list
227b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    ///////////////////////////////////////////////////////////////////////////
228b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
22944fd8d24f761f82d21e9b00932648a1b6bf91449John Reck    protected static native long nFinishRecording(long renderer);
23065b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy
23152036b19a5f82bc4d75cfcbff99c65df8d25a99bRomain Guy    @Override
232a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    public int drawRenderNode(RenderNode renderNode, Rect dirty, int flags) {
233a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik        return nDrawRenderNode(mRenderer, renderNode.getNativeDisplayList(), dirty, flags);
234b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
235b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
236a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    private static native int nDrawRenderNode(long renderer, long renderNode,
2371271e2cc80b01d577e9db339459ef0222bb9320dChet Haase            Rect dirty, int flags);
238da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
239e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
2406c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    // Hardware layer
2416c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
242051910b9f998030dacb8a0722588cc715813fde1Raph Levien
243ada830f639591b99c3e40de22b07296c7932a33fRomain Guy    void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
244a4e16c58c9e3c983251e0475125a2a6f5bec2dbfChris Craik        layer.setLayerPaint(paint);
24512f5e3433226f0a2886a98b0b8da8d5e947c5cdeJohn Reck        nDrawLayer(mRenderer, layer.getLayerHandle(), x, y);
2466c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
2476c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
24836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawLayer(long renderer, long layer, float x, float y);
249aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
2506c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
2516410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    // Support
2526410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    ///////////////////////////////////////////////////////////////////////////
2536410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2546410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private Rect getInternalClipBounds() {
2556410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mClipBounds == null) mClipBounds = new Rect();
2566410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mClipBounds;
2576410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2586410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2596410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2606410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private RectF getPathBounds() {
2616410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mPathBounds == null) mPathBounds = new RectF();
2626410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mPathBounds;
2636410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2646410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2656410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] getPointStorage() {
2666410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mPoint == null) mPoint = new float[2];
2676410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mPoint;
2686410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2696410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2706410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] getLineStorage() {
2716410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mLine == null) mLine = new float[4];
2726410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mLine;
2736410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
2746410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
2756410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    ///////////////////////////////////////////////////////////////////////////
276e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Clipping
277e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
278e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
279e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
280e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path) {
281735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
282e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
283e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
284e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
285e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path, Region.Op op) {
286735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
287e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
288e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
28936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipPath(long renderer, long path, int op);
290735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy
291e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
292e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom) {
293079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
294e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
295051910b9f998030dacb8a0722588cc715813fde1Raph Levien
29636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRect(long renderer, float left, float top,
297079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            float right, float bottom, int op);
298e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
299e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
300e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
301079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
302e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
303e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
304e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
305e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(int left, int top, int right, int bottom) {
306daf98e941e140e8739458126640183b9f296a2abChet Haase        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
307e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
308051910b9f998030dacb8a0722588cc715813fde1Raph Levien
30936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRect(long renderer, int left, int top,
310735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy            int right, int bottom, int op);
311e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
312e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
313e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect) {
314079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
315051910b9f998030dacb8a0722588cc715813fde1Raph Levien                Region.Op.INTERSECT.nativeInt);
316e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
317e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
318e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
319e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect, Region.Op op) {
320079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
321e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
322e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
323e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
324e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect) {
325079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
326079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                Region.Op.INTERSECT.nativeInt);
327e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
328e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
329e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
330e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect, Region.Op op) {
331079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
332e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
333e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
334e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
335e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region) {
336735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
337e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
338e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
339e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
340e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region, Region.Op op) {
341735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
342e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
343e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
34436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRegion(long renderer, long region, int op);
345735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy
346e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
347e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean getClipBounds(Rect bounds) {
3489d5316e3f56d138504565ff311145ac01621dff4Romain Guy        return nGetClipBounds(mRenderer, bounds);
349e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
350e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
35136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nGetClipBounds(long renderer, Rect bounds);
3529d5316e3f56d138504565ff311145ac01621dff4Romain Guy
353e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
354e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
355ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger        return nQuickReject(mRenderer, left, top, right, bottom);
356e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
357051910b9f998030dacb8a0722588cc715813fde1Raph Levien
35836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nQuickReject(long renderer, float left, float top,
359ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger            float right, float bottom);
360e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
361e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
362e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(Path path, EdgeType type) {
3636410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        RectF pathBounds = getPathBounds();
3646410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        path.computeBounds(pathBounds, true);
3656410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
3666410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy                pathBounds.right, pathBounds.bottom);
367e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
368e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
369e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
370e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(RectF rect, EdgeType type) {
371ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
372e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
373e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
374e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
375e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Transformations
376e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
377e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
378e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
379e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void translate(float dx, float dy) {
380807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy        if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
381e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
382051910b9f998030dacb8a0722588cc715813fde1Raph Levien
38336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nTranslate(long renderer, float dx, float dy);
384e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
385e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
386e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void skew(float sx, float sy) {
387807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy        nSkew(mRenderer, sx, sy);
388e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
389e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
39036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSkew(long renderer, float sx, float sy);
391807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy
392e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
393e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void rotate(float degrees) {
394f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nRotate(mRenderer, degrees);
395e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
396051910b9f998030dacb8a0722588cc715813fde1Raph Levien
39736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRotate(long renderer, float degrees);
398e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
399e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
400e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void scale(float sx, float sy) {
401f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nScale(mRenderer, sx, sy);
402e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
403051910b9f998030dacb8a0722588cc715813fde1Raph Levien
40436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nScale(long renderer, float sx, float sy);
405f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
406e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
407e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setMatrix(Matrix matrix) {
408e707859415f4c8e1c01228dfaa58fb0a690d442eRomain Guy        nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
409e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
410051910b9f998030dacb8a0722588cc715813fde1Raph Levien
41136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetMatrix(long renderer, long matrix);
412e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
4135ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    @SuppressWarnings("deprecation")
414e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
415f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    public void getMatrix(Matrix matrix) {
416f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nGetMatrix(mRenderer, matrix.native_instance);
417e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
418051910b9f998030dacb8a0722588cc715813fde1Raph Levien
41936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nGetMatrix(long renderer, long matrix);
420e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
421e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
422e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void concat(Matrix matrix) {
4234e7b772b733593fbe25c733e95b8dcea293234b6Romain Guy        if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
424e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
425051910b9f998030dacb8a0722588cc715813fde1Raph Levien
42636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nConcatMatrix(long renderer, long matrix);
427051910b9f998030dacb8a0722588cc715813fde1Raph Levien
428e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
429e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // State management
430e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
431e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
432e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
433e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save() {
4348aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
435e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
436051910b9f998030dacb8a0722588cc715813fde1Raph Levien
437e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
438e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save(int saveFlags) {
439bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nSave(mRenderer, saveFlags);
440e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
441e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
44236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSave(long renderer, int flags);
443051910b9f998030dacb8a0722588cc715813fde1Raph Levien
444e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
445e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
446189887e0ae171c1b7601991442104a30e56c50abRomain Guy        if (bounds != null) {
447189887e0ae171c1b7601991442104a30e56c50abRomain Guy            return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
448189887e0ae171c1b7601991442104a30e56c50abRomain Guy        }
449189887e0ae171c1b7601991442104a30e56c50abRomain Guy
45076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
45176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        return nSaveLayer(mRenderer, nativePaint, saveFlags);
452e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
453e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
45436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayer(long renderer, long paint, int saveFlags);
455189887e0ae171c1b7601991442104a30e56c50abRomain Guy
456e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
457e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
458e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
45901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (left < right && top < bottom) {
46076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
46176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger            return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
46201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
46301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return save(saveFlags);
464e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
465e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
46636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayer(long renderer, float left, float top,
46736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint, int saveFlags);
468bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
469e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
470e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
471189887e0ae171c1b7601991442104a30e56c50abRomain Guy        if (bounds != null) {
472189887e0ae171c1b7601991442104a30e56c50abRomain Guy            return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
473189887e0ae171c1b7601991442104a30e56c50abRomain Guy                    alpha, saveFlags);
474189887e0ae171c1b7601991442104a30e56c50abRomain Guy        }
475189887e0ae171c1b7601991442104a30e56c50abRomain Guy        return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
476e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
477e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
47836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags);
479189887e0ae171c1b7601991442104a30e56c50abRomain Guy
480e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
481e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
482e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
48301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (left < right && top < bottom) {
48401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
48501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
48601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return save(saveFlags);
487e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
488e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
48936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
490bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            float bottom, int alpha, int saveFlags);
491051910b9f998030dacb8a0722588cc715813fde1Raph Levien
492e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
493e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restore() {
494bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestore(mRenderer);
495e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
496051910b9f998030dacb8a0722588cc715813fde1Raph Levien
49736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRestore(long renderer);
498e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
499e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
500e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restoreToCount(int saveCount) {
501bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestoreToCount(mRenderer, saveCount);
502e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
503e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
50436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRestoreToCount(long renderer, int saveCount);
505051910b9f998030dacb8a0722588cc715813fde1Raph Levien
506e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
507e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getSaveCount() {
508bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nGetSaveCount(mRenderer);
509e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
510051910b9f998030dacb8a0722588cc715813fde1Raph Levien
51136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nGetSaveCount(long renderer);
512e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
513e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
514e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Filtering
515e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
516e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
517e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
518e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setDrawFilter(DrawFilter filter) {
5196926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        mFilter = filter;
5205ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        if (filter == null) {
5215ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            nResetPaintFilter(mRenderer);
5225ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        } else if (filter instanceof PaintFlagsDrawFilter) {
5235ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
5245ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
5255ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        }
526e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
527e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
52836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResetPaintFilter(long renderer);
52936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetupPaintFilter(long renderer, int clearBits, int setBits);
5305ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
531e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
532e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public DrawFilter getDrawFilter() {
5336926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        return mFilter;
534e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
535e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
536e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
537e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Drawing
538e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
539e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
540e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
54124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese    public void drawArc(float left, float top, float right, float bottom,
54224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese            float startAngle, float sweepAngle, boolean useCenter, Paint paint) {
54324609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese        nDrawArc(mRenderer, left, top, right, bottom,
544d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                startAngle, sweepAngle, useCenter, paint.mNativePaint);
545e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
546e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
54736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawArc(long renderer, float left, float top,
5487d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            float right, float bottom, float startAngle, float sweepAngle,
54936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            boolean useCenter, long paint);
5508b2f5267f16c295f12faab810527cd6311997e34Romain Guy
551e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
552e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawARGB(int a, int r, int g, int b) {
55385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
554e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
555e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
556e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
557f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
558f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        Bitmap bitmap = patch.getBitmap();
5591abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
56076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
561f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
56276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
563f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    }
564f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy
565f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    @Override
5663b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
5673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        Bitmap bitmap = patch.getBitmap();
5681abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
56976d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
570f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
57176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
572deba785f122a47915756ffd991f5540d952cf937Romain Guy    }
573deba785f122a47915756ffd991f5540d952cf937Romain Guy
574f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger    private static native void nDrawPatch(long renderer, long bitmap, long chunk,
57536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, float right, float bottom, long paint);
576deba785f122a47915756ffd991f5540d952cf937Romain Guy
577deba785f122a47915756ffd991f5540d952cf937Romain Guy    @Override
578e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
5791abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
580d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
581f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
582e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
583e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
584f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger    private static native void nDrawBitmap(long renderer, long bitmap, float left,
585f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger            float top, long paint);
586dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy
587e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
588e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
5891abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
590d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
591f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
592e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
593e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
594f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger    private static native void nDrawBitmap(long renderer, long bitmap,
59536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            long matrix, long paint);
596f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
597e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
598e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
5991abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
600d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
601694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy
602d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        int left, top, right, bottom;
603d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (src == null) {
604d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = top = 0;
605d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = bitmap.getWidth();
606d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = bitmap.getHeight();
607d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
608d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = src.left;
609d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = src.right;
610d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            top = src.top;
611d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = src.bottom;
612445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
613d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
614f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
615d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
616e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
617e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
618e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
619e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
6201abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
621d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
622d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
623d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        float left, top, right, bottom;
624d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (src == null) {
625d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = top = 0;
626d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = bitmap.getWidth();
627d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = bitmap.getHeight();
628d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
629d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            left = src.left;
630d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            right = src.right;
631d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            top = src.top;
632d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            bottom = src.bottom;
633ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy        }
634d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III
635f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
636d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
637e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
638e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
639f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger    private static native void nDrawBitmap(long renderer, long bitmap,
640ce0537b80087a6225273040a987414b1dd081aa0Romain Guy            float srcLeft, float srcTop, float srcRight, float srcBottom,
64136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, float right, float bottom, long paint);
642ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
643e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
644e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
645e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
646e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (width < 0) {
647e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("width must be >= 0");
648e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
649e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
650e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (height < 0) {
651e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("height must be >= 0");
652e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
653e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
654e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (Math.abs(stride) < width) {
655e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("abs(stride) must be >= width");
656e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
657e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
658e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        int lastScanline = offset + (height - 1) * stride;
659e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        int length = colors.length;
660e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
661e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
662e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy                (lastScanline + width > length)) {
663e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new ArrayIndexOutOfBoundsException();
664e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
665e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
66676d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
66776d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawBitmap(mRenderer, colors, offset, stride, x, y,
66876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                width, height, hasAlpha, nativePaint);
669e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
670e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
67136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
67236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float x, float y, int width, int height, boolean hasAlpha, long nativePaint);
673e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
674e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
675e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
676e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
677ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
678e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
679e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
680e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
681e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
682e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int vertOffset, int[] colors, int colorOffset, Paint paint) {
6831abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
6845a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
6855a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            throw new ArrayIndexOutOfBoundsException();
6865a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        }
6875a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
6885a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        if (meshWidth == 0 || meshHeight == 0) {
6895a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            return;
6905a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        }
6915a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
6925a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        final int count = (meshWidth + 1) * (meshHeight + 1);
6935a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        checkRange(verts.length, vertOffset, count * 2);
6945a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
695ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        if (colors != null) {
696ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy            checkRange(colors.length, colorOffset, count);
697ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        }
6985a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
699d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
700f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger        nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, meshWidth, meshHeight,
701d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                verts, vertOffset, colors, colorOffset, nativePaint);
702e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
703e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
704f29d5a5b211786248d0557157c304c5fff428bd4Derek Sollenberger    private static native void nDrawBitmapMesh(long renderer, long bitmap,
7055a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            int meshWidth, int meshHeight, float[] verts, int vertOffset,
70636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int[] colors, int colorOffset, long paint);
7075a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
708e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
709e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawCircle(float cx, float cy, float radius, Paint paint) {
710d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
711e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
712e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
71336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawCircle(long renderer, float cx, float cy,
71436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float radius, long paint);
71501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
716e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
71752244fff29042926e21fa897ef5ab11148e35299John Reck    public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
71852244fff29042926e21fa897ef5ab11148e35299John Reck            CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
71952244fff29042926e21fa897ef5ab11148e35299John Reck        nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
72052244fff29042926e21fa897ef5ab11148e35299John Reck                radius.getNativeContainer(), paint.getNativeContainer());
72152244fff29042926e21fa897ef5ab11148e35299John Reck    }
72252244fff29042926e21fa897ef5ab11148e35299John Reck
72352244fff29042926e21fa897ef5ab11148e35299John Reck    private static native void nDrawCircle(long renderer, long propCx,
72452244fff29042926e21fa897ef5ab11148e35299John Reck            long propCy, long propRadius, long propPaint);
72552244fff29042926e21fa897ef5ab11148e35299John Reck
72652244fff29042926e21fa897ef5ab11148e35299John Reck    @Override
727072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi    public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
728072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi            CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
729072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi            CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
730072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi        nDrawRoundRect(mRenderer, left.getNativeContainer(), top.getNativeContainer(),
731072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi                right.getNativeContainer(), bottom.getNativeContainer(),
732072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi                rx.getNativeContainer(), ry.getNativeContainer(),
733072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi                paint.getNativeContainer());
734072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi    }
735072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi
736072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi    private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
737072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi            long propRight, long propBottom, long propRx, long propRy, long propPaint);
738072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi
739072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi    @Override
740e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color) {
74185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(color, PorterDuff.Mode.SRC_OVER);
742e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
743e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
744e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
745e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color, PorterDuff.Mode mode) {
74685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        nDrawColor(mRenderer, color, mode.nativeInt);
747e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
748051910b9f998030dacb8a0722588cc715813fde1Raph Levien
74936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawColor(long renderer, int color, int mode);
750e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
751e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
752e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
7536410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        float[] line = getLineStorage();
7546410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[0] = startX;
7556410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[1] = startY;
7566410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[2] = stopX;
7576410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[3] = stopY;
7586410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        drawLines(line, 0, 4, paint);
759e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
760e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
761e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
762e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, int offset, int count, Paint paint) {
7635d11676414b3606792e23c269cf75b44faa1a2afChris Craik        if (count < 4) return;
7645d11676414b3606792e23c269cf75b44faa1a2afChris Craik
765759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        if ((offset | count) < 0 || offset + count > pts.length) {
766759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
767759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        }
768d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
769e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
770e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
77136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawLines(long renderer, float[] points,
77236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int offset, int count, long paint);
773759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
774e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
775e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, Paint paint) {
776759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        drawLines(pts, 0, pts.length, paint);
777e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
778e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
779e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
78024609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese    public void drawOval(float left, float top, float right, float bottom, Paint paint) {
78124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese        nDrawOval(mRenderer, left, top, right, bottom, paint.mNativePaint);
782e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
783e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
78436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawOval(long renderer, float left, float top,
78536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint);
786c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
787e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
788e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPaint(Paint paint) {
7896410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        final Rect r = getInternalClipBounds();
7906926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        nGetClipBounds(mRenderer, r);
7916926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
792e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
793e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
794e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
795e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPath(Path path, Paint paint) {
796d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (path.isSimplePath) {
797d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            if (path.rects != null) {
798d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
799a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy            }
800d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
801d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
802a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy        }
803e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
804e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
80536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPath(long renderer, long path, long paint);
80636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRects(long renderer, long region, long paint);
8077fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy
808e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
809e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture) {
81075582e889d4895483309e38364266073be6d46b8Romain Guy        picture.endRecording();
81175582e889d4895483309e38364266073be6d46b8Romain Guy        // TODO: Implement rendering
812e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
813e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
814e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
815e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPoint(float x, float y, Paint paint) {
8166410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        float[] point = getPointStorage();
8176410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        point[0] = x;
8186410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        point[1] = y;
8196410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        drawPoints(point, 0, 2, paint);
820e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
821e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
822e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
823ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy    public void drawPoints(float[] pts, Paint paint) {
824ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy        drawPoints(pts, 0, pts.length, paint);
825e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
826e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
827e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
828ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
8295d11676414b3606792e23c269cf75b44faa1a2afChris Craik        if (count < 2) return;
8305d11676414b3606792e23c269cf75b44faa1a2afChris Craik
831d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
832e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
833e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
83436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPoints(long renderer, float[] points,
83536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int offset, int count, long paint);
836ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy
8373f0d6167227d6d2cdd85f7718d92db859b443e92Raph Levien    // Note: drawPosText just uses implementation in Canvas
838eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
839e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
840e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
841765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        if (left == right || top == bottom) return;
842d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
843e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
844e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
84536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRect(long renderer, float left, float top,
84636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint);
847c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
848e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
849e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(Rect r, Paint paint) {
850c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
851e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
852e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
853e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
854c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    public void drawRect(RectF r, Paint paint) {
855c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
856e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
857e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
858e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
859e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRGB(int r, int g, int b) {
86085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
861e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
862e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
863e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
8644d1c1538e2422d0a5b19ad1cd2fb353ed6279a88Chris Craik    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
8654d1c1538e2422d0a5b19ad1cd2fb353ed6279a88Chris Craik            Paint paint) {
866d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
867e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
868e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
86936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRoundRect(long renderer, float left, float top,
87036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, float rx, float y, long paint);
87101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
872e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
873e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
874a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((index | count | (index + count) | (text.length - index - count)) < 0) {
875a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
876a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
87761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
878d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawText(mRenderer, text, index, count, x, y,
879d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
880e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
881051910b9f998030dacb8a0722588cc715813fde1Raph Levien
88236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawText(long renderer, char[] text, int index, int count,
8831a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien            float x, float y, int bidiFlags, long paint, long typeface);
884e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
885e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
886e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
887d82f8a9a3869448e6d7d4b3fc962e34e33a1ba0eRaph Levien        if ((start | end | (end - start) | (text.length() - end)) < 0) {
888d82f8a9a3869448e6d7d4b3fc962e34e33a1ba0eRaph Levien            throw new IndexOutOfBoundsException();
889d82f8a9a3869448e6d7d4b3fc962e34e33a1ba0eRaph Levien        }
890d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (text instanceof String || text instanceof SpannedString ||
891d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                text instanceof SpannableString) {
892d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
893d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                    paint.mNativePaint, paint.mNativeTypeface);
894d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else if (text instanceof GraphicsOperations) {
895d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            ((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
896d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
897d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            char[] buf = TemporaryBuffer.obtain(end - start);
898d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TextUtils.getChars(text, start, end, buf, 0);
899d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawText(mRenderer, buf, 0, end - start, x, y,
900d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                    paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
901d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TemporaryBuffer.recycle(buf);
902a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
903e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
904e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
905e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
906e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
907a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((start | end | (end - start) | (text.length() - end)) < 0) {
908a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
909a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
91061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
911d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawText(mRenderer, text, start, end, x, y,
912d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
913e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
914e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
91536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawText(long renderer, String text, int start, int end,
9161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien            float x, float y, int bidiFlags, long paint, long typeface);
917a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
918e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
919e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, float x, float y, Paint paint) {
920d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawText(mRenderer, text, 0, text.length(), x, y,
921d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
922e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
923e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
924e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
925e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
926e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float vOffset, Paint paint) {
927325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        if (index < 0 || index + count > text.length) {
928325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            throw new ArrayIndexOutOfBoundsException();
929325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        }
930325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
931d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
9329d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
933e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
934e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
93536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
9369d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
9379d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long typeface);
938325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
939e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
940e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
941325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        if (text.length() == 0) return;
942325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
943d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
9449d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
945e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
946e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
94736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
9489d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
9499d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            long typeface);
950325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
951e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
952e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
953051910b9f998030dacb8a0722588cc715813fde1Raph Levien            float x, float y, boolean isRtl, Paint paint) {
95461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((index | count | text.length - index - count) < 0) {
95561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
95661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
95761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
958051910b9f998030dacb8a0722588cc715813fde1Raph Levien        nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, isRtl,
959d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                paint.mNativePaint, paint.mNativeTypeface);
960e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
961e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
96236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
963051910b9f998030dacb8a0722588cc715813fde1Raph Levien            int contextIndex, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
96461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
965e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
966e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
967051910b9f998030dacb8a0722588cc715813fde1Raph Levien            float x, float y, boolean isRtl, Paint paint) {
96861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((start | end | end - start | text.length() - end) < 0) {
96961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
97061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
97161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
972d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        if (text instanceof String || text instanceof SpannedString ||
973d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III                text instanceof SpannableString) {
974d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
975051910b9f998030dacb8a0722588cc715813fde1Raph Levien                    contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
976d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else if (text instanceof GraphicsOperations) {
977d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            ((GraphicsOperations) text).drawTextRun(this, start, end,
978051910b9f998030dacb8a0722588cc715813fde1Raph Levien                    contextStart, contextEnd, x, y, isRtl, paint);
979d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III        } else {
980d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            int contextLen = contextEnd - contextStart;
981d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            int len = end - start;
982d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            char[] buf = TemporaryBuffer.obtain(contextLen);
983d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
984d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
985051910b9f998030dacb8a0722588cc715813fde1Raph Levien                    x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
986d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III            TemporaryBuffer.recycle(buf);
98761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
988e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
989e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
99036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextRun(long renderer, String text, int start, int end,
991051910b9f998030dacb8a0722588cc715813fde1Raph Levien            int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
99261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
993e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
994e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
995e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
996e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int indexOffset, int indexCount, Paint paint) {
9976926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        // TODO: Implement
998e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
999e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
1000