GLES20Canvas.java revision 04fc583c3dd3144bc6b718fcac4b3e1afdfdb067
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;
21db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guyimport android.graphics.ColorFilter;
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 {
44a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    // Must match modifiers used in the JNI layer
45a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    private static final int MODIFIER_NONE = 0;
46a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    private static final int MODIFIER_SHADOW = 1;
47a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    private static final int MODIFIER_SHADER = 2;
48a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy
49e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private final boolean mOpaque;
5036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private long mRenderer;
51f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy
52f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    // The native renderer will be destroyed when this object dies.
53f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    // DO NOT overwrite this reference once it is set.
54eea60692b060737faeaa02bb30f5b79e2202b482Romain Guy    @SuppressWarnings({"unused", "FieldCanBeLocal"})
55f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    private CanvasFinalizer mFinalizer;
56f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy
57e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private int mWidth;
58e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private int mHeight;
59ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
606410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] mPoint;
616410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] mLine;
626926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy
636410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private Rect mClipBounds;
646410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private RectF mPathBounds;
656926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy
666926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    private DrawFilter mFilter;
67da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
68163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    ///////////////////////////////////////////////////////////////////////////
69163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    // JNI
70163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    ///////////////////////////////////////////////////////////////////////////
71163935113919a184122b8b3bd672ef08c8df65dcRomain Guy
72163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    private static native boolean nIsAvailable();
73163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    private static boolean sIsAvailable = nIsAvailable();
74163935113919a184122b8b3bd672ef08c8df65dcRomain Guy
75163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    static boolean isAvailable() {
76163935113919a184122b8b3bd672ef08c8df65dcRomain Guy        return sIsAvailable;
77163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    }
78e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
79e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
80e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Constructors
81e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
82b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
836c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    /**
846c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     * Creates a canvas to render directly on screen.
856c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     */
86b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    GLES20Canvas(boolean translucent) {
87b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        this(false, translucent);
88b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
89e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
90f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy    protected GLES20Canvas(boolean record, boolean translucent) {
91e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mOpaque = !translucent;
92e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
93b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        if (record) {
94162a0217563f4665da6eb183dfce0fef740f641fJeff Brown            mRenderer = nCreateDisplayListRenderer();
95b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        } else {
96b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy            mRenderer = nCreateRenderer();
97b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        }
986c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
996c319ca1275c8db892c39b48fc54864c949f9171Romain Guy        setupFinalizer();
1006c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
1016c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
1026c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    private void setupFinalizer() {
103fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        if (mRenderer == 0) {
104fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            throw new IllegalStateException("Could not create GLES20Canvas renderer");
1055c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        } else {
106162a0217563f4665da6eb183dfce0fef740f641fJeff Brown            mFinalizer = new CanvasFinalizer(mRenderer);
107fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        }
108e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
109b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
110162a0217563f4665da6eb183dfce0fef740f641fJeff Brown    protected void resetDisplayListRenderer() {
111162a0217563f4665da6eb183dfce0fef740f641fJeff Brown        nResetDisplayListRenderer(mRenderer);
112162a0217563f4665da6eb183dfce0fef740f641fJeff Brown    }
113162a0217563f4665da6eb183dfce0fef740f641fJeff Brown
11436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native long nCreateRenderer();
11536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native long nCreateDisplayListRenderer();
11636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResetDisplayListRenderer(long renderer);
11736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDestroyRenderer(long renderer);
1185c13d89c1332fcc499379b9064b891187b75ca32Chet Haase
119162a0217563f4665da6eb183dfce0fef740f641fJeff Brown    private static final class CanvasFinalizer {
12036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        private final long mRenderer;
1215977baa1fa24125c148a72699b53e62abaf08960Chet Haase
12236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        public CanvasFinalizer(long renderer) {
123f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy            mRenderer = renderer;
1245c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        }
1255c13d89c1332fcc499379b9064b891187b75ca32Chet Haase
1265c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        @Override
127f890fab5a6715548e520a6f010a3bfe7607ce56ePatrick Dubroy        protected void finalize() throws Throwable {
128171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy            try {
129162a0217563f4665da6eb183dfce0fef740f641fJeff Brown                nDestroyRenderer(mRenderer);
130171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy            } finally {
131171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy                super.finalize();
132171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy            }
133e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        }
134e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
135ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
136ba9b613437c34873fa95800a25fc51720638267cChris Craik    public static void setProperty(String name, String value) {
137ba9b613437c34873fa95800a25fc51720638267cChris Craik        nSetProperty(name, value);
138ba9b613437c34873fa95800a25fc51720638267cChris Craik    }
139ba9b613437c34873fa95800a25fc51720638267cChris Craik
140ba9b613437c34873fa95800a25fc51720638267cChris Craik    private static native void nSetProperty(String name, String value);
141ba9b613437c34873fa95800a25fc51720638267cChris Craik
142e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
1436c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    // Hardware layers
1446c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
14511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
14611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    @Override
14711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    void pushLayerUpdate(HardwareLayer layer) {
14804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        nPushLayerUpdate(mRenderer, layer.getLayer());
14911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
15011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
15111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    @Override
152e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    void cancelLayerUpdate(HardwareLayer layer) {
15304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        nCancelLayerUpdate(mRenderer, layer.getLayer());
154e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    }
155e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy
156e93482f5eac3df581d57e64c2a771a96aa868585Romain Guy    @Override
157405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    void flushLayerUpdates() {
158405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        nFlushLayerUpdates(mRenderer);
159405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    }
160405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
161405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    @Override
16211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    void clearLayerUpdates() {
16311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        nClearLayerUpdates(mRenderer);
16411cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    }
16511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
16636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    static native boolean nCopyLayer(long layerId, long bitmap);
16736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nClearLayerUpdates(long renderer);
16836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nFlushLayerUpdates(long renderer);
16936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nPushLayerUpdate(long renderer, long layer);
17036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nCancelLayerUpdate(long renderer, long layer);
17111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
1726c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
173e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Canvas management
174e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
175e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
176e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
177e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean isOpaque() {
178e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mOpaque;
179e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
180e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
181e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
182e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getWidth() {
183e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mWidth;
184e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
185e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
186e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
187e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getHeight() {
188e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mHeight;
189e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
190e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
191f61970fc79e9c5cf340fa942597628242361864aRomain Guy    @Override
192f61970fc79e9c5cf340fa942597628242361864aRomain Guy    public int getMaximumBitmapWidth() {
193f61970fc79e9c5cf340fa942597628242361864aRomain Guy        return nGetMaximumTextureWidth();
194f61970fc79e9c5cf340fa942597628242361864aRomain Guy    }
195f61970fc79e9c5cf340fa942597628242361864aRomain Guy
196f61970fc79e9c5cf340fa942597628242361864aRomain Guy    @Override
197f61970fc79e9c5cf340fa942597628242361864aRomain Guy    public int getMaximumBitmapHeight() {
198f61970fc79e9c5cf340fa942597628242361864aRomain Guy        return nGetMaximumTextureHeight();
199f61970fc79e9c5cf340fa942597628242361864aRomain Guy    }
200f61970fc79e9c5cf340fa942597628242361864aRomain Guy
201f61970fc79e9c5cf340fa942597628242361864aRomain Guy    private static native int nGetMaximumTextureWidth();
202530041d3191ce817832a0108514617768e43cda6Romain Guy    private static native int nGetMaximumTextureHeight();
203f61970fc79e9c5cf340fa942597628242361864aRomain Guy
2042bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy    /**
2052bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy     * Returns the native OpenGLRenderer object.
2062bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy     */
20736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    long getRenderer() {
2082bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy        return mRenderer;
2092bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy    }
2102bf68f063b0077ddef6ebfe54f2ae5e063c2c229Romain Guy
211e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
212e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Setup
213e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
214e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
215e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
216e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setViewport(int width, int height) {
217e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mWidth = width;
218e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mHeight = height;
219e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
220e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        nSetViewport(mRenderer, width, height);
221e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
222e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
22336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetViewport(long renderer, int width, int height);
224e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
225b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
22644b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase    public int onPreDraw(Rect dirty) {
2277d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        if (dirty != null) {
22844b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
22944b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase                    mOpaque);
2307d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        } else {
23144b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return nPrepare(mRenderer, mOpaque);
2327d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        }
233e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
234b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
23536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nPrepare(long renderer, boolean opaque);
23636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nPrepareDirty(long renderer, int left, int top, int right, int bottom,
2377d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            boolean opaque);
238e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
239b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
240b35ab7b72967adcfd01cec483a705dafe8b951d1Gilles Debunne    public void onPostDraw() {
241b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        nFinish(mRenderer);
242b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
2439ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy
24436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nFinish(long renderer);
245b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
246530041d3191ce817832a0108514617768e43cda6Romain Guy    /**
247530041d3191ce817832a0108514617768e43cda6Romain Guy     * Returns the size of the stencil buffer required by the underlying
248530041d3191ce817832a0108514617768e43cda6Romain Guy     * implementation.
249530041d3191ce817832a0108514617768e43cda6Romain Guy     *
250530041d3191ce817832a0108514617768e43cda6Romain Guy     * @return The minimum number of bits the stencil buffer must. Always >= 0.
251530041d3191ce817832a0108514617768e43cda6Romain Guy     *
252530041d3191ce817832a0108514617768e43cda6Romain Guy     * @hide
253530041d3191ce817832a0108514617768e43cda6Romain Guy     */
254530041d3191ce817832a0108514617768e43cda6Romain Guy    public static int getStencilSize() {
255530041d3191ce817832a0108514617768e43cda6Romain Guy        return nGetStencilSize();
256530041d3191ce817832a0108514617768e43cda6Romain Guy    }
257530041d3191ce817832a0108514617768e43cda6Romain Guy
258530041d3191ce817832a0108514617768e43cda6Romain Guy    private static native int nGetStencilSize();
259530041d3191ce817832a0108514617768e43cda6Romain Guy
260530041d3191ce817832a0108514617768e43cda6Romain Guy    ///////////////////////////////////////////////////////////////////////////
261530041d3191ce817832a0108514617768e43cda6Romain Guy    // Functor
262530041d3191ce817832a0108514617768e43cda6Romain Guy    ///////////////////////////////////////////////////////////////////////////
263530041d3191ce817832a0108514617768e43cda6Romain Guy
264da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    @Override
26536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    public int callDrawGLFunction(long drawGLFunction) {
266daf98e941e140e8739458126640183b9f296a2abChet Haase        return nCallDrawGLFunction(mRenderer, drawGLFunction);
267daf98e941e140e8739458126640183b9f296a2abChet Haase    }
268daf98e941e140e8739458126640183b9f296a2abChet Haase
26936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nCallDrawGLFunction(long renderer, long drawGLFunction);
270daf98e941e140e8739458126640183b9f296a2abChet Haase
2718f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy    @Override
2728f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy    public int invokeFunctors(Rect dirty) {
2738f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        return nInvokeFunctors(mRenderer, dirty);
2748f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy    }
2758f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
27636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nInvokeFunctors(long renderer, Rect dirty);
2778f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
278ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    @Override
27936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    public void detachFunctor(long functor) {
280ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        nDetachFunctor(mRenderer, functor);
281ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    }
282ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
28336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDetachFunctor(long renderer, long functor);
284ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
285ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    @Override
28636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    public void attachFunctor(long functor) {
287ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        nAttachFunctor(mRenderer, functor);
288ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    }
289ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
29036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nAttachFunctor(long renderer, long functor);
291ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
292bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    ///////////////////////////////////////////////////////////////////////////
293bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    // Memory
294bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    ///////////////////////////////////////////////////////////////////////////
295bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
296bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    /**
2976d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     * Must match Caches::FlushMode values
2986d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     *
299bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * @see #flushCaches(int)
300bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     */
3013b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static final int FLUSH_CACHES_LAYERS = 0;
3026d7475d666baefaa3ba9f0dcee25238739454241Romain Guy
3036d7475d666baefaa3ba9f0dcee25238739454241Romain Guy    /**
3046d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     * Must match Caches::FlushMode values
3056d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     *
3066d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     * @see #flushCaches(int)
3076d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     */
3083b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static final int FLUSH_CACHES_MODERATE = 1;
309bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
310bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    /**
3116d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     * Must match Caches::FlushMode values
3126d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     *
313bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * @see #flushCaches(int)
314bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     */
3153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static final int FLUSH_CACHES_FULL = 2;
316bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
317bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    /**
318bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * Flush caches to reclaim as much memory as possible. The amount of memory
319bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * to reclaim is indicate by the level parameter.
320bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     *
321bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
322bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * {@link #FLUSH_CACHES_FULL}.
323bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     *
324bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * @param level Hint about the amount of memory to reclaim
325bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     */
3263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static void flushCaches(int level) {
327bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy        nFlushCaches(level);
328bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    }
329bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
330bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    private static native void nFlushCaches(int level);
331bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
3328ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy    /**
3338ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy     * Release all resources associated with the underlying caches. This should
3348ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy     * only be called after a full flushCaches().
3358ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy     *
3368ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy     * @hide
3378ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy     */
3383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static void terminateCaches() {
3398ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        nTerminateCaches();
3408ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy    }
3418ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy
3428ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy    private static native void nTerminateCaches();
3438ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy
3443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static boolean initCaches() {
3453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        return nInitCaches();
3468ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy    }
3478ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy
3483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    private static native boolean nInitCaches();
3493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
3503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    ///////////////////////////////////////////////////////////////////////////
3513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    // Atlas
3523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    ///////////////////////////////////////////////////////////////////////////
3533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
3543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    static void initAtlas(GraphicBuffer buffer, int[] map) {
3553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        nInitAtlas(buffer, map, map.length);
3563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
3573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
3583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count);
3593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
360b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    ///////////////////////////////////////////////////////////////////////////
361b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    // Display list
362b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    ///////////////////////////////////////////////////////////////////////////
363b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
36436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    long getDisplayList(long displayList) {
365162a0217563f4665da6eb183dfce0fef740f641fJeff Brown        return nGetDisplayList(mRenderer, displayList);
366b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
367b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
36836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native long nGetDisplayList(long renderer, long displayList);
36965b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy
37052036b19a5f82bc4d75cfcbff99c65df8d25a99bRomain Guy    @Override
3711271e2cc80b01d577e9db339459ef0222bb9320dChet Haase    public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
3725438979e498750b6a28ada7974d4e9fe17fd8394Chris Craik        return nDrawDisplayList(mRenderer, displayList.getNativeDisplayList(),
3731271e2cc80b01d577e9db339459ef0222bb9320dChet Haase                dirty, flags);
374b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
375b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
37636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nDrawDisplayList(long renderer, long displayList,
3771271e2cc80b01d577e9db339459ef0222bb9320dChet Haase            Rect dirty, int flags);
378da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
379e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
3806c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    // Hardware layer
3816c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
3826c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
383ada830f639591b99c3e40de22b07296c7932a33fRomain Guy    void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
384a4e16c58c9e3c983251e0475125a2a6f5bec2dbfChris Craik        layer.setLayerPaint(paint);
38504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        nDrawLayer(mRenderer, layer.getLayer(), x, y);
3866c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
3876c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
38836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawLayer(long renderer, long layer, float x, float y);
389aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
3906c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    void interrupt() {
3916c319ca1275c8db892c39b48fc54864c949f9171Romain Guy        nInterrupt(mRenderer);
3926c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
3936c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
3946c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    void resume() {
3956c319ca1275c8db892c39b48fc54864c949f9171Romain Guy        nResume(mRenderer);
3966c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    }
3976c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
39836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nInterrupt(long renderer);
39936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResume(long renderer);
4006c319ca1275c8db892c39b48fc54864c949f9171Romain Guy
4016c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    ///////////////////////////////////////////////////////////////////////////
4026410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    // Support
4036410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    ///////////////////////////////////////////////////////////////////////////
4046410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
4056410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private Rect getInternalClipBounds() {
4066410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mClipBounds == null) mClipBounds = new Rect();
4076410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mClipBounds;
4086410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
4096410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
4106410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
4116410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private RectF getPathBounds() {
4126410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mPathBounds == null) mPathBounds = new RectF();
4136410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mPathBounds;
4146410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
4156410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
4166410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] getPointStorage() {
4176410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mPoint == null) mPoint = new float[2];
4186410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mPoint;
4196410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
4206410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
4216410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    private float[] getLineStorage() {
4226410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        if (mLine == null) mLine = new float[4];
4236410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return mLine;
4246410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    }
4256410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy
4266410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy    ///////////////////////////////////////////////////////////////////////////
427e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Clipping
428e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
429e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
430e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
431e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path) {
432735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
433e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
434e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
435e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
436e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path, Region.Op op) {
437735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
438e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
439e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
44036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipPath(long renderer, long path, int op);
441735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy
442e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
443e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom) {
444079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
445e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
446bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
44736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRect(long renderer, float left, float top,
448079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            float right, float bottom, int op);
449e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
450e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
451e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
452079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
453e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
454e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
455e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
456e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(int left, int top, int right, int bottom) {
457daf98e941e140e8739458126640183b9f296a2abChet Haase        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
458e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
459bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
46036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRect(long renderer, int left, int top,
461735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy            int right, int bottom, int op);
462e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
463e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
464e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect) {
465079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
466079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                Region.Op.INTERSECT.nativeInt);
467e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
468e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
469e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
470e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect, Region.Op op) {
471079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
472e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
473e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
474e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
475e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect) {
476079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
477079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                Region.Op.INTERSECT.nativeInt);
478e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
479e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
480e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
481e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect, Region.Op op) {
482079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
483e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
484e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
485e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
486e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region) {
487735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
488e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
489e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
490e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
491e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region, Region.Op op) {
492735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy        return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
493e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
494e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
49536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nClipRegion(long renderer, long region, int op);
496735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy
497e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
498e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean getClipBounds(Rect bounds) {
4999d5316e3f56d138504565ff311145ac01621dff4Romain Guy        return nGetClipBounds(mRenderer, bounds);
500e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
501e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
50236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nGetClipBounds(long renderer, Rect bounds);
5039d5316e3f56d138504565ff311145ac01621dff4Romain Guy
504e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
505e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
506ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger        return nQuickReject(mRenderer, left, top, right, bottom);
507e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
508c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
50936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native boolean nQuickReject(long renderer, float left, float top,
510ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger            float right, float bottom);
511e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
512e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
513e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(Path path, EdgeType type) {
5146410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        RectF pathBounds = getPathBounds();
5156410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        path.computeBounds(pathBounds, true);
5166410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
5176410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy                pathBounds.right, pathBounds.bottom);
518e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
519e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
520e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
521e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(RectF rect, EdgeType type) {
522ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
523e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
524e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
525e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
526e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Transformations
527e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
528e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
529e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
530e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void translate(float dx, float dy) {
531807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy        if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
532e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
533f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
53436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nTranslate(long renderer, float dx, float dy);
535e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
536e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
537e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void skew(float sx, float sy) {
538807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy        nSkew(mRenderer, sx, sy);
539e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
540e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
54136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSkew(long renderer, float sx, float sy);
542807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy
543e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
544e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void rotate(float degrees) {
545f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nRotate(mRenderer, degrees);
546e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
547f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
54836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRotate(long renderer, float degrees);
549e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
550e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
551e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void scale(float sx, float sy) {
552f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nScale(mRenderer, sx, sy);
553e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
554e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
55536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nScale(long renderer, float sx, float sy);
556f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
557e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
558e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setMatrix(Matrix matrix) {
559e707859415f4c8e1c01228dfaa58fb0a690d442eRomain Guy        nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
560e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
561f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
56236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetMatrix(long renderer, long matrix);
563e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
5645ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    @SuppressWarnings("deprecation")
565e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
566f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    public void getMatrix(Matrix matrix) {
567f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nGetMatrix(mRenderer, matrix.native_instance);
568e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
569f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
57036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nGetMatrix(long renderer, long matrix);
571e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
572e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
573e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void concat(Matrix matrix) {
5744e7b772b733593fbe25c733e95b8dcea293234b6Romain Guy        if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
575e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
576e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
57736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nConcatMatrix(long renderer, long matrix);
578f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
579e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
580e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // State management
581e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
582e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
583e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
584e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save() {
5858aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
586e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
587bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
588e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
589e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save(int saveFlags) {
590bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nSave(mRenderer, saveFlags);
591e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
592e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
59336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSave(long renderer, int flags);
594bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
595e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
596e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
597189887e0ae171c1b7601991442104a30e56c50abRomain Guy        if (bounds != null) {
598189887e0ae171c1b7601991442104a30e56c50abRomain Guy            return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
599189887e0ae171c1b7601991442104a30e56c50abRomain Guy        }
600189887e0ae171c1b7601991442104a30e56c50abRomain Guy
60176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
60276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        return nSaveLayer(mRenderer, nativePaint, saveFlags);
603e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
604e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
60536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayer(long renderer, long paint, int saveFlags);
606189887e0ae171c1b7601991442104a30e56c50abRomain Guy
607e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
608e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
609e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
61001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (left < right && top < bottom) {
61176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
61276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger            return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
61301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
61401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return save(saveFlags);
615e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
616e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
61736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayer(long renderer, float left, float top,
61836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint, int saveFlags);
619bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
620e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
621e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
622189887e0ae171c1b7601991442104a30e56c50abRomain Guy        if (bounds != null) {
623189887e0ae171c1b7601991442104a30e56c50abRomain Guy            return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
624189887e0ae171c1b7601991442104a30e56c50abRomain Guy                    alpha, saveFlags);
625189887e0ae171c1b7601991442104a30e56c50abRomain Guy        }
626189887e0ae171c1b7601991442104a30e56c50abRomain Guy        return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
627e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
628e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
62936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags);
630189887e0ae171c1b7601991442104a30e56c50abRomain Guy
631e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
632e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
633e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
63401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        if (left < right && top < bottom) {
63501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy            return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
63601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        }
63701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy        return save(saveFlags);
638e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
639e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
64036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
641bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            float bottom, int alpha, int saveFlags);
642bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
643e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
644e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restore() {
645bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestore(mRenderer);
646e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
647bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
64836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRestore(long renderer);
649e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
650e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
651e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restoreToCount(int saveCount) {
652bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestoreToCount(mRenderer, saveCount);
653e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
654e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
65536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nRestoreToCount(long renderer, int saveCount);
656bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
657e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
658e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getSaveCount() {
659bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nGetSaveCount(mRenderer);
660e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
661bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
66236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int nGetSaveCount(long renderer);
663e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
664e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
665e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Filtering
666e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
667e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
668e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
669e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setDrawFilter(DrawFilter filter) {
6706926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        mFilter = filter;
6715ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        if (filter == null) {
6725ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            nResetPaintFilter(mRenderer);
6735ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        } else if (filter instanceof PaintFlagsDrawFilter) {
6745ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
6755ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
6765ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        }
677e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
678e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
67936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResetPaintFilter(long renderer);
68036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetupPaintFilter(long renderer, int clearBits, int setBits);
6815ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
682e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
683e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public DrawFilter getDrawFilter() {
6846926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        return mFilter;
685e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
686e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
687e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
688e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Drawing
689e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
690e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
691e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
692e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
693e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            Paint paint) {
69476d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
695445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
696445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
697445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                    startAngle, sweepAngle, useCenter, paint.mNativePaint);
698445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
699445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
700445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
701e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
702e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
70336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawArc(long renderer, float left, float top,
7047d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            float right, float bottom, float startAngle, float sweepAngle,
70536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            boolean useCenter, long paint);
7068b2f5267f16c295f12faab810527cd6311997e34Romain Guy
707e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
708e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawARGB(int a, int r, int g, int b) {
70985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
710e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
711e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
712e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
713f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
714f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        Bitmap bitmap = patch.getBitmap();
7151abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
716f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        // Shaders are ignored when drawing patches
71776d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
71876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
71976d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
720f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    }
721f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy
722f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    @Override
7233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
7243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        Bitmap bitmap = patch.getBitmap();
7251abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
726d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing patches
72776d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
72876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
72976d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
730deba785f122a47915756ffd991f5540d952cf937Romain Guy    }
731deba785f122a47915756ffd991f5540d952cf937Romain Guy
73236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPatch(long renderer, long bitmap, byte[] buffer, long chunk,
73336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, float right, float bottom, long paint);
734deba785f122a47915756ffd991f5540d952cf937Romain Guy
735deba785f122a47915756ffd991f5540d952cf937Romain Guy    @Override
736e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
7371abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
738d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
739a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
740445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
74136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
7420c20c3898a533b7b76f60827cb6ea02e17c5953dChris Craik            nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
743445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
744445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
745445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
746e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
747e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
74836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
74936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, long paint);
750dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy
751e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
752e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
7531abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
754d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
755a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
756445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
75736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
7580c20c3898a533b7b76f60827cb6ea02e17c5953dChris Craik            nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
7590c20c3898a533b7b76f60827cb6ea02e17c5953dChris Craik                    matrix.native_instance, nativePaint);
760445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
761445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
762445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
763e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
764e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
76536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
76636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            long matrix, long paint);
767f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
768e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
769e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
7701abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
771d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
772a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
773445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
77436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
775694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy
776445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            int left, top, right, bottom;
777445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (src == null) {
778445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                left = top = 0;
779445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                right = bitmap.getWidth();
780445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                bottom = bitmap.getHeight();
781445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            } else {
782445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                left = src.left;
783445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                right = src.right;
784445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                top = src.top;
785445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                bottom = src.bottom;
786445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            }
787694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy
7880c20c3898a533b7b76f60827cb6ea02e17c5953dChris Craik            nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
789445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                    dst.left, dst.top, dst.right, dst.bottom, nativePaint);
790445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
791445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
792445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
793e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
794e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
795e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
796e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
7971abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
798d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
799a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
800445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
80136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
802445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy
803445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            float left, top, right, bottom;
804445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (src == null) {
805445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                left = top = 0;
806445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                right = bitmap.getWidth();
807445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                bottom = bitmap.getHeight();
808445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            } else {
809445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                left = src.left;
810445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                right = src.right;
811445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                top = src.top;
812445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                bottom = src.bottom;
813445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            }
814445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy
8150c20c3898a533b7b76f60827cb6ea02e17c5953dChris Craik            nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
816445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                    dst.left, dst.top, dst.right, dst.bottom, nativePaint);
817445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
818445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
819ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy        }
820e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
821e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
82236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
823ce0537b80087a6225273040a987414b1dd081aa0Romain Guy            float srcLeft, float srcTop, float srcRight, float srcBottom,
82436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float left, float top, float right, float bottom, long paint);
825ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
826e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
827e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
828e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
829e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (width < 0) {
830e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("width must be >= 0");
831e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
832e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
833e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (height < 0) {
834e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("height must be >= 0");
835e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
836e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
837e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (Math.abs(stride) < width) {
838e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new IllegalArgumentException("abs(stride) must be >= width");
839e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
840e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
841e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        int lastScanline = offset + (height - 1) * stride;
842e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        int length = colors.length;
843e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
844e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
845e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy                (lastScanline + width > length)) {
846e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy            throw new ArrayIndexOutOfBoundsException();
847e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy        }
848e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
849d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
85076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
85176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        nDrawBitmap(mRenderer, colors, offset, stride, x, y,
85276d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger                width, height, hasAlpha, nativePaint);
853e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
854e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
85536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
85636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float x, float y, int width, int height, boolean hasAlpha, long nativePaint);
857e651cc6239616a202f6e96ebc2ed93b4b8b3627cRomain Guy
858e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
859e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
860e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
861d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
862ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
863e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
864e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
865e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
866e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
867e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int vertOffset, int[] colors, int colorOffset, Paint paint) {
8681abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        throwIfCannotDraw(bitmap);
8695a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
8705a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            throw new ArrayIndexOutOfBoundsException();
8715a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        }
8725a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
8735a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        if (meshWidth == 0 || meshHeight == 0) {
8745a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            return;
8755a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        }
8765a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
8775a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        final int count = (meshWidth + 1) * (meshHeight + 1);
8785a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy        checkRange(verts.length, vertOffset, count * 2);
8795a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
880ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        if (colors != null) {
881ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy            checkRange(colors.length, colorOffset, count);
882ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        }
8835a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
884a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
885445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
88636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
8870c20c3898a533b7b76f60827cb6ea02e17c5953dChris Craik            nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
888445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                    verts, vertOffset, colors, colorOffset, nativePaint);
889445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
890445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
891445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
892e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
893e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
89436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer,
8955a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy            int meshWidth, int meshHeight, float[] verts, int vertOffset,
89636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int[] colors, int colorOffset, long paint);
8975a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy
898e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
899e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawCircle(float cx, float cy, float radius, Paint paint) {
90076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
901445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
902445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
903445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
904445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
905445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
906e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
907e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
90836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawCircle(long renderer, float cx, float cy,
90936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float radius, long paint);
91001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
911e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
912e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color) {
91385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(color, PorterDuff.Mode.SRC_OVER);
914e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
915e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
916e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
917e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color, PorterDuff.Mode mode) {
91885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        nDrawColor(mRenderer, color, mode.nativeInt);
919e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
92085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
92136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawColor(long renderer, int color, int mode);
922e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
923e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
924e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
9256410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        float[] line = getLineStorage();
9266410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[0] = startX;
9276410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[1] = startY;
9286410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[2] = stopX;
9296410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        line[3] = stopY;
9306410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        drawLines(line, 0, 4, paint);
931e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
932e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
933e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
934e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, int offset, int count, Paint paint) {
9355d11676414b3606792e23c269cf75b44faa1a2afChris Craik        if (count < 4) return;
9365d11676414b3606792e23c269cf75b44faa1a2afChris Craik
937759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        if ((offset | count) < 0 || offset + count > pts.length) {
938759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
939759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        }
94076d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
941445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
942445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
943445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
944445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
945445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
946e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
947e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
94836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawLines(long renderer, float[] points,
94936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int offset, int count, long paint);
950759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
951e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
952e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, Paint paint) {
953759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        drawLines(pts, 0, pts.length, paint);
954e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
955e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
956e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
957e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawOval(RectF oval, Paint paint) {
95876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
959445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
960445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
961445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
962445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
963445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
964e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
965e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
96636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawOval(long renderer, float left, float top,
96736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint);
968c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy
969e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
970e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPaint(Paint paint) {
9716410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        final Rect r = getInternalClipBounds();
9726926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        nGetClipBounds(mRenderer, r);
9736926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
974e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
975e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
976e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
977e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPath(Path path, Paint paint) {
97876d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
979445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
980445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (path.isSimplePath) {
981445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                if (path.rects != null) {
982445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                    nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
983445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                }
984445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            } else {
985445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
986a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy            }
987445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
988445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
989a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy        }
990e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
991e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
99236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPath(long renderer, long path, long paint);
99336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRects(long renderer, long region, long paint);
9947fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy
995672433d90fab7383cd28beac9d4485b566a90940Romain Guy    void drawRects(float[] rects, int count, Paint paint) {
99676d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
997672433d90fab7383cd28beac9d4485b566a90940Romain Guy        try {
998672433d90fab7383cd28beac9d4485b566a90940Romain Guy            nDrawRects(mRenderer, rects, count, paint.mNativePaint);
999672433d90fab7383cd28beac9d4485b566a90940Romain Guy        } finally {
1000672433d90fab7383cd28beac9d4485b566a90940Romain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1001672433d90fab7383cd28beac9d4485b566a90940Romain Guy        }
1002672433d90fab7383cd28beac9d4485b566a90940Romain Guy    }
1003672433d90fab7383cd28beac9d4485b566a90940Romain Guy
100436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRects(long renderer, float[] rects, int count, long paint);
1005672433d90fab7383cd28beac9d4485b566a90940Romain Guy
1006e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1007e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture) {
1008f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy        if (picture.createdFromStream) {
1009f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy            return;
1010f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy        }
1011f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy
101275582e889d4895483309e38364266073be6d46b8Romain Guy        picture.endRecording();
101375582e889d4895483309e38364266073be6d46b8Romain Guy        // TODO: Implement rendering
1014e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1015e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1016e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1017e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture, Rect dst) {
1018f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy        if (picture.createdFromStream) {
1019f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy            return;
1020f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy        }
1021f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy
102275582e889d4895483309e38364266073be6d46b8Romain Guy        save();
102375582e889d4895483309e38364266073be6d46b8Romain Guy        translate(dst.left, dst.top);
102475582e889d4895483309e38364266073be6d46b8Romain Guy        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
102575582e889d4895483309e38364266073be6d46b8Romain Guy            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
102675582e889d4895483309e38364266073be6d46b8Romain Guy        }
102775582e889d4895483309e38364266073be6d46b8Romain Guy        drawPicture(picture);
102875582e889d4895483309e38364266073be6d46b8Romain Guy        restore();
1029e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1030e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1031e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1032e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture, RectF dst) {
1033f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy        if (picture.createdFromStream) {
1034f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy            return;
1035f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy        }
1036f9d9c065ed75f1196316a9a31f92309f602cef76Romain Guy
103775582e889d4895483309e38364266073be6d46b8Romain Guy        save();
103875582e889d4895483309e38364266073be6d46b8Romain Guy        translate(dst.left, dst.top);
103975582e889d4895483309e38364266073be6d46b8Romain Guy        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
104075582e889d4895483309e38364266073be6d46b8Romain Guy            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
104175582e889d4895483309e38364266073be6d46b8Romain Guy        }
104275582e889d4895483309e38364266073be6d46b8Romain Guy        drawPicture(picture);
104375582e889d4895483309e38364266073be6d46b8Romain Guy        restore();
1044e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1045e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1046e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1047e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPoint(float x, float y, Paint paint) {
10486410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        float[] point = getPointStorage();
10496410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        point[0] = x;
10506410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        point[1] = y;
10516410c0aaf13c9aec606b90ee942f2ac2d98b1609Romain Guy        drawPoints(point, 0, 2, paint);
1052e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1053e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1054e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1055ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy    public void drawPoints(float[] pts, Paint paint) {
1056ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy        drawPoints(pts, 0, pts.length, paint);
1057e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1058e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1059e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1060ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
10615d11676414b3606792e23c269cf75b44faa1a2afChris Craik        if (count < 2) return;
10625d11676414b3606792e23c269cf75b44faa1a2afChris Craik
106376d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
1064445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
1065445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
1066445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
1067445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1068445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
1069e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1070e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
107136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPoints(long renderer, float[] points,
107236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int offset, int count, long paint);
1073ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy
10745ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    @SuppressWarnings("deprecation")
1075e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1076e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
1077eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        if (index < 0 || index + count > text.length || count * 2 > pos.length) {
1078eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy            throw new IndexOutOfBoundsException();
1079eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        }
1080eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
1081eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        int modifiers = setupModifiers(paint);
1082eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        try {
1083eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy            nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
1084eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        } finally {
1085eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1086eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        }
1087e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1088e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
108936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPosText(long renderer, char[] text, int index, int count,
109036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float[] pos, long paint);
1091eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
10925ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    @SuppressWarnings("deprecation")
1093e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1094e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPosText(String text, float[] pos, Paint paint) {
1095eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        if (text.length() * 2 > pos.length) {
1096eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy            throw new ArrayIndexOutOfBoundsException();
1097eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        }
1098eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
1099eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        int modifiers = setupModifiers(paint);
1100eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        try {
1101eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy            nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
1102eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        } finally {
1103eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1104eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        }
1105e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1106e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
110736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawPosText(long renderer, String text, int start, int end,
110836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float[] pos, long paint);
1109eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
1110e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1111e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
1112765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        if (left == right || top == bottom) return;
111376d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
1114445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
1115445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
1116445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
1117445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1118445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
1119e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1120e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
112136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRect(long renderer, float left, float top,
112236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, long paint);
1123c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
1124e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1125e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(Rect r, Paint paint) {
1126c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
1127e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1128e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1129e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1130c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    public void drawRect(RectF r, Paint paint) {
1131c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
1132e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1133e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1134e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1135e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRGB(int r, int g, int b) {
113685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
1137e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1138e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1139e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1140e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
114176d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger        int modifiers = setupModifiers(paint, MODIFIER_SHADER);
1142445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        try {
1143445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
1144445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy                    rx, ry, paint.mNativePaint);
1145445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } finally {
1146445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1147445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        }
1148e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1149e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
115036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawRoundRect(long renderer, float left, float top,
115136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float right, float bottom, float rx, float y, long paint);
115201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy
1153e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1154e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
1155a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((index | count | (index + count) | (text.length - index - count)) < 0) {
1156a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
1157a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
115861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
1159a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = setupModifiers(paint);
116061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
1161da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
116261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
1163a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
116461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
1165e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1166a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
116736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawText(long renderer, char[] text, int index, int count,
116836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float x, float y, int bidiFlags, long paint);
1169e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1170e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1171e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
1172a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = setupModifiers(paint);
117361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
117461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (text instanceof String || text instanceof SpannedString ||
117561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    text instanceof SpannableString) {
1176da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
1177da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                        paint.mNativePaint);
117861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else if (text instanceof GraphicsOperations) {
117961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                ((GraphicsOperations) text).drawText(this, start, end, x, y,
118061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                                                         paint);
118161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else {
118261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                char[] buf = TemporaryBuffer.obtain(end - start);
118361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TextUtils.getChars(text, start, end, buf, 0);
1184da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                nDrawText(mRenderer, buf, 0, end - start, x, y,
1185da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                        paint.mBidiFlags, paint.mNativePaint);
118661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TemporaryBuffer.recycle(buf);
118761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            }
118861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
1189a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1190a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
1191e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1192e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1193e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1194e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
1195a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1196a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
1197a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
119861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
1199a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = setupModifiers(paint);
120061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
1201da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
120261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
1203a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
120461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
1205e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1206e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
120736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawText(long renderer, String text, int start, int end,
120836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            float x, float y, int bidiFlags, long paint);
1209a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
1210e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1211e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, float x, float y, Paint paint) {
1212a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = setupModifiers(paint);
121361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
1214da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
1215da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                    paint.mNativePaint);
121661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
1217a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
121861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
1219e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1220e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1221e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1222e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
1223e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float vOffset, Paint paint) {
1224325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        if (index < 0 || index + count > text.length) {
1225325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            throw new ArrayIndexOutOfBoundsException();
1226325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        }
1227325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
1228325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        int modifiers = setupModifiers(paint);
1229325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        try {
1230325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
1231da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                    paint.mBidiFlags, paint.mNativePaint);
1232325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        } finally {
1233325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1234325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        }
1235e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1236e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
123736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
123836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint);
1239325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
1240e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1241e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
1242325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        if (text.length() == 0) return;
1243325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
1244325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        int modifiers = setupModifiers(paint);
1245325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        try {
1246325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
1247da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                    paint.mBidiFlags, paint.mNativePaint);
1248325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        } finally {
1249325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1250325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        }
1251e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1252e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
125336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
125436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint);
1255325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
1256e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1257e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
1258da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            float x, float y, int dir, Paint paint) {
125961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((index | count | text.length - index - count) < 0) {
126061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
126161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
1262da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio        if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
1263da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            throw new IllegalArgumentException("Unknown direction: " + dir);
1264da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio        }
126561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
1266a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = setupModifiers(paint);
126761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
1268da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
126961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    paint.mNativePaint);
127061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
1271a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
127261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
1273e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1274e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
127536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
127636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int contextIndex, int contextCount, float x, float y, int dir, long nativePaint);
127761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
1278e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1279e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
1280da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            float x, float y, int dir, Paint paint) {
128161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((start | end | end - start | text.length() - end) < 0) {
128261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
128361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
128461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
1285a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = setupModifiers(paint);
128661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
1287da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio            int flags = dir == 0 ? 0 : 1;
128861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (text instanceof String || text instanceof SpannedString ||
128961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    text instanceof SpannableString) {
129061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
1291da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                        contextEnd, x, y, flags, paint.mNativePaint);
129261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else if (text instanceof GraphicsOperations) {
129361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                ((GraphicsOperations) text).drawTextRun(this, start, end,
1294da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                        contextStart, contextEnd, x, y, flags, paint);
129561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else {
129661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                int contextLen = contextEnd - contextStart;
129761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                int len = end - start;
129861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                char[] buf = TemporaryBuffer.obtain(contextLen);
129961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
130061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
1301da12f389eb4be0c08ca3fa9ca7663f4977858df5Fabrice Di Meglio                        x, y, flags, paint.mNativePaint);
130261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TemporaryBuffer.recycle(buf);
130361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            }
130461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
1305a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
130661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
1307e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1308e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
130936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nDrawTextRun(long renderer, String text, int start, int end,
131036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            int contextStart, int contextEnd, float x, float y, int flags, long nativePaint);
131161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
1312e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
1313e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
1314e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
1315e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int indexOffset, int indexCount, Paint paint) {
13166926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        // TODO: Implement
1317e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
1318d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy
1319a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    private int setupModifiers(Bitmap b, Paint paint) {
1320445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        if (b.getConfig() != Bitmap.Config.ALPHA_8) {
1321445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            return MODIFIER_NONE;
1322445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy        } else {
1323445c83c7755fae179cf3328e89307e2775e97a5eRomain Guy            return setupModifiers(paint);
132456215274f25d0040af00bf69b0df990894c0b4b0Romain Guy        }
1325a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    }
1326a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy
1327a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy    private int setupModifiers(Paint paint) {
1328a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        int modifiers = MODIFIER_NONE;
1329db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy
13301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        if (paint.hasShadow) {
13311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
13321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                    paint.shadowColor);
1333a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            modifiers |= MODIFIER_SHADOW;
13341e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        }
13351e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1336d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        final Shader shader = paint.getShader();
1337d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        if (shader != null) {
133806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            nSetupShader(mRenderer, shader.native_shader);
1339a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy            modifiers |= MODIFIER_SHADER;
1340db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        }
1341db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy
1342a168d7372132d6c87835878794b6ed43d0d282fdRomain Guy        return modifiers;
1343db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    }
13441e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1345765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy    private int setupModifiers(Paint paint, int flags) {
1346765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        int modifiers = MODIFIER_NONE;
1347765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy
1348765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
1349765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy            nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1350765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy                    paint.shadowColor);
1351765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy            modifiers |= MODIFIER_SHADOW;
1352765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        }
1353765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy
1354765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        final Shader shader = paint.getShader();
1355765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        if (shader != null && (flags & MODIFIER_SHADER) != 0) {
1356765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy            nSetupShader(mRenderer, shader.native_shader);
1357765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy            modifiers |= MODIFIER_SHADER;
1358765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        }
1359765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy
1360765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy        return modifiers;
1361765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy    }
1362765dcf32307dbd93ce43f064c426ce157be2d2aeRomain Guy
136336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetupShader(long renderer, long shader);
136436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nSetupShadow(long renderer, float radius,
13657d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            float dx, float dy, int color);
13661e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
136736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nResetModifiers(long renderer, int modifiers);
1368e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
1369