blob: f4ab133f03762db3a37544f0a3c82c23a37e6936 [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 Guye4d01122010-06-16 18:44:05 -0700147 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800148 // Hardware layers
149 ///////////////////////////////////////////////////////////////////////////
150
Romain Guya9489272011-06-22 20:58:11 -0700151 static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
Romain Guyada830f2011-01-13 12:13:20 -0800152 static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
153 static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
Romain Guy846a5332012-07-11 17:44:57 -0700154 static native void nSetOpaqueLayer(int layerId, boolean isOpaque);
Romain Guya9489272011-06-22 20:58:11 -0700155 static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
156 SurfaceTexture surface);
Romain Guy302a9df2011-08-16 13:55:02 -0700157 static native void nSetTextureLayerTransform(int layerId, int matrix);
Romain Guyada830f2011-01-13 12:13:20 -0800158 static native void nDestroyLayer(int layerId);
159 static native void nDestroyLayerDeferred(int layerId);
Romain Guy2bf68f02012-03-02 13:37:47 -0800160 static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
161 int left, int top, int right, int bottom);
Romain Guy77a81162011-06-14 16:45:55 -0700162 static native boolean nCopyLayer(int layerId, int bitmap);
Romain Guy57066eb2011-01-12 12:53:32 -0800163
Romain Guy6c319ca2011-01-11 14:29:25 -0800164 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700165 // Canvas management
166 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700167
168 @Override
169 public boolean isOpaque() {
170 return mOpaque;
171 }
172
173 @Override
174 public int getWidth() {
175 return mWidth;
176 }
177
178 @Override
179 public int getHeight() {
180 return mHeight;
181 }
182
Romain Guyf61970fc2011-07-07 14:10:06 -0700183 @Override
184 public int getMaximumBitmapWidth() {
185 return nGetMaximumTextureWidth();
186 }
187
188 @Override
189 public int getMaximumBitmapHeight() {
190 return nGetMaximumTextureHeight();
191 }
192
193 private static native int nGetMaximumTextureWidth();
Romain Guy530041d2012-01-25 18:56:29 -0800194 private static native int nGetMaximumTextureHeight();
Romain Guyf61970fc2011-07-07 14:10:06 -0700195
Romain Guy2bf68f02012-03-02 13:37:47 -0800196 /**
197 * Returns the native OpenGLRenderer object.
198 */
199 int getRenderer() {
200 return mRenderer;
201 }
202
Romain Guye4d01122010-06-16 18:44:05 -0700203 ///////////////////////////////////////////////////////////////////////////
204 // Setup
205 ///////////////////////////////////////////////////////////////////////////
206
207 @Override
208 public void setViewport(int width, int height) {
209 mWidth = width;
210 mHeight = height;
211
212 nSetViewport(mRenderer, width, height);
213 }
214
Romain Guy7d7b5492011-01-24 16:33:45 -0800215 private static native void nSetViewport(int renderer, int width, int height);
Romain Guye4d01122010-06-16 18:44:05 -0700216
Romain Guy7d7b5492011-01-24 16:33:45 -0800217 @Override
Chet Haase44b2fe32012-06-06 19:03:58 -0700218 public int onPreDraw(Rect dirty) {
Romain Guy7d7b5492011-01-24 16:33:45 -0800219 if (dirty != null) {
Chet Haase44b2fe32012-06-06 19:03:58 -0700220 return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
221 mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800222 } else {
Chet Haase44b2fe32012-06-06 19:03:58 -0700223 return nPrepare(mRenderer, mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800224 }
225 }
226
Chet Haase44b2fe32012-06-06 19:03:58 -0700227 private static native int nPrepare(int renderer, boolean opaque);
228 private static native int nPrepareDirty(int renderer, int left, int top, int right, int bottom,
Romain Guy7d7b5492011-01-24 16:33:45 -0800229 boolean opaque);
Romain Guye4d01122010-06-16 18:44:05 -0700230
Romain Guyb051e892010-09-28 19:09:36 -0700231 @Override
Gilles Debunneb35ab7b2011-12-05 15:54:00 -0800232 public void onPostDraw() {
Romain Guyb025b9c2010-09-16 14:16:48 -0700233 nFinish(mRenderer);
234 }
Romain Guy9ace8f52011-07-07 20:50:11 -0700235
Romain Guy7d7b5492011-01-24 16:33:45 -0800236 private static native void nFinish(int renderer);
Romain Guyb025b9c2010-09-16 14:16:48 -0700237
Romain Guy530041d2012-01-25 18:56:29 -0800238 /**
239 * Returns the size of the stencil buffer required by the underlying
240 * implementation.
241 *
242 * @return The minimum number of bits the stencil buffer must. Always >= 0.
243 *
244 * @hide
245 */
246 public static int getStencilSize() {
247 return nGetStencilSize();
248 }
249
250 private static native int nGetStencilSize();
251
252 ///////////////////////////////////////////////////////////////////////////
253 // Functor
254 ///////////////////////////////////////////////////////////////////////////
255
Romain Guyda8532c2010-08-31 11:50:35 -0700256 @Override
Romain Guy65549432012-03-26 16:45:05 -0700257 public int callDrawGLFunction(int drawGLFunction) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800258 return nCallDrawGLFunction(mRenderer, drawGLFunction);
259 }
260
Romain Guy65549432012-03-26 16:45:05 -0700261 private static native int nCallDrawGLFunction(int renderer, int drawGLFunction);
Chet Haasedaf98e92011-01-10 14:10:36 -0800262
Romain Guy8f3b8e32012-03-27 16:33:45 -0700263 @Override
264 public int invokeFunctors(Rect dirty) {
265 return nInvokeFunctors(mRenderer, dirty);
266 }
267
268 private static native int nInvokeFunctors(int renderer, Rect dirty);
269
Romain Guyba6be8a2012-04-23 18:22:09 -0700270 @Override
271 public void detachFunctor(int functor) {
272 nDetachFunctor(mRenderer, functor);
273 }
274
275 private static native void nDetachFunctor(int renderer, int functor);
276
277 @Override
278 public void attachFunctor(int functor) {
279 nAttachFunctor(mRenderer, functor);
280 }
281
282 private static native void nAttachFunctor(int renderer, int functor);
283
Romain Guybdf76092011-07-18 15:00:43 -0700284 ///////////////////////////////////////////////////////////////////////////
285 // Memory
286 ///////////////////////////////////////////////////////////////////////////
287
288 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700289 * Must match Caches::FlushMode values
290 *
Romain Guybdf76092011-07-18 15:00:43 -0700291 * @see #flushCaches(int)
292 */
Romain Guy6d7475d2011-07-27 16:28:21 -0700293 public static final int FLUSH_CACHES_LAYERS = 0;
294
295 /**
296 * Must match Caches::FlushMode values
297 *
298 * @see #flushCaches(int)
299 */
300 public static final int FLUSH_CACHES_MODERATE = 1;
Romain Guybdf76092011-07-18 15:00:43 -0700301
302 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700303 * Must match Caches::FlushMode values
304 *
Romain Guybdf76092011-07-18 15:00:43 -0700305 * @see #flushCaches(int)
306 */
Romain Guy6d7475d2011-07-27 16:28:21 -0700307 public static final int FLUSH_CACHES_FULL = 2;
Romain Guybdf76092011-07-18 15:00:43 -0700308
309 /**
310 * Flush caches to reclaim as much memory as possible. The amount of memory
311 * to reclaim is indicate by the level parameter.
312 *
313 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
314 * {@link #FLUSH_CACHES_FULL}.
315 *
316 * @param level Hint about the amount of memory to reclaim
317 *
318 * @hide
319 */
320 public static void flushCaches(int level) {
321 nFlushCaches(level);
322 }
323
324 private static native void nFlushCaches(int level);
325
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800326 /**
327 * Release all resources associated with the underlying caches. This should
328 * only be called after a full flushCaches().
329 *
330 * @hide
331 */
332 public static void terminateCaches() {
333 nTerminateCaches();
334 }
335
336 private static native void nTerminateCaches();
337
338 /**
339 * @hide
340 */
341 public static void initCaches() {
342 nInitCaches();
343 }
344
345 private static native void nInitCaches();
346
Romain Guyb051e892010-09-28 19:09:36 -0700347 ///////////////////////////////////////////////////////////////////////////
348 // Display list
349 ///////////////////////////////////////////////////////////////////////////
350
Jeff Brown162a0212011-07-21 17:02:54 -0700351 int getDisplayList(int displayList) {
352 return nGetDisplayList(mRenderer, displayList);
Romain Guyb051e892010-09-28 19:09:36 -0700353 }
354
Jeff Brown162a0212011-07-21 17:02:54 -0700355 private static native int nGetDisplayList(int renderer, int displayList);
Romain Guyb051e892010-09-28 19:09:36 -0700356
Chet Haase5c13d892010-10-08 08:37:55 -0700357 static void destroyDisplayList(int displayList) {
Romain Guyb051e892010-09-28 19:09:36 -0700358 nDestroyDisplayList(displayList);
359 }
360
Chet Haase5c13d892010-10-08 08:37:55 -0700361 private static native void nDestroyDisplayList(int displayList);
Romain Guyb051e892010-09-28 19:09:36 -0700362
Romain Guy65b345f2011-07-27 18:51:50 -0700363 static int getDisplayListSize(int displayList) {
364 return nGetDisplayListSize(displayList);
365 }
366
367 private static native int nGetDisplayListSize(int displayList);
368
Romain Guy13631f32012-01-30 17:41:55 -0800369 static void setDisplayListName(int displayList, String name) {
370 nSetDisplayListName(displayList, name);
371 }
372
373 private static native void nSetDisplayListName(int displayList, String name);
374
Romain Guyb051e892010-09-28 19:09:36 -0700375 @Override
Chet Haase1271e2c2012-04-20 09:54:27 -0700376 public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
Romain Guy33f6beb2012-02-16 19:24:51 -0800377 return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList(),
Chet Haase1271e2c2012-04-20 09:54:27 -0700378 dirty, flags);
Romain Guyb051e892010-09-28 19:09:36 -0700379 }
380
Romain Guy65549432012-03-26 16:45:05 -0700381 private static native int nDrawDisplayList(int renderer, int displayList,
Chet Haase1271e2c2012-04-20 09:54:27 -0700382 Rect dirty, int flags);
Romain Guyda8532c2010-08-31 11:50:35 -0700383
Chet Haaseed30fd82011-04-22 16:18:45 -0700384 @Override
385 void outputDisplayList(DisplayList displayList) {
Jeff Brown162a0212011-07-21 17:02:54 -0700386 nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList());
Chet Haaseed30fd82011-04-22 16:18:45 -0700387 }
388
389 private static native void nOutputDisplayList(int renderer, int displayList);
390
Romain Guye4d01122010-06-16 18:44:05 -0700391 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800392 // Hardware layer
393 ///////////////////////////////////////////////////////////////////////////
394
Romain Guyada830f2011-01-13 12:13:20 -0800395 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
Romain Guy6c319ca2011-01-11 14:29:25 -0800396 final GLES20Layer glLayer = (GLES20Layer) layer;
Romain Guya168d732011-03-18 16:50:13 -0700397 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800398 try {
399 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
400 nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
401 } finally {
402 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
403 }
Romain Guy6c319ca2011-01-11 14:29:25 -0800404 }
405
Romain Guy7d7b5492011-01-24 16:33:45 -0800406 private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
Romain Guyaa6c24c2011-04-28 18:40:04 -0700407
Romain Guy6c319ca2011-01-11 14:29:25 -0800408 void interrupt() {
409 nInterrupt(mRenderer);
410 }
411
412 void resume() {
413 nResume(mRenderer);
414 }
415
Romain Guy7d7b5492011-01-24 16:33:45 -0800416 private static native void nInterrupt(int renderer);
417 private static native void nResume(int renderer);
Romain Guy6c319ca2011-01-11 14:29:25 -0800418
419 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700420 // Clipping
421 ///////////////////////////////////////////////////////////////////////////
422
423 @Override
424 public boolean clipPath(Path path) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800425 // TODO: Implement
426 path.computeBounds(mPathBounds, true);
427 return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
428 mPathBounds.right, mPathBounds.bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700429 }
430
431 @Override
432 public boolean clipPath(Path path, Region.Op op) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800433 // TODO: Implement
434 path.computeBounds(mPathBounds, true);
435 return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
436 mPathBounds.right, mPathBounds.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700437 }
438
439 @Override
440 public boolean clipRect(float left, float top, float right, float bottom) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700441 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700442 }
Romain Guybb9524b2010-06-22 18:56:38 -0700443
Romain Guy7d7b5492011-01-24 16:33:45 -0800444 private static native boolean nClipRect(int renderer, float left, float top,
Romain Guy079ba2c2010-07-16 14:12:24 -0700445 float right, float bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700446
447 @Override
448 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700449 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700450 }
451
452 @Override
453 public boolean clipRect(int left, int top, int right, int bottom) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800454 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700455 }
Romain Guybb9524b2010-06-22 18:56:38 -0700456
Romain Guy7d7b5492011-01-24 16:33:45 -0800457 private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom,
458 int op);
Romain Guye4d01122010-06-16 18:44:05 -0700459
460 @Override
461 public boolean clipRect(Rect rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700462 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
463 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700464 }
465
466 @Override
467 public boolean clipRect(Rect rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700468 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700469 }
470
471 @Override
472 public boolean clipRect(RectF rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700473 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
474 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700475 }
476
477 @Override
478 public boolean clipRect(RectF rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700479 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700480 }
481
482 @Override
483 public boolean clipRegion(Region region) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800484 // TODO: Implement
485 region.getBounds(mClipBounds);
486 return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
487 mClipBounds.right, mClipBounds.bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700488 }
489
490 @Override
491 public boolean clipRegion(Region region, Region.Op op) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800492 // TODO: Implement
493 region.getBounds(mClipBounds);
494 return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
495 mClipBounds.right, mClipBounds.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700496 }
497
498 @Override
499 public boolean getClipBounds(Rect bounds) {
Romain Guy9d5316e2010-06-24 19:30:36 -0700500 return nGetClipBounds(mRenderer, bounds);
Romain Guye4d01122010-06-16 18:44:05 -0700501 }
502
Romain Guy7d7b5492011-01-24 16:33:45 -0800503 private static native boolean nGetClipBounds(int renderer, Rect bounds);
Romain Guy9d5316e2010-06-24 19:30:36 -0700504
Romain Guye4d01122010-06-16 18:44:05 -0700505 @Override
506 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
Romain Guyc7d53492010-06-25 13:41:57 -0700507 return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700508 }
Romain Guyc7d53492010-06-25 13:41:57 -0700509
Romain Guy7d7b5492011-01-24 16:33:45 -0800510 private static native boolean nQuickReject(int renderer, float left, float top,
Romain Guyc7d53492010-06-25 13:41:57 -0700511 float right, float bottom, int edge);
Romain Guye4d01122010-06-16 18:44:05 -0700512
513 @Override
514 public boolean quickReject(Path path, EdgeType type) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800515 path.computeBounds(mPathBounds, true);
516 return nQuickReject(mRenderer, mPathBounds.left, mPathBounds.top,
517 mPathBounds.right, mPathBounds.bottom, type.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700518 }
519
520 @Override
521 public boolean quickReject(RectF rect, EdgeType type) {
Romain Guy7677d8f2012-01-17 11:22:42 -0800522 return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom, type.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700523 }
524
525 ///////////////////////////////////////////////////////////////////////////
526 // Transformations
527 ///////////////////////////////////////////////////////////////////////////
528
529 @Override
530 public void translate(float dx, float dy) {
Romain Guy807daf72011-01-18 11:19:19 -0800531 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
Romain Guye4d01122010-06-16 18:44:05 -0700532 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700533
Romain Guy7d7b5492011-01-24 16:33:45 -0800534 private static native void nTranslate(int renderer, float dx, float dy);
Romain Guye4d01122010-06-16 18:44:05 -0700535
536 @Override
537 public void skew(float sx, float sy) {
Romain Guy807daf72011-01-18 11:19:19 -0800538 nSkew(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700539 }
540
Romain Guy7d7b5492011-01-24 16:33:45 -0800541 private static native void nSkew(int renderer, float sx, float sy);
Romain Guy807daf72011-01-18 11:19:19 -0800542
Romain Guye4d01122010-06-16 18:44:05 -0700543 @Override
544 public void rotate(float degrees) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700545 nRotate(mRenderer, degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700546 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700547
Romain Guy7d7b5492011-01-24 16:33:45 -0800548 private static native void nRotate(int renderer, float degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700549
550 @Override
551 public void scale(float sx, float sy) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700552 nScale(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700553 }
Romain Guye4d01122010-06-16 18:44:05 -0700554
Romain Guy7d7b5492011-01-24 16:33:45 -0800555 private static native void nScale(int renderer, float sx, float sy);
Romain Guyf6a11b82010-06-23 17:47:49 -0700556
Romain Guye4d01122010-06-16 18:44:05 -0700557 @Override
558 public void setMatrix(Matrix matrix) {
Romain Guye7078592011-10-28 14:32:20 -0700559 nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700560 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700561
Romain Guy7d7b5492011-01-24 16:33:45 -0800562 private static native void nSetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700563
Romain Guy5ff9df62012-01-23 17:09:05 -0800564 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -0700565 @Override
Romain Guyf6a11b82010-06-23 17:47:49 -0700566 public void getMatrix(Matrix matrix) {
567 nGetMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700568 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700569
Romain Guy7d7b5492011-01-24 16:33:45 -0800570 private static native void nGetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700571
572 @Override
573 public void concat(Matrix matrix) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700574 nConcatMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700575 }
576
Romain Guy7d7b5492011-01-24 16:33:45 -0800577 private static native void nConcatMatrix(int renderer, int matrix);
Romain Guyf6a11b82010-06-23 17:47:49 -0700578
Romain Guye4d01122010-06-16 18:44:05 -0700579 ///////////////////////////////////////////////////////////////////////////
580 // State management
581 ///////////////////////////////////////////////////////////////////////////
582
583 @Override
584 public int save() {
Romain Guy8aef54f2010-09-01 15:13:49 -0700585 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
Romain Guye4d01122010-06-16 18:44:05 -0700586 }
Romain Guybb9524b2010-06-22 18:56:38 -0700587
Romain Guye4d01122010-06-16 18:44:05 -0700588 @Override
589 public int save(int saveFlags) {
Romain Guybb9524b2010-06-22 18:56:38 -0700590 return nSave(mRenderer, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700591 }
592
Romain Guy7d7b5492011-01-24 16:33:45 -0800593 private static native int nSave(int renderer, int flags);
Romain Guybb9524b2010-06-22 18:56:38 -0700594
Romain Guye4d01122010-06-16 18:44:05 -0700595 @Override
596 public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700597 if (bounds != null) {
598 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
599 }
600
Romain Guy445c83c2012-02-16 16:43:07 -0800601 int count;
Romain Guy189887e2011-08-25 11:45:13 -0700602 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800603 try {
604 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
605 count = nSaveLayer(mRenderer, nativePaint, saveFlags);
606 } finally {
607 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
608 }
Romain Guy189887e2011-08-25 11:45:13 -0700609 return count;
Romain Guye4d01122010-06-16 18:44:05 -0700610 }
611
Romain Guy189887e2011-08-25 11:45:13 -0700612 private static native int nSaveLayer(int renderer, int paint, int saveFlags);
613
Romain Guye4d01122010-06-16 18:44:05 -0700614 @Override
615 public int saveLayer(float left, float top, float right, float bottom, Paint paint,
616 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800617 if (left < right && top < bottom) {
Romain Guy445c83c2012-02-16 16:43:07 -0800618 int count;
Romain Guya168d732011-03-18 16:50:13 -0700619 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800620 try {
621 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
622 count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
623 } finally {
624 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
625 }
Romain Guy01d58e42011-01-19 21:54:02 -0800626 return count;
627 }
628 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700629 }
630
Romain Guy7d7b5492011-01-24 16:33:45 -0800631 private static native int nSaveLayer(int renderer, float left, float top,
632 float right, float bottom, int paint, int saveFlags);
Romain Guybd6b79b2010-06-26 00:13:53 -0700633
Romain Guye4d01122010-06-16 18:44:05 -0700634 @Override
635 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700636 if (bounds != null) {
637 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
638 alpha, saveFlags);
639 }
640 return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700641 }
642
Romain Guy189887e2011-08-25 11:45:13 -0700643 private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags);
644
Romain Guye4d01122010-06-16 18:44:05 -0700645 @Override
646 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
647 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800648 if (left < right && top < bottom) {
649 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
650 }
651 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700652 }
653
Romain Guy7d7b5492011-01-24 16:33:45 -0800654 private static native int nSaveLayerAlpha(int renderer, float left, float top, float right,
Romain Guybd6b79b2010-06-26 00:13:53 -0700655 float bottom, int alpha, int saveFlags);
656
Romain Guye4d01122010-06-16 18:44:05 -0700657 @Override
658 public void restore() {
Romain Guybb9524b2010-06-22 18:56:38 -0700659 nRestore(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700660 }
Romain Guybb9524b2010-06-22 18:56:38 -0700661
Romain Guy7d7b5492011-01-24 16:33:45 -0800662 private static native void nRestore(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700663
664 @Override
665 public void restoreToCount(int saveCount) {
Romain Guybb9524b2010-06-22 18:56:38 -0700666 nRestoreToCount(mRenderer, saveCount);
Romain Guye4d01122010-06-16 18:44:05 -0700667 }
668
Romain Guy7d7b5492011-01-24 16:33:45 -0800669 private static native void nRestoreToCount(int renderer, int saveCount);
Romain Guybb9524b2010-06-22 18:56:38 -0700670
Romain Guye4d01122010-06-16 18:44:05 -0700671 @Override
672 public int getSaveCount() {
Romain Guybb9524b2010-06-22 18:56:38 -0700673 return nGetSaveCount(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700674 }
Romain Guybb9524b2010-06-22 18:56:38 -0700675
Romain Guy7d7b5492011-01-24 16:33:45 -0800676 private static native int nGetSaveCount(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700677
678 ///////////////////////////////////////////////////////////////////////////
679 // Filtering
680 ///////////////////////////////////////////////////////////////////////////
681
682 @Override
683 public void setDrawFilter(DrawFilter filter) {
Romain Guy6926c722010-07-12 20:20:03 -0700684 mFilter = filter;
Romain Guy5ff9df62012-01-23 17:09:05 -0800685 if (filter == null) {
686 nResetPaintFilter(mRenderer);
687 } else if (filter instanceof PaintFlagsDrawFilter) {
688 PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
689 nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
690 }
Romain Guye4d01122010-06-16 18:44:05 -0700691 }
692
Romain Guy5ff9df62012-01-23 17:09:05 -0800693 private static native void nResetPaintFilter(int renderer);
694 private static native void nSetupPaintFilter(int renderer, int clearBits, int setBits);
695
Romain Guye4d01122010-06-16 18:44:05 -0700696 @Override
697 public DrawFilter getDrawFilter() {
Romain Guy6926c722010-07-12 20:20:03 -0700698 return mFilter;
Romain Guye4d01122010-06-16 18:44:05 -0700699 }
700
701 ///////////////////////////////////////////////////////////////////////////
702 // Drawing
703 ///////////////////////////////////////////////////////////////////////////
704
705 @Override
706 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
707 Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800708 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800709 try {
710 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
711 startAngle, sweepAngle, useCenter, paint.mNativePaint);
712 } finally {
713 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
714 }
Romain Guye4d01122010-06-16 18:44:05 -0700715 }
716
Romain Guy7d7b5492011-01-24 16:33:45 -0800717 private static native void nDrawArc(int renderer, float left, float top,
718 float right, float bottom, float startAngle, float sweepAngle,
719 boolean useCenter, int paint);
Romain Guy8b2f5262011-01-23 16:15:02 -0800720
Romain Guye4d01122010-06-16 18:44:05 -0700721 @Override
722 public void drawARGB(int a, int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700723 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -0700724 }
725
726 @Override
Romain Guydeba7852010-07-07 17:54:48 -0700727 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800728 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700729 // Shaders are ignored when drawing patches
Romain Guya168d732011-03-18 16:50:13 -0700730 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800731 try {
732 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
733 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, chunks,
734 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
735 } finally {
736 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
737 }
Romain Guydeba7852010-07-07 17:54:48 -0700738 }
739
Romain Guy7d7b5492011-01-24 16:33:45 -0800740 private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800741 float left, float top, float right, float bottom, int paint);
Romain Guydeba7852010-07-07 17:54:48 -0700742
743 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700744 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800745 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700746 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700747 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800748 try {
749 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
750 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
751 } finally {
752 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
753 }
Romain Guye4d01122010-06-16 18:44:05 -0700754 }
755
Romain Guy7d7b5492011-01-24 16:33:45 -0800756 private static native void nDrawBitmap(
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800757 int renderer, int bitmap, byte[] buffer, float left, float top, int paint);
Romain Guydbd77cd2010-07-09 10:36:05 -0700758
Romain Guye4d01122010-06-16 18:44:05 -0700759 @Override
760 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800761 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700762 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700763 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800764 try {
765 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
766 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
767 matrix.native_instance, nativePaint);
768 } finally {
769 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
770 }
Romain Guye4d01122010-06-16 18:44:05 -0700771 }
772
Romain Guy7d7b5492011-01-24 16:33:45 -0800773 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buff,
774 int matrix, int paint);
Romain Guyf86ef572010-07-01 11:05:42 -0700775
Romain Guye4d01122010-06-16 18:44:05 -0700776 @Override
777 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800778 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700779 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700780 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800781 try {
782 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guy694b5192010-07-21 21:33:20 -0700783
Romain Guy445c83c2012-02-16 16:43:07 -0800784 int left, top, right, bottom;
785 if (src == null) {
786 left = top = 0;
787 right = bitmap.getWidth();
788 bottom = bitmap.getHeight();
789 } else {
790 left = src.left;
791 right = src.right;
792 top = src.top;
793 bottom = src.bottom;
794 }
795
796 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
797 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
798 } finally {
799 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy694b5192010-07-21 21:33:20 -0700800 }
Romain Guye4d01122010-06-16 18:44:05 -0700801 }
802
803 @Override
804 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800805 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guyd27977d2010-07-14 19:18:51 -0700806 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700807 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800808 try {
809 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
810
811 float left, top, right, bottom;
812 if (src == null) {
813 left = top = 0;
814 right = bitmap.getWidth();
815 bottom = bitmap.getHeight();
816 } else {
817 left = src.left;
818 right = src.right;
819 top = src.top;
820 bottom = src.bottom;
821 }
822
823 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
824 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
825 } finally {
826 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guyff98fa52011-11-28 09:35:09 -0800827 }
Romain Guye4d01122010-06-16 18:44:05 -0700828 }
829
Romain Guy7d7b5492011-01-24 16:33:45 -0800830 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
Romain Guyce0537b2010-06-29 21:05:21 -0700831 float srcLeft, float srcTop, float srcRight, float srcBottom,
Romain Guydbd77cd2010-07-09 10:36:05 -0700832 float left, float top, float right, float bottom, int paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700833
Romain Guye4d01122010-06-16 18:44:05 -0700834 @Override
835 public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
836 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guye651cc62012-05-14 19:44:40 -0700837 if (width < 0) {
838 throw new IllegalArgumentException("width must be >= 0");
839 }
840
841 if (height < 0) {
842 throw new IllegalArgumentException("height must be >= 0");
843 }
844
845 if (Math.abs(stride) < width) {
846 throw new IllegalArgumentException("abs(stride) must be >= width");
847 }
848
849 int lastScanline = offset + (height - 1) * stride;
850 int length = colors.length;
851
852 if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
853 (lastScanline + width > length)) {
854 throw new ArrayIndexOutOfBoundsException();
855 }
856
Romain Guyd27977d2010-07-14 19:18:51 -0700857 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700858 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800859 try {
Romain Guy445c83c2012-02-16 16:43:07 -0800860 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guye651cc62012-05-14 19:44:40 -0700861 nDrawBitmap(mRenderer, colors, offset, stride, x, y,
862 width, height, hasAlpha, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800863 } finally {
864 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
865 }
Romain Guye4d01122010-06-16 18:44:05 -0700866 }
867
Romain Guye651cc62012-05-14 19:44:40 -0700868 private static native void nDrawBitmap(int renderer, int[] colors, int offset, int stride,
869 float x, float y, int width, int height, boolean hasAlpha, int nativePaint);
870
Romain Guye4d01122010-06-16 18:44:05 -0700871 @Override
872 public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
873 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700874 // Shaders are ignored when drawing bitmaps
Romain Guyce0537b2010-06-29 21:05:21 -0700875 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700876 }
877
878 @Override
879 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
880 int vertOffset, int[] colors, int colorOffset, Paint paint) {
Romain Guybc52cce2012-02-07 19:40:19 -0800881 if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
Romain Guy5a7b4662011-01-20 19:09:30 -0800882 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
883 throw new ArrayIndexOutOfBoundsException();
884 }
885
886 if (meshWidth == 0 || meshHeight == 0) {
887 return;
888 }
889
890 final int count = (meshWidth + 1) * (meshHeight + 1);
891 checkRange(verts.length, vertOffset, count * 2);
892
893 // TODO: Colors are ignored for now
894 colors = null;
895 colorOffset = 0;
896
Romain Guya168d732011-03-18 16:50:13 -0700897 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800898 try {
899 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
900 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
901 verts, vertOffset, colors, colorOffset, nativePaint);
902 } finally {
903 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
904 }
Romain Guye4d01122010-06-16 18:44:05 -0700905 }
906
Romain Guy7d7b5492011-01-24 16:33:45 -0800907 private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
Romain Guy5a7b4662011-01-20 19:09:30 -0800908 int meshWidth, int meshHeight, float[] verts, int vertOffset,
909 int[] colors, int colorOffset, int paint);
910
Romain Guye4d01122010-06-16 18:44:05 -0700911 @Override
912 public void drawCircle(float cx, float cy, float radius, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800913 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800914 try {
915 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
916 } finally {
917 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
918 }
Romain Guye4d01122010-06-16 18:44:05 -0700919 }
920
Romain Guy7d7b5492011-01-24 16:33:45 -0800921 private static native void nDrawCircle(int renderer, float cx, float cy,
922 float radius, int paint);
Romain Guy01d58e42011-01-19 21:54:02 -0800923
Romain Guye4d01122010-06-16 18:44:05 -0700924 @Override
925 public void drawColor(int color) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700926 drawColor(color, PorterDuff.Mode.SRC_OVER);
Romain Guye4d01122010-06-16 18:44:05 -0700927 }
928
929 @Override
930 public void drawColor(int color, PorterDuff.Mode mode) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700931 nDrawColor(mRenderer, color, mode.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700932 }
Romain Guy85bf02f2010-06-22 13:11:24 -0700933
Romain Guy7d7b5492011-01-24 16:33:45 -0800934 private static native void nDrawColor(int renderer, int color, int mode);
Romain Guye4d01122010-06-16 18:44:05 -0700935
936 @Override
937 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -0700938 mLine[0] = startX;
939 mLine[1] = startY;
940 mLine[2] = stopX;
941 mLine[3] = stopY;
Romain Guy759ea802010-09-16 20:49:46 -0700942 drawLines(mLine, 0, 4, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700943 }
944
945 @Override
946 public void drawLines(float[] pts, int offset, int count, Paint paint) {
Romain Guy759ea802010-09-16 20:49:46 -0700947 if ((offset | count) < 0 || offset + count > pts.length) {
948 throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
949 }
Romain Guy765dcf32012-02-27 13:28:22 -0800950 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800951 try {
952 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
953 } finally {
954 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
955 }
Romain Guye4d01122010-06-16 18:44:05 -0700956 }
957
Romain Guy7d7b5492011-01-24 16:33:45 -0800958 private static native void nDrawLines(int renderer, float[] points,
959 int offset, int count, int paint);
Romain Guy759ea802010-09-16 20:49:46 -0700960
Romain Guye4d01122010-06-16 18:44:05 -0700961 @Override
962 public void drawLines(float[] pts, Paint paint) {
Romain Guy759ea802010-09-16 20:49:46 -0700963 drawLines(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700964 }
965
966 @Override
967 public void drawOval(RectF oval, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800968 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800969 try {
970 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
971 } finally {
972 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
973 }
Romain Guye4d01122010-06-16 18:44:05 -0700974 }
975
Romain Guy7d7b5492011-01-24 16:33:45 -0800976 private static native void nDrawOval(int renderer, float left, float top,
977 float right, float bottom, int paint);
Romain Guyc1cd9ba32011-01-23 14:18:41 -0800978
Romain Guye4d01122010-06-16 18:44:05 -0700979 @Override
980 public void drawPaint(Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -0700981 final Rect r = mClipBounds;
982 nGetClipBounds(mRenderer, r);
983 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700984 }
985
986 @Override
987 public void drawPath(Path path, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -0800988 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800989 try {
990 if (path.isSimplePath) {
991 if (path.rects != null) {
992 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
993 }
994 } else {
995 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
Romain Guya48a1a82010-08-10 14:59:15 -0700996 }
Romain Guy445c83c2012-02-16 16:43:07 -0800997 } finally {
998 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya48a1a82010-08-10 14:59:15 -0700999 }
Romain Guye4d01122010-06-16 18:44:05 -07001000 }
1001
Romain Guy7d7b5492011-01-24 16:33:45 -08001002 private static native void nDrawPath(int renderer, int path, int paint);
1003 private static native void nDrawRects(int renderer, int region, int paint);
Romain Guy7fbcc042010-08-04 15:40:07 -07001004
Romain Guye4d01122010-06-16 18:44:05 -07001005 @Override
1006 public void drawPicture(Picture picture) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001007 if (picture.createdFromStream) {
1008 return;
1009 }
1010
Romain Guy75582e82012-01-18 18:13:35 -08001011 picture.endRecording();
1012 // TODO: Implement rendering
Romain Guye4d01122010-06-16 18:44:05 -07001013 }
1014
1015 @Override
1016 public void drawPicture(Picture picture, Rect dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001017 if (picture.createdFromStream) {
1018 return;
1019 }
1020
Romain Guy75582e82012-01-18 18:13:35 -08001021 save();
1022 translate(dst.left, dst.top);
1023 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1024 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1025 }
1026 drawPicture(picture);
1027 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001028 }
1029
1030 @Override
1031 public void drawPicture(Picture picture, RectF dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001032 if (picture.createdFromStream) {
1033 return;
1034 }
1035
Romain Guy75582e82012-01-18 18:13:35 -08001036 save();
1037 translate(dst.left, dst.top);
1038 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1039 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1040 }
1041 drawPicture(picture);
1042 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001043 }
1044
1045 @Override
1046 public void drawPoint(float x, float y, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -07001047 mPoint[0] = x;
1048 mPoint[1] = y;
Romain Guyed6fcb02011-03-21 13:11:28 -07001049 drawPoints(mPoint, 0, 2, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001050 }
1051
1052 @Override
1053 public void drawPoints(float[] pts, Paint paint) {
Romain Guyed6fcb02011-03-21 13:11:28 -07001054 drawPoints(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001055 }
1056
1057 @Override
Romain Guyed6fcb02011-03-21 13:11:28 -07001058 public void drawPoints(float[] pts, int offset, int count, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001059 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001060 try {
1061 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
1062 } finally {
1063 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1064 }
Romain Guyed6fcb02011-03-21 13:11:28 -07001065 }
1066
1067 private static native void nDrawPoints(int renderer, float[] points,
1068 int offset, int count, int paint);
1069
Romain Guy5ff9df62012-01-23 17:09:05 -08001070 @SuppressWarnings("deprecation")
Romain Guyed6fcb02011-03-21 13:11:28 -07001071 @Override
Romain Guye4d01122010-06-16 18:44:05 -07001072 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001073 if (index < 0 || index + count > text.length || count * 2 > pos.length) {
1074 throw new IndexOutOfBoundsException();
1075 }
1076
1077 int modifiers = setupModifiers(paint);
1078 try {
1079 nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
1080 } finally {
1081 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1082 }
Romain Guye4d01122010-06-16 18:44:05 -07001083 }
1084
Romain Guyeb9a5362012-01-17 17:39:26 -08001085 private static native void nDrawPosText(int renderer, char[] text, int index, int count,
1086 float[] pos, int paint);
1087
Romain Guy5ff9df62012-01-23 17:09:05 -08001088 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -07001089 @Override
1090 public void drawPosText(String text, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001091 if (text.length() * 2 > pos.length) {
1092 throw new ArrayIndexOutOfBoundsException();
1093 }
1094
1095 int modifiers = setupModifiers(paint);
1096 try {
1097 nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
1098 } finally {
1099 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1100 }
Romain Guye4d01122010-06-16 18:44:05 -07001101 }
1102
Romain Guyeb9a5362012-01-17 17:39:26 -08001103 private static native void nDrawPosText(int renderer, String text, int start, int end,
1104 float[] pos, int paint);
1105
Romain Guye4d01122010-06-16 18:44:05 -07001106 @Override
1107 public void drawRect(float left, float top, float right, float bottom, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001108 if (left == right || top == bottom) return;
1109 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001110 try {
1111 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
1112 } finally {
1113 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1114 }
Romain Guye4d01122010-06-16 18:44:05 -07001115 }
1116
Romain Guy7d7b5492011-01-24 16:33:45 -08001117 private static native void nDrawRect(int renderer, float left, float top,
1118 float right, float bottom, int paint);
Romain Guyc7d53492010-06-25 13:41:57 -07001119
Romain Guye4d01122010-06-16 18:44:05 -07001120 @Override
1121 public void drawRect(Rect r, Paint paint) {
Romain Guyc7d53492010-06-25 13:41:57 -07001122 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001123 }
1124
1125 @Override
Romain Guyc7d53492010-06-25 13:41:57 -07001126 public void drawRect(RectF r, Paint paint) {
1127 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001128 }
1129
1130 @Override
1131 public void drawRGB(int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -07001132 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -07001133 }
1134
1135 @Override
1136 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001137 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001138 try {
1139 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
1140 rx, ry, paint.mNativePaint);
1141 } finally {
1142 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1143 }
Romain Guye4d01122010-06-16 18:44:05 -07001144 }
1145
Romain Guy7d7b5492011-01-24 16:33:45 -08001146 private static native void nDrawRoundRect(int renderer, float left, float top,
Romain Guy01d58e42011-01-19 21:54:02 -08001147 float right, float bottom, float rx, float y, int paint);
1148
Romain Guye4d01122010-06-16 18:44:05 -07001149 @Override
1150 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001151 if ((index | count | (index + count) | (text.length - index - count)) < 0) {
1152 throw new IndexOutOfBoundsException();
1153 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001154
Romain Guya168d732011-03-18 16:50:13 -07001155 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001156 try {
1157 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
1158 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001159 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001160 }
Romain Guye4d01122010-06-16 18:44:05 -07001161 }
Romain Guya1db5742010-07-20 13:09:13 -07001162
Romain Guy7d7b5492011-01-24 16:33:45 -08001163 private static native void nDrawText(int renderer, char[] text, int index, int count,
1164 float x, float y, int bidiFlags, int paint);
Romain Guye4d01122010-06-16 18:44:05 -07001165
1166 @Override
1167 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001168 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001169 try {
1170 if (text instanceof String || text instanceof SpannedString ||
1171 text instanceof SpannableString) {
1172 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
1173 paint.mNativePaint);
1174 } else if (text instanceof GraphicsOperations) {
1175 ((GraphicsOperations) text).drawText(this, start, end, x, y,
1176 paint);
1177 } else {
1178 char[] buf = TemporaryBuffer.obtain(end - start);
1179 TextUtils.getChars(text, start, end, buf, 0);
Romain Guy7d7b5492011-01-24 16:33:45 -08001180 nDrawText(mRenderer, buf, 0, end - start, x, y,
1181 paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001182 TemporaryBuffer.recycle(buf);
1183 }
1184 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001185 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya1db5742010-07-20 13:09:13 -07001186 }
Romain Guye4d01122010-06-16 18:44:05 -07001187 }
1188
1189 @Override
1190 public void drawText(String text, int start, int end, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001191 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1192 throw new IndexOutOfBoundsException();
1193 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001194
Romain Guya168d732011-03-18 16:50:13 -07001195 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001196 try {
1197 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
1198 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001199 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001200 }
Romain Guye4d01122010-06-16 18:44:05 -07001201 }
1202
Romain Guy7d7b5492011-01-24 16:33:45 -08001203 private static native void nDrawText(int renderer, String text, int start, int end,
1204 float x, float y, int bidiFlags, int paint);
Romain Guya1db5742010-07-20 13:09:13 -07001205
Romain Guye4d01122010-06-16 18:44:05 -07001206 @Override
1207 public void drawText(String text, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001208 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001209 try {
1210 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
1211 paint.mNativePaint);
1212 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001213 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001214 }
Romain Guye4d01122010-06-16 18:44:05 -07001215 }
1216
1217 @Override
1218 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
1219 float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001220 if (index < 0 || index + count > text.length) {
1221 throw new ArrayIndexOutOfBoundsException();
1222 }
1223
1224 int modifiers = setupModifiers(paint);
1225 try {
1226 nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
1227 paint.mBidiFlags, paint.mNativePaint);
1228 } finally {
1229 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1230 }
Romain Guye4d01122010-06-16 18:44:05 -07001231 }
1232
Romain Guy325740f2012-02-24 16:48:34 -08001233 private static native void nDrawTextOnPath(int renderer, char[] text, int index, int count,
1234 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
1235
Romain Guye4d01122010-06-16 18:44:05 -07001236 @Override
1237 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001238 if (text.length() == 0) return;
1239
1240 int modifiers = setupModifiers(paint);
1241 try {
1242 nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
1243 paint.mBidiFlags, paint.mNativePaint);
1244 } finally {
1245 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1246 }
Romain Guye4d01122010-06-16 18:44:05 -07001247 }
1248
Romain Guy325740f2012-02-24 16:48:34 -08001249 private static native void nDrawTextOnPath(int renderer, String text, int start, int end,
1250 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
1251
Romain Guye4d01122010-06-16 18:44:05 -07001252 @Override
1253 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
1254 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001255 if ((index | count | text.length - index - count) < 0) {
1256 throw new IndexOutOfBoundsException();
1257 }
1258 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
1259 throw new IllegalArgumentException("Unknown direction: " + dir);
1260 }
1261
Romain Guya168d732011-03-18 16:50:13 -07001262 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001263 try {
1264 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
1265 paint.mNativePaint);
1266 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001267 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001268 }
Romain Guye4d01122010-06-16 18:44:05 -07001269 }
1270
Romain Guy7d7b5492011-01-24 16:33:45 -08001271 private static native void nDrawTextRun(int renderer, char[] text, int index, int count,
Romain Guy61c8c9c2010-08-09 20:48:09 -07001272 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
1273
Romain Guye4d01122010-06-16 18:44:05 -07001274 @Override
1275 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
1276 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001277 if ((start | end | end - start | text.length() - end) < 0) {
1278 throw new IndexOutOfBoundsException();
1279 }
1280
Romain Guya168d732011-03-18 16:50:13 -07001281 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001282 try {
1283 int flags = dir == 0 ? 0 : 1;
1284 if (text instanceof String || text instanceof SpannedString ||
1285 text instanceof SpannableString) {
1286 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
1287 contextEnd, x, y, flags, paint.mNativePaint);
1288 } else if (text instanceof GraphicsOperations) {
1289 ((GraphicsOperations) text).drawTextRun(this, start, end,
1290 contextStart, contextEnd, x, y, flags, paint);
1291 } else {
1292 int contextLen = contextEnd - contextStart;
1293 int len = end - start;
1294 char[] buf = TemporaryBuffer.obtain(contextLen);
1295 TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
1296 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
1297 x, y, flags, paint.mNativePaint);
1298 TemporaryBuffer.recycle(buf);
1299 }
1300 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001301 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001302 }
Romain Guye4d01122010-06-16 18:44:05 -07001303 }
1304
Romain Guy7d7b5492011-01-24 16:33:45 -08001305 private static native void nDrawTextRun(int renderer, String text, int start, int end,
Romain Guy61c8c9c2010-08-09 20:48:09 -07001306 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
1307
Romain Guye4d01122010-06-16 18:44:05 -07001308 @Override
1309 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
1310 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
1311 int indexOffset, int indexCount, Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -07001312 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -07001313 }
Romain Guyd27977d2010-07-14 19:18:51 -07001314
Romain Guya168d732011-03-18 16:50:13 -07001315 private int setupModifiers(Bitmap b, Paint paint) {
Romain Guy445c83c2012-02-16 16:43:07 -08001316 if (b.getConfig() != Bitmap.Config.ALPHA_8) {
1317 final ColorFilter filter = paint.getColorFilter();
1318 if (filter != null) {
1319 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
1320 return MODIFIER_COLOR_FILTER;
1321 }
1322
1323 return MODIFIER_NONE;
1324 } else {
Romain Guya168d732011-03-18 16:50:13 -07001325 return setupModifiers(paint);
1326 }
Romain Guya168d732011-03-18 16:50:13 -07001327 }
1328
1329 private int setupModifiers(Paint paint) {
1330 int modifiers = MODIFIER_NONE;
Romain Guydb1938e2010-08-02 18:50:22 -07001331
Romain Guy1e45aae2010-08-13 19:39:53 -07001332 if (paint.hasShadow) {
1333 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1334 paint.shadowColor);
Romain Guya168d732011-03-18 16:50:13 -07001335 modifiers |= MODIFIER_SHADOW;
Romain Guy1e45aae2010-08-13 19:39:53 -07001336 }
1337
Romain Guyd27977d2010-07-14 19:18:51 -07001338 final Shader shader = paint.getShader();
1339 if (shader != null) {
Romain Guy06f96e22010-07-30 19:18:16 -07001340 nSetupShader(mRenderer, shader.native_shader);
Romain Guya168d732011-03-18 16:50:13 -07001341 modifiers |= MODIFIER_SHADER;
Romain Guydb1938e2010-08-02 18:50:22 -07001342 }
1343
1344 final ColorFilter filter = paint.getColorFilter();
1345 if (filter != null) {
1346 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guya168d732011-03-18 16:50:13 -07001347 modifiers |= MODIFIER_COLOR_FILTER;
Romain Guydb1938e2010-08-02 18:50:22 -07001348 }
1349
Romain Guya168d732011-03-18 16:50:13 -07001350 return modifiers;
Romain Guydb1938e2010-08-02 18:50:22 -07001351 }
Romain Guy1e45aae2010-08-13 19:39:53 -07001352
Romain Guy765dcf32012-02-27 13:28:22 -08001353 private int setupModifiers(Paint paint, int flags) {
1354 int modifiers = MODIFIER_NONE;
1355
1356 if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
1357 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1358 paint.shadowColor);
1359 modifiers |= MODIFIER_SHADOW;
1360 }
1361
1362 final Shader shader = paint.getShader();
1363 if (shader != null && (flags & MODIFIER_SHADER) != 0) {
1364 nSetupShader(mRenderer, shader.native_shader);
1365 modifiers |= MODIFIER_SHADER;
1366 }
1367
1368 final ColorFilter filter = paint.getColorFilter();
1369 if (filter != null && (flags & MODIFIER_COLOR_FILTER) != 0) {
1370 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
1371 modifiers |= MODIFIER_COLOR_FILTER;
1372 }
1373
1374 return modifiers;
1375 }
1376
Romain Guya168d732011-03-18 16:50:13 -07001377 private int setupColorFilter(Paint paint) {
Romain Guydb1938e2010-08-02 18:50:22 -07001378 final ColorFilter filter = paint.getColorFilter();
1379 if (filter != null) {
1380 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guya168d732011-03-18 16:50:13 -07001381 return MODIFIER_COLOR_FILTER;
Romain Guyd27977d2010-07-14 19:18:51 -07001382 }
Romain Guy56215272011-03-23 16:55:38 -07001383 return MODIFIER_NONE;
Romain Guyd27977d2010-07-14 19:18:51 -07001384 }
Romain Guya168d732011-03-18 16:50:13 -07001385
Romain Guy7d7b5492011-01-24 16:33:45 -08001386 private static native void nSetupShader(int renderer, int shader);
1387 private static native void nSetupColorFilter(int renderer, int colorFilter);
1388 private static native void nSetupShadow(int renderer, float radius,
1389 float dx, float dy, int color);
Romain Guy1e45aae2010-08-13 19:39:53 -07001390
Romain Guya168d732011-03-18 16:50:13 -07001391 private static native void nResetModifiers(int renderer, int modifiers);
Romain Guye4d01122010-06-16 18:44:05 -07001392}