blob: 2ec9a7da8655c5b2bf673c725d8fcfdaf3442462 [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;
24import android.graphics.Paint;
Romain Guy5ff9df62012-01-23 17:09:05 -080025import android.graphics.PaintFlagsDrawFilter;
Romain Guye4d01122010-06-16 18:44:05 -070026import android.graphics.Path;
27import android.graphics.Picture;
28import android.graphics.PorterDuff;
29import android.graphics.Rect;
30import android.graphics.RectF;
31import android.graphics.Region;
Romain Guyd27977d2010-07-14 19:18:51 -070032import android.graphics.Shader;
Romain Guye5e0c502011-06-15 15:18:31 -070033import android.graphics.SurfaceTexture;
Romain Guya1db5742010-07-20 13:09:13 -070034import android.graphics.TemporaryBuffer;
35import android.text.GraphicsOperations;
36import android.text.SpannableString;
37import android.text.SpannedString;
38import android.text.TextUtils;
Romain Guye4d01122010-06-16 18:44:05 -070039
Romain Guye4d01122010-06-16 18:44:05 -070040/**
41 * An implementation of Canvas on top of OpenGL ES 2.0.
42 */
Romain Guyb051e892010-09-28 19:09:36 -070043class GLES20Canvas extends HardwareCanvas {
Romain Guya168d732011-03-18 16:50:13 -070044 // Must match modifiers used in the JNI layer
45 private static final int MODIFIER_NONE = 0;
46 private static final int MODIFIER_SHADOW = 1;
47 private static final int MODIFIER_SHADER = 2;
48 private static final int MODIFIER_COLOR_FILTER = 4;
49
Romain Guye4d01122010-06-16 18:44:05 -070050 private final boolean mOpaque;
Romain Guyfb8b7632010-08-23 21:05:08 -070051 private int mRenderer;
Patrick Dubroyf890fab2010-12-19 16:47:17 -080052
53 // The native renderer will be destroyed when this object dies.
54 // DO NOT overwrite this reference once it is set.
Romain Guyeea60692011-07-26 20:35:55 -070055 @SuppressWarnings({"unused", "FieldCanBeLocal"})
Patrick Dubroyf890fab2010-12-19 16:47:17 -080056 private CanvasFinalizer mFinalizer;
57
Romain Guye4d01122010-06-16 18:44:05 -070058 private int mWidth;
59 private int mHeight;
Romain Guyce0537b2010-06-29 21:05:21 -070060
61 private final float[] mPoint = new float[2];
62 private final float[] mLine = new float[4];
Romain Guy6926c722010-07-12 20:20:03 -070063
64 private final Rect mClipBounds = new Rect();
Romain Guy7677d8f2012-01-17 11:22:42 -080065 private final RectF mPathBounds = new RectF();
Romain Guy6926c722010-07-12 20:20:03 -070066
67 private DrawFilter mFilter;
Romain Guyda8532c2010-08-31 11:50:35 -070068
Romain Guy16393512010-08-08 00:14:31 -070069 ///////////////////////////////////////////////////////////////////////////
70 // JNI
71 ///////////////////////////////////////////////////////////////////////////
72
73 private static native boolean nIsAvailable();
74 private static boolean sIsAvailable = nIsAvailable();
75
76 static boolean isAvailable() {
77 return sIsAvailable;
78 }
Romain Guye4d01122010-06-16 18:44:05 -070079
80 ///////////////////////////////////////////////////////////////////////////
81 // Constructors
82 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -070083
Romain Guy6c319ca2011-01-11 14:29:25 -080084 /**
85 * Creates a canvas to render directly on screen.
86 */
Romain Guyb051e892010-09-28 19:09:36 -070087 GLES20Canvas(boolean translucent) {
88 this(false, translucent);
89 }
Romain Guy6c319ca2011-01-11 14:29:25 -080090
91 /**
92 * Creates a canvas to render into an FBO.
93 */
Romain Guyada830f2011-01-13 12:13:20 -080094 GLES20Canvas(int layer, boolean translucent) {
Romain Guy6c319ca2011-01-11 14:29:25 -080095 mOpaque = !translucent;
Romain Guyada830f2011-01-13 12:13:20 -080096 mRenderer = nCreateLayerRenderer(layer);
Romain Guy6c319ca2011-01-11 14:29:25 -080097 setupFinalizer();
98 }
Romain Guye4d01122010-06-16 18:44:05 -070099
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800100 protected GLES20Canvas(boolean record, boolean translucent) {
Romain Guye4d01122010-06-16 18:44:05 -0700101 mOpaque = !translucent;
102
Romain Guyb051e892010-09-28 19:09:36 -0700103 if (record) {
Jeff Brown162a0212011-07-21 17:02:54 -0700104 mRenderer = nCreateDisplayListRenderer();
Romain Guyb051e892010-09-28 19:09:36 -0700105 } else {
106 mRenderer = nCreateRenderer();
107 }
Romain Guy6c319ca2011-01-11 14:29:25 -0800108
109 setupFinalizer();
110 }
111
112 private void setupFinalizer() {
Romain Guyfb8b7632010-08-23 21:05:08 -0700113 if (mRenderer == 0) {
114 throw new IllegalStateException("Could not create GLES20Canvas renderer");
Chet Haase5c13d892010-10-08 08:37:55 -0700115 } else {
Jeff Brown162a0212011-07-21 17:02:54 -0700116 mFinalizer = new CanvasFinalizer(mRenderer);
Romain Guyfb8b7632010-08-23 21:05:08 -0700117 }
Romain Guye4d01122010-06-16 18:44:05 -0700118 }
Romain Guye4d01122010-06-16 18:44:05 -0700119
Jeff Brown162a0212011-07-21 17:02:54 -0700120 protected void resetDisplayListRenderer() {
121 nResetDisplayListRenderer(mRenderer);
122 }
123
Romain Guy6c319ca2011-01-11 14:29:25 -0800124 private static native int nCreateRenderer();
Romain Guyada830f2011-01-13 12:13:20 -0800125 private static native int nCreateLayerRenderer(int layer);
Jeff Brown162a0212011-07-21 17:02:54 -0700126 private static native int nCreateDisplayListRenderer();
127 private static native void nResetDisplayListRenderer(int renderer);
Chet Haase5c13d892010-10-08 08:37:55 -0700128 private static native void nDestroyRenderer(int renderer);
129
Jeff Brown162a0212011-07-21 17:02:54 -0700130 private static final class CanvasFinalizer {
131 private final int mRenderer;
Chet Haase5c13d892010-10-08 08:37:55 -0700132
Jeff Brown162a0212011-07-21 17:02:54 -0700133 public CanvasFinalizer(int renderer) {
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800134 mRenderer = renderer;
Chet Haase5c13d892010-10-08 08:37:55 -0700135 }
136
137 @Override
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800138 protected void finalize() throws Throwable {
Romain Guy171c5922011-01-06 10:04:23 -0800139 try {
Jeff Brown162a0212011-07-21 17:02:54 -0700140 nDestroyRenderer(mRenderer);
Romain Guy171c5922011-01-06 10:04:23 -0800141 } finally {
142 super.finalize();
143 }
Romain Guye4d01122010-06-16 18:44:05 -0700144 }
145 }
Romain Guyce0537b2010-06-29 21:05:21 -0700146
Romain Guyef359272013-01-31 19:07:29 -0800147 @Override
148 public void setName(String name) {
149 super.setName(name);
150 nSetName(mRenderer, name);
151 }
152
153 private static native void nSetName(int renderer, String name);
154
Romain Guye4d01122010-06-16 18:44:05 -0700155 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800156 // Hardware layers
157 ///////////////////////////////////////////////////////////////////////////
Romain Guy11cb6422012-09-21 00:39:43 -0700158
159 @Override
160 void pushLayerUpdate(HardwareLayer layer) {
161 nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
162 }
163
164 @Override
165 void clearLayerUpdates() {
166 nClearLayerUpdates(mRenderer);
167 }
168
Romain Guya9489272011-06-22 20:58:11 -0700169 static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
Romain Guyada830f2011-01-13 12:13:20 -0800170 static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
Chet Haase603f6de2012-09-14 15:31:25 -0700171 static native boolean nResizeLayer(int layerId, int width, int height, int[] layerInfo);
Romain Guy846a5332012-07-11 17:44:57 -0700172 static native void nSetOpaqueLayer(int layerId, boolean isOpaque);
Chet Haased15ebf22012-09-05 11:40:29 -0700173 static native void nSetLayerPaint(int layerId, int nativePaint);
174 static native void nSetLayerColorFilter(int layerId, int nativeColorFilter);
Romain Guya9489272011-06-22 20:58:11 -0700175 static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
176 SurfaceTexture surface);
Romain Guyef09a212012-09-25 12:17:14 -0700177 static native void nClearLayerTexture(int layerId);
Romain Guy302a9df2011-08-16 13:55:02 -0700178 static native void nSetTextureLayerTransform(int layerId, int matrix);
Romain Guyada830f2011-01-13 12:13:20 -0800179 static native void nDestroyLayer(int layerId);
180 static native void nDestroyLayerDeferred(int layerId);
Romain Guy2bf68f02012-03-02 13:37:47 -0800181 static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
182 int left, int top, int right, int bottom);
Romain Guy77a81162011-06-14 16:45:55 -0700183 static native boolean nCopyLayer(int layerId, int bitmap);
Romain Guy57066eb2011-01-12 12:53:32 -0800184
Romain Guy11cb6422012-09-21 00:39:43 -0700185 private static native void nClearLayerUpdates(int renderer);
186 private static native void nPushLayerUpdate(int renderer, int layer);
187
Romain Guy6c319ca2011-01-11 14:29:25 -0800188 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700189 // Canvas management
190 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700191
192 @Override
193 public boolean isOpaque() {
194 return mOpaque;
195 }
196
197 @Override
198 public int getWidth() {
199 return mWidth;
200 }
201
202 @Override
203 public int getHeight() {
204 return mHeight;
205 }
206
Romain Guyf61970fc2011-07-07 14:10:06 -0700207 @Override
208 public int getMaximumBitmapWidth() {
209 return nGetMaximumTextureWidth();
210 }
211
212 @Override
213 public int getMaximumBitmapHeight() {
214 return nGetMaximumTextureHeight();
215 }
216
217 private static native int nGetMaximumTextureWidth();
Romain Guy530041d2012-01-25 18:56:29 -0800218 private static native int nGetMaximumTextureHeight();
Romain Guyf61970fc2011-07-07 14:10:06 -0700219
Romain Guy2bf68f02012-03-02 13:37:47 -0800220 /**
221 * Returns the native OpenGLRenderer object.
222 */
223 int getRenderer() {
224 return mRenderer;
225 }
226
Romain Guye4d01122010-06-16 18:44:05 -0700227 ///////////////////////////////////////////////////////////////////////////
228 // Setup
229 ///////////////////////////////////////////////////////////////////////////
230
231 @Override
232 public void setViewport(int width, int height) {
233 mWidth = width;
234 mHeight = height;
235
236 nSetViewport(mRenderer, width, height);
237 }
238
Romain Guy7d7b5492011-01-24 16:33:45 -0800239 private static native void nSetViewport(int renderer, int width, int height);
Romain Guye4d01122010-06-16 18:44:05 -0700240
Romain Guy7d7b5492011-01-24 16:33:45 -0800241 @Override
Chet Haase44b2fe32012-06-06 19:03:58 -0700242 public int onPreDraw(Rect dirty) {
Romain Guy7d7b5492011-01-24 16:33:45 -0800243 if (dirty != null) {
Chet Haase44b2fe32012-06-06 19:03:58 -0700244 return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
245 mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800246 } else {
Chet Haase44b2fe32012-06-06 19:03:58 -0700247 return nPrepare(mRenderer, mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800248 }
249 }
250
Chet Haase44b2fe32012-06-06 19:03:58 -0700251 private static native int nPrepare(int renderer, boolean opaque);
252 private static native int nPrepareDirty(int renderer, int left, int top, int right, int bottom,
Romain Guy7d7b5492011-01-24 16:33:45 -0800253 boolean opaque);
Romain Guye4d01122010-06-16 18:44:05 -0700254
Romain Guyb051e892010-09-28 19:09:36 -0700255 @Override
Gilles Debunneb35ab7b2011-12-05 15:54:00 -0800256 public void onPostDraw() {
Romain Guyb025b9c2010-09-16 14:16:48 -0700257 nFinish(mRenderer);
258 }
Romain Guy9ace8f52011-07-07 20:50:11 -0700259
Romain Guy7d7b5492011-01-24 16:33:45 -0800260 private static native void nFinish(int renderer);
Romain Guyb025b9c2010-09-16 14:16:48 -0700261
Romain Guy530041d2012-01-25 18:56:29 -0800262 /**
263 * Returns the size of the stencil buffer required by the underlying
264 * implementation.
265 *
266 * @return The minimum number of bits the stencil buffer must. Always >= 0.
267 *
268 * @hide
269 */
270 public static int getStencilSize() {
271 return nGetStencilSize();
272 }
273
274 private static native int nGetStencilSize();
275
276 ///////////////////////////////////////////////////////////////////////////
277 // Functor
278 ///////////////////////////////////////////////////////////////////////////
279
Romain Guyda8532c2010-08-31 11:50:35 -0700280 @Override
Romain Guy65549432012-03-26 16:45:05 -0700281 public int callDrawGLFunction(int drawGLFunction) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800282 return nCallDrawGLFunction(mRenderer, drawGLFunction);
283 }
284
Romain Guy65549432012-03-26 16:45:05 -0700285 private static native int nCallDrawGLFunction(int renderer, int drawGLFunction);
Chet Haasedaf98e92011-01-10 14:10:36 -0800286
Romain Guy8f3b8e32012-03-27 16:33:45 -0700287 @Override
288 public int invokeFunctors(Rect dirty) {
289 return nInvokeFunctors(mRenderer, dirty);
290 }
291
292 private static native int nInvokeFunctors(int renderer, Rect dirty);
293
Romain Guyba6be8a2012-04-23 18:22:09 -0700294 @Override
295 public void detachFunctor(int functor) {
296 nDetachFunctor(mRenderer, functor);
297 }
298
299 private static native void nDetachFunctor(int renderer, int functor);
300
301 @Override
302 public void attachFunctor(int functor) {
303 nAttachFunctor(mRenderer, functor);
304 }
305
306 private static native void nAttachFunctor(int renderer, int functor);
307
Romain Guybdf76092011-07-18 15:00:43 -0700308 ///////////////////////////////////////////////////////////////////////////
309 // Memory
310 ///////////////////////////////////////////////////////////////////////////
311
312 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700313 * Must match Caches::FlushMode values
314 *
Romain Guybdf76092011-07-18 15:00:43 -0700315 * @see #flushCaches(int)
316 */
Romain Guy6d7475d2011-07-27 16:28:21 -0700317 public static final int FLUSH_CACHES_LAYERS = 0;
318
319 /**
320 * Must match Caches::FlushMode values
321 *
322 * @see #flushCaches(int)
323 */
324 public static final int FLUSH_CACHES_MODERATE = 1;
Romain Guybdf76092011-07-18 15:00:43 -0700325
326 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700327 * Must match Caches::FlushMode values
328 *
Romain Guybdf76092011-07-18 15:00:43 -0700329 * @see #flushCaches(int)
330 */
Romain Guy6d7475d2011-07-27 16:28:21 -0700331 public static final int FLUSH_CACHES_FULL = 2;
Romain Guybdf76092011-07-18 15:00:43 -0700332
333 /**
334 * Flush caches to reclaim as much memory as possible. The amount of memory
335 * to reclaim is indicate by the level parameter.
336 *
337 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
338 * {@link #FLUSH_CACHES_FULL}.
339 *
340 * @param level Hint about the amount of memory to reclaim
341 *
342 * @hide
343 */
344 public static void flushCaches(int level) {
345 nFlushCaches(level);
346 }
347
348 private static native void nFlushCaches(int level);
349
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800350 /**
351 * Release all resources associated with the underlying caches. This should
352 * only be called after a full flushCaches().
353 *
354 * @hide
355 */
356 public static void terminateCaches() {
357 nTerminateCaches();
358 }
359
360 private static native void nTerminateCaches();
361
362 /**
363 * @hide
364 */
365 public static void initCaches() {
366 nInitCaches();
367 }
368
369 private static native void nInitCaches();
370
Romain Guyb051e892010-09-28 19:09:36 -0700371 ///////////////////////////////////////////////////////////////////////////
372 // Display list
373 ///////////////////////////////////////////////////////////////////////////
374
Jeff Brown162a0212011-07-21 17:02:54 -0700375 int getDisplayList(int displayList) {
376 return nGetDisplayList(mRenderer, displayList);
Romain Guyb051e892010-09-28 19:09:36 -0700377 }
378
Jeff Brown162a0212011-07-21 17:02:54 -0700379 private static native int nGetDisplayList(int renderer, int displayList);
Romain Guy52036b12013-02-14 18:03:37 -0800380
381 @Override
382 void outputDisplayList(DisplayList displayList) {
383 nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList());
Romain Guyb051e892010-09-28 19:09:36 -0700384 }
385
Romain Guy52036b12013-02-14 18:03:37 -0800386 private static native void nOutputDisplayList(int renderer, int displayList);
Romain Guy13631f32012-01-30 17:41:55 -0800387
Romain Guyb051e892010-09-28 19:09:36 -0700388 @Override
Chet Haase1271e2c2012-04-20 09:54:27 -0700389 public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
Romain Guy33f6beb2012-02-16 19:24:51 -0800390 return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList(),
Chet Haase1271e2c2012-04-20 09:54:27 -0700391 dirty, flags);
Romain Guyb051e892010-09-28 19:09:36 -0700392 }
393
Romain Guy65549432012-03-26 16:45:05 -0700394 private static native int nDrawDisplayList(int renderer, int displayList,
Chet Haase1271e2c2012-04-20 09:54:27 -0700395 Rect dirty, int flags);
Romain Guyda8532c2010-08-31 11:50:35 -0700396
Romain Guye4d01122010-06-16 18:44:05 -0700397 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800398 // Hardware layer
399 ///////////////////////////////////////////////////////////////////////////
400
Romain Guyada830f2011-01-13 12:13:20 -0800401 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
Chris Craika4e16c52013-03-22 10:00:48 -0700402 layer.setLayerPaint(paint);
403
Romain Guy6c319ca2011-01-11 14:29:25 -0800404 final GLES20Layer glLayer = (GLES20Layer) layer;
Chris Craika4e16c52013-03-22 10:00:48 -0700405 nDrawLayer(mRenderer, glLayer.getLayer(), x, y);
Romain Guy6c319ca2011-01-11 14:29:25 -0800406 }
407
Chris Craika4e16c52013-03-22 10:00:48 -0700408 private static native void nDrawLayer(int renderer, int layer, float x, float y);
Romain Guyaa6c24c2011-04-28 18:40:04 -0700409
Romain Guy6c319ca2011-01-11 14:29:25 -0800410 void interrupt() {
411 nInterrupt(mRenderer);
412 }
413
414 void resume() {
415 nResume(mRenderer);
416 }
417
Romain Guy7d7b5492011-01-24 16:33:45 -0800418 private static native void nInterrupt(int renderer);
419 private static native void nResume(int renderer);
Romain Guy6c319ca2011-01-11 14:29:25 -0800420
421 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700422 // Clipping
423 ///////////////////////////////////////////////////////////////////////////
424
425 @Override
426 public boolean clipPath(Path path) {
Romain Guy735738c2012-12-03 12:34:51 -0800427 return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700428 }
429
430 @Override
431 public boolean clipPath(Path path, Region.Op op) {
Romain Guy735738c2012-12-03 12:34:51 -0800432 return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700433 }
434
Romain Guy735738c2012-12-03 12:34:51 -0800435 private static native boolean nClipPath(int renderer, int path, int op);
436
Romain Guye4d01122010-06-16 18:44:05 -0700437 @Override
438 public boolean clipRect(float left, float top, float right, float bottom) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700439 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700440 }
Romain Guybb9524b2010-06-22 18:56:38 -0700441
Romain Guy7d7b5492011-01-24 16:33:45 -0800442 private static native boolean nClipRect(int renderer, float left, float top,
Romain Guy079ba2c2010-07-16 14:12:24 -0700443 float right, float bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700444
445 @Override
446 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700447 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700448 }
449
450 @Override
451 public boolean clipRect(int left, int top, int right, int bottom) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800452 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700453 }
Romain Guybb9524b2010-06-22 18:56:38 -0700454
Romain Guy735738c2012-12-03 12:34:51 -0800455 private static native boolean nClipRect(int renderer, int left, int top,
456 int right, int bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700457
458 @Override
459 public boolean clipRect(Rect rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700460 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
461 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700462 }
463
464 @Override
465 public boolean clipRect(Rect rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700466 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700467 }
468
469 @Override
470 public boolean clipRect(RectF rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700471 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
472 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700473 }
474
475 @Override
476 public boolean clipRect(RectF rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700477 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700478 }
479
480 @Override
481 public boolean clipRegion(Region region) {
Romain Guy735738c2012-12-03 12:34:51 -0800482 return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700483 }
484
485 @Override
486 public boolean clipRegion(Region region, Region.Op op) {
Romain Guy735738c2012-12-03 12:34:51 -0800487 return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700488 }
489
Romain Guy735738c2012-12-03 12:34:51 -0800490 private static native boolean nClipRegion(int renderer, int region, int op);
491
Romain Guye4d01122010-06-16 18:44:05 -0700492 @Override
493 public boolean getClipBounds(Rect bounds) {
Romain Guy9d5316e2010-06-24 19:30:36 -0700494 return nGetClipBounds(mRenderer, bounds);
Romain Guye4d01122010-06-16 18:44:05 -0700495 }
496
Romain Guy7d7b5492011-01-24 16:33:45 -0800497 private static native boolean nGetClipBounds(int renderer, Rect bounds);
Romain Guy9d5316e2010-06-24 19:30:36 -0700498
Romain Guye4d01122010-06-16 18:44:05 -0700499 @Override
500 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400501 return nQuickReject(mRenderer, left, top, right, bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700502 }
Romain Guyc7d53492010-06-25 13:41:57 -0700503
Romain Guy7d7b5492011-01-24 16:33:45 -0800504 private static native boolean nQuickReject(int renderer, float left, float top,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400505 float right, float bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700506
507 @Override
508 public boolean quickReject(Path path, EdgeType type) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800509 path.computeBounds(mPathBounds, true);
510 return nQuickReject(mRenderer, mPathBounds.left, mPathBounds.top,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400511 mPathBounds.right, mPathBounds.bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700512 }
513
514 @Override
515 public boolean quickReject(RectF rect, EdgeType type) {
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400516 return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700517 }
518
519 ///////////////////////////////////////////////////////////////////////////
520 // Transformations
521 ///////////////////////////////////////////////////////////////////////////
522
523 @Override
524 public void translate(float dx, float dy) {
Romain Guy807daf72011-01-18 11:19:19 -0800525 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
Romain Guye4d01122010-06-16 18:44:05 -0700526 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700527
Romain Guy7d7b5492011-01-24 16:33:45 -0800528 private static native void nTranslate(int renderer, float dx, float dy);
Romain Guye4d01122010-06-16 18:44:05 -0700529
530 @Override
531 public void skew(float sx, float sy) {
Romain Guy807daf72011-01-18 11:19:19 -0800532 nSkew(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700533 }
534
Romain Guy7d7b5492011-01-24 16:33:45 -0800535 private static native void nSkew(int renderer, float sx, float sy);
Romain Guy807daf72011-01-18 11:19:19 -0800536
Romain Guye4d01122010-06-16 18:44:05 -0700537 @Override
538 public void rotate(float degrees) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700539 nRotate(mRenderer, degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700540 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700541
Romain Guy7d7b5492011-01-24 16:33:45 -0800542 private static native void nRotate(int renderer, float degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700543
544 @Override
545 public void scale(float sx, float sy) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700546 nScale(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700547 }
Romain Guye4d01122010-06-16 18:44:05 -0700548
Romain Guy7d7b5492011-01-24 16:33:45 -0800549 private static native void nScale(int renderer, float sx, float sy);
Romain Guyf6a11b82010-06-23 17:47:49 -0700550
Romain Guye4d01122010-06-16 18:44:05 -0700551 @Override
552 public void setMatrix(Matrix matrix) {
Romain Guye7078592011-10-28 14:32:20 -0700553 nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700554 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700555
Romain Guy7d7b5492011-01-24 16:33:45 -0800556 private static native void nSetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700557
Romain Guy5ff9df62012-01-23 17:09:05 -0800558 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -0700559 @Override
Romain Guyf6a11b82010-06-23 17:47:49 -0700560 public void getMatrix(Matrix matrix) {
561 nGetMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700562 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700563
Romain Guy7d7b5492011-01-24 16:33:45 -0800564 private static native void nGetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700565
566 @Override
567 public void concat(Matrix matrix) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700568 nConcatMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700569 }
570
Romain Guy7d7b5492011-01-24 16:33:45 -0800571 private static native void nConcatMatrix(int renderer, int matrix);
Romain Guyf6a11b82010-06-23 17:47:49 -0700572
Romain Guye4d01122010-06-16 18:44:05 -0700573 ///////////////////////////////////////////////////////////////////////////
574 // State management
575 ///////////////////////////////////////////////////////////////////////////
576
577 @Override
578 public int save() {
Romain Guy8aef54f2010-09-01 15:13:49 -0700579 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
Romain Guye4d01122010-06-16 18:44:05 -0700580 }
Romain Guybb9524b2010-06-22 18:56:38 -0700581
Romain Guye4d01122010-06-16 18:44:05 -0700582 @Override
583 public int save(int saveFlags) {
Romain Guybb9524b2010-06-22 18:56:38 -0700584 return nSave(mRenderer, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700585 }
586
Romain Guy7d7b5492011-01-24 16:33:45 -0800587 private static native int nSave(int renderer, int flags);
Romain Guybb9524b2010-06-22 18:56:38 -0700588
Romain Guye4d01122010-06-16 18:44:05 -0700589 @Override
590 public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700591 if (bounds != null) {
592 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
593 }
594
Romain Guy445c83c2012-02-16 16:43:07 -0800595 int count;
Romain Guy189887e2011-08-25 11:45:13 -0700596 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800597 try {
598 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
599 count = nSaveLayer(mRenderer, nativePaint, saveFlags);
600 } finally {
601 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
602 }
Romain Guy189887e2011-08-25 11:45:13 -0700603 return count;
Romain Guye4d01122010-06-16 18:44:05 -0700604 }
605
Romain Guy189887e2011-08-25 11:45:13 -0700606 private static native int nSaveLayer(int renderer, int paint, int saveFlags);
607
Romain Guye4d01122010-06-16 18:44:05 -0700608 @Override
609 public int saveLayer(float left, float top, float right, float bottom, Paint paint,
610 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800611 if (left < right && top < bottom) {
Romain Guy445c83c2012-02-16 16:43:07 -0800612 int count;
Romain Guya168d732011-03-18 16:50:13 -0700613 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800614 try {
615 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
616 count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
617 } finally {
618 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
619 }
Romain Guy01d58e42011-01-19 21:54:02 -0800620 return count;
621 }
622 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700623 }
624
Romain Guy7d7b5492011-01-24 16:33:45 -0800625 private static native int nSaveLayer(int renderer, float left, float top,
626 float right, float bottom, int paint, int saveFlags);
Romain Guybd6b79b2010-06-26 00:13:53 -0700627
Romain Guye4d01122010-06-16 18:44:05 -0700628 @Override
629 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700630 if (bounds != null) {
631 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
632 alpha, saveFlags);
633 }
634 return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700635 }
636
Romain Guy189887e2011-08-25 11:45:13 -0700637 private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags);
638
Romain Guye4d01122010-06-16 18:44:05 -0700639 @Override
640 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
641 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800642 if (left < right && top < bottom) {
643 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
644 }
645 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700646 }
647
Romain Guy7d7b5492011-01-24 16:33:45 -0800648 private static native int nSaveLayerAlpha(int renderer, float left, float top, float right,
Romain Guybd6b79b2010-06-26 00:13:53 -0700649 float bottom, int alpha, int saveFlags);
650
Romain Guye4d01122010-06-16 18:44:05 -0700651 @Override
652 public void restore() {
Romain Guybb9524b2010-06-22 18:56:38 -0700653 nRestore(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700654 }
Romain Guybb9524b2010-06-22 18:56:38 -0700655
Romain Guy7d7b5492011-01-24 16:33:45 -0800656 private static native void nRestore(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700657
658 @Override
659 public void restoreToCount(int saveCount) {
Romain Guybb9524b2010-06-22 18:56:38 -0700660 nRestoreToCount(mRenderer, saveCount);
Romain Guye4d01122010-06-16 18:44:05 -0700661 }
662
Romain Guy7d7b5492011-01-24 16:33:45 -0800663 private static native void nRestoreToCount(int renderer, int saveCount);
Romain Guybb9524b2010-06-22 18:56:38 -0700664
Romain Guye4d01122010-06-16 18:44:05 -0700665 @Override
666 public int getSaveCount() {
Romain Guybb9524b2010-06-22 18:56:38 -0700667 return nGetSaveCount(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700668 }
Romain Guybb9524b2010-06-22 18:56:38 -0700669
Romain Guy7d7b5492011-01-24 16:33:45 -0800670 private static native int nGetSaveCount(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700671
672 ///////////////////////////////////////////////////////////////////////////
673 // Filtering
674 ///////////////////////////////////////////////////////////////////////////
675
676 @Override
677 public void setDrawFilter(DrawFilter filter) {
Romain Guy6926c722010-07-12 20:20:03 -0700678 mFilter = filter;
Romain Guy5ff9df62012-01-23 17:09:05 -0800679 if (filter == null) {
680 nResetPaintFilter(mRenderer);
681 } else if (filter instanceof PaintFlagsDrawFilter) {
682 PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
683 nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
684 }
Romain Guye4d01122010-06-16 18:44:05 -0700685 }
686
Romain Guy5ff9df62012-01-23 17:09:05 -0800687 private static native void nResetPaintFilter(int renderer);
688 private static native void nSetupPaintFilter(int renderer, int clearBits, int setBits);
689
Romain Guye4d01122010-06-16 18:44:05 -0700690 @Override
691 public DrawFilter getDrawFilter() {
Romain Guy6926c722010-07-12 20:20:03 -0700692 return mFilter;
Romain Guye4d01122010-06-16 18:44:05 -0700693 }
694
695 ///////////////////////////////////////////////////////////////////////////
696 // Drawing
697 ///////////////////////////////////////////////////////////////////////////
698
699 @Override
700 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
701 Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800702 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800703 try {
704 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
705 startAngle, sweepAngle, useCenter, paint.mNativePaint);
706 } finally {
707 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
708 }
Romain Guye4d01122010-06-16 18:44:05 -0700709 }
710
Romain Guy7d7b5492011-01-24 16:33:45 -0800711 private static native void nDrawArc(int renderer, float left, float top,
712 float right, float bottom, float startAngle, float sweepAngle,
713 boolean useCenter, int paint);
Romain Guy8b2f5262011-01-23 16:15:02 -0800714
Romain Guye4d01122010-06-16 18:44:05 -0700715 @Override
716 public void drawARGB(int a, int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700717 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -0700718 }
719
720 @Override
Romain Guydeba7852010-07-07 17:54:48 -0700721 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800722 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700723 // Shaders are ignored when drawing patches
Romain Guya168d732011-03-18 16:50:13 -0700724 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800725 try {
726 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
727 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, chunks,
728 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
729 } finally {
730 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
731 }
Romain Guydeba7852010-07-07 17:54:48 -0700732 }
733
Romain Guy7d7b5492011-01-24 16:33:45 -0800734 private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800735 float left, float top, float right, float bottom, int paint);
Romain Guydeba7852010-07-07 17:54:48 -0700736
737 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700738 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800739 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700740 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700741 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800742 try {
743 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
744 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
745 } finally {
746 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
747 }
Romain Guye4d01122010-06-16 18:44:05 -0700748 }
749
Romain Guy7d7b5492011-01-24 16:33:45 -0800750 private static native void nDrawBitmap(
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800751 int renderer, int bitmap, byte[] buffer, float left, float top, int paint);
Romain Guydbd77cd2010-07-09 10:36:05 -0700752
Romain Guye4d01122010-06-16 18:44:05 -0700753 @Override
754 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800755 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700756 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700757 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800758 try {
759 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
760 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
761 matrix.native_instance, nativePaint);
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 nDrawBitmap(int renderer, int bitmap, byte[] buff,
768 int matrix, int paint);
Romain Guyf86ef572010-07-01 11:05:42 -0700769
Romain Guye4d01122010-06-16 18:44:05 -0700770 @Override
771 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800772 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700773 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700774 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800775 try {
776 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guy694b5192010-07-21 21:33:20 -0700777
Romain Guy445c83c2012-02-16 16:43:07 -0800778 int left, top, right, bottom;
779 if (src == null) {
780 left = top = 0;
781 right = bitmap.getWidth();
782 bottom = bitmap.getHeight();
783 } else {
784 left = src.left;
785 right = src.right;
786 top = src.top;
787 bottom = src.bottom;
788 }
789
790 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
791 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
792 } finally {
793 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy694b5192010-07-21 21:33:20 -0700794 }
Romain Guye4d01122010-06-16 18:44:05 -0700795 }
796
797 @Override
798 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800799 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700800 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700801 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800802 try {
803 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
804
805 float left, top, right, bottom;
806 if (src == null) {
807 left = top = 0;
808 right = bitmap.getWidth();
809 bottom = bitmap.getHeight();
810 } else {
811 left = src.left;
812 right = src.right;
813 top = src.top;
814 bottom = src.bottom;
815 }
816
817 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
818 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
819 } finally {
820 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guyff98fa52011-11-28 09:35:09 -0800821 }
Romain Guye4d01122010-06-16 18:44:05 -0700822 }
823
Romain Guy7d7b5492011-01-24 16:33:45 -0800824 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
Romain Guyce0537b2010-06-29 21:05:21 -0700825 float srcLeft, float srcTop, float srcRight, float srcBottom,
Romain Guydbd77cd2010-07-09 10:36:05 -0700826 float left, float top, float right, float bottom, int paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700827
Romain Guye4d01122010-06-16 18:44:05 -0700828 @Override
829 public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
830 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guye651cc62012-05-14 19:44:40 -0700831 if (width < 0) {
832 throw new IllegalArgumentException("width must be >= 0");
833 }
834
835 if (height < 0) {
836 throw new IllegalArgumentException("height must be >= 0");
837 }
838
839 if (Math.abs(stride) < width) {
840 throw new IllegalArgumentException("abs(stride) must be >= width");
841 }
842
843 int lastScanline = offset + (height - 1) * stride;
844 int length = colors.length;
845
846 if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
847 (lastScanline + width > length)) {
848 throw new ArrayIndexOutOfBoundsException();
849 }
850
Romain Guyd27977d2010-07-14 19:18:51 -0700851 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700852 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800853 try {
Romain Guy445c83c2012-02-16 16:43:07 -0800854 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guye651cc62012-05-14 19:44:40 -0700855 nDrawBitmap(mRenderer, colors, offset, stride, x, y,
856 width, height, hasAlpha, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800857 } finally {
858 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
859 }
Romain Guye4d01122010-06-16 18:44:05 -0700860 }
861
Romain Guye651cc62012-05-14 19:44:40 -0700862 private static native void nDrawBitmap(int renderer, int[] colors, int offset, int stride,
863 float x, float y, int width, int height, boolean hasAlpha, int nativePaint);
864
Romain Guye4d01122010-06-16 18:44:05 -0700865 @Override
866 public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
867 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700868 // Shaders are ignored when drawing bitmaps
Romain Guyce0537b2010-06-29 21:05:21 -0700869 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700870 }
871
872 @Override
873 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
874 int vertOffset, int[] colors, int colorOffset, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800875 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guy5a7b4662011-01-20 19:09:30 -0800876 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
877 throw new ArrayIndexOutOfBoundsException();
878 }
879
880 if (meshWidth == 0 || meshHeight == 0) {
881 return;
882 }
883
884 final int count = (meshWidth + 1) * (meshHeight + 1);
885 checkRange(verts.length, vertOffset, count * 2);
886
Romain Guyff316ec2013-02-13 18:39:43 -0800887 if (colors != null) {
888 checkRange(colors.length, colorOffset, count);
889 }
Romain Guy5a7b4662011-01-20 19:09:30 -0800890
Romain Guya168d732011-03-18 16:50:13 -0700891 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800892 try {
893 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
894 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
895 verts, vertOffset, colors, colorOffset, nativePaint);
896 } finally {
897 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
898 }
Romain Guye4d01122010-06-16 18:44:05 -0700899 }
900
Romain Guy7d7b5492011-01-24 16:33:45 -0800901 private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
Romain Guy5a7b4662011-01-20 19:09:30 -0800902 int meshWidth, int meshHeight, float[] verts, int vertOffset,
903 int[] colors, int colorOffset, int paint);
904
Romain Guye4d01122010-06-16 18:44:05 -0700905 @Override
906 public void drawCircle(float cx, float cy, float radius, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800907 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800908 try {
909 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
910 } finally {
911 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
912 }
Romain Guye4d01122010-06-16 18:44:05 -0700913 }
914
Romain Guy7d7b5492011-01-24 16:33:45 -0800915 private static native void nDrawCircle(int renderer, float cx, float cy,
916 float radius, int paint);
Romain Guy01d58e42011-01-19 21:54:02 -0800917
Romain Guye4d01122010-06-16 18:44:05 -0700918 @Override
919 public void drawColor(int color) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700920 drawColor(color, PorterDuff.Mode.SRC_OVER);
Romain Guye4d01122010-06-16 18:44:05 -0700921 }
922
923 @Override
924 public void drawColor(int color, PorterDuff.Mode mode) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700925 nDrawColor(mRenderer, color, mode.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700926 }
Romain Guy85bf02f2010-06-22 13:11:24 -0700927
Romain Guy7d7b5492011-01-24 16:33:45 -0800928 private static native void nDrawColor(int renderer, int color, int mode);
Romain Guye4d01122010-06-16 18:44:05 -0700929
930 @Override
931 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -0700932 mLine[0] = startX;
933 mLine[1] = startY;
934 mLine[2] = stopX;
935 mLine[3] = stopY;
Romain Guy759ea802010-09-16 20:49:46 -0700936 drawLines(mLine, 0, 4, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700937 }
938
939 @Override
940 public void drawLines(float[] pts, int offset, int count, Paint paint) {
Chris Craik5d116762013-02-19 17:49:31 -0800941 if (count < 4) return;
942
Romain Guy759ea802010-09-16 20:49:46 -0700943 if ((offset | count) < 0 || offset + count > pts.length) {
944 throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
945 }
Romain Guy765dcf32012-02-27 13:28:22 -0800946 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800947 try {
948 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
949 } finally {
950 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
951 }
Romain Guye4d01122010-06-16 18:44:05 -0700952 }
953
Romain Guy7d7b5492011-01-24 16:33:45 -0800954 private static native void nDrawLines(int renderer, float[] points,
955 int offset, int count, int paint);
Romain Guy759ea802010-09-16 20:49:46 -0700956
Romain Guye4d01122010-06-16 18:44:05 -0700957 @Override
958 public void drawLines(float[] pts, Paint paint) {
Romain Guy759ea802010-09-16 20:49:46 -0700959 drawLines(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700960 }
961
962 @Override
963 public void drawOval(RectF oval, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800964 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800965 try {
966 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
967 } finally {
968 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
969 }
Romain Guye4d01122010-06-16 18:44:05 -0700970 }
971
Romain Guy7d7b5492011-01-24 16:33:45 -0800972 private static native void nDrawOval(int renderer, float left, float top,
973 float right, float bottom, int paint);
Romain Guyc1cd9ba32011-01-23 14:18:41 -0800974
Romain Guye4d01122010-06-16 18:44:05 -0700975 @Override
976 public void drawPaint(Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -0700977 final Rect r = mClipBounds;
978 nGetClipBounds(mRenderer, r);
979 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700980 }
981
982 @Override
983 public void drawPath(Path path, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800984 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800985 try {
986 if (path.isSimplePath) {
987 if (path.rects != null) {
988 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
989 }
990 } else {
991 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
Romain Guya48a1a82010-08-10 14:59:15 -0700992 }
Romain Guy445c83c2012-02-16 16:43:07 -0800993 } finally {
994 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya48a1a82010-08-10 14:59:15 -0700995 }
Romain Guye4d01122010-06-16 18:44:05 -0700996 }
997
Romain Guy7d7b5492011-01-24 16:33:45 -0800998 private static native void nDrawPath(int renderer, int path, int paint);
999 private static native void nDrawRects(int renderer, int region, int paint);
Romain Guy7fbcc042010-08-04 15:40:07 -07001000
Romain Guy672433d2013-01-04 19:05:13 -08001001 void drawRects(float[] rects, int count, Paint paint) {
1002 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
1003 try {
1004 nDrawRects(mRenderer, rects, count, paint.mNativePaint);
1005 } finally {
1006 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1007 }
1008 }
1009
1010 private static native void nDrawRects(int renderer, float[] rects, int count, int paint);
1011
Romain Guye4d01122010-06-16 18:44:05 -07001012 @Override
1013 public void drawPicture(Picture picture) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001014 if (picture.createdFromStream) {
1015 return;
1016 }
1017
Romain Guy75582e82012-01-18 18:13:35 -08001018 picture.endRecording();
1019 // TODO: Implement rendering
Romain Guye4d01122010-06-16 18:44:05 -07001020 }
1021
1022 @Override
1023 public void drawPicture(Picture picture, Rect dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001024 if (picture.createdFromStream) {
1025 return;
1026 }
1027
Romain Guy75582e82012-01-18 18:13:35 -08001028 save();
1029 translate(dst.left, dst.top);
1030 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1031 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1032 }
1033 drawPicture(picture);
1034 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001035 }
1036
1037 @Override
1038 public void drawPicture(Picture picture, RectF dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001039 if (picture.createdFromStream) {
1040 return;
1041 }
1042
Romain Guy75582e82012-01-18 18:13:35 -08001043 save();
1044 translate(dst.left, dst.top);
1045 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1046 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1047 }
1048 drawPicture(picture);
1049 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001050 }
1051
1052 @Override
1053 public void drawPoint(float x, float y, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -07001054 mPoint[0] = x;
1055 mPoint[1] = y;
Romain Guyed6fcb02011-03-21 13:11:28 -07001056 drawPoints(mPoint, 0, 2, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001057 }
1058
1059 @Override
1060 public void drawPoints(float[] pts, Paint paint) {
Romain Guyed6fcb02011-03-21 13:11:28 -07001061 drawPoints(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001062 }
1063
1064 @Override
Romain Guyed6fcb02011-03-21 13:11:28 -07001065 public void drawPoints(float[] pts, int offset, int count, Paint paint) {
Chris Craik5d116762013-02-19 17:49:31 -08001066 if (count < 2) return;
1067
Romain Guy765dcf32012-02-27 13:28:22 -08001068 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001069 try {
1070 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
1071 } finally {
1072 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1073 }
Romain Guyed6fcb02011-03-21 13:11:28 -07001074 }
1075
1076 private static native void nDrawPoints(int renderer, float[] points,
1077 int offset, int count, int paint);
1078
Romain Guy5ff9df62012-01-23 17:09:05 -08001079 @SuppressWarnings("deprecation")
Romain Guyed6fcb02011-03-21 13:11:28 -07001080 @Override
Romain Guye4d01122010-06-16 18:44:05 -07001081 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001082 if (index < 0 || index + count > text.length || count * 2 > pos.length) {
1083 throw new IndexOutOfBoundsException();
1084 }
1085
1086 int modifiers = setupModifiers(paint);
1087 try {
1088 nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
1089 } finally {
1090 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1091 }
Romain Guye4d01122010-06-16 18:44:05 -07001092 }
1093
Romain Guyeb9a5362012-01-17 17:39:26 -08001094 private static native void nDrawPosText(int renderer, char[] text, int index, int count,
1095 float[] pos, int paint);
1096
Romain Guy5ff9df62012-01-23 17:09:05 -08001097 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -07001098 @Override
1099 public void drawPosText(String text, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001100 if (text.length() * 2 > pos.length) {
1101 throw new ArrayIndexOutOfBoundsException();
1102 }
1103
1104 int modifiers = setupModifiers(paint);
1105 try {
1106 nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
1107 } finally {
1108 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1109 }
Romain Guye4d01122010-06-16 18:44:05 -07001110 }
1111
Romain Guyeb9a5362012-01-17 17:39:26 -08001112 private static native void nDrawPosText(int renderer, String text, int start, int end,
1113 float[] pos, int paint);
1114
Romain Guye4d01122010-06-16 18:44:05 -07001115 @Override
1116 public void drawRect(float left, float top, float right, float bottom, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001117 if (left == right || top == bottom) return;
1118 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001119 try {
1120 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
1121 } finally {
1122 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1123 }
Romain Guye4d01122010-06-16 18:44:05 -07001124 }
1125
Romain Guy7d7b5492011-01-24 16:33:45 -08001126 private static native void nDrawRect(int renderer, float left, float top,
1127 float right, float bottom, int paint);
Romain Guyc7d53492010-06-25 13:41:57 -07001128
Romain Guye4d01122010-06-16 18:44:05 -07001129 @Override
1130 public void drawRect(Rect r, Paint paint) {
Romain Guyc7d53492010-06-25 13:41:57 -07001131 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001132 }
1133
1134 @Override
Romain Guyc7d53492010-06-25 13:41:57 -07001135 public void drawRect(RectF r, Paint paint) {
1136 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001137 }
1138
1139 @Override
1140 public void drawRGB(int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -07001141 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -07001142 }
1143
1144 @Override
1145 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001146 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001147 try {
1148 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
1149 rx, ry, paint.mNativePaint);
1150 } finally {
1151 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1152 }
Romain Guye4d01122010-06-16 18:44:05 -07001153 }
1154
Romain Guy7d7b5492011-01-24 16:33:45 -08001155 private static native void nDrawRoundRect(int renderer, float left, float top,
Romain Guy01d58e42011-01-19 21:54:02 -08001156 float right, float bottom, float rx, float y, int paint);
1157
Romain Guye4d01122010-06-16 18:44:05 -07001158 @Override
1159 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001160 if ((index | count | (index + count) | (text.length - index - count)) < 0) {
1161 throw new IndexOutOfBoundsException();
1162 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001163
Romain Guya168d732011-03-18 16:50:13 -07001164 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001165 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001166 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001167 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001168 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001169 }
Romain Guye4d01122010-06-16 18:44:05 -07001170 }
Romain Guya1db5742010-07-20 13:09:13 -07001171
Romain Guy7d7b5492011-01-24 16:33:45 -08001172 private static native void nDrawText(int renderer, char[] text, int index, int count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001173 float x, float y, int bidiFlags, int paint);
Romain Guye4d01122010-06-16 18:44:05 -07001174
1175 @Override
1176 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001177 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001178 try {
1179 if (text instanceof String || text instanceof SpannedString ||
1180 text instanceof SpannableString) {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001181 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
1182 paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001183 } else if (text instanceof GraphicsOperations) {
1184 ((GraphicsOperations) text).drawText(this, start, end, x, y,
1185 paint);
1186 } else {
1187 char[] buf = TemporaryBuffer.obtain(end - start);
1188 TextUtils.getChars(text, start, end, buf, 0);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001189 nDrawText(mRenderer, buf, 0, end - start, x, y,
1190 paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001191 TemporaryBuffer.recycle(buf);
1192 }
1193 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001194 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya1db5742010-07-20 13:09:13 -07001195 }
Romain Guye4d01122010-06-16 18:44:05 -07001196 }
1197
1198 @Override
1199 public void drawText(String text, int start, int end, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001200 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1201 throw new IndexOutOfBoundsException();
1202 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001203
Romain Guya168d732011-03-18 16:50:13 -07001204 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001205 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001206 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001207 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001208 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001209 }
Romain Guye4d01122010-06-16 18:44:05 -07001210 }
1211
Romain Guy7d7b5492011-01-24 16:33:45 -08001212 private static native void nDrawText(int renderer, String text, int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001213 float x, float y, int bidiFlags, int paint);
Romain Guya1db5742010-07-20 13:09:13 -07001214
Romain Guye4d01122010-06-16 18:44:05 -07001215 @Override
1216 public void drawText(String text, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001217 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001218 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001219 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
1220 paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001221 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001222 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001223 }
Romain Guye4d01122010-06-16 18:44:05 -07001224 }
1225
1226 @Override
1227 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
1228 float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001229 if (index < 0 || index + count > text.length) {
1230 throw new ArrayIndexOutOfBoundsException();
1231 }
1232
1233 int modifiers = setupModifiers(paint);
1234 try {
1235 nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001236 paint.mBidiFlags, paint.mNativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001237 } finally {
1238 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1239 }
Romain Guye4d01122010-06-16 18:44:05 -07001240 }
1241
Romain Guy325740f2012-02-24 16:48:34 -08001242 private static native void nDrawTextOnPath(int renderer, char[] text, int index, int count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001243 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001244
Romain Guye4d01122010-06-16 18:44:05 -07001245 @Override
1246 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001247 if (text.length() == 0) return;
1248
1249 int modifiers = setupModifiers(paint);
1250 try {
1251 nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001252 paint.mBidiFlags, paint.mNativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001253 } finally {
1254 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1255 }
Romain Guye4d01122010-06-16 18:44:05 -07001256 }
1257
Romain Guy325740f2012-02-24 16:48:34 -08001258 private static native void nDrawTextOnPath(int renderer, String text, int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001259 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001260
Romain Guye4d01122010-06-16 18:44:05 -07001261 @Override
1262 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001263 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001264 if ((index | count | text.length - index - count) < 0) {
1265 throw new IndexOutOfBoundsException();
1266 }
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001267 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
1268 throw new IllegalArgumentException("Unknown direction: " + dir);
1269 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001270
Romain Guya168d732011-03-18 16:50:13 -07001271 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001272 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001273 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
Romain Guy61c8c9c2010-08-09 20:48:09 -07001274 paint.mNativePaint);
1275 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001276 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001277 }
Romain Guye4d01122010-06-16 18:44:05 -07001278 }
1279
Romain Guy7d7b5492011-01-24 16:33:45 -08001280 private static native void nDrawTextRun(int renderer, char[] text, int index, int count,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001281 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001282
Romain Guye4d01122010-06-16 18:44:05 -07001283 @Override
1284 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001285 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001286 if ((start | end | end - start | text.length() - end) < 0) {
1287 throw new IndexOutOfBoundsException();
1288 }
1289
Romain Guya168d732011-03-18 16:50:13 -07001290 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001291 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001292 int flags = dir == 0 ? 0 : 1;
Romain Guy61c8c9c2010-08-09 20:48:09 -07001293 if (text instanceof String || text instanceof SpannedString ||
1294 text instanceof SpannableString) {
1295 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001296 contextEnd, x, y, flags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001297 } else if (text instanceof GraphicsOperations) {
1298 ((GraphicsOperations) text).drawTextRun(this, start, end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001299 contextStart, contextEnd, x, y, flags, paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001300 } else {
1301 int contextLen = contextEnd - contextStart;
1302 int len = end - start;
1303 char[] buf = TemporaryBuffer.obtain(contextLen);
1304 TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
1305 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001306 x, y, flags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001307 TemporaryBuffer.recycle(buf);
1308 }
1309 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001310 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001311 }
Romain Guye4d01122010-06-16 18:44:05 -07001312 }
1313
Romain Guy7d7b5492011-01-24 16:33:45 -08001314 private static native void nDrawTextRun(int renderer, String text, int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001315 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001316
Romain Guye4d01122010-06-16 18:44:05 -07001317 @Override
1318 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
1319 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
1320 int indexOffset, int indexCount, Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -07001321 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -07001322 }
Romain Guyd27977d2010-07-14 19:18:51 -07001323
Romain Guya168d732011-03-18 16:50:13 -07001324 private int setupModifiers(Bitmap b, Paint paint) {
Romain Guy445c83c2012-02-16 16:43:07 -08001325 if (b.getConfig() != Bitmap.Config.ALPHA_8) {
1326 final ColorFilter filter = paint.getColorFilter();
1327 if (filter != null) {
1328 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
1329 return MODIFIER_COLOR_FILTER;
1330 }
1331
1332 return MODIFIER_NONE;
1333 } else {
Romain Guya168d732011-03-18 16:50:13 -07001334 return setupModifiers(paint);
1335 }
Romain Guya168d732011-03-18 16:50:13 -07001336 }
1337
1338 private int setupModifiers(Paint paint) {
1339 int modifiers = MODIFIER_NONE;
Romain Guydb1938e2010-08-02 18:50:22 -07001340
Romain Guy1e45aae2010-08-13 19:39:53 -07001341 if (paint.hasShadow) {
1342 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1343 paint.shadowColor);
Romain Guya168d732011-03-18 16:50:13 -07001344 modifiers |= MODIFIER_SHADOW;
Romain Guy1e45aae2010-08-13 19:39:53 -07001345 }
1346
Romain Guyd27977d2010-07-14 19:18:51 -07001347 final Shader shader = paint.getShader();
1348 if (shader != null) {
Romain Guy06f96e22010-07-30 19:18:16 -07001349 nSetupShader(mRenderer, shader.native_shader);
Romain Guya168d732011-03-18 16:50:13 -07001350 modifiers |= MODIFIER_SHADER;
Romain Guydb1938e2010-08-02 18:50:22 -07001351 }
1352
1353 final ColorFilter filter = paint.getColorFilter();
1354 if (filter != null) {
1355 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guya168d732011-03-18 16:50:13 -07001356 modifiers |= MODIFIER_COLOR_FILTER;
Romain Guydb1938e2010-08-02 18:50:22 -07001357 }
1358
Romain Guya168d732011-03-18 16:50:13 -07001359 return modifiers;
Romain Guydb1938e2010-08-02 18:50:22 -07001360 }
Romain Guy1e45aae2010-08-13 19:39:53 -07001361
Romain Guy765dcf32012-02-27 13:28:22 -08001362 private int setupModifiers(Paint paint, int flags) {
1363 int modifiers = MODIFIER_NONE;
1364
1365 if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
1366 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1367 paint.shadowColor);
1368 modifiers |= MODIFIER_SHADOW;
1369 }
1370
1371 final Shader shader = paint.getShader();
1372 if (shader != null && (flags & MODIFIER_SHADER) != 0) {
1373 nSetupShader(mRenderer, shader.native_shader);
1374 modifiers |= MODIFIER_SHADER;
1375 }
1376
1377 final ColorFilter filter = paint.getColorFilter();
1378 if (filter != null && (flags & MODIFIER_COLOR_FILTER) != 0) {
1379 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
1380 modifiers |= MODIFIER_COLOR_FILTER;
1381 }
1382
1383 return modifiers;
1384 }
1385
Romain Guya168d732011-03-18 16:50:13 -07001386 private int setupColorFilter(Paint paint) {
Romain Guydb1938e2010-08-02 18:50:22 -07001387 final ColorFilter filter = paint.getColorFilter();
1388 if (filter != null) {
1389 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guya168d732011-03-18 16:50:13 -07001390 return MODIFIER_COLOR_FILTER;
Romain Guyd27977d2010-07-14 19:18:51 -07001391 }
Romain Guy56215272011-03-23 16:55:38 -07001392 return MODIFIER_NONE;
Romain Guyd27977d2010-07-14 19:18:51 -07001393 }
Romain Guya168d732011-03-18 16:50:13 -07001394
Romain Guy7d7b5492011-01-24 16:33:45 -08001395 private static native void nSetupShader(int renderer, int shader);
1396 private static native void nSetupColorFilter(int renderer, int colorFilter);
1397 private static native void nSetupShadow(int renderer, float radius,
1398 float dx, float dy, int color);
Romain Guy1e45aae2010-08-13 19:39:53 -07001399
Romain Guya168d732011-03-18 16:50:13 -07001400 private static native void nResetModifiers(int renderer, int modifiers);
Romain Guye4d01122010-06-16 18:44:05 -07001401}