blob: d2d1f1b396dc9703d23f50be1933dcebd8c0a7d1 [file] [log] [blame]
Romain Guye4d01122010-06-16 18:44:05 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.graphics.Bitmap;
20import android.graphics.Canvas;
Romain Guydb1938e2010-08-02 18:50:22 -070021import android.graphics.ColorFilter;
Romain Guye4d01122010-06-16 18:44:05 -070022import android.graphics.DrawFilter;
23import android.graphics.Matrix;
Romain Guy3b748a42013-04-17 18:54:38 -070024import android.graphics.NinePatch;
Romain Guye4d01122010-06-16 18:44:05 -070025import android.graphics.Paint;
Romain Guy5ff9df62012-01-23 17:09:05 -080026import android.graphics.PaintFlagsDrawFilter;
Romain Guye4d01122010-06-16 18:44:05 -070027import android.graphics.Path;
28import android.graphics.Picture;
29import android.graphics.PorterDuff;
30import android.graphics.Rect;
31import android.graphics.RectF;
32import android.graphics.Region;
Romain Guyd27977d2010-07-14 19:18:51 -070033import android.graphics.Shader;
Romain Guye5e0c502011-06-15 15:18:31 -070034import android.graphics.SurfaceTexture;
Romain Guya1db5742010-07-20 13:09:13 -070035import android.graphics.TemporaryBuffer;
36import android.text.GraphicsOperations;
37import android.text.SpannableString;
38import android.text.SpannedString;
39import android.text.TextUtils;
Romain Guye4d01122010-06-16 18:44:05 -070040
Romain Guye4d01122010-06-16 18:44:05 -070041/**
42 * An implementation of Canvas on top of OpenGL ES 2.0.
43 */
Romain Guyb051e892010-09-28 19:09:36 -070044class GLES20Canvas extends HardwareCanvas {
Romain Guya168d732011-03-18 16:50:13 -070045 // Must match modifiers used in the JNI layer
46 private static final int MODIFIER_NONE = 0;
47 private static final int MODIFIER_SHADOW = 1;
48 private static final int MODIFIER_SHADER = 2;
49 private static final int MODIFIER_COLOR_FILTER = 4;
50
Romain Guye4d01122010-06-16 18:44:05 -070051 private final boolean mOpaque;
Romain Guyfb8b7632010-08-23 21:05:08 -070052 private int mRenderer;
Patrick Dubroyf890fab2010-12-19 16:47:17 -080053
54 // The native renderer will be destroyed when this object dies.
55 // DO NOT overwrite this reference once it is set.
Romain Guyeea60692011-07-26 20:35:55 -070056 @SuppressWarnings({"unused", "FieldCanBeLocal"})
Patrick Dubroyf890fab2010-12-19 16:47:17 -080057 private CanvasFinalizer mFinalizer;
58
Romain Guye4d01122010-06-16 18:44:05 -070059 private int mWidth;
60 private int mHeight;
Romain Guyce0537b2010-06-29 21:05:21 -070061
Romain Guy6410c0a2013-06-17 11:21:58 -070062 private float[] mPoint;
63 private float[] mLine;
Romain Guy6926c722010-07-12 20:20:03 -070064
Romain Guy6410c0a2013-06-17 11:21:58 -070065 private Rect mClipBounds;
66 private RectF mPathBounds;
Romain Guy6926c722010-07-12 20:20:03 -070067
68 private DrawFilter mFilter;
Romain Guyda8532c2010-08-31 11:50:35 -070069
Romain Guy16393512010-08-08 00:14:31 -070070 ///////////////////////////////////////////////////////////////////////////
71 // JNI
72 ///////////////////////////////////////////////////////////////////////////
73
74 private static native boolean nIsAvailable();
75 private static boolean sIsAvailable = nIsAvailable();
76
77 static boolean isAvailable() {
78 return sIsAvailable;
79 }
Romain Guye4d01122010-06-16 18:44:05 -070080
81 ///////////////////////////////////////////////////////////////////////////
82 // Constructors
83 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -070084
Romain Guy6c319ca2011-01-11 14:29:25 -080085 /**
86 * Creates a canvas to render directly on screen.
87 */
Romain Guyb051e892010-09-28 19:09:36 -070088 GLES20Canvas(boolean translucent) {
89 this(false, translucent);
90 }
Romain Guy6c319ca2011-01-11 14:29:25 -080091
92 /**
93 * Creates a canvas to render into an FBO.
94 */
Romain Guyada830f2011-01-13 12:13:20 -080095 GLES20Canvas(int layer, boolean translucent) {
Romain Guy6c319ca2011-01-11 14:29:25 -080096 mOpaque = !translucent;
Romain Guyada830f2011-01-13 12:13:20 -080097 mRenderer = nCreateLayerRenderer(layer);
Romain Guy6c319ca2011-01-11 14:29:25 -080098 setupFinalizer();
99 }
Romain Guye4d01122010-06-16 18:44:05 -0700100
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800101 protected GLES20Canvas(boolean record, boolean translucent) {
Romain Guye4d01122010-06-16 18:44:05 -0700102 mOpaque = !translucent;
103
Romain Guyb051e892010-09-28 19:09:36 -0700104 if (record) {
Jeff Brown162a0212011-07-21 17:02:54 -0700105 mRenderer = nCreateDisplayListRenderer();
Romain Guyb051e892010-09-28 19:09:36 -0700106 } else {
107 mRenderer = nCreateRenderer();
108 }
Romain Guy6c319ca2011-01-11 14:29:25 -0800109
110 setupFinalizer();
111 }
112
113 private void setupFinalizer() {
Romain Guyfb8b7632010-08-23 21:05:08 -0700114 if (mRenderer == 0) {
115 throw new IllegalStateException("Could not create GLES20Canvas renderer");
Chet Haase5c13d892010-10-08 08:37:55 -0700116 } else {
Jeff Brown162a0212011-07-21 17:02:54 -0700117 mFinalizer = new CanvasFinalizer(mRenderer);
Romain Guyfb8b7632010-08-23 21:05:08 -0700118 }
Romain Guye4d01122010-06-16 18:44:05 -0700119 }
Romain Guye4d01122010-06-16 18:44:05 -0700120
Jeff Brown162a0212011-07-21 17:02:54 -0700121 protected void resetDisplayListRenderer() {
122 nResetDisplayListRenderer(mRenderer);
123 }
124
Romain Guy6c319ca2011-01-11 14:29:25 -0800125 private static native int nCreateRenderer();
Romain Guyada830f2011-01-13 12:13:20 -0800126 private static native int nCreateLayerRenderer(int layer);
Jeff Brown162a0212011-07-21 17:02:54 -0700127 private static native int nCreateDisplayListRenderer();
128 private static native void nResetDisplayListRenderer(int renderer);
Chet Haase5c13d892010-10-08 08:37:55 -0700129 private static native void nDestroyRenderer(int renderer);
130
Jeff Brown162a0212011-07-21 17:02:54 -0700131 private static final class CanvasFinalizer {
132 private final int mRenderer;
Chet Haase5c13d892010-10-08 08:37:55 -0700133
Jeff Brown162a0212011-07-21 17:02:54 -0700134 public CanvasFinalizer(int renderer) {
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800135 mRenderer = renderer;
Chet Haase5c13d892010-10-08 08:37:55 -0700136 }
137
138 @Override
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800139 protected void finalize() throws Throwable {
Romain Guy171c5922011-01-06 10:04:23 -0800140 try {
Jeff Brown162a0212011-07-21 17:02:54 -0700141 nDestroyRenderer(mRenderer);
Romain Guy171c5922011-01-06 10:04:23 -0800142 } finally {
143 super.finalize();
144 }
Romain Guye4d01122010-06-16 18:44:05 -0700145 }
146 }
Romain Guyce0537b2010-06-29 21:05:21 -0700147
Romain Guyef359272013-01-31 19:07:29 -0800148 @Override
149 public void setName(String name) {
150 super.setName(name);
151 nSetName(mRenderer, name);
152 }
153
154 private static native void nSetName(int renderer, String name);
155
Romain Guye4d01122010-06-16 18:44:05 -0700156 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800157 // Hardware layers
158 ///////////////////////////////////////////////////////////////////////////
Romain Guy11cb6422012-09-21 00:39:43 -0700159
160 @Override
161 void pushLayerUpdate(HardwareLayer layer) {
162 nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
163 }
164
165 @Override
Romain Guye93482f2013-06-17 13:14:51 -0700166 void cancelLayerUpdate(HardwareLayer layer) {
167 nCancelLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
168 }
169
170 @Override
Romain Guy40543602013-06-12 15:31:28 -0700171 void flushLayerUpdates() {
172 nFlushLayerUpdates(mRenderer);
173 }
174
175 @Override
Romain Guy11cb6422012-09-21 00:39:43 -0700176 void clearLayerUpdates() {
177 nClearLayerUpdates(mRenderer);
178 }
179
Romain Guya9489272011-06-22 20:58:11 -0700180 static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
Romain Guyada830f2011-01-13 12:13:20 -0800181 static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
Chet Haase603f6de2012-09-14 15:31:25 -0700182 static native boolean nResizeLayer(int layerId, int width, int height, int[] layerInfo);
Romain Guy846a5332012-07-11 17:44:57 -0700183 static native void nSetOpaqueLayer(int layerId, boolean isOpaque);
Chet Haased15ebf22012-09-05 11:40:29 -0700184 static native void nSetLayerPaint(int layerId, int nativePaint);
185 static native void nSetLayerColorFilter(int layerId, int nativeColorFilter);
Romain Guya9489272011-06-22 20:58:11 -0700186 static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
187 SurfaceTexture surface);
Romain Guyef09a212012-09-25 12:17:14 -0700188 static native void nClearLayerTexture(int layerId);
Romain Guy302a9df2011-08-16 13:55:02 -0700189 static native void nSetTextureLayerTransform(int layerId, int matrix);
Romain Guyada830f2011-01-13 12:13:20 -0800190 static native void nDestroyLayer(int layerId);
191 static native void nDestroyLayerDeferred(int layerId);
Romain Guy2bf68f02012-03-02 13:37:47 -0800192 static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
193 int left, int top, int right, int bottom);
Romain Guy77a81162011-06-14 16:45:55 -0700194 static native boolean nCopyLayer(int layerId, int bitmap);
Romain Guy57066eb2011-01-12 12:53:32 -0800195
Romain Guy11cb6422012-09-21 00:39:43 -0700196 private static native void nClearLayerUpdates(int renderer);
Romain Guy40543602013-06-12 15:31:28 -0700197 private static native void nFlushLayerUpdates(int renderer);
Romain Guy11cb6422012-09-21 00:39:43 -0700198 private static native void nPushLayerUpdate(int renderer, int layer);
Romain Guye93482f2013-06-17 13:14:51 -0700199 private static native void nCancelLayerUpdate(int renderer, int layer);
Romain Guy11cb6422012-09-21 00:39:43 -0700200
Romain Guy6c319ca2011-01-11 14:29:25 -0800201 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700202 // Canvas management
203 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700204
205 @Override
206 public boolean isOpaque() {
207 return mOpaque;
208 }
209
210 @Override
211 public int getWidth() {
212 return mWidth;
213 }
214
215 @Override
216 public int getHeight() {
217 return mHeight;
218 }
219
Romain Guyf61970fc2011-07-07 14:10:06 -0700220 @Override
221 public int getMaximumBitmapWidth() {
222 return nGetMaximumTextureWidth();
223 }
224
225 @Override
226 public int getMaximumBitmapHeight() {
227 return nGetMaximumTextureHeight();
228 }
229
230 private static native int nGetMaximumTextureWidth();
Romain Guy530041d2012-01-25 18:56:29 -0800231 private static native int nGetMaximumTextureHeight();
Romain Guyf61970fc2011-07-07 14:10:06 -0700232
Romain Guy2bf68f02012-03-02 13:37:47 -0800233 /**
234 * Returns the native OpenGLRenderer object.
235 */
236 int getRenderer() {
237 return mRenderer;
238 }
239
Romain Guye4d01122010-06-16 18:44:05 -0700240 ///////////////////////////////////////////////////////////////////////////
241 // Setup
242 ///////////////////////////////////////////////////////////////////////////
243
244 @Override
245 public void setViewport(int width, int height) {
246 mWidth = width;
247 mHeight = height;
248
249 nSetViewport(mRenderer, width, height);
250 }
251
Romain Guy7d7b5492011-01-24 16:33:45 -0800252 private static native void nSetViewport(int renderer, int width, int height);
Romain Guye4d01122010-06-16 18:44:05 -0700253
Romain Guy7d7b5492011-01-24 16:33:45 -0800254 @Override
Chet Haase44b2fe32012-06-06 19:03:58 -0700255 public int onPreDraw(Rect dirty) {
Romain Guy7d7b5492011-01-24 16:33:45 -0800256 if (dirty != null) {
Chet Haase44b2fe32012-06-06 19:03:58 -0700257 return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
258 mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800259 } else {
Chet Haase44b2fe32012-06-06 19:03:58 -0700260 return nPrepare(mRenderer, mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800261 }
262 }
263
Chet Haase44b2fe32012-06-06 19:03:58 -0700264 private static native int nPrepare(int renderer, boolean opaque);
265 private static native int nPrepareDirty(int renderer, int left, int top, int right, int bottom,
Romain Guy7d7b5492011-01-24 16:33:45 -0800266 boolean opaque);
Romain Guye4d01122010-06-16 18:44:05 -0700267
Romain Guyb051e892010-09-28 19:09:36 -0700268 @Override
Gilles Debunneb35ab7b2011-12-05 15:54:00 -0800269 public void onPostDraw() {
Romain Guyb025b9c2010-09-16 14:16:48 -0700270 nFinish(mRenderer);
271 }
Romain Guy9ace8f52011-07-07 20:50:11 -0700272
Romain Guy7d7b5492011-01-24 16:33:45 -0800273 private static native void nFinish(int renderer);
Romain Guyb025b9c2010-09-16 14:16:48 -0700274
Romain Guy530041d2012-01-25 18:56:29 -0800275 /**
276 * Returns the size of the stencil buffer required by the underlying
277 * implementation.
278 *
279 * @return The minimum number of bits the stencil buffer must. Always >= 0.
280 *
281 * @hide
282 */
283 public static int getStencilSize() {
284 return nGetStencilSize();
285 }
286
287 private static native int nGetStencilSize();
288
Romain Guy78dd96d2013-05-03 14:24:16 -0700289 void setCountOverdrawEnabled(boolean enabled) {
290 nSetCountOverdrawEnabled(mRenderer, enabled);
291 }
292
293 static native void nSetCountOverdrawEnabled(int renderer, boolean enabled);
294
295 float getOverdraw() {
296 return nGetOverdraw(mRenderer);
297 }
298
299 static native float nGetOverdraw(int renderer);
300
Romain Guy530041d2012-01-25 18:56:29 -0800301 ///////////////////////////////////////////////////////////////////////////
302 // Functor
303 ///////////////////////////////////////////////////////////////////////////
304
Romain Guyda8532c2010-08-31 11:50:35 -0700305 @Override
Romain Guy65549432012-03-26 16:45:05 -0700306 public int callDrawGLFunction(int drawGLFunction) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800307 return nCallDrawGLFunction(mRenderer, drawGLFunction);
308 }
309
Romain Guy65549432012-03-26 16:45:05 -0700310 private static native int nCallDrawGLFunction(int renderer, int drawGLFunction);
Chet Haasedaf98e92011-01-10 14:10:36 -0800311
Romain Guy8f3b8e32012-03-27 16:33:45 -0700312 @Override
313 public int invokeFunctors(Rect dirty) {
314 return nInvokeFunctors(mRenderer, dirty);
315 }
316
317 private static native int nInvokeFunctors(int renderer, Rect dirty);
318
Romain Guyba6be8a2012-04-23 18:22:09 -0700319 @Override
320 public void detachFunctor(int functor) {
321 nDetachFunctor(mRenderer, functor);
322 }
323
324 private static native void nDetachFunctor(int renderer, int functor);
325
326 @Override
327 public void attachFunctor(int functor) {
328 nAttachFunctor(mRenderer, functor);
329 }
330
331 private static native void nAttachFunctor(int renderer, int functor);
332
Romain Guybdf76092011-07-18 15:00:43 -0700333 ///////////////////////////////////////////////////////////////////////////
334 // Memory
335 ///////////////////////////////////////////////////////////////////////////
336
337 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700338 * Must match Caches::FlushMode values
339 *
Romain Guybdf76092011-07-18 15:00:43 -0700340 * @see #flushCaches(int)
341 */
Romain Guy3b748a42013-04-17 18:54:38 -0700342 static final int FLUSH_CACHES_LAYERS = 0;
Romain Guy6d7475d2011-07-27 16:28:21 -0700343
344 /**
345 * Must match Caches::FlushMode values
346 *
347 * @see #flushCaches(int)
348 */
Romain Guy3b748a42013-04-17 18:54:38 -0700349 static final int FLUSH_CACHES_MODERATE = 1;
Romain Guybdf76092011-07-18 15:00:43 -0700350
351 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700352 * Must match Caches::FlushMode values
353 *
Romain Guybdf76092011-07-18 15:00:43 -0700354 * @see #flushCaches(int)
355 */
Romain Guy3b748a42013-04-17 18:54:38 -0700356 static final int FLUSH_CACHES_FULL = 2;
Romain Guybdf76092011-07-18 15:00:43 -0700357
358 /**
359 * Flush caches to reclaim as much memory as possible. The amount of memory
360 * to reclaim is indicate by the level parameter.
361 *
362 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
363 * {@link #FLUSH_CACHES_FULL}.
364 *
365 * @param level Hint about the amount of memory to reclaim
Romain Guybdf76092011-07-18 15:00:43 -0700366 */
Romain Guy3b748a42013-04-17 18:54:38 -0700367 static void flushCaches(int level) {
Romain Guybdf76092011-07-18 15:00:43 -0700368 nFlushCaches(level);
369 }
370
371 private static native void nFlushCaches(int level);
372
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800373 /**
374 * Release all resources associated with the underlying caches. This should
375 * only be called after a full flushCaches().
376 *
377 * @hide
378 */
Romain Guy3b748a42013-04-17 18:54:38 -0700379 static void terminateCaches() {
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800380 nTerminateCaches();
381 }
382
383 private static native void nTerminateCaches();
384
Romain Guy3b748a42013-04-17 18:54:38 -0700385 static boolean initCaches() {
386 return nInitCaches();
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800387 }
388
Romain Guy3b748a42013-04-17 18:54:38 -0700389 private static native boolean nInitCaches();
390
391 ///////////////////////////////////////////////////////////////////////////
392 // Atlas
393 ///////////////////////////////////////////////////////////////////////////
394
395 static void initAtlas(GraphicBuffer buffer, int[] map) {
396 nInitAtlas(buffer, map, map.length);
397 }
398
399 private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count);
400
Romain Guyb051e892010-09-28 19:09:36 -0700401 ///////////////////////////////////////////////////////////////////////////
402 // Display list
403 ///////////////////////////////////////////////////////////////////////////
404
Jeff Brown162a0212011-07-21 17:02:54 -0700405 int getDisplayList(int displayList) {
406 return nGetDisplayList(mRenderer, displayList);
Romain Guyb051e892010-09-28 19:09:36 -0700407 }
408
Jeff Brown162a0212011-07-21 17:02:54 -0700409 private static native int nGetDisplayList(int renderer, int displayList);
Romain Guy52036b12013-02-14 18:03:37 -0800410
411 @Override
412 void outputDisplayList(DisplayList displayList) {
413 nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList());
Romain Guyb051e892010-09-28 19:09:36 -0700414 }
415
Romain Guy52036b12013-02-14 18:03:37 -0800416 private static native void nOutputDisplayList(int renderer, int displayList);
Romain Guy13631f32012-01-30 17:41:55 -0800417
Romain Guyb051e892010-09-28 19:09:36 -0700418 @Override
Chet Haase1271e2c2012-04-20 09:54:27 -0700419 public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
Romain Guy33f6beb2012-02-16 19:24:51 -0800420 return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList(),
Chet Haase1271e2c2012-04-20 09:54:27 -0700421 dirty, flags);
Romain Guyb051e892010-09-28 19:09:36 -0700422 }
423
Romain Guy65549432012-03-26 16:45:05 -0700424 private static native int nDrawDisplayList(int renderer, int displayList,
Chet Haase1271e2c2012-04-20 09:54:27 -0700425 Rect dirty, int flags);
Romain Guyda8532c2010-08-31 11:50:35 -0700426
Romain Guye4d01122010-06-16 18:44:05 -0700427 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800428 // Hardware layer
429 ///////////////////////////////////////////////////////////////////////////
430
Romain Guyada830f2011-01-13 12:13:20 -0800431 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
Chris Craika4e16c52013-03-22 10:00:48 -0700432 layer.setLayerPaint(paint);
433
Romain Guy6c319ca2011-01-11 14:29:25 -0800434 final GLES20Layer glLayer = (GLES20Layer) layer;
Chris Craika4e16c52013-03-22 10:00:48 -0700435 nDrawLayer(mRenderer, glLayer.getLayer(), x, y);
Romain Guy6c319ca2011-01-11 14:29:25 -0800436 }
437
Chris Craika4e16c52013-03-22 10:00:48 -0700438 private static native void nDrawLayer(int renderer, int layer, float x, float y);
Romain Guyaa6c24c2011-04-28 18:40:04 -0700439
Romain Guy6c319ca2011-01-11 14:29:25 -0800440 void interrupt() {
441 nInterrupt(mRenderer);
442 }
443
444 void resume() {
445 nResume(mRenderer);
446 }
447
Romain Guy7d7b5492011-01-24 16:33:45 -0800448 private static native void nInterrupt(int renderer);
449 private static native void nResume(int renderer);
Romain Guy6c319ca2011-01-11 14:29:25 -0800450
451 ///////////////////////////////////////////////////////////////////////////
Romain Guy6410c0a2013-06-17 11:21:58 -0700452 // Support
453 ///////////////////////////////////////////////////////////////////////////
454
455 private Rect getInternalClipBounds() {
456 if (mClipBounds == null) mClipBounds = new Rect();
457 return mClipBounds;
458 }
459
460
461 private RectF getPathBounds() {
462 if (mPathBounds == null) mPathBounds = new RectF();
463 return mPathBounds;
464 }
465
466 private float[] getPointStorage() {
467 if (mPoint == null) mPoint = new float[2];
468 return mPoint;
469 }
470
471 private float[] getLineStorage() {
472 if (mLine == null) mLine = new float[4];
473 return mLine;
474 }
475
476 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700477 // Clipping
478 ///////////////////////////////////////////////////////////////////////////
479
480 @Override
481 public boolean clipPath(Path path) {
Romain Guy735738c2012-12-03 12:34:51 -0800482 return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700483 }
484
485 @Override
486 public boolean clipPath(Path path, Region.Op op) {
Romain Guy735738c2012-12-03 12:34:51 -0800487 return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700488 }
489
Romain Guy735738c2012-12-03 12:34:51 -0800490 private static native boolean nClipPath(int renderer, int path, int op);
491
Romain Guye4d01122010-06-16 18:44:05 -0700492 @Override
493 public boolean clipRect(float left, float top, float right, float bottom) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700494 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700495 }
Romain Guybb9524b2010-06-22 18:56:38 -0700496
Romain Guy7d7b5492011-01-24 16:33:45 -0800497 private static native boolean nClipRect(int renderer, float left, float top,
Romain Guy079ba2c2010-07-16 14:12:24 -0700498 float right, float bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700499
500 @Override
501 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700502 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700503 }
504
505 @Override
506 public boolean clipRect(int left, int top, int right, int bottom) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800507 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700508 }
Romain Guybb9524b2010-06-22 18:56:38 -0700509
Romain Guy735738c2012-12-03 12:34:51 -0800510 private static native boolean nClipRect(int renderer, int left, int top,
511 int right, int bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700512
513 @Override
514 public boolean clipRect(Rect rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700515 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
516 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700517 }
518
519 @Override
520 public boolean clipRect(Rect rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700521 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700522 }
523
524 @Override
525 public boolean clipRect(RectF rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700526 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
527 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700528 }
529
530 @Override
531 public boolean clipRect(RectF rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700532 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700533 }
534
535 @Override
536 public boolean clipRegion(Region region) {
Romain Guy735738c2012-12-03 12:34:51 -0800537 return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700538 }
539
540 @Override
541 public boolean clipRegion(Region region, Region.Op op) {
Romain Guy735738c2012-12-03 12:34:51 -0800542 return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700543 }
544
Romain Guy735738c2012-12-03 12:34:51 -0800545 private static native boolean nClipRegion(int renderer, int region, int op);
546
Romain Guye4d01122010-06-16 18:44:05 -0700547 @Override
548 public boolean getClipBounds(Rect bounds) {
Romain Guy9d5316e2010-06-24 19:30:36 -0700549 return nGetClipBounds(mRenderer, bounds);
Romain Guye4d01122010-06-16 18:44:05 -0700550 }
551
Romain Guy7d7b5492011-01-24 16:33:45 -0800552 private static native boolean nGetClipBounds(int renderer, Rect bounds);
Romain Guy9d5316e2010-06-24 19:30:36 -0700553
Romain Guye4d01122010-06-16 18:44:05 -0700554 @Override
555 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400556 return nQuickReject(mRenderer, left, top, right, bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700557 }
Romain Guyc7d53492010-06-25 13:41:57 -0700558
Romain Guy7d7b5492011-01-24 16:33:45 -0800559 private static native boolean nQuickReject(int renderer, float left, float top,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400560 float right, float bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700561
562 @Override
563 public boolean quickReject(Path path, EdgeType type) {
Romain Guy6410c0a2013-06-17 11:21:58 -0700564 RectF pathBounds = getPathBounds();
565 path.computeBounds(pathBounds, true);
566 return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
567 pathBounds.right, pathBounds.bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700568 }
569
570 @Override
571 public boolean quickReject(RectF rect, EdgeType type) {
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400572 return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700573 }
574
575 ///////////////////////////////////////////////////////////////////////////
576 // Transformations
577 ///////////////////////////////////////////////////////////////////////////
578
579 @Override
580 public void translate(float dx, float dy) {
Romain Guy807daf72011-01-18 11:19:19 -0800581 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
Romain Guye4d01122010-06-16 18:44:05 -0700582 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700583
Romain Guy7d7b5492011-01-24 16:33:45 -0800584 private static native void nTranslate(int renderer, float dx, float dy);
Romain Guye4d01122010-06-16 18:44:05 -0700585
586 @Override
587 public void skew(float sx, float sy) {
Romain Guy807daf72011-01-18 11:19:19 -0800588 nSkew(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700589 }
590
Romain Guy7d7b5492011-01-24 16:33:45 -0800591 private static native void nSkew(int renderer, float sx, float sy);
Romain Guy807daf72011-01-18 11:19:19 -0800592
Romain Guye4d01122010-06-16 18:44:05 -0700593 @Override
594 public void rotate(float degrees) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700595 nRotate(mRenderer, degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700596 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700597
Romain Guy7d7b5492011-01-24 16:33:45 -0800598 private static native void nRotate(int renderer, float degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700599
600 @Override
601 public void scale(float sx, float sy) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700602 nScale(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700603 }
Romain Guye4d01122010-06-16 18:44:05 -0700604
Romain Guy7d7b5492011-01-24 16:33:45 -0800605 private static native void nScale(int renderer, float sx, float sy);
Romain Guyf6a11b82010-06-23 17:47:49 -0700606
Romain Guye4d01122010-06-16 18:44:05 -0700607 @Override
608 public void setMatrix(Matrix matrix) {
Romain Guye7078592011-10-28 14:32:20 -0700609 nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700610 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700611
Romain Guy7d7b5492011-01-24 16:33:45 -0800612 private static native void nSetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700613
Romain Guy5ff9df62012-01-23 17:09:05 -0800614 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -0700615 @Override
Romain Guyf6a11b82010-06-23 17:47:49 -0700616 public void getMatrix(Matrix matrix) {
617 nGetMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700618 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700619
Romain Guy7d7b5492011-01-24 16:33:45 -0800620 private static native void nGetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700621
622 @Override
623 public void concat(Matrix matrix) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700624 if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700625 }
626
Romain Guy7d7b5492011-01-24 16:33:45 -0800627 private static native void nConcatMatrix(int renderer, int matrix);
Romain Guyf6a11b82010-06-23 17:47:49 -0700628
Romain Guye4d01122010-06-16 18:44:05 -0700629 ///////////////////////////////////////////////////////////////////////////
630 // State management
631 ///////////////////////////////////////////////////////////////////////////
632
633 @Override
634 public int save() {
Romain Guy8aef54f2010-09-01 15:13:49 -0700635 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
Romain Guye4d01122010-06-16 18:44:05 -0700636 }
Romain Guybb9524b2010-06-22 18:56:38 -0700637
Romain Guye4d01122010-06-16 18:44:05 -0700638 @Override
639 public int save(int saveFlags) {
Romain Guybb9524b2010-06-22 18:56:38 -0700640 return nSave(mRenderer, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700641 }
642
Romain Guy7d7b5492011-01-24 16:33:45 -0800643 private static native int nSave(int renderer, int flags);
Romain Guybb9524b2010-06-22 18:56:38 -0700644
Romain Guye4d01122010-06-16 18:44:05 -0700645 @Override
646 public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700647 if (bounds != null) {
648 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
649 }
650
Romain Guy445c83c2012-02-16 16:43:07 -0800651 int count;
Romain Guy189887e2011-08-25 11:45:13 -0700652 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800653 try {
654 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
655 count = nSaveLayer(mRenderer, nativePaint, saveFlags);
656 } finally {
657 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
658 }
Romain Guy189887e2011-08-25 11:45:13 -0700659 return count;
Romain Guye4d01122010-06-16 18:44:05 -0700660 }
661
Romain Guy189887e2011-08-25 11:45:13 -0700662 private static native int nSaveLayer(int renderer, int paint, int saveFlags);
663
Romain Guye4d01122010-06-16 18:44:05 -0700664 @Override
665 public int saveLayer(float left, float top, float right, float bottom, Paint paint,
666 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800667 if (left < right && top < bottom) {
Romain Guy445c83c2012-02-16 16:43:07 -0800668 int count;
Romain Guya168d732011-03-18 16:50:13 -0700669 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800670 try {
671 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
672 count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
673 } finally {
674 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
675 }
Romain Guy01d58e42011-01-19 21:54:02 -0800676 return count;
677 }
678 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700679 }
680
Romain Guy7d7b5492011-01-24 16:33:45 -0800681 private static native int nSaveLayer(int renderer, float left, float top,
682 float right, float bottom, int paint, int saveFlags);
Romain Guybd6b79b2010-06-26 00:13:53 -0700683
Romain Guye4d01122010-06-16 18:44:05 -0700684 @Override
685 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700686 if (bounds != null) {
687 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
688 alpha, saveFlags);
689 }
690 return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700691 }
692
Romain Guy189887e2011-08-25 11:45:13 -0700693 private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags);
694
Romain Guye4d01122010-06-16 18:44:05 -0700695 @Override
696 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
697 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800698 if (left < right && top < bottom) {
699 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
700 }
701 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700702 }
703
Romain Guy7d7b5492011-01-24 16:33:45 -0800704 private static native int nSaveLayerAlpha(int renderer, float left, float top, float right,
Romain Guybd6b79b2010-06-26 00:13:53 -0700705 float bottom, int alpha, int saveFlags);
706
Romain Guye4d01122010-06-16 18:44:05 -0700707 @Override
708 public void restore() {
Romain Guybb9524b2010-06-22 18:56:38 -0700709 nRestore(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700710 }
Romain Guybb9524b2010-06-22 18:56:38 -0700711
Romain Guy7d7b5492011-01-24 16:33:45 -0800712 private static native void nRestore(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700713
714 @Override
715 public void restoreToCount(int saveCount) {
Romain Guybb9524b2010-06-22 18:56:38 -0700716 nRestoreToCount(mRenderer, saveCount);
Romain Guye4d01122010-06-16 18:44:05 -0700717 }
718
Romain Guy7d7b5492011-01-24 16:33:45 -0800719 private static native void nRestoreToCount(int renderer, int saveCount);
Romain Guybb9524b2010-06-22 18:56:38 -0700720
Romain Guye4d01122010-06-16 18:44:05 -0700721 @Override
722 public int getSaveCount() {
Romain Guybb9524b2010-06-22 18:56:38 -0700723 return nGetSaveCount(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700724 }
Romain Guybb9524b2010-06-22 18:56:38 -0700725
Romain Guy7d7b5492011-01-24 16:33:45 -0800726 private static native int nGetSaveCount(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700727
728 ///////////////////////////////////////////////////////////////////////////
729 // Filtering
730 ///////////////////////////////////////////////////////////////////////////
731
732 @Override
733 public void setDrawFilter(DrawFilter filter) {
Romain Guy6926c722010-07-12 20:20:03 -0700734 mFilter = filter;
Romain Guy5ff9df62012-01-23 17:09:05 -0800735 if (filter == null) {
736 nResetPaintFilter(mRenderer);
737 } else if (filter instanceof PaintFlagsDrawFilter) {
738 PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
739 nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
740 }
Romain Guye4d01122010-06-16 18:44:05 -0700741 }
742
Romain Guy5ff9df62012-01-23 17:09:05 -0800743 private static native void nResetPaintFilter(int renderer);
744 private static native void nSetupPaintFilter(int renderer, int clearBits, int setBits);
745
Romain Guye4d01122010-06-16 18:44:05 -0700746 @Override
747 public DrawFilter getDrawFilter() {
Romain Guy6926c722010-07-12 20:20:03 -0700748 return mFilter;
Romain Guye4d01122010-06-16 18:44:05 -0700749 }
750
751 ///////////////////////////////////////////////////////////////////////////
752 // Drawing
753 ///////////////////////////////////////////////////////////////////////////
754
755 @Override
756 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
757 Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800758 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800759 try {
760 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
761 startAngle, sweepAngle, useCenter, paint.mNativePaint);
762 } finally {
763 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
764 }
Romain Guye4d01122010-06-16 18:44:05 -0700765 }
766
Romain Guy7d7b5492011-01-24 16:33:45 -0800767 private static native void nDrawArc(int renderer, float left, float top,
768 float right, float bottom, float startAngle, float sweepAngle,
769 boolean useCenter, int paint);
Romain Guy8b2f5262011-01-23 16:15:02 -0800770
Romain Guye4d01122010-06-16 18:44:05 -0700771 @Override
772 public void drawARGB(int a, int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700773 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -0700774 }
775
776 @Override
Romain Guyf3187b72013-06-07 12:17:11 -0700777 public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
778 Bitmap bitmap = patch.getBitmap();
779 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
780 // Shaders are ignored when drawing patches
781 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
782 try {
783 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700784 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
Romain Guyf3187b72013-06-07 12:17:11 -0700785 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
786 } finally {
787 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
788 }
789 }
790
791 @Override
Romain Guy3b748a42013-04-17 18:54:38 -0700792 public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
793 Bitmap bitmap = patch.getBitmap();
Romain Guybc52cce2012-02-07 19:40:19 -0800794 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700795 // Shaders are ignored when drawing patches
Romain Guya168d732011-03-18 16:50:13 -0700796 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800797 try {
798 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700799 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
Romain Guy445c83c2012-02-16 16:43:07 -0800800 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
801 } finally {
802 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
803 }
Romain Guydeba7852010-07-07 17:54:48 -0700804 }
805
Chris Craik0c20c382013-07-02 10:48:54 -0700806 private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, int chunk,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800807 float left, float top, float right, float bottom, int paint);
Romain Guydeba7852010-07-07 17:54:48 -0700808
809 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700810 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800811 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700812 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700813 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800814 try {
815 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700816 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800817 } finally {
818 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
819 }
Romain Guye4d01122010-06-16 18:44:05 -0700820 }
821
Chris Craik0c20c382013-07-02 10:48:54 -0700822 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
Romain Guy3b748a42013-04-17 18:54:38 -0700823 float left, float top, int paint);
Romain Guydbd77cd2010-07-09 10:36:05 -0700824
Romain Guye4d01122010-06-16 18:44:05 -0700825 @Override
826 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800827 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700828 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700829 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800830 try {
831 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700832 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
833 matrix.native_instance, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800834 } finally {
835 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
836 }
Romain Guye4d01122010-06-16 18:44:05 -0700837 }
838
Chris Craik0c20c382013-07-02 10:48:54 -0700839 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
840 int matrix, int paint);
Romain Guyf86ef572010-07-01 11:05:42 -0700841
Romain Guye4d01122010-06-16 18:44:05 -0700842 @Override
843 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800844 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700845 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700846 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800847 try {
848 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guy694b5192010-07-21 21:33:20 -0700849
Romain Guy445c83c2012-02-16 16:43:07 -0800850 int left, top, right, bottom;
851 if (src == null) {
852 left = top = 0;
853 right = bitmap.getWidth();
854 bottom = bitmap.getHeight();
855 } else {
856 left = src.left;
857 right = src.right;
858 top = src.top;
859 bottom = src.bottom;
860 }
861
Chris Craik0c20c382013-07-02 10:48:54 -0700862 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
Romain Guy445c83c2012-02-16 16:43:07 -0800863 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
864 } finally {
865 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy694b5192010-07-21 21:33:20 -0700866 }
Romain Guye4d01122010-06-16 18:44:05 -0700867 }
868
869 @Override
870 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800871 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700872 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700873 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800874 try {
875 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
876
877 float left, top, right, bottom;
878 if (src == null) {
879 left = top = 0;
880 right = bitmap.getWidth();
881 bottom = bitmap.getHeight();
882 } else {
883 left = src.left;
884 right = src.right;
885 top = src.top;
886 bottom = src.bottom;
887 }
888
Chris Craik0c20c382013-07-02 10:48:54 -0700889 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
Romain Guy445c83c2012-02-16 16:43:07 -0800890 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
891 } finally {
892 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guyff98fa52011-11-28 09:35:09 -0800893 }
Romain Guye4d01122010-06-16 18:44:05 -0700894 }
895
Chris Craik0c20c382013-07-02 10:48:54 -0700896 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
Romain Guyce0537b2010-06-29 21:05:21 -0700897 float srcLeft, float srcTop, float srcRight, float srcBottom,
Romain Guydbd77cd2010-07-09 10:36:05 -0700898 float left, float top, float right, float bottom, int paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700899
Romain Guye4d01122010-06-16 18:44:05 -0700900 @Override
901 public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
902 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guye651cc62012-05-14 19:44:40 -0700903 if (width < 0) {
904 throw new IllegalArgumentException("width must be >= 0");
905 }
906
907 if (height < 0) {
908 throw new IllegalArgumentException("height must be >= 0");
909 }
910
911 if (Math.abs(stride) < width) {
912 throw new IllegalArgumentException("abs(stride) must be >= width");
913 }
914
915 int lastScanline = offset + (height - 1) * stride;
916 int length = colors.length;
917
918 if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
919 (lastScanline + width > length)) {
920 throw new ArrayIndexOutOfBoundsException();
921 }
922
Romain Guyd27977d2010-07-14 19:18:51 -0700923 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700924 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800925 try {
Romain Guy445c83c2012-02-16 16:43:07 -0800926 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guye651cc62012-05-14 19:44:40 -0700927 nDrawBitmap(mRenderer, colors, offset, stride, x, y,
928 width, height, hasAlpha, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800929 } finally {
930 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
931 }
Romain Guye4d01122010-06-16 18:44:05 -0700932 }
933
Romain Guye651cc62012-05-14 19:44:40 -0700934 private static native void nDrawBitmap(int renderer, int[] colors, int offset, int stride,
935 float x, float y, int width, int height, boolean hasAlpha, int nativePaint);
936
Romain Guye4d01122010-06-16 18:44:05 -0700937 @Override
938 public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
939 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700940 // Shaders are ignored when drawing bitmaps
Romain Guyce0537b2010-06-29 21:05:21 -0700941 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700942 }
943
944 @Override
945 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
946 int vertOffset, int[] colors, int colorOffset, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800947 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guy5a7b4662011-01-20 19:09:30 -0800948 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
949 throw new ArrayIndexOutOfBoundsException();
950 }
951
952 if (meshWidth == 0 || meshHeight == 0) {
953 return;
954 }
955
956 final int count = (meshWidth + 1) * (meshHeight + 1);
957 checkRange(verts.length, vertOffset, count * 2);
958
Romain Guyff316ec2013-02-13 18:39:43 -0800959 if (colors != null) {
960 checkRange(colors.length, colorOffset, count);
961 }
Romain Guy5a7b4662011-01-20 19:09:30 -0800962
Romain Guya168d732011-03-18 16:50:13 -0700963 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800964 try {
Chris Craik0c20c382013-07-02 10:48:54 -0700965 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
966 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
Romain Guy445c83c2012-02-16 16:43:07 -0800967 verts, vertOffset, colors, colorOffset, nativePaint);
968 } finally {
969 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
970 }
Romain Guye4d01122010-06-16 18:44:05 -0700971 }
972
Chris Craik0c20c382013-07-02 10:48:54 -0700973 private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
Romain Guy5a7b4662011-01-20 19:09:30 -0800974 int meshWidth, int meshHeight, float[] verts, int vertOffset,
975 int[] colors, int colorOffset, int paint);
976
Romain Guye4d01122010-06-16 18:44:05 -0700977 @Override
978 public void drawCircle(float cx, float cy, float radius, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800979 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800980 try {
981 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
982 } finally {
983 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
984 }
Romain Guye4d01122010-06-16 18:44:05 -0700985 }
986
Romain Guy7d7b5492011-01-24 16:33:45 -0800987 private static native void nDrawCircle(int renderer, float cx, float cy,
988 float radius, int paint);
Romain Guy01d58e42011-01-19 21:54:02 -0800989
Romain Guye4d01122010-06-16 18:44:05 -0700990 @Override
991 public void drawColor(int color) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700992 drawColor(color, PorterDuff.Mode.SRC_OVER);
Romain Guye4d01122010-06-16 18:44:05 -0700993 }
994
995 @Override
996 public void drawColor(int color, PorterDuff.Mode mode) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700997 nDrawColor(mRenderer, color, mode.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700998 }
Romain Guy85bf02f2010-06-22 13:11:24 -0700999
Romain Guy7d7b5492011-01-24 16:33:45 -08001000 private static native void nDrawColor(int renderer, int color, int mode);
Romain Guye4d01122010-06-16 18:44:05 -07001001
1002 @Override
1003 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
Romain Guy6410c0a2013-06-17 11:21:58 -07001004 float[] line = getLineStorage();
1005 line[0] = startX;
1006 line[1] = startY;
1007 line[2] = stopX;
1008 line[3] = stopY;
1009 drawLines(line, 0, 4, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001010 }
1011
1012 @Override
1013 public void drawLines(float[] pts, int offset, int count, Paint paint) {
Chris Craik5d116762013-02-19 17:49:31 -08001014 if (count < 4) return;
1015
Romain Guy759ea802010-09-16 20:49:46 -07001016 if ((offset | count) < 0 || offset + count > pts.length) {
1017 throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
1018 }
Romain Guy765dcf32012-02-27 13:28:22 -08001019 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001020 try {
1021 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
1022 } finally {
1023 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1024 }
Romain Guye4d01122010-06-16 18:44:05 -07001025 }
1026
Romain Guy7d7b5492011-01-24 16:33:45 -08001027 private static native void nDrawLines(int renderer, float[] points,
1028 int offset, int count, int paint);
Romain Guy759ea802010-09-16 20:49:46 -07001029
Romain Guye4d01122010-06-16 18:44:05 -07001030 @Override
1031 public void drawLines(float[] pts, Paint paint) {
Romain Guy759ea802010-09-16 20:49:46 -07001032 drawLines(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001033 }
1034
1035 @Override
1036 public void drawOval(RectF oval, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001037 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001038 try {
1039 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
1040 } finally {
1041 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1042 }
Romain Guye4d01122010-06-16 18:44:05 -07001043 }
1044
Romain Guy7d7b5492011-01-24 16:33:45 -08001045 private static native void nDrawOval(int renderer, float left, float top,
1046 float right, float bottom, int paint);
Romain Guyc1cd9ba32011-01-23 14:18:41 -08001047
Romain Guye4d01122010-06-16 18:44:05 -07001048 @Override
1049 public void drawPaint(Paint paint) {
Romain Guy6410c0a2013-06-17 11:21:58 -07001050 final Rect r = getInternalClipBounds();
Romain Guy6926c722010-07-12 20:20:03 -07001051 nGetClipBounds(mRenderer, r);
1052 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001053 }
1054
1055 @Override
1056 public void drawPath(Path path, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001057 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001058 try {
1059 if (path.isSimplePath) {
1060 if (path.rects != null) {
1061 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
1062 }
1063 } else {
1064 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
Romain Guya48a1a82010-08-10 14:59:15 -07001065 }
Romain Guy445c83c2012-02-16 16:43:07 -08001066 } finally {
1067 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya48a1a82010-08-10 14:59:15 -07001068 }
Romain Guye4d01122010-06-16 18:44:05 -07001069 }
1070
Romain Guy7d7b5492011-01-24 16:33:45 -08001071 private static native void nDrawPath(int renderer, int path, int paint);
1072 private static native void nDrawRects(int renderer, int region, int paint);
Romain Guy7fbcc042010-08-04 15:40:07 -07001073
Romain Guy672433d2013-01-04 19:05:13 -08001074 void drawRects(float[] rects, int count, Paint paint) {
1075 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
1076 try {
1077 nDrawRects(mRenderer, rects, count, paint.mNativePaint);
1078 } finally {
1079 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1080 }
1081 }
1082
1083 private static native void nDrawRects(int renderer, float[] rects, int count, int paint);
1084
Romain Guye4d01122010-06-16 18:44:05 -07001085 @Override
1086 public void drawPicture(Picture picture) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001087 if (picture.createdFromStream) {
1088 return;
1089 }
1090
Romain Guy75582e82012-01-18 18:13:35 -08001091 picture.endRecording();
1092 // TODO: Implement rendering
Romain Guye4d01122010-06-16 18:44:05 -07001093 }
1094
1095 @Override
1096 public void drawPicture(Picture picture, Rect dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001097 if (picture.createdFromStream) {
1098 return;
1099 }
1100
Romain Guy75582e82012-01-18 18:13:35 -08001101 save();
1102 translate(dst.left, dst.top);
1103 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1104 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1105 }
1106 drawPicture(picture);
1107 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001108 }
1109
1110 @Override
1111 public void drawPicture(Picture picture, RectF dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001112 if (picture.createdFromStream) {
1113 return;
1114 }
1115
Romain Guy75582e82012-01-18 18:13:35 -08001116 save();
1117 translate(dst.left, dst.top);
1118 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1119 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1120 }
1121 drawPicture(picture);
1122 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001123 }
1124
1125 @Override
1126 public void drawPoint(float x, float y, Paint paint) {
Romain Guy6410c0a2013-06-17 11:21:58 -07001127 float[] point = getPointStorage();
1128 point[0] = x;
1129 point[1] = y;
1130 drawPoints(point, 0, 2, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001131 }
1132
1133 @Override
1134 public void drawPoints(float[] pts, Paint paint) {
Romain Guyed6fcb02011-03-21 13:11:28 -07001135 drawPoints(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001136 }
1137
1138 @Override
Romain Guyed6fcb02011-03-21 13:11:28 -07001139 public void drawPoints(float[] pts, int offset, int count, Paint paint) {
Chris Craik5d116762013-02-19 17:49:31 -08001140 if (count < 2) return;
1141
Romain Guy765dcf32012-02-27 13:28:22 -08001142 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001143 try {
1144 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
1145 } finally {
1146 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1147 }
Romain Guyed6fcb02011-03-21 13:11:28 -07001148 }
1149
1150 private static native void nDrawPoints(int renderer, float[] points,
1151 int offset, int count, int paint);
1152
Romain Guy5ff9df62012-01-23 17:09:05 -08001153 @SuppressWarnings("deprecation")
Romain Guyed6fcb02011-03-21 13:11:28 -07001154 @Override
Romain Guye4d01122010-06-16 18:44:05 -07001155 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001156 if (index < 0 || index + count > text.length || count * 2 > pos.length) {
1157 throw new IndexOutOfBoundsException();
1158 }
1159
1160 int modifiers = setupModifiers(paint);
1161 try {
1162 nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
1163 } finally {
1164 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1165 }
Romain Guye4d01122010-06-16 18:44:05 -07001166 }
1167
Romain Guyeb9a5362012-01-17 17:39:26 -08001168 private static native void nDrawPosText(int renderer, char[] text, int index, int count,
1169 float[] pos, int paint);
1170
Romain Guy5ff9df62012-01-23 17:09:05 -08001171 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -07001172 @Override
1173 public void drawPosText(String text, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001174 if (text.length() * 2 > pos.length) {
1175 throw new ArrayIndexOutOfBoundsException();
1176 }
1177
1178 int modifiers = setupModifiers(paint);
1179 try {
1180 nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
1181 } finally {
1182 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1183 }
Romain Guye4d01122010-06-16 18:44:05 -07001184 }
1185
Romain Guyeb9a5362012-01-17 17:39:26 -08001186 private static native void nDrawPosText(int renderer, String text, int start, int end,
1187 float[] pos, int paint);
1188
Romain Guye4d01122010-06-16 18:44:05 -07001189 @Override
1190 public void drawRect(float left, float top, float right, float bottom, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001191 if (left == right || top == bottom) return;
1192 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001193 try {
1194 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
1195 } finally {
1196 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1197 }
Romain Guye4d01122010-06-16 18:44:05 -07001198 }
1199
Romain Guy7d7b5492011-01-24 16:33:45 -08001200 private static native void nDrawRect(int renderer, float left, float top,
1201 float right, float bottom, int paint);
Romain Guyc7d53492010-06-25 13:41:57 -07001202
Romain Guye4d01122010-06-16 18:44:05 -07001203 @Override
1204 public void drawRect(Rect r, Paint paint) {
Romain Guyc7d53492010-06-25 13:41:57 -07001205 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001206 }
1207
1208 @Override
Romain Guyc7d53492010-06-25 13:41:57 -07001209 public void drawRect(RectF r, Paint paint) {
1210 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001211 }
1212
1213 @Override
1214 public void drawRGB(int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -07001215 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -07001216 }
1217
1218 @Override
1219 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001220 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001221 try {
1222 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
1223 rx, ry, paint.mNativePaint);
1224 } finally {
1225 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1226 }
Romain Guye4d01122010-06-16 18:44:05 -07001227 }
1228
Romain Guy7d7b5492011-01-24 16:33:45 -08001229 private static native void nDrawRoundRect(int renderer, float left, float top,
Romain Guy01d58e42011-01-19 21:54:02 -08001230 float right, float bottom, float rx, float y, int paint);
1231
Romain Guye4d01122010-06-16 18:44:05 -07001232 @Override
1233 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001234 if ((index | count | (index + count) | (text.length - index - count)) < 0) {
1235 throw new IndexOutOfBoundsException();
1236 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001237
Romain Guya168d732011-03-18 16:50:13 -07001238 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001239 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001240 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001241 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001242 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001243 }
Romain Guye4d01122010-06-16 18:44:05 -07001244 }
Romain Guya1db5742010-07-20 13:09:13 -07001245
Romain Guy7d7b5492011-01-24 16:33:45 -08001246 private static native void nDrawText(int renderer, char[] text, int index, int count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001247 float x, float y, int bidiFlags, int paint);
Romain Guye4d01122010-06-16 18:44:05 -07001248
1249 @Override
1250 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001251 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001252 try {
1253 if (text instanceof String || text instanceof SpannedString ||
1254 text instanceof SpannableString) {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001255 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
1256 paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001257 } else if (text instanceof GraphicsOperations) {
1258 ((GraphicsOperations) text).drawText(this, start, end, x, y,
1259 paint);
1260 } else {
1261 char[] buf = TemporaryBuffer.obtain(end - start);
1262 TextUtils.getChars(text, start, end, buf, 0);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001263 nDrawText(mRenderer, buf, 0, end - start, x, y,
1264 paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001265 TemporaryBuffer.recycle(buf);
1266 }
1267 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001268 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya1db5742010-07-20 13:09:13 -07001269 }
Romain Guye4d01122010-06-16 18:44:05 -07001270 }
1271
1272 @Override
1273 public void drawText(String text, int start, int end, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001274 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1275 throw new IndexOutOfBoundsException();
1276 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001277
Romain Guya168d732011-03-18 16:50:13 -07001278 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001279 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001280 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001281 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001282 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001283 }
Romain Guye4d01122010-06-16 18:44:05 -07001284 }
1285
Romain Guy7d7b5492011-01-24 16:33:45 -08001286 private static native void nDrawText(int renderer, String text, int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001287 float x, float y, int bidiFlags, int paint);
Romain Guya1db5742010-07-20 13:09:13 -07001288
Romain Guye4d01122010-06-16 18:44:05 -07001289 @Override
1290 public void drawText(String text, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001291 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001292 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001293 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
1294 paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001295 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001296 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001297 }
Romain Guye4d01122010-06-16 18:44:05 -07001298 }
1299
1300 @Override
1301 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
1302 float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001303 if (index < 0 || index + count > text.length) {
1304 throw new ArrayIndexOutOfBoundsException();
1305 }
1306
1307 int modifiers = setupModifiers(paint);
1308 try {
1309 nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001310 paint.mBidiFlags, paint.mNativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001311 } finally {
1312 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1313 }
Romain Guye4d01122010-06-16 18:44:05 -07001314 }
1315
Romain Guy325740f2012-02-24 16:48:34 -08001316 private static native void nDrawTextOnPath(int renderer, char[] text, int index, int count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001317 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001318
Romain Guye4d01122010-06-16 18:44:05 -07001319 @Override
1320 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001321 if (text.length() == 0) return;
1322
1323 int modifiers = setupModifiers(paint);
1324 try {
1325 nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001326 paint.mBidiFlags, paint.mNativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001327 } finally {
1328 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1329 }
Romain Guye4d01122010-06-16 18:44:05 -07001330 }
1331
Romain Guy325740f2012-02-24 16:48:34 -08001332 private static native void nDrawTextOnPath(int renderer, String text, int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001333 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001334
Romain Guye4d01122010-06-16 18:44:05 -07001335 @Override
1336 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001337 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001338 if ((index | count | text.length - index - count) < 0) {
1339 throw new IndexOutOfBoundsException();
1340 }
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001341 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
1342 throw new IllegalArgumentException("Unknown direction: " + dir);
1343 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001344
Romain Guya168d732011-03-18 16:50:13 -07001345 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001346 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001347 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
Romain Guy61c8c9c2010-08-09 20:48:09 -07001348 paint.mNativePaint);
1349 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001350 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001351 }
Romain Guye4d01122010-06-16 18:44:05 -07001352 }
1353
Romain Guy7d7b5492011-01-24 16:33:45 -08001354 private static native void nDrawTextRun(int renderer, char[] text, int index, int count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001355 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001356
Romain Guye4d01122010-06-16 18:44:05 -07001357 @Override
1358 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001359 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001360 if ((start | end | end - start | text.length() - end) < 0) {
1361 throw new IndexOutOfBoundsException();
1362 }
1363
Romain Guya168d732011-03-18 16:50:13 -07001364 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001365 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001366 int flags = dir == 0 ? 0 : 1;
Romain Guy61c8c9c2010-08-09 20:48:09 -07001367 if (text instanceof String || text instanceof SpannedString ||
1368 text instanceof SpannableString) {
1369 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001370 contextEnd, x, y, flags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001371 } else if (text instanceof GraphicsOperations) {
1372 ((GraphicsOperations) text).drawTextRun(this, start, end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001373 contextStart, contextEnd, x, y, flags, paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001374 } else {
1375 int contextLen = contextEnd - contextStart;
1376 int len = end - start;
1377 char[] buf = TemporaryBuffer.obtain(contextLen);
1378 TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
1379 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001380 x, y, flags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001381 TemporaryBuffer.recycle(buf);
1382 }
1383 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001384 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001385 }
Romain Guye4d01122010-06-16 18:44:05 -07001386 }
1387
Romain Guy7d7b5492011-01-24 16:33:45 -08001388 private static native void nDrawTextRun(int renderer, String text, int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001389 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001390
Romain Guye4d01122010-06-16 18:44:05 -07001391 @Override
1392 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
1393 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
1394 int indexOffset, int indexCount, Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -07001395 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -07001396 }
Romain Guyd27977d2010-07-14 19:18:51 -07001397
Romain Guya168d732011-03-18 16:50:13 -07001398 private int setupModifiers(Bitmap b, Paint paint) {
Romain Guy445c83c2012-02-16 16:43:07 -08001399 if (b.getConfig() != Bitmap.Config.ALPHA_8) {
1400 final ColorFilter filter = paint.getColorFilter();
1401 if (filter != null) {
1402 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
1403 return MODIFIER_COLOR_FILTER;
1404 }
1405
1406 return MODIFIER_NONE;
1407 } else {
Romain Guya168d732011-03-18 16:50:13 -07001408 return setupModifiers(paint);
1409 }
Romain Guya168d732011-03-18 16:50:13 -07001410 }
1411
1412 private int setupModifiers(Paint paint) {
1413 int modifiers = MODIFIER_NONE;
Romain Guydb1938e2010-08-02 18:50:22 -07001414
Romain Guy1e45aae2010-08-13 19:39:53 -07001415 if (paint.hasShadow) {
1416 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1417 paint.shadowColor);
Romain Guya168d732011-03-18 16:50:13 -07001418 modifiers |= MODIFIER_SHADOW;
Romain Guy1e45aae2010-08-13 19:39:53 -07001419 }
1420
Romain Guyd27977d2010-07-14 19:18:51 -07001421 final Shader shader = paint.getShader();
1422 if (shader != null) {
Romain Guy06f96e22010-07-30 19:18:16 -07001423 nSetupShader(mRenderer, shader.native_shader);
Romain Guya168d732011-03-18 16:50:13 -07001424 modifiers |= MODIFIER_SHADER;
Romain Guydb1938e2010-08-02 18:50:22 -07001425 }
1426
1427 final ColorFilter filter = paint.getColorFilter();
1428 if (filter != null) {
1429 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guya168d732011-03-18 16:50:13 -07001430 modifiers |= MODIFIER_COLOR_FILTER;
Romain Guydb1938e2010-08-02 18:50:22 -07001431 }
1432
Romain Guya168d732011-03-18 16:50:13 -07001433 return modifiers;
Romain Guydb1938e2010-08-02 18:50:22 -07001434 }
Romain Guy1e45aae2010-08-13 19:39:53 -07001435
Romain Guy765dcf32012-02-27 13:28:22 -08001436 private int setupModifiers(Paint paint, int flags) {
1437 int modifiers = MODIFIER_NONE;
1438
1439 if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
1440 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1441 paint.shadowColor);
1442 modifiers |= MODIFIER_SHADOW;
1443 }
1444
1445 final Shader shader = paint.getShader();
1446 if (shader != null && (flags & MODIFIER_SHADER) != 0) {
1447 nSetupShader(mRenderer, shader.native_shader);
1448 modifiers |= MODIFIER_SHADER;
1449 }
1450
1451 final ColorFilter filter = paint.getColorFilter();
1452 if (filter != null && (flags & MODIFIER_COLOR_FILTER) != 0) {
1453 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
1454 modifiers |= MODIFIER_COLOR_FILTER;
1455 }
1456
1457 return modifiers;
1458 }
1459
Romain Guya168d732011-03-18 16:50:13 -07001460 private int setupColorFilter(Paint paint) {
Romain Guydb1938e2010-08-02 18:50:22 -07001461 final ColorFilter filter = paint.getColorFilter();
1462 if (filter != null) {
1463 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guya168d732011-03-18 16:50:13 -07001464 return MODIFIER_COLOR_FILTER;
Romain Guyd27977d2010-07-14 19:18:51 -07001465 }
Romain Guy56215272011-03-23 16:55:38 -07001466 return MODIFIER_NONE;
Romain Guyd27977d2010-07-14 19:18:51 -07001467 }
Romain Guya168d732011-03-18 16:50:13 -07001468
Romain Guy7d7b5492011-01-24 16:33:45 -08001469 private static native void nSetupShader(int renderer, int shader);
1470 private static native void nSetupColorFilter(int renderer, int colorFilter);
1471 private static native void nSetupShadow(int renderer, float radius,
1472 float dx, float dy, int color);
Romain Guy1e45aae2010-08-13 19:39:53 -07001473
Romain Guya168d732011-03-18 16:50:13 -07001474 private static native void nResetModifiers(int renderer, int modifiers);
Romain Guye4d01122010-06-16 18:44:05 -07001475}