GLES20Canvas.java revision da96f8ac2c1c35a54f3f36e6d776cb386a251d03
1/* 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.ColorFilter; 22import 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; 31import android.graphics.Shader; 32import android.graphics.SurfaceTexture; 33import android.graphics.TemporaryBuffer; 34import android.text.GraphicsOperations; 35import android.text.SpannableString; 36import android.text.SpannedString; 37import android.text.TextUtils; 38 39/** 40 * An implementation of Canvas on top of OpenGL ES 2.0. 41 */ 42class GLES20Canvas extends HardwareCanvas { 43 // 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; 47 private static final int MODIFIER_COLOR_FILTER = 4; 48 49 private final boolean mOpaque; 50 private int mRenderer; 51 52 // The native renderer will be destroyed when this object dies. 53 // DO NOT overwrite this reference once it is set. 54 @SuppressWarnings({"unused", "FieldCanBeLocal"}) 55 private CanvasFinalizer mFinalizer; 56 57 private int mWidth; 58 private int mHeight; 59 60 private final float[] mPoint = new float[2]; 61 private final float[] mLine = new float[4]; 62 63 private final Rect mClipBounds = new Rect(); 64 65 private DrawFilter mFilter; 66 67 /////////////////////////////////////////////////////////////////////////// 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 } 77 78 /////////////////////////////////////////////////////////////////////////// 79 // Constructors 80 /////////////////////////////////////////////////////////////////////////// 81 82 /** 83 * Creates a canvas to render directly on screen. 84 */ 85 GLES20Canvas(boolean translucent) { 86 this(false, translucent); 87 } 88 89 /** 90 * Creates a canvas to render into an FBO. 91 */ 92 GLES20Canvas(int layer, boolean translucent) { 93 mOpaque = !translucent; 94 mRenderer = nCreateLayerRenderer(layer); 95 setupFinalizer(); 96 } 97 98 protected GLES20Canvas(boolean record, boolean translucent) { 99 mOpaque = !translucent; 100 101 if (record) { 102 mRenderer = nCreateDisplayListRenderer(); 103 } else { 104 mRenderer = nCreateRenderer(); 105 } 106 107 setupFinalizer(); 108 } 109 110 private void setupFinalizer() { 111 if (mRenderer == 0) { 112 throw new IllegalStateException("Could not create GLES20Canvas renderer"); 113 } else { 114 mFinalizer = new CanvasFinalizer(mRenderer); 115 } 116 } 117 118 protected void resetDisplayListRenderer() { 119 nResetDisplayListRenderer(mRenderer); 120 } 121 122 private static native int nCreateRenderer(); 123 private static native int nCreateLayerRenderer(int layer); 124 private static native int nCreateDisplayListRenderer(); 125 private static native void nResetDisplayListRenderer(int renderer); 126 private static native void nDestroyRenderer(int renderer); 127 128 private static final class CanvasFinalizer { 129 private final int mRenderer; 130 131 public CanvasFinalizer(int renderer) { 132 mRenderer = renderer; 133 } 134 135 @Override 136 protected void finalize() throws Throwable { 137 try { 138 nDestroyRenderer(mRenderer); 139 } finally { 140 super.finalize(); 141 } 142 } 143 } 144 145 /////////////////////////////////////////////////////////////////////////// 146 // Hardware layers 147 /////////////////////////////////////////////////////////////////////////// 148 149 static native int nCreateTextureLayer(boolean opaque, int[] layerInfo); 150 static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo); 151 static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo); 152 static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque, 153 SurfaceTexture surface); 154 static native void nSetTextureLayerTransform(int layerId, int matrix); 155 static native void nDestroyLayer(int layerId); 156 static native void nDestroyLayerDeferred(int layerId); 157 static native void nFlushLayer(int layerId); 158 static native boolean nCopyLayer(int layerId, int bitmap); 159 160 /////////////////////////////////////////////////////////////////////////// 161 // Canvas management 162 /////////////////////////////////////////////////////////////////////////// 163 164 @Override 165 public boolean isOpaque() { 166 return mOpaque; 167 } 168 169 @Override 170 public int getWidth() { 171 return mWidth; 172 } 173 174 @Override 175 public int getHeight() { 176 return mHeight; 177 } 178 179 @Override 180 public int getMaximumBitmapWidth() { 181 return nGetMaximumTextureWidth(); 182 } 183 184 @Override 185 public int getMaximumBitmapHeight() { 186 return nGetMaximumTextureHeight(); 187 } 188 189 private static native int nGetMaximumTextureWidth(); 190 private static native int nGetMaximumTextureHeight(); 191 192 /////////////////////////////////////////////////////////////////////////// 193 // Setup 194 /////////////////////////////////////////////////////////////////////////// 195 196 @Override 197 public void setViewport(int width, int height) { 198 mWidth = width; 199 mHeight = height; 200 201 nSetViewport(mRenderer, width, height); 202 } 203 204 private static native void nSetViewport(int renderer, int width, int height); 205 206 /** 207 * Preserves the back buffer of the current surface after a buffer swap. 208 * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current 209 * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL 210 * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. 211 * 212 * @return True if the swap behavior was successfully changed, 213 * false otherwise. 214 * 215 * @hide 216 */ 217 public static boolean preserveBackBuffer() { 218 return nPreserveBackBuffer(); 219 } 220 221 private static native boolean nPreserveBackBuffer(); 222 223 /** 224 * Indicates whether the current surface preserves its back buffer 225 * after a buffer swap. 226 * 227 * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, 228 * false otherwise 229 * 230 * @hide 231 */ 232 public static boolean isBackBufferPreserved() { 233 return nIsBackBufferPreserved(); 234 } 235 236 private static native boolean nIsBackBufferPreserved(); 237 238 /** 239 * Disables v-sync. For performance testing only. 240 * 241 * @hide 242 */ 243 public static void disableVsync() { 244 nDisableVsync(); 245 } 246 247 private static native void nDisableVsync(); 248 249 @Override 250 void onPreDraw(Rect dirty) { 251 if (dirty != null) { 252 nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, mOpaque); 253 } else { 254 nPrepare(mRenderer, mOpaque); 255 } 256 } 257 258 private static native void nPrepare(int renderer, boolean opaque); 259 private static native void nPrepareDirty(int renderer, int left, int top, int right, int bottom, 260 boolean opaque); 261 262 @Override 263 void onPostDraw() { 264 nFinish(mRenderer); 265 } 266 267 private static native void nFinish(int renderer); 268 269 @Override 270 public boolean callDrawGLFunction(int drawGLFunction) { 271 return nCallDrawGLFunction(mRenderer, drawGLFunction); 272 } 273 274 private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction); 275 276 277 /////////////////////////////////////////////////////////////////////////// 278 // Memory 279 /////////////////////////////////////////////////////////////////////////// 280 281 /** 282 * Must match Caches::FlushMode values 283 * 284 * @see #flushCaches(int) 285 */ 286 public static final int FLUSH_CACHES_LAYERS = 0; 287 288 /** 289 * Must match Caches::FlushMode values 290 * 291 * @see #flushCaches(int) 292 */ 293 public static final int FLUSH_CACHES_MODERATE = 1; 294 295 /** 296 * Must match Caches::FlushMode values 297 * 298 * @see #flushCaches(int) 299 */ 300 public static final int FLUSH_CACHES_FULL = 2; 301 302 /** 303 * Flush caches to reclaim as much memory as possible. The amount of memory 304 * to reclaim is indicate by the level parameter. 305 * 306 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or 307 * {@link #FLUSH_CACHES_FULL}. 308 * 309 * @param level Hint about the amount of memory to reclaim 310 * 311 * @hide 312 */ 313 public static void flushCaches(int level) { 314 nFlushCaches(level); 315 } 316 317 private static native void nFlushCaches(int level); 318 319 /** 320 * Release all resources associated with the underlying caches. This should 321 * only be called after a full flushCaches(). 322 * 323 * @hide 324 */ 325 public static void terminateCaches() { 326 nTerminateCaches(); 327 } 328 329 private static native void nTerminateCaches(); 330 331 /** 332 * @hide 333 */ 334 public static void initCaches() { 335 nInitCaches(); 336 } 337 338 private static native void nInitCaches(); 339 340 /////////////////////////////////////////////////////////////////////////// 341 // Display list 342 /////////////////////////////////////////////////////////////////////////// 343 344 int getDisplayList(int displayList) { 345 return nGetDisplayList(mRenderer, displayList); 346 } 347 348 private static native int nGetDisplayList(int renderer, int displayList); 349 350 static void destroyDisplayList(int displayList) { 351 nDestroyDisplayList(displayList); 352 } 353 354 private static native void nDestroyDisplayList(int displayList); 355 356 static int getDisplayListSize(int displayList) { 357 return nGetDisplayListSize(displayList); 358 } 359 360 private static native int nGetDisplayListSize(int displayList); 361 362 @Override 363 public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) { 364 return nDrawDisplayList(mRenderer, 365 ((GLES20DisplayList) displayList).getNativeDisplayList(), width, height, dirty); 366 } 367 368 private static native boolean nDrawDisplayList(int renderer, int displayList, 369 int width, int height, Rect dirty); 370 371 @Override 372 void outputDisplayList(DisplayList displayList) { 373 nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList()); 374 } 375 376 private static native void nOutputDisplayList(int renderer, int displayList); 377 378 /////////////////////////////////////////////////////////////////////////// 379 // Hardware layer 380 /////////////////////////////////////////////////////////////////////////// 381 382 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) { 383 final GLES20Layer glLayer = (GLES20Layer) layer; 384 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 385 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 386 nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint); 387 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 388 } 389 390 private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint); 391 392 void interrupt() { 393 nInterrupt(mRenderer); 394 } 395 396 void resume() { 397 nResume(mRenderer); 398 } 399 400 private static native void nInterrupt(int renderer); 401 private static native void nResume(int renderer); 402 403 /////////////////////////////////////////////////////////////////////////// 404 // Clipping 405 /////////////////////////////////////////////////////////////////////////// 406 407 @Override 408 public boolean clipPath(Path path) { 409 throw new UnsupportedOperationException(); 410 } 411 412 @Override 413 public boolean clipPath(Path path, Region.Op op) { 414 throw new UnsupportedOperationException(); 415 } 416 417 @Override 418 public boolean clipRect(float left, float top, float right, float bottom) { 419 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 420 } 421 422 private static native boolean nClipRect(int renderer, float left, float top, 423 float right, float bottom, int op); 424 425 @Override 426 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) { 427 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt); 428 } 429 430 @Override 431 public boolean clipRect(int left, int top, int right, int bottom) { 432 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 433 } 434 435 private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom, 436 int op); 437 438 @Override 439 public boolean clipRect(Rect rect) { 440 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 441 Region.Op.INTERSECT.nativeInt); 442 } 443 444 @Override 445 public boolean clipRect(Rect rect, Region.Op op) { 446 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 447 } 448 449 @Override 450 public boolean clipRect(RectF rect) { 451 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 452 Region.Op.INTERSECT.nativeInt); 453 } 454 455 @Override 456 public boolean clipRect(RectF rect, Region.Op op) { 457 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 458 } 459 460 @Override 461 public boolean clipRegion(Region region) { 462 throw new UnsupportedOperationException(); 463 } 464 465 @Override 466 public boolean clipRegion(Region region, Region.Op op) { 467 throw new UnsupportedOperationException(); 468 } 469 470 @Override 471 public boolean getClipBounds(Rect bounds) { 472 return nGetClipBounds(mRenderer, bounds); 473 } 474 475 private static native boolean nGetClipBounds(int renderer, Rect bounds); 476 477 @Override 478 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) { 479 return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt); 480 } 481 482 private static native boolean nQuickReject(int renderer, float left, float top, 483 float right, float bottom, int edge); 484 485 @Override 486 public boolean quickReject(Path path, EdgeType type) { 487 throw new UnsupportedOperationException(); 488 } 489 490 @Override 491 public boolean quickReject(RectF rect, EdgeType type) { 492 return quickReject(rect.left, rect.top, rect.right, rect.bottom, type); 493 } 494 495 /////////////////////////////////////////////////////////////////////////// 496 // Transformations 497 /////////////////////////////////////////////////////////////////////////// 498 499 @Override 500 public void translate(float dx, float dy) { 501 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy); 502 } 503 504 private static native void nTranslate(int renderer, float dx, float dy); 505 506 @Override 507 public void skew(float sx, float sy) { 508 nSkew(mRenderer, sx, sy); 509 } 510 511 private static native void nSkew(int renderer, float sx, float sy); 512 513 @Override 514 public void rotate(float degrees) { 515 nRotate(mRenderer, degrees); 516 } 517 518 private static native void nRotate(int renderer, float degrees); 519 520 @Override 521 public void scale(float sx, float sy) { 522 nScale(mRenderer, sx, sy); 523 } 524 525 private static native void nScale(int renderer, float sx, float sy); 526 527 @Override 528 public void setMatrix(Matrix matrix) { 529 nSetMatrix(mRenderer, matrix.native_instance); 530 } 531 532 private static native void nSetMatrix(int renderer, int matrix); 533 534 @Override 535 public void getMatrix(Matrix matrix) { 536 nGetMatrix(mRenderer, matrix.native_instance); 537 } 538 539 private static native void nGetMatrix(int renderer, int matrix); 540 541 @Override 542 public void concat(Matrix matrix) { 543 nConcatMatrix(mRenderer, matrix.native_instance); 544 } 545 546 private static native void nConcatMatrix(int renderer, int matrix); 547 548 /////////////////////////////////////////////////////////////////////////// 549 // State management 550 /////////////////////////////////////////////////////////////////////////// 551 552 @Override 553 public int save() { 554 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG); 555 } 556 557 @Override 558 public int save(int saveFlags) { 559 return nSave(mRenderer, saveFlags); 560 } 561 562 private static native int nSave(int renderer, int flags); 563 564 @Override 565 public int saveLayer(RectF bounds, Paint paint, int saveFlags) { 566 if (bounds != null) { 567 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags); 568 } 569 570 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 571 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 572 int count = nSaveLayer(mRenderer, nativePaint, saveFlags); 573 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 574 return count; 575 } 576 577 private static native int nSaveLayer(int renderer, int paint, int saveFlags); 578 579 @Override 580 public int saveLayer(float left, float top, float right, float bottom, Paint paint, 581 int saveFlags) { 582 if (left < right && top < bottom) { 583 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 584 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 585 int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); 586 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 587 return count; 588 } 589 return save(saveFlags); 590 } 591 592 private static native int nSaveLayer(int renderer, float left, float top, 593 float right, float bottom, int paint, int saveFlags); 594 595 @Override 596 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { 597 if (bounds != null) { 598 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 599 alpha, saveFlags); 600 } 601 return nSaveLayerAlpha(mRenderer, alpha, saveFlags); 602 } 603 604 private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags); 605 606 @Override 607 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, 608 int saveFlags) { 609 if (left < right && top < bottom) { 610 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags); 611 } 612 return save(saveFlags); 613 } 614 615 private static native int nSaveLayerAlpha(int renderer, float left, float top, float right, 616 float bottom, int alpha, int saveFlags); 617 618 @Override 619 public void restore() { 620 nRestore(mRenderer); 621 } 622 623 private static native void nRestore(int renderer); 624 625 @Override 626 public void restoreToCount(int saveCount) { 627 nRestoreToCount(mRenderer, saveCount); 628 } 629 630 private static native void nRestoreToCount(int renderer, int saveCount); 631 632 @Override 633 public int getSaveCount() { 634 return nGetSaveCount(mRenderer); 635 } 636 637 private static native int nGetSaveCount(int renderer); 638 639 /////////////////////////////////////////////////////////////////////////// 640 // Filtering 641 /////////////////////////////////////////////////////////////////////////// 642 643 @Override 644 public void setDrawFilter(DrawFilter filter) { 645 mFilter = filter; 646 } 647 648 @Override 649 public DrawFilter getDrawFilter() { 650 return mFilter; 651 } 652 653 /////////////////////////////////////////////////////////////////////////// 654 // Drawing 655 /////////////////////////////////////////////////////////////////////////// 656 657 @Override 658 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, 659 Paint paint) { 660 int modifiers = setupModifiers(paint); 661 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, 662 useCenter, paint.mNativePaint); 663 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 664 } 665 666 private static native void nDrawArc(int renderer, float left, float top, 667 float right, float bottom, float startAngle, float sweepAngle, 668 boolean useCenter, int paint); 669 670 @Override 671 public void drawARGB(int a, int r, int g, int b) { 672 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 673 } 674 675 @Override 676 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) { 677 // Shaders are ignored when drawing patches 678 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 679 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 680 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, chunks, 681 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 682 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 683 } 684 685 private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks, 686 float left, float top, float right, float bottom, int paint); 687 688 @Override 689 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { 690 // Shaders are ignored when drawing bitmaps 691 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 692 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 693 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint); 694 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 695 } 696 697 private static native void nDrawBitmap( 698 int renderer, int bitmap, byte[] buffer, float left, float top, int paint); 699 700 @Override 701 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { 702 // Shaders are ignored when drawing bitmaps 703 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 704 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 705 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, 706 matrix.native_instance, nativePaint); 707 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 708 } 709 710 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buff, 711 int matrix, int paint); 712 713 @Override 714 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { 715 // Shaders are ignored when drawing bitmaps 716 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 717 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 718 719 int left, top, right, bottom; 720 if (src == null) { 721 left = top = 0; 722 right = bitmap.getWidth(); 723 bottom = bitmap.getHeight(); 724 } else { 725 left = src.left; 726 right = src.right; 727 top = src.top; 728 bottom = src.bottom; 729 } 730 731 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, 732 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 733 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 734 } 735 736 @Override 737 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { 738 // Shaders are ignored when drawing bitmaps 739 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 740 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 741 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, src.left, src.top, src.right, 742 src.bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint); 743 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 744 } 745 746 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer, 747 float srcLeft, float srcTop, float srcRight, float srcBottom, 748 float left, float top, float right, float bottom, int paint); 749 750 @Override 751 public void drawBitmap(int[] colors, int offset, int stride, float x, float y, 752 int width, int height, boolean hasAlpha, Paint paint) { 753 // Shaders are ignored when drawing bitmaps 754 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 755 final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 756 final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config); 757 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 758 nDrawBitmap(mRenderer, b.mNativeBitmap, b.mBuffer, x, y, nativePaint); 759 b.recycle(); 760 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 761 } 762 763 @Override 764 public void drawBitmap(int[] colors, int offset, int stride, int x, int y, 765 int width, int height, boolean hasAlpha, Paint paint) { 766 // Shaders are ignored when drawing bitmaps 767 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint); 768 } 769 770 @Override 771 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, 772 int vertOffset, int[] colors, int colorOffset, Paint paint) { 773 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) { 774 throw new ArrayIndexOutOfBoundsException(); 775 } 776 777 if (meshWidth == 0 || meshHeight == 0) { 778 return; 779 } 780 781 final int count = (meshWidth + 1) * (meshHeight + 1); 782 checkRange(verts.length, vertOffset, count * 2); 783 784 // TODO: Colors are ignored for now 785 colors = null; 786 colorOffset = 0; 787 788 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 789 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 790 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight, 791 verts, vertOffset, colors, colorOffset, nativePaint); 792 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 793 } 794 795 private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer, 796 int meshWidth, int meshHeight, float[] verts, int vertOffset, 797 int[] colors, int colorOffset, int paint); 798 799 @Override 800 public void drawCircle(float cx, float cy, float radius, Paint paint) { 801 int modifiers = setupModifiers(paint); 802 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint); 803 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 804 } 805 806 private static native void nDrawCircle(int renderer, float cx, float cy, 807 float radius, int paint); 808 809 @Override 810 public void drawColor(int color) { 811 drawColor(color, PorterDuff.Mode.SRC_OVER); 812 } 813 814 @Override 815 public void drawColor(int color, PorterDuff.Mode mode) { 816 nDrawColor(mRenderer, color, mode.nativeInt); 817 } 818 819 private static native void nDrawColor(int renderer, int color, int mode); 820 821 @Override 822 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { 823 mLine[0] = startX; 824 mLine[1] = startY; 825 mLine[2] = stopX; 826 mLine[3] = stopY; 827 drawLines(mLine, 0, 4, paint); 828 } 829 830 @Override 831 public void drawLines(float[] pts, int offset, int count, Paint paint) { 832 if ((offset | count) < 0 || offset + count > pts.length) { 833 throw new IllegalArgumentException("The lines array must contain 4 elements per line."); 834 } 835 int modifiers = setupModifiers(paint); 836 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint); 837 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 838 } 839 840 private static native void nDrawLines(int renderer, float[] points, 841 int offset, int count, int paint); 842 843 @Override 844 public void drawLines(float[] pts, Paint paint) { 845 drawLines(pts, 0, pts.length, paint); 846 } 847 848 @Override 849 public void drawOval(RectF oval, Paint paint) { 850 int modifiers = setupModifiers(paint); 851 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint); 852 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 853 } 854 855 private static native void nDrawOval(int renderer, float left, float top, 856 float right, float bottom, int paint); 857 858 @Override 859 public void drawPaint(Paint paint) { 860 final Rect r = mClipBounds; 861 nGetClipBounds(mRenderer, r); 862 drawRect(r.left, r.top, r.right, r.bottom, paint); 863 } 864 865 @Override 866 public void drawPath(Path path, Paint paint) { 867 int modifiers = setupModifiers(paint); 868 if (path.isSimplePath) { 869 if (path.rects != null) { 870 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint); 871 } 872 } else { 873 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint); 874 } 875 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 876 } 877 878 private static native void nDrawPath(int renderer, int path, int paint); 879 private static native void nDrawRects(int renderer, int region, int paint); 880 881 @Override 882 public void drawPicture(Picture picture) { 883 throw new UnsupportedOperationException(); 884 } 885 886 @Override 887 public void drawPicture(Picture picture, Rect dst) { 888 throw new UnsupportedOperationException(); 889 } 890 891 @Override 892 public void drawPicture(Picture picture, RectF dst) { 893 throw new UnsupportedOperationException(); 894 } 895 896 @Override 897 public void drawPoint(float x, float y, Paint paint) { 898 mPoint[0] = x; 899 mPoint[1] = y; 900 drawPoints(mPoint, 0, 2, paint); 901 } 902 903 @Override 904 public void drawPoints(float[] pts, Paint paint) { 905 drawPoints(pts, 0, pts.length, paint); 906 } 907 908 @Override 909 public void drawPoints(float[] pts, int offset, int count, Paint paint) { 910 int modifiers = setupModifiers(paint); 911 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint); 912 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 913 } 914 915 private static native void nDrawPoints(int renderer, float[] points, 916 int offset, int count, int paint); 917 918 @Override 919 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { 920 // TODO: Implement 921 } 922 923 @Override 924 public void drawPosText(String text, float[] pos, Paint paint) { 925 // TODO: Implement 926 } 927 928 @Override 929 public void drawRect(float left, float top, float right, float bottom, Paint paint) { 930 int modifiers = setupModifiers(paint); 931 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint); 932 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 933 } 934 935 private static native void nDrawRect(int renderer, float left, float top, 936 float right, float bottom, int paint); 937 938 @Override 939 public void drawRect(Rect r, Paint paint) { 940 drawRect(r.left, r.top, r.right, r.bottom, paint); 941 } 942 943 @Override 944 public void drawRect(RectF r, Paint paint) { 945 drawRect(r.left, r.top, r.right, r.bottom, paint); 946 } 947 948 @Override 949 public void drawRGB(int r, int g, int b) { 950 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 951 } 952 953 @Override 954 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { 955 int modifiers = setupModifiers(paint); 956 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 957 rx, ry, paint.mNativePaint); 958 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 959 } 960 961 private static native void nDrawRoundRect(int renderer, float left, float top, 962 float right, float bottom, float rx, float y, int paint); 963 964 @Override 965 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { 966 if ((index | count | (index + count) | (text.length - index - count)) < 0) { 967 throw new IndexOutOfBoundsException(); 968 } 969 970 int modifiers = setupModifiers(paint); 971 try { 972 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); 973 } finally { 974 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 975 } 976 } 977 978 private static native void nDrawText(int renderer, char[] text, int index, int count, 979 float x, float y, int bidiFlags, int paint); 980 981 @Override 982 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { 983 int modifiers = setupModifiers(paint); 984 try { 985 if (text instanceof String || text instanceof SpannedString || 986 text instanceof SpannableString) { 987 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, 988 paint.mNativePaint); 989 } else if (text instanceof GraphicsOperations) { 990 ((GraphicsOperations) text).drawText(this, start, end, x, y, 991 paint); 992 } else { 993 char[] buf = TemporaryBuffer.obtain(end - start); 994 TextUtils.getChars(text, start, end, buf, 0); 995 nDrawText(mRenderer, buf, 0, end - start, x, y, 996 paint.mBidiFlags, paint.mNativePaint); 997 TemporaryBuffer.recycle(buf); 998 } 999 } finally { 1000 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1001 } 1002 } 1003 1004 @Override 1005 public void drawText(String text, int start, int end, float x, float y, Paint paint) { 1006 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1007 throw new IndexOutOfBoundsException(); 1008 } 1009 1010 int modifiers = setupModifiers(paint); 1011 try { 1012 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); 1013 } finally { 1014 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1015 } 1016 } 1017 1018 private static native void nDrawText(int renderer, String text, int start, int end, 1019 float x, float y, int bidiFlags, int paint); 1020 1021 @Override 1022 public void drawText(String text, float x, float y, Paint paint) { 1023 int modifiers = setupModifiers(paint); 1024 try { 1025 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, 1026 paint.mNativePaint); 1027 } finally { 1028 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1029 } 1030 } 1031 1032 @Override 1033 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, 1034 float vOffset, Paint paint) { 1035 // TODO: Implement 1036 } 1037 1038 @Override 1039 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { 1040 // TODO: Implement 1041 } 1042 1043 @Override 1044 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, 1045 float x, float y, int dir, Paint paint) { 1046 if ((index | count | text.length - index - count) < 0) { 1047 throw new IndexOutOfBoundsException(); 1048 } 1049 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) { 1050 throw new IllegalArgumentException("Unknown direction: " + dir); 1051 } 1052 1053 int modifiers = setupModifiers(paint); 1054 try { 1055 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir, 1056 paint.mNativePaint); 1057 } finally { 1058 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1059 } 1060 } 1061 1062 private static native void nDrawTextRun(int renderer, char[] text, int index, int count, 1063 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint); 1064 1065 @Override 1066 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, 1067 float x, float y, int dir, Paint paint) { 1068 if ((start | end | end - start | text.length() - end) < 0) { 1069 throw new IndexOutOfBoundsException(); 1070 } 1071 1072 int modifiers = setupModifiers(paint); 1073 try { 1074 int flags = dir == 0 ? 0 : 1; 1075 if (text instanceof String || text instanceof SpannedString || 1076 text instanceof SpannableString) { 1077 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart, 1078 contextEnd, x, y, flags, paint.mNativePaint); 1079 } else if (text instanceof GraphicsOperations) { 1080 ((GraphicsOperations) text).drawTextRun(this, start, end, 1081 contextStart, contextEnd, x, y, flags, paint); 1082 } else { 1083 int contextLen = contextEnd - contextStart; 1084 int len = end - start; 1085 char[] buf = TemporaryBuffer.obtain(contextLen); 1086 TextUtils.getChars(text, contextStart, contextEnd, buf, 0); 1087 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen, 1088 x, y, flags, paint.mNativePaint); 1089 TemporaryBuffer.recycle(buf); 1090 } 1091 } finally { 1092 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1093 } 1094 } 1095 1096 private static native void nDrawTextRun(int renderer, String text, int start, int end, 1097 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint); 1098 1099 @Override 1100 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, 1101 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, 1102 int indexOffset, int indexCount, Paint paint) { 1103 // TODO: Implement 1104 } 1105 1106 private int setupModifiers(Bitmap b, Paint paint) { 1107 if (b.getConfig() == Bitmap.Config.ALPHA_8) { 1108 return setupModifiers(paint); 1109 } 1110 1111 final ColorFilter filter = paint.getColorFilter(); 1112 if (filter != null) { 1113 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1114 return MODIFIER_COLOR_FILTER; 1115 } 1116 1117 return MODIFIER_NONE; 1118 } 1119 1120 private int setupModifiers(Paint paint) { 1121 int modifiers = MODIFIER_NONE; 1122 1123 if (paint.hasShadow) { 1124 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy, 1125 paint.shadowColor); 1126 modifiers |= MODIFIER_SHADOW; 1127 } 1128 1129 final Shader shader = paint.getShader(); 1130 if (shader != null) { 1131 nSetupShader(mRenderer, shader.native_shader); 1132 modifiers |= MODIFIER_SHADER; 1133 } 1134 1135 final ColorFilter filter = paint.getColorFilter(); 1136 if (filter != null) { 1137 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1138 modifiers |= MODIFIER_COLOR_FILTER; 1139 } 1140 1141 return modifiers; 1142 } 1143 1144 private int setupColorFilter(Paint paint) { 1145 final ColorFilter filter = paint.getColorFilter(); 1146 if (filter != null) { 1147 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1148 return MODIFIER_COLOR_FILTER; 1149 } 1150 return MODIFIER_NONE; 1151 } 1152 1153 private static native void nSetupShader(int renderer, int shader); 1154 private static native void nSetupColorFilter(int renderer, int colorFilter); 1155 private static native void nSetupShadow(int renderer, float radius, 1156 float dx, float dy, int color); 1157 1158 private static native void nResetModifiers(int renderer, int modifiers); 1159} 1160