GLES20Canvas.java revision b051e895ccb696604349c6c5efe7c4747e1d1ab6
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;
24e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Paint;
25e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Path;
26e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Picture;
27e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.PorterDuff;
28e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Rect;
29e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.RectF;
30e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Region;
31d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guyimport android.graphics.Shader;
32a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.graphics.TemporaryBuffer;
33a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.GraphicsOperations;
34a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.SpannableString;
35a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.SpannedString;
36a1db574036c9bc2d397b69f8200594027e1fff16Romain Guyimport android.text.TextUtils;
37e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
38e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/**
39e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * An implementation of Canvas on top of OpenGL ES 2.0.
40e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
41b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guyclass GLES20Canvas extends HardwareCanvas {
42e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private final boolean mOpaque;
43fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    private int mRenderer;
44e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
45e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private int mWidth;
46e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private int mHeight;
47ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
48ce0537b80087a6225273040a987414b1dd081aa0Romain Guy    private final float[] mPoint = new float[2];
49ce0537b80087a6225273040a987414b1dd081aa0Romain Guy    private final float[] mLine = new float[4];
506926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy
516926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    private final Rect mClipBounds = new Rect();
526926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy
536926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    private DrawFilter mFilter;
54da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
55da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    private boolean mContextLocked;
56da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
57163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    ///////////////////////////////////////////////////////////////////////////
58163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    // JNI
59163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    ///////////////////////////////////////////////////////////////////////////
60163935113919a184122b8b3bd672ef08c8df65dcRomain Guy
61163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    private static native boolean nIsAvailable();
62163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    private static boolean sIsAvailable = nIsAvailable();
63163935113919a184122b8b3bd672ef08c8df65dcRomain Guy
64163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    static boolean isAvailable() {
65163935113919a184122b8b3bd672ef08c8df65dcRomain Guy        return sIsAvailable;
66163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    }
67e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
68e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
69e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Constructors
70e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
71b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
72b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    GLES20Canvas(boolean translucent) {
73b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        this(false, translucent);
74b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
75e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
76b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    GLES20Canvas(boolean record, boolean translucent) {
77e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mOpaque = !translucent;
78e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
79b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        if (record) {
80b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy            mRenderer = nCreateDisplayListRenderer();
81b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        } else {
82b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy            mRenderer = nCreateRenderer();
83b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        }
84b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
85fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        if (mRenderer == 0) {
86fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            throw new IllegalStateException("Could not create GLES20Canvas renderer");
87fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        }
88e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
89b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
90b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    private native int nCreateRenderer();
91b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    private native int nCreateDisplayListRenderer();
92b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
93b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
94fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    public synchronized void destroy() {
95fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        if (mRenderer != 0) {
96e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            nDestroyRenderer(mRenderer);
97fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            mRenderer = 0;
98e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        }
99e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
100ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
101e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private native void nDestroyRenderer(int renderer);
102e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
103e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
104e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Canvas management
105e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
106e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
107e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
108e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean isOpaque() {
109e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mOpaque;
110e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
111e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
112e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
113e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getWidth() {
114e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mWidth;
115e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
116e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
117e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
118e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getHeight() {
119e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        return mHeight;
120e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
121e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
122e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
123e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Setup
124e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
125e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
126e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
127e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setViewport(int width, int height) {
128e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mWidth = width;
129e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        mHeight = height;
130e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
131e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        nSetViewport(mRenderer, width, height);
132e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
133e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
134e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private native void nSetViewport(int renderer, int width, int height);
135e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
136b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
137e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    void onPreDraw() {
138e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        nPrepare(mRenderer);
139e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
140b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
141e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    private native void nPrepare(int renderer);
142e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
143b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
144b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    void onPostDraw() {
145b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        nFinish(mRenderer);
146b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    }
147b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
148b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy    private native void nFinish(int renderer);
149b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
150da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    @Override
151da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    public boolean acquireContext() {
152da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        if (!mContextLocked) {
153da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy            nAcquireContext(mRenderer);
154da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy            mContextLocked = true;
155da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        }
156da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        return mContextLocked;
157da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    }
158da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
159da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    private native void nAcquireContext(int renderer);
160da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
161da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    @Override
162da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    public void releaseContext() {
163da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        if (mContextLocked) {
164da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy            nReleaseContext(mRenderer);
165da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy            mContextLocked = false;
166da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy        }
167da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    }
168da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
169da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy    private native void nReleaseContext(int renderer);
170b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
171b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    ///////////////////////////////////////////////////////////////////////////
172b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    // Display list
173b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    ///////////////////////////////////////////////////////////////////////////
174b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
175b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    int getDisplayList() {
176b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        return nCreateDisplayList(mRenderer);
177b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
178b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
179b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    private native int nCreateDisplayList(int renderer);
180b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
181b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    void destroyDisplayList(int displayList) {
182b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        nDestroyDisplayList(displayList);
183b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
184b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
185b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    private native void nDestroyDisplayList(int displayList);
186b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
187b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    @Override
188b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    public void drawDisplayList(DisplayList displayList) {
189b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
190b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
191b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
192b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    private native void nDrawDisplayList(int renderer, int displayList);
193da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy
194e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
195e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Clipping
196e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
197e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
198e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
199e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path) {
200e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
201e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
202e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
203e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
204e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipPath(Path path, Region.Op op) {
205e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
206e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
207e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
208e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
209e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom) {
210079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
211e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
212bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
213079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy    private native boolean nClipRect(int renderer, float left, float top,
214079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            float right, float bottom, int op);
215e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
216e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
217e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
218079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
219e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
220e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
221e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
222e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(int left, int top, int right, int bottom) {
223079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
224e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
225bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
226079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy    private native boolean nClipRect(int renderer, int left, int top, int right, int bottom, int op);
227e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
228e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
229e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect) {
230079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
231079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                Region.Op.INTERSECT.nativeInt);
232e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
233e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
234e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
235e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(Rect rect, Region.Op op) {
236079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
237e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
238e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
239e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
240e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect) {
241079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
242079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                Region.Op.INTERSECT.nativeInt);
243e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
244e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
245e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
246e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRect(RectF rect, Region.Op op) {
247079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
248e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
249e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
250e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
251e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region) {
252e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
253e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
254e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
255e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
256e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean clipRegion(Region region, Region.Op op) {
257e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
258e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
259e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
260e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
261e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean getClipBounds(Rect bounds) {
2629d5316e3f56d138504565ff311145ac01621dff4Romain Guy        return nGetClipBounds(mRenderer, bounds);
263e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
264e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
2659d5316e3f56d138504565ff311145ac01621dff4Romain Guy    private native boolean nGetClipBounds(int renderer, Rect bounds);
2669d5316e3f56d138504565ff311145ac01621dff4Romain Guy
267e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
268e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
269c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
270e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
271c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
272c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    private native boolean nQuickReject(int renderer, float left, float top,
273c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy            float right, float bottom, int edge);
274e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
275e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
276e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(Path path, EdgeType type) {
277bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        throw new UnsupportedOperationException();
278e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
279e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
280e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
281e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public boolean quickReject(RectF rect, EdgeType type) {
282bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return quickReject(rect.left, rect.top, rect.right, rect.bottom, type);
283e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
284e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
285e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
286e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Transformations
287e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
288e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
289e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
290e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void translate(float dx, float dy) {
291f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nTranslate(mRenderer, dx, dy);
292e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
293f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
294f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    private native void nTranslate(int renderer, float dx, float dy);
295e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
296e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
297e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void skew(float sx, float sy) {
298e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
299e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
300e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
301e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
302e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void rotate(float degrees) {
303f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nRotate(mRenderer, degrees);
304e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
305f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
306f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    private native void nRotate(int renderer, float degrees);
307e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
308e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
309e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void scale(float sx, float sy) {
310f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nScale(mRenderer, sx, sy);
311e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
312e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
313f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    private native void nScale(int renderer, float sx, float sy);
314f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
315e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
316e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setMatrix(Matrix matrix) {
317f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nSetMatrix(mRenderer, matrix.native_instance);
318e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
319f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
320f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    private native void nSetMatrix(int renderer, int matrix);
321e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
322e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
323f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    public void getMatrix(Matrix matrix) {
324f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nGetMatrix(mRenderer, matrix.native_instance);
325e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
326f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
327f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    private native void nGetMatrix(int renderer, int matrix);
328e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
329e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
330e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void concat(Matrix matrix) {
331f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        nConcatMatrix(mRenderer, matrix.native_instance);
332e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
333e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
334f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    private native void nConcatMatrix(int renderer, int matrix);
335f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
336e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
337e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // State management
338e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
339e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
340e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
341e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save() {
3428aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy        return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
343e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
344bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
345e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
346e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int save(int saveFlags) {
347bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nSave(mRenderer, saveFlags);
348e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
349e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
350bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    private native int nSave(int renderer, int flags);
351bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
352e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
353e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
354bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
355e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
356e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
357e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
358e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayer(float left, float top, float right, float bottom, Paint paint,
359e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
360bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        int nativePaint = paint == null ? 0 : paint.mNativePaint;
361bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
362e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
363e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
364bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
365bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            int paint, int saveFlags);
366bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
367e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
368e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
369bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
370bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy                alpha, saveFlags);
371e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
372e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
373e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
374e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
375e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int saveFlags) {
376bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
377e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
378e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
379bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
380bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            float bottom, int alpha, int saveFlags);
381bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
382e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
383e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restore() {
384bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestore(mRenderer);
385e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
386bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
387bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    private native void nRestore(int renderer);
388e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
389e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
390e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void restoreToCount(int saveCount) {
391bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        nRestoreToCount(mRenderer, saveCount);
392e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
393e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
394bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    private native void nRestoreToCount(int renderer, int saveCount);
395bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
396e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
397e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public int getSaveCount() {
398bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return nGetSaveCount(mRenderer);
399e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
400bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
401bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    private native int nGetSaveCount(int renderer);
402e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
403e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
404e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Filtering
405e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
406e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
407e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
408e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void setDrawFilter(DrawFilter filter) {
4096926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        mFilter = filter;
410e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
411e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
412e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
413e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public DrawFilter getDrawFilter() {
4146926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        return mFilter;
415e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
416e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
417e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
418e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    // Drawing
419e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    ///////////////////////////////////////////////////////////////////////////
420e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
421e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
422e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
423e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            Paint paint) {
424e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
425e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
426e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
427e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
428e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawARGB(int a, int r, int g, int b) {
42985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
430e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
431e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
432e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
433deba785f122a47915756ffd991f5540d952cf937Romain Guy    public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
434d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing patches
435db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasColorFilter = paint != null && setupColorFilter(paint);
436deba785f122a47915756ffd991f5540d952cf937Romain Guy        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
437dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy        nDrawPatch(mRenderer, bitmap.mNativeBitmap, chunks, dst.left, dst.top,
438dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy                dst.right, dst.bottom, nativePaint);
439db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasColorFilter) nResetModifiers(mRenderer);
440deba785f122a47915756ffd991f5540d952cf937Romain Guy    }
441deba785f122a47915756ffd991f5540d952cf937Romain Guy
442deba785f122a47915756ffd991f5540d952cf937Romain Guy    private native void nDrawPatch(int renderer, int bitmap, byte[] chunks, float left, float top,
443dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy            float right, float bottom, int paint);
444deba785f122a47915756ffd991f5540d952cf937Romain Guy
445deba785f122a47915756ffd991f5540d952cf937Romain Guy    @Override
446e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
447d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
448db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasColorFilter = paint != null && setupColorFilter(paint);
449ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
450dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
451db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasColorFilter) nResetModifiers(mRenderer);
452e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
453e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
454dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy    private native void nDrawBitmap(int renderer, int bitmap, float left, float top, int paint);
455dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy
456e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
457e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
458d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
459db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasColorFilter = paint != null && setupColorFilter(paint);
460ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
461dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
462db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasColorFilter) nResetModifiers(mRenderer);
463e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
464e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
465dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy    private native void nDrawBitmap(int renderer, int bitmap, int matrix, int paint);
466f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
467e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
468e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
469d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
470db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasColorFilter = paint != null && setupColorFilter(paint);
471ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
472694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy
473694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy        int left, top, right, bottom;
474694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy        if (src == null) {
475694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            left = top = 0;
476694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            right = bitmap.getWidth();
477694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            bottom = bitmap.getHeight();
478694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy        } else {
479694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            left = src.left;
480694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            right = src.right;
481694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            top = src.top;
482694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy            bottom = src.bottom;
483694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy        }
484694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy
485694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
486694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
487db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasColorFilter) nResetModifiers(mRenderer);
488e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
489e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
490e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
491e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
492d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
493db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasColorFilter = paint != null && setupColorFilter(paint);
494ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
495ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
496694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy                dst.left, dst.top, dst.right, dst.bottom, nativePaint);
497db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasColorFilter) nResetModifiers(mRenderer);
498e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
499e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
500ce0537b80087a6225273040a987414b1dd081aa0Romain Guy    private native void nDrawBitmap(int renderer, int bitmap,
501ce0537b80087a6225273040a987414b1dd081aa0Romain Guy            float srcLeft, float srcTop, float srcRight, float srcBottom,
502dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy            float left, float top, float right, float bottom, int paint);
503ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
504e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
505e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
506e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
507d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
508db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasColorFilter = paint != null && setupColorFilter(paint);
5096926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
5106926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config);
5116926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
5126926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        nDrawBitmap(mRenderer, b.mNativeBitmap, x, y, nativePaint);
5136926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        b.recycle();
514db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasColorFilter) nResetModifiers(mRenderer);
515e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
516e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
517e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
518e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
519e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int width, int height, boolean hasAlpha, Paint paint) {
520d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // Shaders are ignored when drawing bitmaps
521ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
522e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
523e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
524e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
525e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
526e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int vertOffset, int[] colors, int colorOffset, Paint paint) {
5276926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        // TODO: Implement
528e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
529e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
530e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
531e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawCircle(float cx, float cy, float radius, Paint paint) {
532e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
533e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
534e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
535e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
536e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color) {
53785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(color, PorterDuff.Mode.SRC_OVER);
538e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
539e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
540e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
541e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawColor(int color, PorterDuff.Mode mode) {
54285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        nDrawColor(mRenderer, color, mode.nativeInt);
543e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
54485bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
54585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy    private native void nDrawColor(int renderer, int color, int mode);
546e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
547e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
548e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
549ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        mLine[0] = startX;
550ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        mLine[1] = startY;
551ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        mLine[2] = stopX;
552ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        mLine[3] = stopY;
553759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        drawLines(mLine, 0, 4, paint);
554e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
555e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
556e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
557e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, int offset, int count, Paint paint) {
558759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        if ((offset | count) < 0 || offset + count > pts.length) {
559759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
560759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        }
561759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        boolean hasModifier = setupModifiers(paint);
562759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
563759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        if (hasModifier) nResetModifiers(mRenderer);
564e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
565e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
566759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy    private native void nDrawLines(int renderer, float[] points, int offset, int count, int paint);
567759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy
568e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
569e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawLines(float[] pts, Paint paint) {
570759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy        drawLines(pts, 0, pts.length, paint);
571e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
572e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
573e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
574e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawOval(RectF oval, Paint paint) {
575e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
576e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
577e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
578e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
579e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPaint(Paint paint) {
5806926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        final Rect r = mClipBounds;
5816926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        nGetClipBounds(mRenderer, r);
5826926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
583e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
584e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
585e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
586e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPath(Path path, Paint paint) {
5877fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy        boolean hasModifier = setupModifiers(paint);
588a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy        if (path.isSimplePath) {
589a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy            if (path.rects != null) {
590a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy                nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
591a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy            }
592a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy        } else {
593a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy            nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
594a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy        }
5957fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy        if (hasModifier) nResetModifiers(mRenderer);
596e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
597e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
5987fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy    private native void nDrawPath(int renderer, int path, int paint);
599a48a1a87ba17f20f7006eaab21dcedf86c015c13Romain Guy    private native void nDrawRects(int renderer, int region, int paint);
6007fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy
601e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
602e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture) {
603e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
604e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
605e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
606e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
607e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture, Rect dst) {
608e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
609e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
610e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
611e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
612e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPicture(Picture picture, RectF dst) {
613e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
614e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
615e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
616e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
617e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPoint(float x, float y, Paint paint) {
618ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        mPoint[0] = x;
619ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        mPoint[1] = y;
620ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        drawPoints(mPoint, 0, 1, paint);
621e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
622e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
623e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
624e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
625e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        // TODO: Implement
626e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
627e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
628e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
629e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPoints(float[] pts, Paint paint) {
630ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        drawPoints(pts, 0, pts.length / 2, paint);
631e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
632e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
633e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
634e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
635e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
636e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
637e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
638e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
639e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawPosText(String text, float[] pos, Paint paint) {
640e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
641e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
642e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
643e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
644e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
645db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasModifier = setupModifiers(paint);
646c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
647db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (hasModifier) nResetModifiers(mRenderer);
648e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
649e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
650c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    private native void nDrawRect(int renderer, float left, float top, float right, float bottom,
651c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy            int paint);
652c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
653e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
654e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRect(Rect r, Paint paint) {
655c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
656e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
657e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
658e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
659c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    public void drawRect(RectF r, Paint paint) {
660c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        drawRect(r.left, r.top, r.right, r.bottom, paint);
661e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
662e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
663e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
664e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRGB(int r, int g, int b) {
66585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
666e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
667e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
668e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
669e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
670d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        // TODO: Implement
671e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
672e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
673e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
674e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
675a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((index | count | (index + count) | (text.length - index - count)) < 0) {
676a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
677a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
67861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
679db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasModifier = setupModifiers(paint);
68061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
68161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
68261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
68361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (hasModifier) nResetModifiers(mRenderer);
68461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
685e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
686a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
687a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y,
688a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            int bidiFlags, int paint);
689e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
690e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
691e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
692db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasModifier = setupModifiers(paint);
69361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
69461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (text instanceof String || text instanceof SpannedString ||
69561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    text instanceof SpannableString) {
69661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
69761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        paint.mNativePaint);
69861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else if (text instanceof GraphicsOperations) {
69961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                ((GraphicsOperations) text).drawText(this, start, end, x, y,
70061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                                                         paint);
70161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else {
70261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                char[] buf = TemporaryBuffer.obtain(end - start);
70361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TextUtils.getChars(text, start, end, buf, 0);
70461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint);
70561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TemporaryBuffer.recycle(buf);
70661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            }
70761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
70861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (hasModifier) nResetModifiers(mRenderer);
709a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
710e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
711e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
712e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
713e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
714a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        if ((start | end | (end - start) | (text.length() - end)) < 0) {
715a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            throw new IndexOutOfBoundsException();
716a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy        }
71761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
718db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasModifier = setupModifiers(paint);
71961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
72061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
72161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
72261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (hasModifier) nResetModifiers(mRenderer);
72361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
724e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
725e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
726a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    private native void nDrawText(int renderer, String text, int start, int end, float x, float y,
727a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy            int bidiFlags, int paint);
728a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
729e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
730e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawText(String text, float x, float y, Paint paint) {
731db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasModifier = setupModifiers(paint);
73261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
73361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
73461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    paint.mNativePaint);
73561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
73661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (hasModifier) nResetModifiers(mRenderer);
73761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
738e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
739e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
740e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
741e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
742e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float vOffset, Paint paint) {
743e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
744e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
745e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
746e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
747e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
748e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        throw new UnsupportedOperationException();
749e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
750e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
751e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
752e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
753e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float x, float y, int dir, Paint paint) {
75461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((index | count | text.length - index - count) < 0) {
75561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
75661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
75761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
75861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IllegalArgumentException("Unknown direction: " + dir);
75961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
76061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
76161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        boolean hasModifier = setupModifiers(paint);
76261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
76361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
76461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    paint.mNativePaint);
76561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
76661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (hasModifier) nResetModifiers(mRenderer);
76761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
768e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
769e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
77061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    private native void nDrawTextRun(int renderer, char[] text, int index, int count,
77161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
77261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
773e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
774e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
775e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float x, float y, int dir, Paint paint) {
77661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        if ((start | end | end - start | text.length() - end) < 0) {
77761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            throw new IndexOutOfBoundsException();
77861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
77961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
78061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        boolean hasModifier = setupModifiers(paint);
78161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        try {
78261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            int flags = dir == 0 ? 0 : 1;
78361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (text instanceof String || text instanceof SpannedString ||
78461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    text instanceof SpannableString) {
78561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
78661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        contextEnd, x, y, flags, paint.mNativePaint);
78761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else if (text instanceof GraphicsOperations) {
78861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                ((GraphicsOperations) text).drawTextRun(this, start, end,
78961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        contextStart, contextEnd, x, y, flags, paint);
79061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            } else {
79161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                int contextLen = contextEnd - contextStart;
79261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                int len = end - start;
79361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                char[] buf = TemporaryBuffer.obtain(contextLen);
79461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
79561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
79661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        x, y, flags, paint.mNativePaint);
79761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                TemporaryBuffer.recycle(buf);
79861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            }
79961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        } finally {
80061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            if (hasModifier) nResetModifiers(mRenderer);
80161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        }
802e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
803e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
80461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    private native void nDrawTextRun(int renderer, String text, int start, int end,
80561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy            int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
80661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
807e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    @Override
808e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
809e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
810e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            int indexOffset, int indexCount, Paint paint) {
8116926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy        // TODO: Implement
812e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    }
813d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy
814db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    private boolean setupModifiers(Paint paint) {
815db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        boolean hasModifier = false;
816db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy
8171e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        if (paint.hasShadow) {
8181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
8191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                    paint.shadowColor);
8201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            hasModifier = true;
8211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        }
8221e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
823d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        final Shader shader = paint.getShader();
824d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        if (shader != null) {
82506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            nSetupShader(mRenderer, shader.native_shader);
826db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy            hasModifier = true;
827db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        }
828db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy
829db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        final ColorFilter filter = paint.getColorFilter();
830db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (filter != null) {
831db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy            nSetupColorFilter(mRenderer, filter.nativeColorFilter);
832db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy            hasModifier = true;
833db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        }
834db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy
835db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        return hasModifier;
836db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    }
8371e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
838db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    private boolean setupColorFilter(Paint paint) {
839db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        final ColorFilter filter = paint.getColorFilter();
840db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        if (filter != null) {
841db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy            nSetupColorFilter(mRenderer, filter.nativeColorFilter);
84206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            return true;
843d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        }
844db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy        return false;
845d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy    }
846db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy
84706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    private native void nSetupShader(int renderer, int shader);
848db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    private native void nSetupColorFilter(int renderer, int colorFilter);
8491e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    private native void nSetupShadow(int renderer, float radius, float dx, float dy, int color);
8501e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
851db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy    private native void nResetModifiers(int renderer);
852e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
853