blob: b058685009c4a925ff9a886597a829f54f801301 [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;
25import android.graphics.Path;
26import android.graphics.Picture;
27import android.graphics.PorterDuff;
28import android.graphics.Rect;
29import android.graphics.RectF;
30import android.graphics.Region;
Romain Guyd27977d2010-07-14 19:18:51 -070031import android.graphics.Shader;
Romain Guya1db5742010-07-20 13:09:13 -070032import android.graphics.TemporaryBuffer;
33import android.text.GraphicsOperations;
34import android.text.SpannableString;
35import android.text.SpannedString;
36import android.text.TextUtils;
Romain Guye4d01122010-06-16 18:44:05 -070037
38import javax.microedition.khronos.opengles.GL;
39
40/**
41 * An implementation of Canvas on top of OpenGL ES 2.0.
42 */
Romain Guye4d01122010-06-16 18:44:05 -070043class GLES20Canvas extends Canvas {
44 @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
45 private final GL mGl;
46 private final boolean mOpaque;
Romain Guyfb8b7632010-08-23 21:05:08 -070047 private int mRenderer;
Romain Guye4d01122010-06-16 18:44:05 -070048
49 private int mWidth;
50 private int mHeight;
Romain Guyce0537b2010-06-29 21:05:21 -070051
52 private final float[] mPoint = new float[2];
53 private final float[] mLine = new float[4];
Romain Guy6926c722010-07-12 20:20:03 -070054
55 private final Rect mClipBounds = new Rect();
56
57 private DrawFilter mFilter;
Romain Guy16393512010-08-08 00:14:31 -070058
59 ///////////////////////////////////////////////////////////////////////////
60 // JNI
61 ///////////////////////////////////////////////////////////////////////////
62
63 private static native boolean nIsAvailable();
64 private static boolean sIsAvailable = nIsAvailable();
65
66 static boolean isAvailable() {
67 return sIsAvailable;
68 }
Romain Guye4d01122010-06-16 18:44:05 -070069
70 ///////////////////////////////////////////////////////////////////////////
71 // Constructors
72 ///////////////////////////////////////////////////////////////////////////
73
74 GLES20Canvas(GL gl, boolean translucent) {
75 mGl = gl;
76 mOpaque = !translucent;
77
78 mRenderer = nCreateRenderer();
Romain Guyfb8b7632010-08-23 21:05:08 -070079 if (mRenderer == 0) {
80 throw new IllegalStateException("Could not create GLES20Canvas renderer");
81 }
Romain Guye4d01122010-06-16 18:44:05 -070082 }
Romain Guyfb8b7632010-08-23 21:05:08 -070083
Romain Guye4d01122010-06-16 18:44:05 -070084 private native int nCreateRenderer();
85
Romain Guyfb8b7632010-08-23 21:05:08 -070086 /**
87 * This method <strong>must</strong> be called before releasing a
88 * reference to a GLES20Canvas. This method is responsible for freeing
89 * native resources associated with the hardware. Not invoking this
90 * method properly can result in memory leaks.
91 *
92 * @hide
93 */
94 public synchronized void destroy() {
95 if (mRenderer != 0) {
Romain Guye4d01122010-06-16 18:44:05 -070096 nDestroyRenderer(mRenderer);
Romain Guyfb8b7632010-08-23 21:05:08 -070097 mRenderer = 0;
Romain Guye4d01122010-06-16 18:44:05 -070098 }
99 }
Romain Guyce0537b2010-06-29 21:05:21 -0700100
Romain Guye4d01122010-06-16 18:44:05 -0700101 private native void nDestroyRenderer(int renderer);
102
103 ///////////////////////////////////////////////////////////////////////////
104 // Canvas management
105 ///////////////////////////////////////////////////////////////////////////
106
107 @Override
108 public boolean isHardwareAccelerated() {
109 return true;
110 }
111
112 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700113 public void setBitmap(Bitmap bitmap) {
114 throw new UnsupportedOperationException();
115 }
116
117 @Override
118 public boolean isOpaque() {
119 return mOpaque;
120 }
121
122 @Override
123 public int getWidth() {
124 return mWidth;
125 }
126
127 @Override
128 public int getHeight() {
129 return mHeight;
130 }
131
132 ///////////////////////////////////////////////////////////////////////////
133 // Setup
134 ///////////////////////////////////////////////////////////////////////////
135
136 @Override
137 public void setViewport(int width, int height) {
138 mWidth = width;
139 mHeight = height;
140
141 nSetViewport(mRenderer, width, height);
142 }
143
144 private native void nSetViewport(int renderer, int width, int height);
145
146 void onPreDraw() {
147 nPrepare(mRenderer);
148 }
149
150 private native void nPrepare(int renderer);
151
152 ///////////////////////////////////////////////////////////////////////////
153 // Clipping
154 ///////////////////////////////////////////////////////////////////////////
155
156 @Override
157 public boolean clipPath(Path path) {
158 throw new UnsupportedOperationException();
159 }
160
161 @Override
162 public boolean clipPath(Path path, Region.Op op) {
163 throw new UnsupportedOperationException();
164 }
165
166 @Override
167 public boolean clipRect(float left, float top, float right, float bottom) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700168 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700169 }
Romain Guybb9524b2010-06-22 18:56:38 -0700170
Romain Guy079ba2c2010-07-16 14:12:24 -0700171 private native boolean nClipRect(int renderer, float left, float top,
172 float right, float bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700173
174 @Override
175 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700176 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700177 }
178
179 @Override
180 public boolean clipRect(int left, int top, int right, int bottom) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700181 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700182 }
Romain Guybb9524b2010-06-22 18:56:38 -0700183
Romain Guy079ba2c2010-07-16 14:12:24 -0700184 private native boolean nClipRect(int renderer, int left, int top, int right, int bottom, int op);
Romain Guye4d01122010-06-16 18:44:05 -0700185
186 @Override
187 public boolean clipRect(Rect rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700188 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
189 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700190 }
191
192 @Override
193 public boolean clipRect(Rect rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700194 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700195 }
196
197 @Override
198 public boolean clipRect(RectF rect) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700199 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
200 Region.Op.INTERSECT.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700201 }
202
203 @Override
204 public boolean clipRect(RectF rect, Region.Op op) {
Romain Guy079ba2c2010-07-16 14:12:24 -0700205 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700206 }
207
208 @Override
209 public boolean clipRegion(Region region) {
210 throw new UnsupportedOperationException();
211 }
212
213 @Override
214 public boolean clipRegion(Region region, Region.Op op) {
215 throw new UnsupportedOperationException();
216 }
217
218 @Override
219 public boolean getClipBounds(Rect bounds) {
Romain Guy9d5316e2010-06-24 19:30:36 -0700220 return nGetClipBounds(mRenderer, bounds);
Romain Guye4d01122010-06-16 18:44:05 -0700221 }
222
Romain Guy9d5316e2010-06-24 19:30:36 -0700223 private native boolean nGetClipBounds(int renderer, Rect bounds);
224
Romain Guye4d01122010-06-16 18:44:05 -0700225 @Override
226 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
Romain Guyc7d53492010-06-25 13:41:57 -0700227 return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700228 }
Romain Guyc7d53492010-06-25 13:41:57 -0700229
230 private native boolean nQuickReject(int renderer, float left, float top,
231 float right, float bottom, int edge);
Romain Guye4d01122010-06-16 18:44:05 -0700232
233 @Override
234 public boolean quickReject(Path path, EdgeType type) {
Romain Guybb9524b2010-06-22 18:56:38 -0700235 throw new UnsupportedOperationException();
Romain Guye4d01122010-06-16 18:44:05 -0700236 }
237
238 @Override
239 public boolean quickReject(RectF rect, EdgeType type) {
Romain Guybb9524b2010-06-22 18:56:38 -0700240 return quickReject(rect.left, rect.top, rect.right, rect.bottom, type);
Romain Guye4d01122010-06-16 18:44:05 -0700241 }
242
243 ///////////////////////////////////////////////////////////////////////////
244 // Transformations
245 ///////////////////////////////////////////////////////////////////////////
246
247 @Override
248 public void translate(float dx, float dy) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700249 nTranslate(mRenderer, dx, dy);
Romain Guye4d01122010-06-16 18:44:05 -0700250 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700251
252 private native void nTranslate(int renderer, float dx, float dy);
Romain Guye4d01122010-06-16 18:44:05 -0700253
254 @Override
255 public void skew(float sx, float sy) {
256 throw new UnsupportedOperationException();
257 }
258
259 @Override
260 public void rotate(float degrees) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700261 nRotate(mRenderer, degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700262 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700263
264 private native void nRotate(int renderer, float degrees);
Romain Guye4d01122010-06-16 18:44:05 -0700265
266 @Override
267 public void scale(float sx, float sy) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700268 nScale(mRenderer, sx, sy);
Romain Guye4d01122010-06-16 18:44:05 -0700269 }
Romain Guye4d01122010-06-16 18:44:05 -0700270
Romain Guyf6a11b82010-06-23 17:47:49 -0700271 private native void nScale(int renderer, float sx, float sy);
272
Romain Guye4d01122010-06-16 18:44:05 -0700273 @Override
274 public void setMatrix(Matrix matrix) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700275 nSetMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700276 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700277
278 private native void nSetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700279
280 @Override
Romain Guyf6a11b82010-06-23 17:47:49 -0700281 public void getMatrix(Matrix matrix) {
282 nGetMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700283 }
Romain Guyf6a11b82010-06-23 17:47:49 -0700284
285 private native void nGetMatrix(int renderer, int matrix);
Romain Guye4d01122010-06-16 18:44:05 -0700286
287 @Override
288 public void concat(Matrix matrix) {
Romain Guyf6a11b82010-06-23 17:47:49 -0700289 nConcatMatrix(mRenderer, matrix.native_instance);
Romain Guye4d01122010-06-16 18:44:05 -0700290 }
291
Romain Guyf6a11b82010-06-23 17:47:49 -0700292 private native void nConcatMatrix(int renderer, int matrix);
293
Romain Guye4d01122010-06-16 18:44:05 -0700294 ///////////////////////////////////////////////////////////////////////////
295 // State management
296 ///////////////////////////////////////////////////////////////////////////
297
298 @Override
299 public int save() {
Romain Guybb9524b2010-06-22 18:56:38 -0700300 return nSave(mRenderer, 0);
Romain Guye4d01122010-06-16 18:44:05 -0700301 }
Romain Guybb9524b2010-06-22 18:56:38 -0700302
Romain Guye4d01122010-06-16 18:44:05 -0700303 @Override
304 public int save(int saveFlags) {
Romain Guybb9524b2010-06-22 18:56:38 -0700305 return nSave(mRenderer, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700306 }
307
Romain Guybb9524b2010-06-22 18:56:38 -0700308 private native int nSave(int renderer, int flags);
309
Romain Guye4d01122010-06-16 18:44:05 -0700310 @Override
311 public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
Romain Guybd6b79b2010-06-26 00:13:53 -0700312 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700313 }
314
315 @Override
316 public int saveLayer(float left, float top, float right, float bottom, Paint paint,
317 int saveFlags) {
Romain Guybd6b79b2010-06-26 00:13:53 -0700318 int nativePaint = paint == null ? 0 : paint.mNativePaint;
319 return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700320 }
321
Romain Guybd6b79b2010-06-26 00:13:53 -0700322 private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
323 int paint, int saveFlags);
324
Romain Guye4d01122010-06-16 18:44:05 -0700325 @Override
326 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
Romain Guybd6b79b2010-06-26 00:13:53 -0700327 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
328 alpha, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700329 }
330
331 @Override
332 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
333 int saveFlags) {
Romain Guybd6b79b2010-06-26 00:13:53 -0700334 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
Romain Guye4d01122010-06-16 18:44:05 -0700335 }
336
Romain Guybd6b79b2010-06-26 00:13:53 -0700337 private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
338 float bottom, int alpha, int saveFlags);
339
Romain Guye4d01122010-06-16 18:44:05 -0700340 @Override
341 public void restore() {
Romain Guybb9524b2010-06-22 18:56:38 -0700342 nRestore(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700343 }
Romain Guybb9524b2010-06-22 18:56:38 -0700344
345 private native void nRestore(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700346
347 @Override
348 public void restoreToCount(int saveCount) {
Romain Guybb9524b2010-06-22 18:56:38 -0700349 nRestoreToCount(mRenderer, saveCount);
Romain Guye4d01122010-06-16 18:44:05 -0700350 }
351
Romain Guybb9524b2010-06-22 18:56:38 -0700352 private native void nRestoreToCount(int renderer, int saveCount);
353
Romain Guye4d01122010-06-16 18:44:05 -0700354 @Override
355 public int getSaveCount() {
Romain Guybb9524b2010-06-22 18:56:38 -0700356 return nGetSaveCount(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700357 }
Romain Guybb9524b2010-06-22 18:56:38 -0700358
359 private native int nGetSaveCount(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700360
361 ///////////////////////////////////////////////////////////////////////////
362 // Filtering
363 ///////////////////////////////////////////////////////////////////////////
364
365 @Override
366 public void setDrawFilter(DrawFilter filter) {
Romain Guy6926c722010-07-12 20:20:03 -0700367 mFilter = filter;
Romain Guye4d01122010-06-16 18:44:05 -0700368 }
369
370 @Override
371 public DrawFilter getDrawFilter() {
Romain Guy6926c722010-07-12 20:20:03 -0700372 return mFilter;
Romain Guye4d01122010-06-16 18:44:05 -0700373 }
374
375 ///////////////////////////////////////////////////////////////////////////
376 // Drawing
377 ///////////////////////////////////////////////////////////////////////////
378
379 @Override
380 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
381 Paint paint) {
382 throw new UnsupportedOperationException();
383 }
384
385 @Override
386 public void drawARGB(int a, int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700387 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -0700388 }
389
390 @Override
Romain Guydeba7852010-07-07 17:54:48 -0700391 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700392 // Shaders are ignored when drawing patches
Romain Guydb1938e2010-08-02 18:50:22 -0700393 boolean hasColorFilter = paint != null && setupColorFilter(paint);
Romain Guydeba7852010-07-07 17:54:48 -0700394 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guydbd77cd2010-07-09 10:36:05 -0700395 nDrawPatch(mRenderer, bitmap.mNativeBitmap, chunks, dst.left, dst.top,
396 dst.right, dst.bottom, nativePaint);
Romain Guydb1938e2010-08-02 18:50:22 -0700397 if (hasColorFilter) nResetModifiers(mRenderer);
Romain Guydeba7852010-07-07 17:54:48 -0700398 }
399
400 private native void nDrawPatch(int renderer, int bitmap, byte[] chunks, float left, float top,
Romain Guydbd77cd2010-07-09 10:36:05 -0700401 float right, float bottom, int paint);
Romain Guydeba7852010-07-07 17:54:48 -0700402
403 @Override
Romain Guye4d01122010-06-16 18:44:05 -0700404 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700405 // Shaders are ignored when drawing bitmaps
Romain Guydb1938e2010-08-02 18:50:22 -0700406 boolean hasColorFilter = paint != null && setupColorFilter(paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700407 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guydbd77cd2010-07-09 10:36:05 -0700408 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
Romain Guydb1938e2010-08-02 18:50:22 -0700409 if (hasColorFilter) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700410 }
411
Romain Guydbd77cd2010-07-09 10:36:05 -0700412 private native void nDrawBitmap(int renderer, int bitmap, float left, float top, int paint);
413
Romain Guye4d01122010-06-16 18:44:05 -0700414 @Override
415 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700416 // Shaders are ignored when drawing bitmaps
Romain Guydb1938e2010-08-02 18:50:22 -0700417 boolean hasColorFilter = paint != null && setupColorFilter(paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700418 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guydbd77cd2010-07-09 10:36:05 -0700419 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
Romain Guydb1938e2010-08-02 18:50:22 -0700420 if (hasColorFilter) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700421 }
422
Romain Guydbd77cd2010-07-09 10:36:05 -0700423 private native void nDrawBitmap(int renderer, int bitmap, int matrix, int paint);
Romain Guyf86ef572010-07-01 11:05:42 -0700424
Romain Guye4d01122010-06-16 18:44:05 -0700425 @Override
426 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700427 // Shaders are ignored when drawing bitmaps
Romain Guydb1938e2010-08-02 18:50:22 -0700428 boolean hasColorFilter = paint != null && setupColorFilter(paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700429 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
Romain Guy694b5192010-07-21 21:33:20 -0700430
431 int left, top, right, bottom;
432 if (src == null) {
433 left = top = 0;
434 right = bitmap.getWidth();
435 bottom = bitmap.getHeight();
436 } else {
437 left = src.left;
438 right = src.right;
439 top = src.top;
440 bottom = src.bottom;
441 }
442
443 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
444 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
Romain Guydb1938e2010-08-02 18:50:22 -0700445 if (hasColorFilter) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700446 }
447
448 @Override
449 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700450 // Shaders are ignored when drawing bitmaps
Romain Guydb1938e2010-08-02 18:50:22 -0700451 boolean hasColorFilter = paint != null && setupColorFilter(paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700452 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
453 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
Romain Guy694b5192010-07-21 21:33:20 -0700454 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
Romain Guydb1938e2010-08-02 18:50:22 -0700455 if (hasColorFilter) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700456 }
457
Romain Guyce0537b2010-06-29 21:05:21 -0700458 private native void nDrawBitmap(int renderer, int bitmap,
459 float srcLeft, float srcTop, float srcRight, float srcBottom,
Romain Guydbd77cd2010-07-09 10:36:05 -0700460 float left, float top, float right, float bottom, int paint);
Romain Guyce0537b2010-06-29 21:05:21 -0700461
Romain Guye4d01122010-06-16 18:44:05 -0700462 @Override
463 public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
464 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700465 // Shaders are ignored when drawing bitmaps
Romain Guydb1938e2010-08-02 18:50:22 -0700466 boolean hasColorFilter = paint != null && setupColorFilter(paint);
Romain Guy6926c722010-07-12 20:20:03 -0700467 final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
468 final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config);
469 final int nativePaint = paint == null ? 0 : paint.mNativePaint;
470 nDrawBitmap(mRenderer, b.mNativeBitmap, x, y, nativePaint);
471 b.recycle();
Romain Guydb1938e2010-08-02 18:50:22 -0700472 if (hasColorFilter) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700473 }
474
475 @Override
476 public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
477 int width, int height, boolean hasAlpha, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700478 // Shaders are ignored when drawing bitmaps
Romain Guyce0537b2010-06-29 21:05:21 -0700479 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700480 }
481
482 @Override
483 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
484 int vertOffset, int[] colors, int colorOffset, Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -0700485 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -0700486 }
487
488 @Override
489 public void drawCircle(float cx, float cy, float radius, Paint paint) {
490 throw new UnsupportedOperationException();
491 }
492
493 @Override
494 public void drawColor(int color) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700495 drawColor(color, PorterDuff.Mode.SRC_OVER);
Romain Guye4d01122010-06-16 18:44:05 -0700496 }
497
498 @Override
499 public void drawColor(int color, PorterDuff.Mode mode) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700500 nDrawColor(mRenderer, color, mode.nativeInt);
Romain Guye4d01122010-06-16 18:44:05 -0700501 }
Romain Guy85bf02f2010-06-22 13:11:24 -0700502
503 private native void nDrawColor(int renderer, int color, int mode);
Romain Guye4d01122010-06-16 18:44:05 -0700504
505 @Override
506 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -0700507 mLine[0] = startX;
508 mLine[1] = startY;
509 mLine[2] = stopX;
510 mLine[3] = stopY;
511 drawLines(mLine, 0, 1, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700512 }
513
514 @Override
515 public void drawLines(float[] pts, int offset, int count, Paint paint) {
516 // TODO: Implement
517 }
518
519 @Override
520 public void drawLines(float[] pts, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -0700521 drawLines(pts, 0, pts.length / 4, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700522 }
523
524 @Override
525 public void drawOval(RectF oval, Paint paint) {
526 throw new UnsupportedOperationException();
527 }
528
529 @Override
530 public void drawPaint(Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -0700531 final Rect r = mClipBounds;
532 nGetClipBounds(mRenderer, r);
533 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700534 }
535
536 @Override
537 public void drawPath(Path path, Paint paint) {
Romain Guy7fbcc042010-08-04 15:40:07 -0700538 boolean hasModifier = setupModifiers(paint);
Romain Guya48a1a82010-08-10 14:59:15 -0700539 if (path.isSimplePath) {
540 if (path.rects != null) {
541 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
542 }
543 } else {
544 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
545 }
Romain Guy7fbcc042010-08-04 15:40:07 -0700546 if (hasModifier) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700547 }
548
Romain Guy7fbcc042010-08-04 15:40:07 -0700549 private native void nDrawPath(int renderer, int path, int paint);
Romain Guya48a1a82010-08-10 14:59:15 -0700550 private native void nDrawRects(int renderer, int region, int paint);
Romain Guy7fbcc042010-08-04 15:40:07 -0700551
Romain Guye4d01122010-06-16 18:44:05 -0700552 @Override
553 public void drawPicture(Picture picture) {
554 throw new UnsupportedOperationException();
555 }
556
557 @Override
558 public void drawPicture(Picture picture, Rect dst) {
559 throw new UnsupportedOperationException();
560 }
561
562 @Override
563 public void drawPicture(Picture picture, RectF dst) {
564 throw new UnsupportedOperationException();
565 }
566
567 @Override
568 public void drawPoint(float x, float y, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -0700569 mPoint[0] = x;
570 mPoint[1] = y;
571 drawPoints(mPoint, 0, 1, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700572 }
573
574 @Override
575 public void drawPoints(float[] pts, int offset, int count, Paint paint) {
576 // TODO: Implement
577 }
578
579 @Override
580 public void drawPoints(float[] pts, Paint paint) {
Romain Guyce0537b2010-06-29 21:05:21 -0700581 drawPoints(pts, 0, pts.length / 2, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700582 }
583
584 @Override
585 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
586 throw new UnsupportedOperationException();
587 }
588
589 @Override
590 public void drawPosText(String text, float[] pos, Paint paint) {
591 throw new UnsupportedOperationException();
592 }
593
594 @Override
595 public void drawRect(float left, float top, float right, float bottom, Paint paint) {
Romain Guydb1938e2010-08-02 18:50:22 -0700596 boolean hasModifier = setupModifiers(paint);
Romain Guyc7d53492010-06-25 13:41:57 -0700597 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
Romain Guydb1938e2010-08-02 18:50:22 -0700598 if (hasModifier) nResetModifiers(mRenderer);
Romain Guye4d01122010-06-16 18:44:05 -0700599 }
600
Romain Guyc7d53492010-06-25 13:41:57 -0700601 private native void nDrawRect(int renderer, float left, float top, float right, float bottom,
602 int paint);
603
Romain Guye4d01122010-06-16 18:44:05 -0700604 @Override
605 public void drawRect(Rect r, Paint paint) {
Romain Guyc7d53492010-06-25 13:41:57 -0700606 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700607 }
608
609 @Override
Romain Guyc7d53492010-06-25 13:41:57 -0700610 public void drawRect(RectF r, Paint paint) {
611 drawRect(r.left, r.top, r.right, r.bottom, paint);
Romain Guye4d01122010-06-16 18:44:05 -0700612 }
613
614 @Override
615 public void drawRGB(int r, int g, int b) {
Romain Guy85bf02f2010-06-22 13:11:24 -0700616 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
Romain Guye4d01122010-06-16 18:44:05 -0700617 }
618
619 @Override
620 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
Romain Guyd27977d2010-07-14 19:18:51 -0700621 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -0700622 }
623
624 @Override
625 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -0700626 if ((index | count | (index + count) | (text.length - index - count)) < 0) {
627 throw new IndexOutOfBoundsException();
628 }
Romain Guy61c8c9c2010-08-09 20:48:09 -0700629
Romain Guydb1938e2010-08-02 18:50:22 -0700630 boolean hasModifier = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -0700631 try {
632 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
633 } finally {
634 if (hasModifier) nResetModifiers(mRenderer);
635 }
Romain Guye4d01122010-06-16 18:44:05 -0700636 }
Romain Guya1db5742010-07-20 13:09:13 -0700637
638 private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y,
639 int bidiFlags, int paint);
Romain Guye4d01122010-06-16 18:44:05 -0700640
641 @Override
642 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
Romain Guydb1938e2010-08-02 18:50:22 -0700643 boolean hasModifier = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -0700644 try {
645 if (text instanceof String || text instanceof SpannedString ||
646 text instanceof SpannableString) {
647 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
648 paint.mNativePaint);
649 } else if (text instanceof GraphicsOperations) {
650 ((GraphicsOperations) text).drawText(this, start, end, x, y,
651 paint);
652 } else {
653 char[] buf = TemporaryBuffer.obtain(end - start);
654 TextUtils.getChars(text, start, end, buf, 0);
655 nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint);
656 TemporaryBuffer.recycle(buf);
657 }
658 } finally {
659 if (hasModifier) nResetModifiers(mRenderer);
Romain Guya1db5742010-07-20 13:09:13 -0700660 }
Romain Guye4d01122010-06-16 18:44:05 -0700661 }
662
663 @Override
664 public void drawText(String text, int start, int end, float x, float y, Paint paint) {
Romain Guya1db5742010-07-20 13:09:13 -0700665 if ((start | end | (end - start) | (text.length() - end)) < 0) {
666 throw new IndexOutOfBoundsException();
667 }
Romain Guy61c8c9c2010-08-09 20:48:09 -0700668
Romain Guydb1938e2010-08-02 18:50:22 -0700669 boolean hasModifier = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -0700670 try {
671 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
672 } finally {
673 if (hasModifier) nResetModifiers(mRenderer);
674 }
Romain Guye4d01122010-06-16 18:44:05 -0700675 }
676
Romain Guya1db5742010-07-20 13:09:13 -0700677 private native void nDrawText(int renderer, String text, int start, int end, float x, float y,
678 int bidiFlags, int paint);
679
Romain Guye4d01122010-06-16 18:44:05 -0700680 @Override
681 public void drawText(String text, float x, float y, Paint paint) {
Romain Guydb1938e2010-08-02 18:50:22 -0700682 boolean hasModifier = setupModifiers(paint);
Romain Guy61c8c9c2010-08-09 20:48:09 -0700683 try {
684 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
685 paint.mNativePaint);
686 } finally {
687 if (hasModifier) nResetModifiers(mRenderer);
688 }
Romain Guye4d01122010-06-16 18:44:05 -0700689 }
690
691 @Override
692 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
693 float vOffset, Paint paint) {
Romain Guye4d01122010-06-16 18:44:05 -0700694 throw new UnsupportedOperationException();
695 }
696
697 @Override
698 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
699 throw new UnsupportedOperationException();
700 }
701
702 @Override
703 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
704 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -0700705 if ((index | count | text.length - index - count) < 0) {
706 throw new IndexOutOfBoundsException();
707 }
708 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
709 throw new IllegalArgumentException("Unknown direction: " + dir);
710 }
711
712 boolean hasModifier = setupModifiers(paint);
713 try {
714 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
715 paint.mNativePaint);
716 } finally {
717 if (hasModifier) nResetModifiers(mRenderer);
718 }
Romain Guye4d01122010-06-16 18:44:05 -0700719 }
720
Romain Guy61c8c9c2010-08-09 20:48:09 -0700721 private native void nDrawTextRun(int renderer, char[] text, int index, int count,
722 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
723
Romain Guye4d01122010-06-16 18:44:05 -0700724 @Override
725 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
726 float x, float y, int dir, Paint paint) {
Romain Guy61c8c9c2010-08-09 20:48:09 -0700727 if ((start | end | end - start | text.length() - end) < 0) {
728 throw new IndexOutOfBoundsException();
729 }
730
731 boolean hasModifier = setupModifiers(paint);
732 try {
733 int flags = dir == 0 ? 0 : 1;
734 if (text instanceof String || text instanceof SpannedString ||
735 text instanceof SpannableString) {
736 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
737 contextEnd, x, y, flags, paint.mNativePaint);
738 } else if (text instanceof GraphicsOperations) {
739 ((GraphicsOperations) text).drawTextRun(this, start, end,
740 contextStart, contextEnd, x, y, flags, paint);
741 } else {
742 int contextLen = contextEnd - contextStart;
743 int len = end - start;
744 char[] buf = TemporaryBuffer.obtain(contextLen);
745 TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
746 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
747 x, y, flags, paint.mNativePaint);
748 TemporaryBuffer.recycle(buf);
749 }
750 } finally {
751 if (hasModifier) nResetModifiers(mRenderer);
752 }
Romain Guye4d01122010-06-16 18:44:05 -0700753 }
754
Romain Guy61c8c9c2010-08-09 20:48:09 -0700755 private native void nDrawTextRun(int renderer, String text, int start, int end,
756 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
757
Romain Guye4d01122010-06-16 18:44:05 -0700758 @Override
759 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
760 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
761 int indexOffset, int indexCount, Paint paint) {
Romain Guy6926c722010-07-12 20:20:03 -0700762 // TODO: Implement
Romain Guye4d01122010-06-16 18:44:05 -0700763 }
Romain Guyd27977d2010-07-14 19:18:51 -0700764
Romain Guydb1938e2010-08-02 18:50:22 -0700765 private boolean setupModifiers(Paint paint) {
766 boolean hasModifier = false;
767
Romain Guy1e45aae2010-08-13 19:39:53 -0700768 if (paint.hasShadow) {
769 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
770 paint.shadowColor);
771 hasModifier = true;
772 }
773
Romain Guyd27977d2010-07-14 19:18:51 -0700774 final Shader shader = paint.getShader();
775 if (shader != null) {
Romain Guy06f96e22010-07-30 19:18:16 -0700776 nSetupShader(mRenderer, shader.native_shader);
Romain Guydb1938e2010-08-02 18:50:22 -0700777 hasModifier = true;
778 }
779
780 final ColorFilter filter = paint.getColorFilter();
781 if (filter != null) {
782 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
783 hasModifier = true;
784 }
785
786 return hasModifier;
787 }
Romain Guy1e45aae2010-08-13 19:39:53 -0700788
Romain Guydb1938e2010-08-02 18:50:22 -0700789 private boolean setupColorFilter(Paint paint) {
790 final ColorFilter filter = paint.getColorFilter();
791 if (filter != null) {
792 nSetupColorFilter(mRenderer, filter.nativeColorFilter);
Romain Guy06f96e22010-07-30 19:18:16 -0700793 return true;
Romain Guyd27977d2010-07-14 19:18:51 -0700794 }
Romain Guydb1938e2010-08-02 18:50:22 -0700795 return false;
Romain Guyd27977d2010-07-14 19:18:51 -0700796 }
Romain Guydb1938e2010-08-02 18:50:22 -0700797
Romain Guy06f96e22010-07-30 19:18:16 -0700798 private native void nSetupShader(int renderer, int shader);
Romain Guydb1938e2010-08-02 18:50:22 -0700799 private native void nSetupColorFilter(int renderer, int colorFilter);
Romain Guy1e45aae2010-08-13 19:39:53 -0700800 private native void nSetupShadow(int renderer, float radius, float dx, float dy, int color);
801
Romain Guydb1938e2010-08-02 18:50:22 -0700802 private native void nResetModifiers(int renderer);
Romain Guye4d01122010-06-16 18:44:05 -0700803}