blob: 34b85d90ae537815c3e2873b2f51a9ba003bad49 [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;
21import android.graphics.DrawFilter;
22import android.graphics.Matrix;
Romain Guy3b748a42013-04-17 18:54:38 -070023import android.graphics.NinePatch;
Romain Guye4d01122010-06-16 18:44:05 -070024import 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 Guya1db5742010-07-20 13:09:13 -070033import android.graphics.TemporaryBuffer;
34import android.text.GraphicsOperations;
35import android.text.SpannableString;
36import android.text.SpannedString;
37import android.text.TextUtils;
Romain Guye4d01122010-06-16 18:44:05 -070038
Romain Guye4d01122010-06-16 18:44:05 -070039/**
40 * An implementation of Canvas on top of OpenGL ES 2.0.
41 */
Romain Guyb051e892010-09-28 19:09:36 -070042class GLES20Canvas extends HardwareCanvas {
Romain Guya168d732011-03-18 16:50:13 -070043 // Must match modifiers used in the JNI layer
44 private static final int MODIFIER_NONE = 0;
45 private static final int MODIFIER_SHADOW = 1;
46 private static final int MODIFIER_SHADER = 2;
Romain Guya168d732011-03-18 16:50:13 -070047
Romain Guye4d01122010-06-16 18:44:05 -070048 private final boolean mOpaque;
John Reck44fd8d22014-02-26 11:00:11 -080049 protected long mRenderer;
Patrick Dubroyf890fab2010-12-19 16:47:17 -080050
51 // The native renderer will be destroyed when this object dies.
52 // DO NOT overwrite this reference once it is set.
Romain Guyeea60692011-07-26 20:35:55 -070053 @SuppressWarnings({"unused", "FieldCanBeLocal"})
Patrick Dubroyf890fab2010-12-19 16:47:17 -080054 private CanvasFinalizer mFinalizer;
55
Romain Guye4d01122010-06-16 18:44:05 -070056 private int mWidth;
57 private int mHeight;
Romain Guyce0537b2010-06-29 21:05:21 -070058
Romain Guy6410c0a2013-06-17 11:21:58 -070059 private float[] mPoint;
60 private float[] mLine;
Romain Guy6926c722010-07-12 20:20:03 -070061
Romain Guy6410c0a2013-06-17 11:21:58 -070062 private Rect mClipBounds;
63 private RectF mPathBounds;
Romain Guy6926c722010-07-12 20:20:03 -070064
65 private DrawFilter mFilter;
Romain Guyda8532c2010-08-31 11:50:35 -070066
Romain Guy16393512010-08-08 00:14:31 -070067 ///////////////////////////////////////////////////////////////////////////
68 // JNI
69 ///////////////////////////////////////////////////////////////////////////
70
71 private static native boolean nIsAvailable();
72 private static boolean sIsAvailable = nIsAvailable();
73
74 static boolean isAvailable() {
75 return sIsAvailable;
76 }
Romain Guye4d01122010-06-16 18:44:05 -070077
78 ///////////////////////////////////////////////////////////////////////////
79 // Constructors
80 ///////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -070081
Romain Guy6c319ca2011-01-11 14:29:25 -080082 /**
83 * Creates a canvas to render directly on screen.
84 */
Romain Guyb051e892010-09-28 19:09:36 -070085 GLES20Canvas(boolean translucent) {
86 this(false, translucent);
87 }
Romain Guye4d01122010-06-16 18:44:05 -070088
Patrick Dubroyf890fab2010-12-19 16:47:17 -080089 protected GLES20Canvas(boolean record, boolean translucent) {
Romain Guye4d01122010-06-16 18:44:05 -070090 mOpaque = !translucent;
91
Romain Guyb051e892010-09-28 19:09:36 -070092 if (record) {
Jeff Brown162a0212011-07-21 17:02:54 -070093 mRenderer = nCreateDisplayListRenderer();
Romain Guyb051e892010-09-28 19:09:36 -070094 } else {
95 mRenderer = nCreateRenderer();
96 }
Romain Guy6c319ca2011-01-11 14:29:25 -080097
98 setupFinalizer();
99 }
100
101 private void setupFinalizer() {
Romain Guyfb8b7632010-08-23 21:05:08 -0700102 if (mRenderer == 0) {
103 throw new IllegalStateException("Could not create GLES20Canvas renderer");
Chet Haase5c13d892010-10-08 08:37:55 -0700104 } else {
Jeff Brown162a0212011-07-21 17:02:54 -0700105 mFinalizer = new CanvasFinalizer(mRenderer);
Romain Guyfb8b7632010-08-23 21:05:08 -0700106 }
Romain Guye4d01122010-06-16 18:44:05 -0700107 }
Romain Guye4d01122010-06-16 18:44:05 -0700108
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000109 private static native long nCreateRenderer();
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000110 private static native long nCreateDisplayListRenderer();
111 private static native void nResetDisplayListRenderer(long renderer);
112 private static native void nDestroyRenderer(long renderer);
Chet Haase5c13d892010-10-08 08:37:55 -0700113
Jeff Brown162a0212011-07-21 17:02:54 -0700114 private static final class CanvasFinalizer {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000115 private final long mRenderer;
Chet Haase5c13d892010-10-08 08:37:55 -0700116
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000117 public CanvasFinalizer(long renderer) {
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800118 mRenderer = renderer;
Chet Haase5c13d892010-10-08 08:37:55 -0700119 }
120
121 @Override
Patrick Dubroyf890fab2010-12-19 16:47:17 -0800122 protected void finalize() throws Throwable {
Romain Guy171c5922011-01-06 10:04:23 -0800123 try {
Jeff Brown162a0212011-07-21 17:02:54 -0700124 nDestroyRenderer(mRenderer);
Romain Guy171c5922011-01-06 10:04:23 -0800125 } finally {
126 super.finalize();
127 }
Romain Guye4d01122010-06-16 18:44:05 -0700128 }
129 }
Romain Guyce0537b2010-06-29 21:05:21 -0700130
Chris Craikba9b6132013-12-15 17:10:19 -0800131 public static void setProperty(String name, String value) {
132 nSetProperty(name, value);
133 }
134
135 private static native void nSetProperty(String name, String value);
136
Romain Guye4d01122010-06-16 18:44:05 -0700137 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800138 // Hardware layers
139 ///////////////////////////////////////////////////////////////////////////
Romain Guy11cb6422012-09-21 00:39:43 -0700140
141 @Override
142 void pushLayerUpdate(HardwareLayer layer) {
John Reck04fc5832014-02-05 16:38:25 -0800143 nPushLayerUpdate(mRenderer, layer.getLayer());
Romain Guy11cb6422012-09-21 00:39:43 -0700144 }
145
146 @Override
Romain Guye93482f2013-06-17 13:14:51 -0700147 void cancelLayerUpdate(HardwareLayer layer) {
John Reck04fc5832014-02-05 16:38:25 -0800148 nCancelLayerUpdate(mRenderer, layer.getLayer());
Romain Guye93482f2013-06-17 13:14:51 -0700149 }
150
151 @Override
Romain Guy40543602013-06-12 15:31:28 -0700152 void flushLayerUpdates() {
153 nFlushLayerUpdates(mRenderer);
154 }
155
156 @Override
Romain Guy11cb6422012-09-21 00:39:43 -0700157 void clearLayerUpdates() {
158 nClearLayerUpdates(mRenderer);
159 }
160
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000161 static native boolean nCopyLayer(long layerId, long bitmap);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000162 private static native void nClearLayerUpdates(long renderer);
163 private static native void nFlushLayerUpdates(long renderer);
164 private static native void nPushLayerUpdate(long renderer, long layer);
165 private static native void nCancelLayerUpdate(long renderer, long layer);
Romain Guy11cb6422012-09-21 00:39:43 -0700166
Romain Guy6c319ca2011-01-11 14:29:25 -0800167 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700168 // Canvas management
169 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700170
171 @Override
172 public boolean isOpaque() {
173 return mOpaque;
174 }
175
176 @Override
177 public int getWidth() {
178 return mWidth;
179 }
180
181 @Override
182 public int getHeight() {
183 return mHeight;
184 }
185
Romain Guyf61970fc2011-07-07 14:10:06 -0700186 @Override
187 public int getMaximumBitmapWidth() {
188 return nGetMaximumTextureWidth();
189 }
190
191 @Override
192 public int getMaximumBitmapHeight() {
193 return nGetMaximumTextureHeight();
194 }
195
196 private static native int nGetMaximumTextureWidth();
Romain Guy530041d2012-01-25 18:56:29 -0800197 private static native int nGetMaximumTextureHeight();
Romain Guyf61970fc2011-07-07 14:10:06 -0700198
Romain Guy2bf68f02012-03-02 13:37:47 -0800199 /**
200 * Returns the native OpenGLRenderer object.
201 */
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000202 long getRenderer() {
Romain Guy2bf68f02012-03-02 13:37:47 -0800203 return mRenderer;
204 }
205
Romain Guye4d01122010-06-16 18:44:05 -0700206 ///////////////////////////////////////////////////////////////////////////
207 // Setup
208 ///////////////////////////////////////////////////////////////////////////
209
210 @Override
211 public void setViewport(int width, int height) {
212 mWidth = width;
213 mHeight = height;
214
215 nSetViewport(mRenderer, width, height);
216 }
217
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000218 private static native void nSetViewport(long renderer, int width, int height);
Romain Guye4d01122010-06-16 18:44:05 -0700219
Romain Guy7d7b5492011-01-24 16:33:45 -0800220 @Override
Chet Haase44b2fe32012-06-06 19:03:58 -0700221 public int onPreDraw(Rect dirty) {
Romain Guy7d7b5492011-01-24 16:33:45 -0800222 if (dirty != null) {
Chet Haase44b2fe32012-06-06 19:03:58 -0700223 return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
224 mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800225 } else {
Chet Haase44b2fe32012-06-06 19:03:58 -0700226 return nPrepare(mRenderer, mOpaque);
Romain Guy7d7b5492011-01-24 16:33:45 -0800227 }
228 }
229
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000230 private static native int nPrepare(long renderer, boolean opaque);
231 private static native int nPrepareDirty(long renderer, int left, int top, int right, int bottom,
Romain Guy7d7b5492011-01-24 16:33:45 -0800232 boolean opaque);
Romain Guye4d01122010-06-16 18:44:05 -0700233
Romain Guyb051e892010-09-28 19:09:36 -0700234 @Override
Gilles Debunneb35ab7b2011-12-05 15:54:00 -0800235 public void onPostDraw() {
Romain Guyb025b9c2010-09-16 14:16:48 -0700236 nFinish(mRenderer);
237 }
Romain Guy9ace8f52011-07-07 20:50:11 -0700238
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000239 private static native void nFinish(long renderer);
Romain Guyb025b9c2010-09-16 14:16:48 -0700240
Romain Guy530041d2012-01-25 18:56:29 -0800241 /**
242 * Returns the size of the stencil buffer required by the underlying
243 * implementation.
244 *
245 * @return The minimum number of bits the stencil buffer must. Always >= 0.
246 *
247 * @hide
248 */
249 public static int getStencilSize() {
250 return nGetStencilSize();
251 }
252
253 private static native int nGetStencilSize();
254
255 ///////////////////////////////////////////////////////////////////////////
256 // Functor
257 ///////////////////////////////////////////////////////////////////////////
258
Romain Guyda8532c2010-08-31 11:50:35 -0700259 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000260 public int callDrawGLFunction(long drawGLFunction) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800261 return nCallDrawGLFunction(mRenderer, drawGLFunction);
262 }
263
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000264 private static native int nCallDrawGLFunction(long renderer, long drawGLFunction);
Chet Haasedaf98e92011-01-10 14:10:36 -0800265
Romain Guy8f3b8e32012-03-27 16:33:45 -0700266 @Override
267 public int invokeFunctors(Rect dirty) {
268 return nInvokeFunctors(mRenderer, dirty);
269 }
270
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000271 private static native int nInvokeFunctors(long renderer, Rect dirty);
Romain Guy8f3b8e32012-03-27 16:33:45 -0700272
Romain Guyba6be8a2012-04-23 18:22:09 -0700273 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000274 public void detachFunctor(long functor) {
Romain Guyba6be8a2012-04-23 18:22:09 -0700275 nDetachFunctor(mRenderer, functor);
276 }
277
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000278 private static native void nDetachFunctor(long renderer, long functor);
Romain Guyba6be8a2012-04-23 18:22:09 -0700279
280 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000281 public void attachFunctor(long functor) {
Romain Guyba6be8a2012-04-23 18:22:09 -0700282 nAttachFunctor(mRenderer, functor);
283 }
284
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000285 private static native void nAttachFunctor(long renderer, long functor);
Romain Guyba6be8a2012-04-23 18:22:09 -0700286
Romain Guybdf76092011-07-18 15:00:43 -0700287 ///////////////////////////////////////////////////////////////////////////
288 // Memory
289 ///////////////////////////////////////////////////////////////////////////
290
291 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700292 * Must match Caches::FlushMode values
293 *
Romain Guybdf76092011-07-18 15:00:43 -0700294 * @see #flushCaches(int)
295 */
Romain Guy3b748a42013-04-17 18:54:38 -0700296 static final int FLUSH_CACHES_LAYERS = 0;
Romain Guy6d7475d2011-07-27 16:28:21 -0700297
298 /**
299 * Must match Caches::FlushMode values
300 *
301 * @see #flushCaches(int)
302 */
Romain Guy3b748a42013-04-17 18:54:38 -0700303 static final int FLUSH_CACHES_MODERATE = 1;
Romain Guybdf76092011-07-18 15:00:43 -0700304
305 /**
Romain Guy6d7475d2011-07-27 16:28:21 -0700306 * Must match Caches::FlushMode values
307 *
Romain Guybdf76092011-07-18 15:00:43 -0700308 * @see #flushCaches(int)
309 */
Romain Guy3b748a42013-04-17 18:54:38 -0700310 static final int FLUSH_CACHES_FULL = 2;
Romain Guybdf76092011-07-18 15:00:43 -0700311
312 /**
313 * Flush caches to reclaim as much memory as possible. The amount of memory
314 * to reclaim is indicate by the level parameter.
315 *
316 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
317 * {@link #FLUSH_CACHES_FULL}.
318 *
319 * @param level Hint about the amount of memory to reclaim
Romain Guybdf76092011-07-18 15:00:43 -0700320 */
Romain Guy3b748a42013-04-17 18:54:38 -0700321 static void flushCaches(int level) {
Romain Guybdf76092011-07-18 15:00:43 -0700322 nFlushCaches(level);
323 }
324
325 private static native void nFlushCaches(int level);
326
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800327 /**
328 * Release all resources associated with the underlying caches. This should
329 * only be called after a full flushCaches().
330 *
331 * @hide
332 */
Romain Guy3b748a42013-04-17 18:54:38 -0700333 static void terminateCaches() {
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800334 nTerminateCaches();
335 }
336
337 private static native void nTerminateCaches();
338
Romain Guy3b748a42013-04-17 18:54:38 -0700339 static boolean initCaches() {
340 return nInitCaches();
Romain Guy8ff6b9e2011-11-09 20:10:18 -0800341 }
342
Romain Guy3b748a42013-04-17 18:54:38 -0700343 private static native boolean nInitCaches();
344
345 ///////////////////////////////////////////////////////////////////////////
346 // Atlas
347 ///////////////////////////////////////////////////////////////////////////
348
Ashok Bhat17ab38f2014-01-27 16:00:23 +0000349 static void initAtlas(GraphicBuffer buffer, long[] map) {
Romain Guy3b748a42013-04-17 18:54:38 -0700350 nInitAtlas(buffer, map, map.length);
351 }
352
Ashok Bhat17ab38f2014-01-27 16:00:23 +0000353 private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count);
Romain Guy3b748a42013-04-17 18:54:38 -0700354
Romain Guyb051e892010-09-28 19:09:36 -0700355 ///////////////////////////////////////////////////////////////////////////
356 // Display list
357 ///////////////////////////////////////////////////////////////////////////
358
John Reck44fd8d22014-02-26 11:00:11 -0800359 protected static native long nFinishRecording(long renderer);
Romain Guy52036b12013-02-14 18:03:37 -0800360
361 @Override
John Reckf666ad72014-03-14 16:24:57 -0700362 public int drawDisplayList(RenderNode displayList, Rect dirty, int flags) {
Chris Craik54389792013-12-20 13:28:11 -0800363 return nDrawDisplayList(mRenderer, displayList.getNativeDisplayList(),
Chet Haase1271e2c2012-04-20 09:54:27 -0700364 dirty, flags);
Romain Guyb051e892010-09-28 19:09:36 -0700365 }
366
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000367 private static native int nDrawDisplayList(long renderer, long displayList,
Chet Haase1271e2c2012-04-20 09:54:27 -0700368 Rect dirty, int flags);
Romain Guyda8532c2010-08-31 11:50:35 -0700369
Romain Guye4d01122010-06-16 18:44:05 -0700370 ///////////////////////////////////////////////////////////////////////////
Romain Guy6c319ca2011-01-11 14:29:25 -0800371 // Hardware layer
372 ///////////////////////////////////////////////////////////////////////////
373
Romain Guyada830f2011-01-13 12:13:20 -0800374 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
Chris Craika4e16c52013-03-22 10:00:48 -0700375 layer.setLayerPaint(paint);
John Reck04fc5832014-02-05 16:38:25 -0800376 nDrawLayer(mRenderer, layer.getLayer(), x, y);
Romain Guy6c319ca2011-01-11 14:29:25 -0800377 }
378
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000379 private static native void nDrawLayer(long renderer, long layer, float x, float y);
Romain Guyaa6c24c2011-04-28 18:40:04 -0700380
Romain Guy6c319ca2011-01-11 14:29:25 -0800381 ///////////////////////////////////////////////////////////////////////////
Romain Guy6410c0a2013-06-17 11:21:58 -0700382 // Support
383 ///////////////////////////////////////////////////////////////////////////
384
385 private Rect getInternalClipBounds() {
386 if (mClipBounds == null) mClipBounds = new Rect();
387 return mClipBounds;
388 }
389
390
391 private RectF getPathBounds() {
392 if (mPathBounds == null) mPathBounds = new RectF();
393 return mPathBounds;
394 }
395
396 private float[] getPointStorage() {
397 if (mPoint == null) mPoint = new float[2];
398 return mPoint;
399 }
400
401 private float[] getLineStorage() {
402 if (mLine == null) mLine = new float[4];
403 return mLine;
404 }
405
406 ///////////////////////////////////////////////////////////////////////////
Romain Guye4d01122010-06-16 18:44:05 -0700407 // Clipping
408 ///////////////////////////////////////////////////////////////////////////
409
410 @Override
411 public boolean clipPath(Path path) {
Romain Guy735738c2012-12-03 12:34:51 -0800412 return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700413 }
414
415 @Override
416 public boolean clipPath(Path path, Region.Op op) {
Romain Guy735738c2012-12-03 12:34:51 -0800417 return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700418 }
419
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000420 private static native boolean nClipPath(long renderer, long path, int op);
Romain Guy735738c2012-12-03 12:34:51 -0800421
Romain Guye4d01122010-06-16 18:44:05 -0700422 @Override
423 public boolean clipRect(float left, float top, float right, float bottom) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700424 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700425 }
Romain Guybb9524b2010-06-22 18:56:38 -0700426
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000427 private static native boolean nClipRect(long renderer, float left, float top,
Romain Guy079ba2c2010-07-16 14:12:24 -0700428 float right, float bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700429
430 @Override
431 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700432 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700433 }
434
435 @Override
436 public boolean clipRect(int left, int top, int right, int bottom) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800437 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700438 }
Romain Guybb9524b2010-06-22 18:56:38 -0700439
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000440 private static native boolean nClipRect(long renderer, int left, int top,
Romain Guy735738c2012-12-03 12:34:51 -0800441 int right, int bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700442
443 @Override
444 public boolean clipRect(Rect rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700445 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
446 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700447 }
448
449 @Override
450 public boolean clipRect(Rect rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700451 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700452 }
453
454 @Override
455 public boolean clipRect(RectF rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700456 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
457 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700458 }
459
460 @Override
461 public boolean clipRect(RectF rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700462 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700463 }
464
465 @Override
466 public boolean clipRegion(Region region) {
Romain Guy735738c2012-12-03 12:34:51 -0800467 return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700468 }
469
470 @Override
471 public boolean clipRegion(Region region, Region.Op op) {
Romain Guy735738c2012-12-03 12:34:51 -0800472 return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700473 }
474
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000475 private static native boolean nClipRegion(long renderer, long region, int op);
Romain Guy735738c2012-12-03 12:34:51 -0800476
Romain Guye4d01122010-06-16 18:44:05 -0700477 @Override
478 public boolean getClipBounds(Rect bounds) {
Romain Guy9d5316e2010-06-24 19:30:36 -0700479 return nGetClipBounds(mRenderer, bounds);
Romain Guye4d01122010-06-16 18:44:05 -0700480 }
481
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000482 private static native boolean nGetClipBounds(long renderer, Rect bounds);
Romain Guy9d5316e2010-06-24 19:30:36 -0700483
Romain Guye4d01122010-06-16 18:44:05 -0700484 @Override
485 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400486 return nQuickReject(mRenderer, left, top, right, bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700487 }
Romain Guyc7d53492010-06-25 13:41:57 -0700488
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000489 private static native boolean nQuickReject(long renderer, float left, float top,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400490 float right, float bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700491
492 @Override
493 public boolean quickReject(Path path, EdgeType type) {
Romain Guy6410c0a2013-06-17 11:21:58 -0700494 RectF pathBounds = getPathBounds();
495 path.computeBounds(pathBounds, true);
496 return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
497 pathBounds.right, pathBounds.bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700498 }
499
500 @Override
501 public boolean quickReject(RectF rect, EdgeType type) {
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400502 return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
Romain Guye4d01122010-06-16 18:44:05 -0700503 }
504
505 ///////////////////////////////////////////////////////////////////////////
506 // Transformations
507 ///////////////////////////////////////////////////////////////////////////
508
509 @Override
510 public void translate(float dx, float dy) {
Romain Guy807daf72011-01-18 11:19:19 -0800511 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
Romain Guye4d01122010-06-16 18:44:05 -0700512 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700513
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000514 private static native void nTranslate(long renderer, float dx, float dy);
Romain Guye4d01122010-06-16 18:44:05 -0700515
516 @Override
517 public void skew(float sx, float sy) {
Romain Guy807daf72011-01-18 11:19:19 -0800518 nSkew(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700519 }
520
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000521 private static native void nSkew(long renderer, float sx, float sy);
Romain Guy807daf72011-01-18 11:19:19 -0800522
Romain Guye4d01122010-06-16 18:44:05 -0700523 @Override
524 public void rotate(float degrees) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700525 nRotate(mRenderer, degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700526 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700527
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000528 private static native void nRotate(long renderer, float degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700529
530 @Override
531 public void scale(float sx, float sy) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700532 nScale(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700533 }
Romain Guye4d01122010-06-16 18:44:05 -0700534
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000535 private static native void nScale(long renderer, float sx, float sy);
Romain Guyf6a11b82010-06-23 17:47:49 -0700536
Romain Guye4d01122010-06-16 18:44:05 -0700537 @Override
538 public void setMatrix(Matrix matrix) {
Romain Guye7078592011-10-28 14:32:20 -0700539 nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700540 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700541
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000542 private static native void nSetMatrix(long renderer, long matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700543
Romain Guy5ff9df62012-01-23 17:09:05 -0800544 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -0700545 @Override
Romain Guyf6a11b82010-06-23 17:47:49 -0700546 public void getMatrix(Matrix matrix) {
547 nGetMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700548 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700549
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000550 private static native void nGetMatrix(long renderer, long matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700551
552 @Override
553 public void concat(Matrix matrix) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700554 if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700555 }
556
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000557 private static native void nConcatMatrix(long renderer, long matrix);
Romain Guyf6a11b82010-06-23 17:47:49 -0700558
Romain Guye4d01122010-06-16 18:44:05 -0700559 ///////////////////////////////////////////////////////////////////////////
560 // State management
561 ///////////////////////////////////////////////////////////////////////////
562
563 @Override
564 public int save() {
Romain Guy8aef54f2010-09-01 15:13:49 -0700565 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
Romain Guye4d01122010-06-16 18:44:05 -0700566 }
Romain Guybb9524b2010-06-22 18:56:38 -0700567
Romain Guye4d01122010-06-16 18:44:05 -0700568 @Override
569 public int save(int saveFlags) {
Romain Guybb9524b2010-06-22 18:56:38 -0700570 return nSave(mRenderer, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700571 }
572
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000573 private static native int nSave(long renderer, int flags);
Romain Guybb9524b2010-06-22 18:56:38 -0700574
Romain Guye4d01122010-06-16 18:44:05 -0700575 @Override
576 public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700577 if (bounds != null) {
578 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
579 }
580
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500581 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
582 return nSaveLayer(mRenderer, nativePaint, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700583 }
584
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000585 private static native int nSaveLayer(long renderer, long paint, int saveFlags);
Romain Guy189887e2011-08-25 11:45:13 -0700586
Romain Guye4d01122010-06-16 18:44:05 -0700587 @Override
588 public int saveLayer(float left, float top, float right, float bottom, Paint paint,
589 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800590 if (left < right && top < bottom) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500591 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
592 return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
Romain Guy01d58e42011-01-19 21:54:02 -0800593 }
594 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700595 }
596
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000597 private static native int nSaveLayer(long renderer, float left, float top,
598 float right, float bottom, long paint, int saveFlags);
Romain Guybd6b79b2010-06-26 00:13:53 -0700599
Romain Guye4d01122010-06-16 18:44:05 -0700600 @Override
601 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
Romain Guy189887e2011-08-25 11:45:13 -0700602 if (bounds != null) {
603 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
604 alpha, saveFlags);
605 }
606 return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700607 }
608
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000609 private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags);
Romain Guy189887e2011-08-25 11:45:13 -0700610
Romain Guye4d01122010-06-16 18:44:05 -0700611 @Override
612 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
613 int saveFlags) {
Romain Guy01d58e42011-01-19 21:54:02 -0800614 if (left < right && top < bottom) {
615 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
616 }
617 return save(saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700618 }
619
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000620 private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
Romain Guybd6b79b2010-06-26 00:13:53 -0700621 float bottom, int alpha, int saveFlags);
622
Romain Guye4d01122010-06-16 18:44:05 -0700623 @Override
624 public void restore() {
Romain Guybb9524b2010-06-22 18:56:38 -0700625 nRestore(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700626 }
Romain Guybb9524b2010-06-22 18:56:38 -0700627
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000628 private static native void nRestore(long renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700629
630 @Override
631 public void restoreToCount(int saveCount) {
Romain Guybb9524b2010-06-22 18:56:38 -0700632 nRestoreToCount(mRenderer, saveCount);
Romain Guye4d01122010-06-16 18:44:05 -0700633 }
634
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000635 private static native void nRestoreToCount(long renderer, int saveCount);
Romain Guybb9524b2010-06-22 18:56:38 -0700636
Romain Guye4d01122010-06-16 18:44:05 -0700637 @Override
638 public int getSaveCount() {
Romain Guybb9524b2010-06-22 18:56:38 -0700639 return nGetSaveCount(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700640 }
Romain Guybb9524b2010-06-22 18:56:38 -0700641
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000642 private static native int nGetSaveCount(long renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700643
644 ///////////////////////////////////////////////////////////////////////////
645 // Filtering
646 ///////////////////////////////////////////////////////////////////////////
647
648 @Override
649 public void setDrawFilter(DrawFilter filter) {
Romain Guy6926c722010-07-12 20:20:03 -0700650 mFilter = filter;
Romain Guy5ff9df62012-01-23 17:09:05 -0800651 if (filter == null) {
652 nResetPaintFilter(mRenderer);
653 } else if (filter instanceof PaintFlagsDrawFilter) {
654 PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter;
655 nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits);
656 }
Romain Guye4d01122010-06-16 18:44:05 -0700657 }
658
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000659 private static native void nResetPaintFilter(long renderer);
660 private static native void nSetupPaintFilter(long renderer, int clearBits, int setBits);
Romain Guy5ff9df62012-01-23 17:09:05 -0800661
Romain Guye4d01122010-06-16 18:44:05 -0700662 @Override
663 public DrawFilter getDrawFilter() {
Romain Guy6926c722010-07-12 20:20:03 -0700664 return mFilter;
Romain Guye4d01122010-06-16 18:44:05 -0700665 }
666
667 ///////////////////////////////////////////////////////////////////////////
668 // Drawing
669 ///////////////////////////////////////////////////////////////////////////
670
671 @Override
672 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
673 Paint paint) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500674 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800675 try {
676 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
677 startAngle, sweepAngle, useCenter, paint.mNativePaint);
678 } finally {
679 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
680 }
Romain Guye4d01122010-06-16 18:44:05 -0700681 }
682
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000683 private static native void nDrawArc(long renderer, float left, float top,
Romain Guy7d7b5492011-01-24 16:33:45 -0800684 float right, float bottom, float startAngle, float sweepAngle,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000685 boolean useCenter, long paint);
Romain Guy8b2f5262011-01-23 16:15:02 -0800686
Romain Guye4d01122010-06-16 18:44:05 -0700687 @Override
688 public void drawARGB(int a, int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700689 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -0700690 }
691
692 @Override
Romain Guyf3187b72013-06-07 12:17:11 -0700693 public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
694 Bitmap bitmap = patch.getBitmap();
Chris Craik1abf5d62013-08-16 12:47:03 -0700695 throwIfCannotDraw(bitmap);
Romain Guyf3187b72013-06-07 12:17:11 -0700696 // Shaders are ignored when drawing patches
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500697 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
698 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
699 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
Romain Guyf3187b72013-06-07 12:17:11 -0700700 }
701
702 @Override
Romain Guy3b748a42013-04-17 18:54:38 -0700703 public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
704 Bitmap bitmap = patch.getBitmap();
Chris Craik1abf5d62013-08-16 12:47:03 -0700705 throwIfCannotDraw(bitmap);
Romain Guyd27977d2010-07-14 19:18:51 -0700706 // Shaders are ignored when drawing patches
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500707 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
708 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
709 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
Romain Guydeba7852010-07-07 17:54:48 -0700710 }
711
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000712 private static native void nDrawPatch(long renderer, long bitmap, byte[] buffer, long chunk,
713 float left, float top, float right, float bottom, long paint);
Romain Guydeba7852010-07-07 17:54:48 -0700714
715 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700716 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
Chris Craik1abf5d62013-08-16 12:47:03 -0700717 throwIfCannotDraw(bitmap);
Romain Guyd27977d2010-07-14 19:18:51 -0700718 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700719 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800720 try {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000721 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700722 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800723 } finally {
724 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
725 }
Romain Guye4d01122010-06-16 18:44:05 -0700726 }
727
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000728 private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
729 float left, float top, long paint);
Romain Guydbd77cd2010-07-09 10:36:05 -0700730
Romain Guye4d01122010-06-16 18:44:05 -0700731 @Override
732 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
Chris Craik1abf5d62013-08-16 12:47:03 -0700733 throwIfCannotDraw(bitmap);
Romain Guyd27977d2010-07-14 19:18:51 -0700734 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700735 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800736 try {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000737 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700738 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
739 matrix.native_instance, nativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -0800740 } finally {
741 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
742 }
Romain Guye4d01122010-06-16 18:44:05 -0700743 }
744
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000745 private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
746 long matrix, long paint);
Romain Guyf86ef572010-07-01 11:05:42 -0700747
Romain Guye4d01122010-06-16 18:44:05 -0700748 @Override
749 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
Chris Craik1abf5d62013-08-16 12:47:03 -0700750 throwIfCannotDraw(bitmap);
Romain Guyd27977d2010-07-14 19:18:51 -0700751 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700752 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800753 try {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000754 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guy694b5192010-07-21 21:33:20 -0700755
Romain Guy445c83c2012-02-16 16:43:07 -0800756 int left, top, right, bottom;
757 if (src == null) {
758 left = top = 0;
759 right = bitmap.getWidth();
760 bottom = bitmap.getHeight();
761 } else {
762 left = src.left;
763 right = src.right;
764 top = src.top;
765 bottom = src.bottom;
766 }
767
Chris Craik0c20c382013-07-02 10:48:54 -0700768 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
Romain Guy445c83c2012-02-16 16:43:07 -0800769 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
770 } finally {
771 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy694b5192010-07-21 21:33:20 -0700772 }
Romain Guye4d01122010-06-16 18:44:05 -0700773 }
774
775 @Override
776 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
Chris Craik1abf5d62013-08-16 12:47:03 -0700777 throwIfCannotDraw(bitmap);
Romain Guyd27977d2010-07-14 19:18:51 -0700778 // Shaders are ignored when drawing bitmaps
Romain Guya168d732011-03-18 16:50:13 -0700779 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800780 try {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000781 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guy445c83c2012-02-16 16:43:07 -0800782
783 float left, top, right, bottom;
784 if (src == null) {
785 left = top = 0;
786 right = bitmap.getWidth();
787 bottom = bitmap.getHeight();
788 } else {
789 left = src.left;
790 right = src.right;
791 top = src.top;
792 bottom = src.bottom;
793 }
794
Chris Craik0c20c382013-07-02 10:48:54 -0700795 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
Romain Guy445c83c2012-02-16 16:43:07 -0800796 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
797 } finally {
798 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guyff98fa52011-11-28 09:35:09 -0800799 }
Romain Guye4d01122010-06-16 18:44:05 -0700800 }
801
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000802 private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
Romain Guyce0537b2010-06-29 21:05:21 -0700803 float srcLeft, float srcTop, float srcRight, float srcBottom,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000804 float left, float top, float right, float bottom, long paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700805
Romain Guye4d01122010-06-16 18:44:05 -0700806 @Override
807 public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
808 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guye651cc62012-05-14 19:44:40 -0700809 if (width < 0) {
810 throw new IllegalArgumentException("width must be >= 0");
811 }
812
813 if (height < 0) {
814 throw new IllegalArgumentException("height must be >= 0");
815 }
816
817 if (Math.abs(stride) < width) {
818 throw new IllegalArgumentException("abs(stride) must be >= width");
819 }
820
821 int lastScanline = offset + (height - 1) * stride;
822 int length = colors.length;
823
824 if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
825 (lastScanline + width > length)) {
826 throw new ArrayIndexOutOfBoundsException();
827 }
828
Romain Guyd27977d2010-07-14 19:18:51 -0700829 // Shaders are ignored when drawing bitmaps
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500830 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
831 nDrawBitmap(mRenderer, colors, offset, stride, x, y,
832 width, height, hasAlpha, nativePaint);
Romain Guye4d01122010-06-16 18:44:05 -0700833 }
834
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000835 private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
836 float x, float y, int width, int height, boolean hasAlpha, long nativePaint);
Romain Guye651cc62012-05-14 19:44:40 -0700837
Romain Guye4d01122010-06-16 18:44:05 -0700838 @Override
839 public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
840 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700841 // Shaders are ignored when drawing bitmaps
Romain Guyce0537b2010-06-29 21:05:21 -0700842 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700843 }
844
845 @Override
846 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
847 int vertOffset, int[] colors, int colorOffset, Paint paint) {
Chris Craik1abf5d62013-08-16 12:47:03 -0700848 throwIfCannotDraw(bitmap);
Romain Guy5a7b4662011-01-20 19:09:30 -0800849 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
850 throw new ArrayIndexOutOfBoundsException();
851 }
852
853 if (meshWidth == 0 || meshHeight == 0) {
854 return;
855 }
856
857 final int count = (meshWidth + 1) * (meshHeight + 1);
858 checkRange(verts.length, vertOffset, count * 2);
859
Romain Guyff316ec2013-02-13 18:39:43 -0800860 if (colors != null) {
861 checkRange(colors.length, colorOffset, count);
862 }
Romain Guy5a7b4662011-01-20 19:09:30 -0800863
Romain Guya168d732011-03-18 16:50:13 -0700864 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
Romain Guy445c83c2012-02-16 16:43:07 -0800865 try {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000866 final long nativePaint = paint == null ? 0 : paint.mNativePaint;
Chris Craik0c20c382013-07-02 10:48:54 -0700867 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
Romain Guy445c83c2012-02-16 16:43:07 -0800868 verts, vertOffset, colors, colorOffset, nativePaint);
869 } finally {
870 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
871 }
Romain Guye4d01122010-06-16 18:44:05 -0700872 }
873
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000874 private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer,
Romain Guy5a7b4662011-01-20 19:09:30 -0800875 int meshWidth, int meshHeight, float[] verts, int vertOffset,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000876 int[] colors, int colorOffset, long paint);
Romain Guy5a7b4662011-01-20 19:09:30 -0800877
Romain Guye4d01122010-06-16 18:44:05 -0700878 @Override
879 public void drawCircle(float cx, float cy, float radius, Paint paint) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500880 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800881 try {
882 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
883 } finally {
884 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
885 }
Romain Guye4d01122010-06-16 18:44:05 -0700886 }
887
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000888 private static native void nDrawCircle(long renderer, float cx, float cy,
889 float radius, long paint);
Romain Guy01d58e42011-01-19 21:54:02 -0800890
Romain Guye4d01122010-06-16 18:44:05 -0700891 @Override
892 public void drawColor(int color) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700893 drawColor(color, PorterDuff.Mode.SRC_OVER);
Romain Guye4d01122010-06-16 18:44:05 -0700894 }
895
896 @Override
897 public void drawColor(int color, PorterDuff.Mode mode) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700898 nDrawColor(mRenderer, color, mode.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700899 }
Romain Guy85bf02f2010-06-22 13:11:24 -0700900
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000901 private static native void nDrawColor(long renderer, int color, int mode);
Romain Guye4d01122010-06-16 18:44:05 -0700902
903 @Override
904 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
Romain Guy6410c0a2013-06-17 11:21:58 -0700905 float[] line = getLineStorage();
906 line[0] = startX;
907 line[1] = startY;
908 line[2] = stopX;
909 line[3] = stopY;
910 drawLines(line, 0, 4, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700911 }
912
913 @Override
914 public void drawLines(float[] pts, int offset, int count, Paint paint) {
Chris Craik5d116762013-02-19 17:49:31 -0800915 if (count < 4) return;
916
Romain Guy759ea802010-09-16 20:49:46 -0700917 if ((offset | count) < 0 || offset + count > pts.length) {
918 throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
919 }
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500920 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800921 try {
922 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
923 } finally {
924 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
925 }
Romain Guye4d01122010-06-16 18:44:05 -0700926 }
927
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000928 private static native void nDrawLines(long renderer, float[] points,
929 int offset, int count, long paint);
Romain Guy759ea802010-09-16 20:49:46 -0700930
Romain Guye4d01122010-06-16 18:44:05 -0700931 @Override
932 public void drawLines(float[] pts, Paint paint) {
Romain Guy759ea802010-09-16 20:49:46 -0700933 drawLines(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700934 }
935
936 @Override
937 public void drawOval(RectF oval, Paint paint) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500938 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800939 try {
940 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
941 } finally {
942 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
943 }
Romain Guye4d01122010-06-16 18:44:05 -0700944 }
945
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000946 private static native void nDrawOval(long renderer, float left, float top,
947 float right, float bottom, long paint);
Romain Guyc1cd9ba32011-01-23 14:18:41 -0800948
Romain Guye4d01122010-06-16 18:44:05 -0700949 @Override
950 public void drawPaint(Paint paint) {
Romain Guy6410c0a2013-06-17 11:21:58 -0700951 final Rect r = getInternalClipBounds();
Romain Guy6926c722010-07-12 20:20:03 -0700952 nGetClipBounds(mRenderer, r);
953 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700954 }
955
956 @Override
957 public void drawPath(Path path, Paint paint) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500958 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -0800959 try {
960 if (path.isSimplePath) {
961 if (path.rects != null) {
962 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
963 }
964 } else {
965 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
Romain Guya48a1a82010-08-10 14:59:15 -0700966 }
Romain Guy445c83c2012-02-16 16:43:07 -0800967 } finally {
968 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya48a1a82010-08-10 14:59:15 -0700969 }
Romain Guye4d01122010-06-16 18:44:05 -0700970 }
971
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000972 private static native void nDrawPath(long renderer, long path, long paint);
973 private static native void nDrawRects(long renderer, long region, long paint);
Romain Guy7fbcc042010-08-04 15:40:07 -0700974
Romain Guy672433d2013-01-04 19:05:13 -0800975 void drawRects(float[] rects, int count, Paint paint) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -0500976 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy672433d2013-01-04 19:05:13 -0800977 try {
978 nDrawRects(mRenderer, rects, count, paint.mNativePaint);
979 } finally {
980 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
981 }
982 }
983
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000984 private static native void nDrawRects(long renderer, float[] rects, int count, long paint);
Romain Guy672433d2013-01-04 19:05:13 -0800985
Romain Guye4d01122010-06-16 18:44:05 -0700986 @Override
987 public void drawPicture(Picture picture) {
Romain Guyf9d9c062012-01-19 16:53:41 -0800988 if (picture.createdFromStream) {
989 return;
990 }
991
Romain Guy75582e82012-01-18 18:13:35 -0800992 picture.endRecording();
993 // TODO: Implement rendering
Romain Guye4d01122010-06-16 18:44:05 -0700994 }
995
996 @Override
997 public void drawPicture(Picture picture, Rect dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -0800998 if (picture.createdFromStream) {
999 return;
1000 }
1001
Romain Guy75582e82012-01-18 18:13:35 -08001002 save();
1003 translate(dst.left, dst.top);
1004 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1005 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1006 }
1007 drawPicture(picture);
1008 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001009 }
1010
1011 @Override
1012 public void drawPicture(Picture picture, RectF dst) {
Romain Guyf9d9c062012-01-19 16:53:41 -08001013 if (picture.createdFromStream) {
1014 return;
1015 }
1016
Romain Guy75582e82012-01-18 18:13:35 -08001017 save();
1018 translate(dst.left, dst.top);
1019 if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1020 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1021 }
1022 drawPicture(picture);
1023 restore();
Romain Guye4d01122010-06-16 18:44:05 -07001024 }
1025
1026 @Override
1027 public void drawPoint(float x, float y, Paint paint) {
Romain Guy6410c0a2013-06-17 11:21:58 -07001028 float[] point = getPointStorage();
1029 point[0] = x;
1030 point[1] = y;
1031 drawPoints(point, 0, 2, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001032 }
1033
1034 @Override
1035 public void drawPoints(float[] pts, Paint paint) {
Romain Guyed6fcb02011-03-21 13:11:28 -07001036 drawPoints(pts, 0, pts.length, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001037 }
1038
1039 @Override
Romain Guyed6fcb02011-03-21 13:11:28 -07001040 public void drawPoints(float[] pts, int offset, int count, Paint paint) {
Chris Craik5d116762013-02-19 17:49:31 -08001041 if (count < 2) return;
1042
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -05001043 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001044 try {
1045 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
1046 } finally {
1047 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1048 }
Romain Guyed6fcb02011-03-21 13:11:28 -07001049 }
1050
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001051 private static native void nDrawPoints(long renderer, float[] points,
1052 int offset, int count, long paint);
Romain Guyed6fcb02011-03-21 13:11:28 -07001053
Romain Guy5ff9df62012-01-23 17:09:05 -08001054 @SuppressWarnings("deprecation")
Romain Guyed6fcb02011-03-21 13:11:28 -07001055 @Override
Romain Guye4d01122010-06-16 18:44:05 -07001056 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001057 if (index < 0 || index + count > text.length || count * 2 > pos.length) {
1058 throw new IndexOutOfBoundsException();
1059 }
1060
1061 int modifiers = setupModifiers(paint);
1062 try {
1063 nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
1064 } finally {
1065 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1066 }
Romain Guye4d01122010-06-16 18:44:05 -07001067 }
1068
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001069 private static native void nDrawPosText(long renderer, char[] text, int index, int count,
1070 float[] pos, long paint);
Romain Guyeb9a5362012-01-17 17:39:26 -08001071
Romain Guy5ff9df62012-01-23 17:09:05 -08001072 @SuppressWarnings("deprecation")
Romain Guye4d01122010-06-16 18:44:05 -07001073 @Override
1074 public void drawPosText(String text, float[] pos, Paint paint) {
Romain Guyeb9a5362012-01-17 17:39:26 -08001075 if (text.length() * 2 > pos.length) {
1076 throw new ArrayIndexOutOfBoundsException();
1077 }
1078
1079 int modifiers = setupModifiers(paint);
1080 try {
1081 nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
1082 } finally {
1083 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1084 }
Romain Guye4d01122010-06-16 18:44:05 -07001085 }
1086
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001087 private static native void nDrawPosText(long renderer, String text, int start, int end,
1088 float[] pos, long paint);
Romain Guyeb9a5362012-01-17 17:39:26 -08001089
Romain Guye4d01122010-06-16 18:44:05 -07001090 @Override
1091 public void drawRect(float left, float top, float right, float bottom, Paint paint) {
Romain Guy765dcf32012-02-27 13:28:22 -08001092 if (left == right || top == bottom) return;
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -05001093 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001094 try {
1095 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
1096 } finally {
1097 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1098 }
Romain Guye4d01122010-06-16 18:44:05 -07001099 }
1100
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001101 private static native void nDrawRect(long renderer, float left, float top,
1102 float right, float bottom, long paint);
Romain Guyc7d53492010-06-25 13:41:57 -07001103
Romain Guye4d01122010-06-16 18:44:05 -07001104 @Override
1105 public void drawRect(Rect r, Paint paint) {
Romain Guyc7d53492010-06-25 13:41:57 -07001106 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001107 }
1108
1109 @Override
Romain Guyc7d53492010-06-25 13:41:57 -07001110 public void drawRect(RectF r, Paint paint) {
1111 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -07001112 }
1113
1114 @Override
1115 public void drawRGB(int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -07001116 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -07001117 }
1118
1119 @Override
Chris Craik4d1c1532014-04-24 14:13:40 -07001120 public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
1121 Paint paint) {
Derek Sollenberger76d3a1b2013-12-10 12:28:58 -05001122 int modifiers = setupModifiers(paint, MODIFIER_SHADER);
Romain Guy445c83c2012-02-16 16:43:07 -08001123 try {
Chris Craik4d1c1532014-04-24 14:13:40 -07001124 nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
Romain Guy445c83c2012-02-16 16:43:07 -08001125 } finally {
1126 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1127 }
Romain Guye4d01122010-06-16 18:44:05 -07001128 }
1129
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001130 private static native void nDrawRoundRect(long renderer, float left, float top,
1131 float right, float bottom, float rx, float y, long paint);
Romain Guy01d58e42011-01-19 21:54:02 -08001132
Romain Guye4d01122010-06-16 18:44:05 -07001133 @Override
1134 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001135 if ((index | count | (index + count) | (text.length - index - count)) < 0) {
1136 throw new IndexOutOfBoundsException();
1137 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001138
Romain Guya168d732011-03-18 16:50:13 -07001139 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001140 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001141 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001142 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001143 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001144 }
Romain Guye4d01122010-06-16 18:44:05 -07001145 }
Romain Guya1db5742010-07-20 13:09:13 -07001146
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001147 private static native void nDrawText(long renderer, char[] text, int index, int count,
1148 float x, float y, int bidiFlags, long paint);
Romain Guye4d01122010-06-16 18:44:05 -07001149
1150 @Override
1151 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001152 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001153 try {
1154 if (text instanceof String || text instanceof SpannedString ||
1155 text instanceof SpannableString) {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001156 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
1157 paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001158 } else if (text instanceof GraphicsOperations) {
1159 ((GraphicsOperations) text).drawText(this, start, end, x, y,
1160 paint);
1161 } else {
1162 char[] buf = TemporaryBuffer.obtain(end - start);
1163 TextUtils.getChars(text, start, end, buf, 0);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001164 nDrawText(mRenderer, buf, 0, end - start, x, y,
1165 paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001166 TemporaryBuffer.recycle(buf);
1167 }
1168 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001169 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guya1db5742010-07-20 13:09:13 -07001170 }
Romain Guye4d01122010-06-16 18:44:05 -07001171 }
1172
1173 @Override
1174 public void drawText(String text, int start, int end, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -07001175 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1176 throw new IndexOutOfBoundsException();
1177 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001178
Romain Guya168d732011-03-18 16:50:13 -07001179 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001180 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001181 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001182 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001183 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001184 }
Romain Guye4d01122010-06-16 18:44:05 -07001185 }
1186
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001187 private static native void nDrawText(long renderer, String text, int start, int end,
1188 float x, float y, int bidiFlags, long paint);
Romain Guya1db5742010-07-20 13:09:13 -07001189
Romain Guye4d01122010-06-16 18:44:05 -07001190 @Override
1191 public void drawText(String text, float x, float y, Paint paint) {
Romain Guya168d732011-03-18 16:50:13 -07001192 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001193 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001194 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
1195 paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001196 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001197 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001198 }
Romain Guye4d01122010-06-16 18:44:05 -07001199 }
1200
1201 @Override
1202 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
1203 float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001204 if (index < 0 || index + count > text.length) {
1205 throw new ArrayIndexOutOfBoundsException();
1206 }
1207
1208 int modifiers = setupModifiers(paint);
1209 try {
1210 nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001211 paint.mBidiFlags, paint.mNativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001212 } finally {
1213 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1214 }
Romain Guye4d01122010-06-16 18:44:05 -07001215 }
1216
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001217 private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
1218 long path, float hOffset, float vOffset, int bidiFlags, long nativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001219
Romain Guye4d01122010-06-16 18:44:05 -07001220 @Override
1221 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
Romain Guy325740f2012-02-24 16:48:34 -08001222 if (text.length() == 0) return;
1223
1224 int modifiers = setupModifiers(paint);
1225 try {
1226 nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001227 paint.mBidiFlags, paint.mNativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001228 } finally {
1229 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1230 }
Romain Guye4d01122010-06-16 18:44:05 -07001231 }
1232
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001233 private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
1234 long path, float hOffset, float vOffset, int bidiFlags, long nativePaint);
Romain Guy325740f2012-02-24 16:48:34 -08001235
Romain Guye4d01122010-06-16 18:44:05 -07001236 @Override
1237 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001238 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001239 if ((index | count | text.length - index - count) < 0) {
1240 throw new IndexOutOfBoundsException();
1241 }
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001242 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
1243 throw new IllegalArgumentException("Unknown direction: " + dir);
1244 }
Romain Guy61c8c9c2010-08-09 20:48:09 -07001245
Romain Guya168d732011-03-18 16:50:13 -07001246 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001247 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001248 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
Romain Guy61c8c9c2010-08-09 20:48:09 -07001249 paint.mNativePaint);
1250 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001251 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001252 }
Romain Guye4d01122010-06-16 18:44:05 -07001253 }
1254
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001255 private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
1256 int contextIndex, int contextCount, float x, float y, int dir, long nativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001257
Romain Guye4d01122010-06-16 18:44:05 -07001258 @Override
1259 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001260 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -07001261 if ((start | end | end - start | text.length() - end) < 0) {
1262 throw new IndexOutOfBoundsException();
1263 }
1264
Romain Guya168d732011-03-18 16:50:13 -07001265 int modifiers = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001266 try {
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001267 int flags = dir == 0 ? 0 : 1;
Romain Guy61c8c9c2010-08-09 20:48:09 -07001268 if (text instanceof String || text instanceof SpannedString ||
1269 text instanceof SpannableString) {
1270 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001271 contextEnd, x, y, flags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001272 } else if (text instanceof GraphicsOperations) {
1273 ((GraphicsOperations) text).drawTextRun(this, start, end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001274 contextStart, contextEnd, x, y, flags, paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001275 } else {
1276 int contextLen = contextEnd - contextStart;
1277 int len = end - start;
1278 char[] buf = TemporaryBuffer.obtain(contextLen);
1279 TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
1280 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001281 x, y, flags, paint.mNativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001282 TemporaryBuffer.recycle(buf);
1283 }
1284 } finally {
Romain Guya168d732011-03-18 16:50:13 -07001285 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001286 }
Romain Guye4d01122010-06-16 18:44:05 -07001287 }
1288
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001289 private static native void nDrawTextRun(long renderer, String text, int start, int end,
1290 int contextStart, int contextEnd, float x, float y, int flags, long nativePaint);
Romain Guy61c8c9c2010-08-09 20:48:09 -07001291
Romain Guye4d01122010-06-16 18:44:05 -07001292 @Override
1293 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
1294 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
1295 int indexOffset, int indexCount, Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -07001296 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -07001297 }
Romain Guyd27977d2010-07-14 19:18:51 -07001298
Romain Guya168d732011-03-18 16:50:13 -07001299 private int setupModifiers(Bitmap b, Paint paint) {
Romain Guy445c83c2012-02-16 16:43:07 -08001300 if (b.getConfig() != Bitmap.Config.ALPHA_8) {
Romain Guy445c83c2012-02-16 16:43:07 -08001301 return MODIFIER_NONE;
1302 } else {
Romain Guya168d732011-03-18 16:50:13 -07001303 return setupModifiers(paint);
1304 }
Romain Guya168d732011-03-18 16:50:13 -07001305 }
1306
1307 private int setupModifiers(Paint paint) {
1308 int modifiers = MODIFIER_NONE;
Romain Guydb1938e2010-08-02 18:50:22 -07001309
Romain Guy1e45aae2010-08-13 19:39:53 -07001310 if (paint.hasShadow) {
1311 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1312 paint.shadowColor);
Romain Guya168d732011-03-18 16:50:13 -07001313 modifiers |= MODIFIER_SHADOW;
Romain Guy1e45aae2010-08-13 19:39:53 -07001314 }
1315
Romain Guyd27977d2010-07-14 19:18:51 -07001316 final Shader shader = paint.getShader();
1317 if (shader != null) {
Romain Guy06f96e22010-07-30 19:18:16 -07001318 nSetupShader(mRenderer, shader.native_shader);
Romain Guya168d732011-03-18 16:50:13 -07001319 modifiers |= MODIFIER_SHADER;
Romain Guydb1938e2010-08-02 18:50:22 -07001320 }
1321
Romain Guya168d732011-03-18 16:50:13 -07001322 return modifiers;
Romain Guydb1938e2010-08-02 18:50:22 -07001323 }
Romain Guy1e45aae2010-08-13 19:39:53 -07001324
Romain Guy765dcf32012-02-27 13:28:22 -08001325 private int setupModifiers(Paint paint, int flags) {
1326 int modifiers = MODIFIER_NONE;
1327
1328 if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
1329 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
1330 paint.shadowColor);
1331 modifiers |= MODIFIER_SHADOW;
1332 }
1333
1334 final Shader shader = paint.getShader();
1335 if (shader != null && (flags & MODIFIER_SHADER) != 0) {
1336 nSetupShader(mRenderer, shader.native_shader);
1337 modifiers |= MODIFIER_SHADER;
1338 }
1339
Romain Guy765dcf32012-02-27 13:28:22 -08001340 return modifiers;
1341 }
1342
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001343 private static native void nSetupShader(long renderer, long shader);
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001344 private static native void nSetupShadow(long renderer, float radius,
Romain Guy7d7b5492011-01-24 16:33:45 -08001345 float dx, float dy, int color);
Romain Guy1e45aae2010-08-13 19:39:53 -07001346
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001347 private static native void nResetModifiers(long renderer, int modifiers);
Romain Guye4d01122010-06-16 18:44:05 -07001348}