GLES20Canvas.java revision 18b4cbeedef21c1fa666a110a157bab66edff976
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.NinePatch; 25import android.graphics.Paint; 26import android.graphics.PaintFlagsDrawFilter; 27import android.graphics.Path; 28import android.graphics.Picture; 29import android.graphics.PorterDuff; 30import android.graphics.Rect; 31import android.graphics.RectF; 32import android.graphics.Region; 33import android.graphics.Shader; 34import android.graphics.SurfaceTexture; 35import android.graphics.TemporaryBuffer; 36import android.text.GraphicsOperations; 37import android.text.SpannableString; 38import android.text.SpannedString; 39import android.text.TextUtils; 40 41/** 42 * An implementation of Canvas on top of OpenGL ES 2.0. 43 */ 44class GLES20Canvas extends HardwareCanvas { 45 // Must match modifiers used in the JNI layer 46 private static final int MODIFIER_NONE = 0; 47 private static final int MODIFIER_SHADOW = 1; 48 private static final int MODIFIER_SHADER = 2; 49 private static final int MODIFIER_COLOR_FILTER = 4; 50 51 private final boolean mOpaque; 52 private long mRenderer; 53 54 // The native renderer will be destroyed when this object dies. 55 // DO NOT overwrite this reference once it is set. 56 @SuppressWarnings({"unused", "FieldCanBeLocal"}) 57 private CanvasFinalizer mFinalizer; 58 59 private int mWidth; 60 private int mHeight; 61 62 private float[] mPoint; 63 private float[] mLine; 64 65 private Rect mClipBounds; 66 private RectF mPathBounds; 67 68 private DrawFilter mFilter; 69 70 /////////////////////////////////////////////////////////////////////////// 71 // JNI 72 /////////////////////////////////////////////////////////////////////////// 73 74 private static native boolean nIsAvailable(); 75 private static boolean sIsAvailable = nIsAvailable(); 76 77 static boolean isAvailable() { 78 return sIsAvailable; 79 } 80 81 /////////////////////////////////////////////////////////////////////////// 82 // Constructors 83 /////////////////////////////////////////////////////////////////////////// 84 85 /** 86 * Creates a canvas to render directly on screen. 87 */ 88 GLES20Canvas(boolean translucent) { 89 this(false, translucent); 90 } 91 92 /** 93 * Creates a canvas to render into an FBO. 94 */ 95 GLES20Canvas(long layer, boolean translucent) { 96 mOpaque = !translucent; 97 mRenderer = nCreateLayerRenderer(layer); 98 setupFinalizer(); 99 } 100 101 protected GLES20Canvas(boolean record, boolean translucent) { 102 mOpaque = !translucent; 103 104 if (record) { 105 mRenderer = nCreateDisplayListRenderer(); 106 } else { 107 mRenderer = nCreateRenderer(); 108 } 109 110 setupFinalizer(); 111 } 112 113 private void setupFinalizer() { 114 if (mRenderer == 0) { 115 throw new IllegalStateException("Could not create GLES20Canvas renderer"); 116 } else { 117 mFinalizer = new CanvasFinalizer(mRenderer); 118 } 119 } 120 121 protected void resetDisplayListRenderer() { 122 nResetDisplayListRenderer(mRenderer); 123 } 124 125 private static native long nCreateRenderer(); 126 private static native long nCreateLayerRenderer(long layer); 127 private static native long nCreateDisplayListRenderer(); 128 private static native void nResetDisplayListRenderer(long renderer); 129 private static native void nDestroyRenderer(long renderer); 130 131 private static final class CanvasFinalizer { 132 private final long mRenderer; 133 134 public CanvasFinalizer(long renderer) { 135 mRenderer = renderer; 136 } 137 138 @Override 139 protected void finalize() throws Throwable { 140 try { 141 nDestroyRenderer(mRenderer); 142 } finally { 143 super.finalize(); 144 } 145 } 146 } 147 148 public static void setProperty(String name, String value) { 149 nSetProperty(name, value); 150 } 151 152 private static native void nSetProperty(String name, String value); 153 154 /////////////////////////////////////////////////////////////////////////// 155 // Hardware layers 156 /////////////////////////////////////////////////////////////////////////// 157 158 @Override 159 void pushLayerUpdate(HardwareLayer layer) { 160 nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer); 161 } 162 163 @Override 164 void cancelLayerUpdate(HardwareLayer layer) { 165 nCancelLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer); 166 } 167 168 @Override 169 void flushLayerUpdates() { 170 nFlushLayerUpdates(mRenderer); 171 } 172 173 @Override 174 void clearLayerUpdates() { 175 nClearLayerUpdates(mRenderer); 176 } 177 178 static native long nCreateTextureLayer(boolean opaque, int[] layerInfo); 179 static native long nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo); 180 static native boolean nResizeLayer(long layerId, int width, int height, int[] layerInfo); 181 static native void nSetOpaqueLayer(long layerId, boolean isOpaque); 182 static native void nSetLayerPaint(long layerId, long nativePaint); 183 static native void nSetLayerColorFilter(long layerId, long nativeColorFilter); 184 static native void nUpdateTextureLayer(long layerId, int width, int height, boolean opaque, 185 SurfaceTexture surface); 186 static native void nClearLayerTexture(long layerId); 187 static native void nSetTextureLayerTransform(long layerId, long matrix); 188 static native void nDestroyLayer(long layerId); 189 static native void nDestroyLayerDeferred(long layerId); 190 static native void nUpdateRenderLayer(long layerId, long renderer, long displayList, 191 int left, int top, int right, int bottom); 192 static native boolean nCopyLayer(long layerId, long bitmap); 193 194 private static native void nClearLayerUpdates(long renderer); 195 private static native void nFlushLayerUpdates(long renderer); 196 private static native void nPushLayerUpdate(long renderer, long layer); 197 private static native void nCancelLayerUpdate(long renderer, long layer); 198 199 /////////////////////////////////////////////////////////////////////////// 200 // Canvas management 201 /////////////////////////////////////////////////////////////////////////// 202 203 @Override 204 public boolean isOpaque() { 205 return mOpaque; 206 } 207 208 @Override 209 public int getWidth() { 210 return mWidth; 211 } 212 213 @Override 214 public int getHeight() { 215 return mHeight; 216 } 217 218 @Override 219 public int getMaximumBitmapWidth() { 220 return nGetMaximumTextureWidth(); 221 } 222 223 @Override 224 public int getMaximumBitmapHeight() { 225 return nGetMaximumTextureHeight(); 226 } 227 228 private static native int nGetMaximumTextureWidth(); 229 private static native int nGetMaximumTextureHeight(); 230 231 /** 232 * Returns the native OpenGLRenderer object. 233 */ 234 long getRenderer() { 235 return mRenderer; 236 } 237 238 /////////////////////////////////////////////////////////////////////////// 239 // Setup 240 /////////////////////////////////////////////////////////////////////////// 241 242 @Override 243 public void setViewport(int width, int height) { 244 mWidth = width; 245 mHeight = height; 246 247 nSetViewport(mRenderer, width, height); 248 } 249 250 private static native void nSetViewport(long renderer, int width, int height); 251 252 @Override 253 public int onPreDraw(Rect dirty) { 254 if (dirty != null) { 255 return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, 256 mOpaque); 257 } else { 258 return nPrepare(mRenderer, mOpaque); 259 } 260 } 261 262 private static native int nPrepare(long renderer, boolean opaque); 263 private static native int nPrepareDirty(long renderer, int left, int top, int right, int bottom, 264 boolean opaque); 265 266 @Override 267 public void onPostDraw() { 268 nFinish(mRenderer); 269 } 270 271 private static native void nFinish(long renderer); 272 273 /** 274 * Returns the size of the stencil buffer required by the underlying 275 * implementation. 276 * 277 * @return The minimum number of bits the stencil buffer must. Always >= 0. 278 * 279 * @hide 280 */ 281 public static int getStencilSize() { 282 return nGetStencilSize(); 283 } 284 285 private static native int nGetStencilSize(); 286 287 void setCountOverdrawEnabled(boolean enabled) { 288 nSetCountOverdrawEnabled(mRenderer, enabled); 289 } 290 291 static native void nSetCountOverdrawEnabled(long renderer, boolean enabled); 292 293 float getOverdraw() { 294 return nGetOverdraw(mRenderer); 295 } 296 297 static native float nGetOverdraw(long renderer); 298 299 /////////////////////////////////////////////////////////////////////////// 300 // Functor 301 /////////////////////////////////////////////////////////////////////////// 302 303 @Override 304 public int callDrawGLFunction(long drawGLFunction) { 305 return nCallDrawGLFunction(mRenderer, drawGLFunction); 306 } 307 308 private static native int nCallDrawGLFunction(long renderer, long drawGLFunction); 309 310 @Override 311 public int invokeFunctors(Rect dirty) { 312 return nInvokeFunctors(mRenderer, dirty); 313 } 314 315 private static native int nInvokeFunctors(long renderer, Rect dirty); 316 317 @Override 318 public void detachFunctor(long functor) { 319 nDetachFunctor(mRenderer, functor); 320 } 321 322 private static native void nDetachFunctor(long renderer, long functor); 323 324 @Override 325 public void attachFunctor(long functor) { 326 nAttachFunctor(mRenderer, functor); 327 } 328 329 private static native void nAttachFunctor(long renderer, long functor); 330 331 /////////////////////////////////////////////////////////////////////////// 332 // Memory 333 /////////////////////////////////////////////////////////////////////////// 334 335 /** 336 * Must match Caches::FlushMode values 337 * 338 * @see #flushCaches(int) 339 */ 340 static final int FLUSH_CACHES_LAYERS = 0; 341 342 /** 343 * Must match Caches::FlushMode values 344 * 345 * @see #flushCaches(int) 346 */ 347 static final int FLUSH_CACHES_MODERATE = 1; 348 349 /** 350 * Must match Caches::FlushMode values 351 * 352 * @see #flushCaches(int) 353 */ 354 static final int FLUSH_CACHES_FULL = 2; 355 356 /** 357 * Flush caches to reclaim as much memory as possible. The amount of memory 358 * to reclaim is indicate by the level parameter. 359 * 360 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or 361 * {@link #FLUSH_CACHES_FULL}. 362 * 363 * @param level Hint about the amount of memory to reclaim 364 */ 365 static void flushCaches(int level) { 366 nFlushCaches(level); 367 } 368 369 private static native void nFlushCaches(int level); 370 371 /** 372 * Release all resources associated with the underlying caches. This should 373 * only be called after a full flushCaches(). 374 * 375 * @hide 376 */ 377 static void terminateCaches() { 378 nTerminateCaches(); 379 } 380 381 private static native void nTerminateCaches(); 382 383 static boolean initCaches() { 384 return nInitCaches(); 385 } 386 387 private static native boolean nInitCaches(); 388 389 /////////////////////////////////////////////////////////////////////////// 390 // Atlas 391 /////////////////////////////////////////////////////////////////////////// 392 393 static void initAtlas(GraphicBuffer buffer, int[] map) { 394 nInitAtlas(buffer, map, map.length); 395 } 396 397 private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count); 398 399 /////////////////////////////////////////////////////////////////////////// 400 // Display list 401 /////////////////////////////////////////////////////////////////////////// 402 403 long getDisplayList(long displayList) { 404 return nGetDisplayList(mRenderer, displayList); 405 } 406 407 private static native long nGetDisplayList(long renderer, long displayList); 408 409 @Override 410 public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) { 411 return nDrawDisplayList(mRenderer, displayList.getNativeDisplayList(), 412 dirty, flags); 413 } 414 415 private static native int nDrawDisplayList(long renderer, long displayList, 416 Rect dirty, int flags); 417 418 /////////////////////////////////////////////////////////////////////////// 419 // Hardware layer 420 /////////////////////////////////////////////////////////////////////////// 421 422 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) { 423 layer.setLayerPaint(paint); 424 425 final GLES20Layer glLayer = (GLES20Layer) layer; 426 nDrawLayer(mRenderer, glLayer.getLayer(), x, y); 427 } 428 429 private static native void nDrawLayer(long renderer, long layer, float x, float y); 430 431 void interrupt() { 432 nInterrupt(mRenderer); 433 } 434 435 void resume() { 436 nResume(mRenderer); 437 } 438 439 private static native void nInterrupt(long renderer); 440 private static native void nResume(long renderer); 441 442 /////////////////////////////////////////////////////////////////////////// 443 // Support 444 /////////////////////////////////////////////////////////////////////////// 445 446 private Rect getInternalClipBounds() { 447 if (mClipBounds == null) mClipBounds = new Rect(); 448 return mClipBounds; 449 } 450 451 452 private RectF getPathBounds() { 453 if (mPathBounds == null) mPathBounds = new RectF(); 454 return mPathBounds; 455 } 456 457 private float[] getPointStorage() { 458 if (mPoint == null) mPoint = new float[2]; 459 return mPoint; 460 } 461 462 private float[] getLineStorage() { 463 if (mLine == null) mLine = new float[4]; 464 return mLine; 465 } 466 467 /////////////////////////////////////////////////////////////////////////// 468 // Clipping 469 /////////////////////////////////////////////////////////////////////////// 470 471 @Override 472 public boolean clipPath(Path path) { 473 return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt); 474 } 475 476 @Override 477 public boolean clipPath(Path path, Region.Op op) { 478 return nClipPath(mRenderer, path.mNativePath, op.nativeInt); 479 } 480 481 private static native boolean nClipPath(long renderer, long path, int op); 482 483 @Override 484 public boolean clipRect(float left, float top, float right, float bottom) { 485 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 486 } 487 488 private static native boolean nClipRect(long renderer, float left, float top, 489 float right, float bottom, int op); 490 491 @Override 492 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) { 493 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt); 494 } 495 496 @Override 497 public boolean clipRect(int left, int top, int right, int bottom) { 498 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 499 } 500 501 private static native boolean nClipRect(long renderer, int left, int top, 502 int right, int bottom, int op); 503 504 @Override 505 public boolean clipRect(Rect rect) { 506 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 507 Region.Op.INTERSECT.nativeInt); 508 } 509 510 @Override 511 public boolean clipRect(Rect rect, Region.Op op) { 512 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 513 } 514 515 @Override 516 public boolean clipRect(RectF rect) { 517 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 518 Region.Op.INTERSECT.nativeInt); 519 } 520 521 @Override 522 public boolean clipRect(RectF rect, Region.Op op) { 523 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 524 } 525 526 @Override 527 public boolean clipRegion(Region region) { 528 return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt); 529 } 530 531 @Override 532 public boolean clipRegion(Region region, Region.Op op) { 533 return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt); 534 } 535 536 private static native boolean nClipRegion(long renderer, long region, int op); 537 538 @Override 539 public boolean getClipBounds(Rect bounds) { 540 return nGetClipBounds(mRenderer, bounds); 541 } 542 543 private static native boolean nGetClipBounds(long renderer, Rect bounds); 544 545 @Override 546 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) { 547 return nQuickReject(mRenderer, left, top, right, bottom); 548 } 549 550 private static native boolean nQuickReject(long renderer, float left, float top, 551 float right, float bottom); 552 553 @Override 554 public boolean quickReject(Path path, EdgeType type) { 555 RectF pathBounds = getPathBounds(); 556 path.computeBounds(pathBounds, true); 557 return nQuickReject(mRenderer, pathBounds.left, pathBounds.top, 558 pathBounds.right, pathBounds.bottom); 559 } 560 561 @Override 562 public boolean quickReject(RectF rect, EdgeType type) { 563 return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom); 564 } 565 566 /////////////////////////////////////////////////////////////////////////// 567 // Transformations 568 /////////////////////////////////////////////////////////////////////////// 569 570 @Override 571 public void translate(float dx, float dy) { 572 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy); 573 } 574 575 private static native void nTranslate(long renderer, float dx, float dy); 576 577 @Override 578 public void skew(float sx, float sy) { 579 nSkew(mRenderer, sx, sy); 580 } 581 582 private static native void nSkew(long renderer, float sx, float sy); 583 584 @Override 585 public void rotate(float degrees) { 586 nRotate(mRenderer, degrees); 587 } 588 589 private static native void nRotate(long renderer, float degrees); 590 591 @Override 592 public void scale(float sx, float sy) { 593 nScale(mRenderer, sx, sy); 594 } 595 596 private static native void nScale(long renderer, float sx, float sy); 597 598 @Override 599 public void setMatrix(Matrix matrix) { 600 nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance); 601 } 602 603 private static native void nSetMatrix(long renderer, long matrix); 604 605 @SuppressWarnings("deprecation") 606 @Override 607 public void getMatrix(Matrix matrix) { 608 nGetMatrix(mRenderer, matrix.native_instance); 609 } 610 611 private static native void nGetMatrix(long renderer, long matrix); 612 613 @Override 614 public void concat(Matrix matrix) { 615 if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance); 616 } 617 618 private static native void nConcatMatrix(long renderer, long matrix); 619 620 /////////////////////////////////////////////////////////////////////////// 621 // State management 622 /////////////////////////////////////////////////////////////////////////// 623 624 @Override 625 public int save() { 626 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG); 627 } 628 629 @Override 630 public int save(int saveFlags) { 631 return nSave(mRenderer, saveFlags); 632 } 633 634 private static native int nSave(long renderer, int flags); 635 636 @Override 637 public int saveLayer(RectF bounds, Paint paint, int saveFlags) { 638 if (bounds != null) { 639 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags); 640 } 641 642 int count; 643 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 644 try { 645 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 646 count = nSaveLayer(mRenderer, nativePaint, saveFlags); 647 } finally { 648 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 649 } 650 return count; 651 } 652 653 private static native int nSaveLayer(long renderer, long paint, int saveFlags); 654 655 @Override 656 public int saveLayer(float left, float top, float right, float bottom, Paint paint, 657 int saveFlags) { 658 if (left < right && top < bottom) { 659 int count; 660 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 661 try { 662 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 663 count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); 664 } finally { 665 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 666 } 667 return count; 668 } 669 return save(saveFlags); 670 } 671 672 private static native int nSaveLayer(long renderer, float left, float top, 673 float right, float bottom, long paint, int saveFlags); 674 675 @Override 676 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { 677 if (bounds != null) { 678 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 679 alpha, saveFlags); 680 } 681 return nSaveLayerAlpha(mRenderer, alpha, saveFlags); 682 } 683 684 private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags); 685 686 @Override 687 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, 688 int saveFlags) { 689 if (left < right && top < bottom) { 690 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags); 691 } 692 return save(saveFlags); 693 } 694 695 private static native int nSaveLayerAlpha(long renderer, float left, float top, float right, 696 float bottom, int alpha, int saveFlags); 697 698 @Override 699 public void restore() { 700 nRestore(mRenderer); 701 } 702 703 private static native void nRestore(long renderer); 704 705 @Override 706 public void restoreToCount(int saveCount) { 707 nRestoreToCount(mRenderer, saveCount); 708 } 709 710 private static native void nRestoreToCount(long renderer, int saveCount); 711 712 @Override 713 public int getSaveCount() { 714 return nGetSaveCount(mRenderer); 715 } 716 717 private static native int nGetSaveCount(long renderer); 718 719 /////////////////////////////////////////////////////////////////////////// 720 // Filtering 721 /////////////////////////////////////////////////////////////////////////// 722 723 @Override 724 public void setDrawFilter(DrawFilter filter) { 725 mFilter = filter; 726 if (filter == null) { 727 nResetPaintFilter(mRenderer); 728 } else if (filter instanceof PaintFlagsDrawFilter) { 729 PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter; 730 nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits); 731 } 732 } 733 734 private static native void nResetPaintFilter(long renderer); 735 private static native void nSetupPaintFilter(long renderer, int clearBits, int setBits); 736 737 @Override 738 public DrawFilter getDrawFilter() { 739 return mFilter; 740 } 741 742 /////////////////////////////////////////////////////////////////////////// 743 // Drawing 744 /////////////////////////////////////////////////////////////////////////// 745 746 @Override 747 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, 748 Paint paint) { 749 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 750 try { 751 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom, 752 startAngle, sweepAngle, useCenter, paint.mNativePaint); 753 } finally { 754 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 755 } 756 } 757 758 private static native void nDrawArc(long renderer, float left, float top, 759 float right, float bottom, float startAngle, float sweepAngle, 760 boolean useCenter, long paint); 761 762 @Override 763 public void drawARGB(int a, int r, int g, int b) { 764 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 765 } 766 767 @Override 768 public void drawPatch(NinePatch patch, Rect dst, Paint paint) { 769 Bitmap bitmap = patch.getBitmap(); 770 throwIfCannotDraw(bitmap); 771 // Shaders are ignored when drawing patches 772 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 773 try { 774 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 775 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk, 776 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 777 } finally { 778 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 779 } 780 } 781 782 @Override 783 public void drawPatch(NinePatch patch, RectF dst, Paint paint) { 784 Bitmap bitmap = patch.getBitmap(); 785 throwIfCannotDraw(bitmap); 786 // Shaders are ignored when drawing patches 787 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 788 try { 789 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 790 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk, 791 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 792 } finally { 793 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 794 } 795 } 796 797 private static native void nDrawPatch(long renderer, long bitmap, byte[] buffer, long chunk, 798 float left, float top, float right, float bottom, long paint); 799 800 @Override 801 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { 802 throwIfCannotDraw(bitmap); 803 // Shaders are ignored when drawing bitmaps 804 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 805 try { 806 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 807 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint); 808 } finally { 809 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 810 } 811 } 812 813 private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer, 814 float left, float top, long paint); 815 816 @Override 817 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { 818 throwIfCannotDraw(bitmap); 819 // Shaders are ignored when drawing bitmaps 820 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 821 try { 822 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 823 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, 824 matrix.native_instance, nativePaint); 825 } finally { 826 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 827 } 828 } 829 830 private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer, 831 long matrix, long paint); 832 833 @Override 834 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { 835 throwIfCannotDraw(bitmap); 836 // Shaders are ignored when drawing bitmaps 837 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 838 try { 839 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 840 841 int left, top, right, bottom; 842 if (src == null) { 843 left = top = 0; 844 right = bitmap.getWidth(); 845 bottom = bitmap.getHeight(); 846 } else { 847 left = src.left; 848 right = src.right; 849 top = src.top; 850 bottom = src.bottom; 851 } 852 853 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, 854 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 855 } finally { 856 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 857 } 858 } 859 860 @Override 861 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { 862 throwIfCannotDraw(bitmap); 863 // Shaders are ignored when drawing bitmaps 864 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 865 try { 866 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 867 868 float left, top, right, bottom; 869 if (src == null) { 870 left = top = 0; 871 right = bitmap.getWidth(); 872 bottom = bitmap.getHeight(); 873 } else { 874 left = src.left; 875 right = src.right; 876 top = src.top; 877 bottom = src.bottom; 878 } 879 880 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, 881 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 882 } finally { 883 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 884 } 885 } 886 887 private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer, 888 float srcLeft, float srcTop, float srcRight, float srcBottom, 889 float left, float top, float right, float bottom, long paint); 890 891 @Override 892 public void drawBitmap(int[] colors, int offset, int stride, float x, float y, 893 int width, int height, boolean hasAlpha, Paint paint) { 894 if (width < 0) { 895 throw new IllegalArgumentException("width must be >= 0"); 896 } 897 898 if (height < 0) { 899 throw new IllegalArgumentException("height must be >= 0"); 900 } 901 902 if (Math.abs(stride) < width) { 903 throw new IllegalArgumentException("abs(stride) must be >= width"); 904 } 905 906 int lastScanline = offset + (height - 1) * stride; 907 int length = colors.length; 908 909 if (offset < 0 || (offset + width > length) || lastScanline < 0 || 910 (lastScanline + width > length)) { 911 throw new ArrayIndexOutOfBoundsException(); 912 } 913 914 // Shaders are ignored when drawing bitmaps 915 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 916 try { 917 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 918 nDrawBitmap(mRenderer, colors, offset, stride, x, y, 919 width, height, hasAlpha, nativePaint); 920 } finally { 921 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 922 } 923 } 924 925 private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride, 926 float x, float y, int width, int height, boolean hasAlpha, long nativePaint); 927 928 @Override 929 public void drawBitmap(int[] colors, int offset, int stride, int x, int y, 930 int width, int height, boolean hasAlpha, Paint paint) { 931 // Shaders are ignored when drawing bitmaps 932 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint); 933 } 934 935 @Override 936 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, 937 int vertOffset, int[] colors, int colorOffset, Paint paint) { 938 throwIfCannotDraw(bitmap); 939 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) { 940 throw new ArrayIndexOutOfBoundsException(); 941 } 942 943 if (meshWidth == 0 || meshHeight == 0) { 944 return; 945 } 946 947 final int count = (meshWidth + 1) * (meshHeight + 1); 948 checkRange(verts.length, vertOffset, count * 2); 949 950 if (colors != null) { 951 checkRange(colors.length, colorOffset, count); 952 } 953 954 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 955 try { 956 final long nativePaint = paint == null ? 0 : paint.mNativePaint; 957 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight, 958 verts, vertOffset, colors, colorOffset, nativePaint); 959 } finally { 960 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 961 } 962 } 963 964 private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer, 965 int meshWidth, int meshHeight, float[] verts, int vertOffset, 966 int[] colors, int colorOffset, long paint); 967 968 @Override 969 public void drawCircle(float cx, float cy, float radius, Paint paint) { 970 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 971 try { 972 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint); 973 } finally { 974 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 975 } 976 } 977 978 private static native void nDrawCircle(long renderer, float cx, float cy, 979 float radius, long paint); 980 981 @Override 982 public void drawColor(int color) { 983 drawColor(color, PorterDuff.Mode.SRC_OVER); 984 } 985 986 @Override 987 public void drawColor(int color, PorterDuff.Mode mode) { 988 nDrawColor(mRenderer, color, mode.nativeInt); 989 } 990 991 private static native void nDrawColor(long renderer, int color, int mode); 992 993 @Override 994 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { 995 float[] line = getLineStorage(); 996 line[0] = startX; 997 line[1] = startY; 998 line[2] = stopX; 999 line[3] = stopY; 1000 drawLines(line, 0, 4, paint); 1001 } 1002 1003 @Override 1004 public void drawLines(float[] pts, int offset, int count, Paint paint) { 1005 if (count < 4) return; 1006 1007 if ((offset | count) < 0 || offset + count > pts.length) { 1008 throw new IllegalArgumentException("The lines array must contain 4 elements per line."); 1009 } 1010 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1011 try { 1012 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint); 1013 } finally { 1014 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1015 } 1016 } 1017 1018 private static native void nDrawLines(long renderer, float[] points, 1019 int offset, int count, long paint); 1020 1021 @Override 1022 public void drawLines(float[] pts, Paint paint) { 1023 drawLines(pts, 0, pts.length, paint); 1024 } 1025 1026 @Override 1027 public void drawOval(RectF oval, Paint paint) { 1028 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1029 try { 1030 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint); 1031 } finally { 1032 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1033 } 1034 } 1035 1036 private static native void nDrawOval(long renderer, float left, float top, 1037 float right, float bottom, long paint); 1038 1039 @Override 1040 public void drawPaint(Paint paint) { 1041 final Rect r = getInternalClipBounds(); 1042 nGetClipBounds(mRenderer, r); 1043 drawRect(r.left, r.top, r.right, r.bottom, paint); 1044 } 1045 1046 @Override 1047 public void drawPath(Path path, Paint paint) { 1048 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1049 try { 1050 if (path.isSimplePath) { 1051 if (path.rects != null) { 1052 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint); 1053 } 1054 } else { 1055 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint); 1056 } 1057 } finally { 1058 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1059 } 1060 } 1061 1062 private static native void nDrawPath(long renderer, long path, long paint); 1063 private static native void nDrawRects(long renderer, long region, long paint); 1064 1065 void drawRects(float[] rects, int count, Paint paint) { 1066 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1067 try { 1068 nDrawRects(mRenderer, rects, count, paint.mNativePaint); 1069 } finally { 1070 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1071 } 1072 } 1073 1074 private static native void nDrawRects(long renderer, float[] rects, int count, long paint); 1075 1076 @Override 1077 public void drawPicture(Picture picture) { 1078 if (picture.createdFromStream) { 1079 return; 1080 } 1081 1082 picture.endRecording(); 1083 // TODO: Implement rendering 1084 } 1085 1086 @Override 1087 public void drawPicture(Picture picture, Rect dst) { 1088 if (picture.createdFromStream) { 1089 return; 1090 } 1091 1092 save(); 1093 translate(dst.left, dst.top); 1094 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1095 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight()); 1096 } 1097 drawPicture(picture); 1098 restore(); 1099 } 1100 1101 @Override 1102 public void drawPicture(Picture picture, RectF dst) { 1103 if (picture.createdFromStream) { 1104 return; 1105 } 1106 1107 save(); 1108 translate(dst.left, dst.top); 1109 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1110 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight()); 1111 } 1112 drawPicture(picture); 1113 restore(); 1114 } 1115 1116 @Override 1117 public void drawPoint(float x, float y, Paint paint) { 1118 float[] point = getPointStorage(); 1119 point[0] = x; 1120 point[1] = y; 1121 drawPoints(point, 0, 2, paint); 1122 } 1123 1124 @Override 1125 public void drawPoints(float[] pts, Paint paint) { 1126 drawPoints(pts, 0, pts.length, paint); 1127 } 1128 1129 @Override 1130 public void drawPoints(float[] pts, int offset, int count, Paint paint) { 1131 if (count < 2) return; 1132 1133 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1134 try { 1135 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint); 1136 } finally { 1137 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1138 } 1139 } 1140 1141 private static native void nDrawPoints(long renderer, float[] points, 1142 int offset, int count, long paint); 1143 1144 @SuppressWarnings("deprecation") 1145 @Override 1146 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { 1147 if (index < 0 || index + count > text.length || count * 2 > pos.length) { 1148 throw new IndexOutOfBoundsException(); 1149 } 1150 1151 int modifiers = setupModifiers(paint); 1152 try { 1153 nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint); 1154 } finally { 1155 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1156 } 1157 } 1158 1159 private static native void nDrawPosText(long renderer, char[] text, int index, int count, 1160 float[] pos, long paint); 1161 1162 @SuppressWarnings("deprecation") 1163 @Override 1164 public void drawPosText(String text, float[] pos, Paint paint) { 1165 if (text.length() * 2 > pos.length) { 1166 throw new ArrayIndexOutOfBoundsException(); 1167 } 1168 1169 int modifiers = setupModifiers(paint); 1170 try { 1171 nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint); 1172 } finally { 1173 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1174 } 1175 } 1176 1177 private static native void nDrawPosText(long renderer, String text, int start, int end, 1178 float[] pos, long paint); 1179 1180 @Override 1181 public void drawRect(float left, float top, float right, float bottom, Paint paint) { 1182 if (left == right || top == bottom) return; 1183 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1184 try { 1185 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint); 1186 } finally { 1187 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1188 } 1189 } 1190 1191 private static native void nDrawRect(long renderer, float left, float top, 1192 float right, float bottom, long paint); 1193 1194 @Override 1195 public void drawRect(Rect r, Paint paint) { 1196 drawRect(r.left, r.top, r.right, r.bottom, paint); 1197 } 1198 1199 @Override 1200 public void drawRect(RectF r, Paint paint) { 1201 drawRect(r.left, r.top, r.right, r.bottom, paint); 1202 } 1203 1204 @Override 1205 public void drawRGB(int r, int g, int b) { 1206 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 1207 } 1208 1209 @Override 1210 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { 1211 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1212 try { 1213 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 1214 rx, ry, paint.mNativePaint); 1215 } finally { 1216 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1217 } 1218 } 1219 1220 private static native void nDrawRoundRect(long renderer, float left, float top, 1221 float right, float bottom, float rx, float y, long paint); 1222 1223 @Override 1224 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { 1225 if ((index | count | (index + count) | (text.length - index - count)) < 0) { 1226 throw new IndexOutOfBoundsException(); 1227 } 1228 1229 int modifiers = setupModifiers(paint); 1230 try { 1231 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); 1232 } finally { 1233 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1234 } 1235 } 1236 1237 private static native void nDrawText(long renderer, char[] text, int index, int count, 1238 float x, float y, int bidiFlags, long paint); 1239 1240 @Override 1241 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { 1242 int modifiers = setupModifiers(paint); 1243 try { 1244 if (text instanceof String || text instanceof SpannedString || 1245 text instanceof SpannableString) { 1246 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, 1247 paint.mNativePaint); 1248 } else if (text instanceof GraphicsOperations) { 1249 ((GraphicsOperations) text).drawText(this, start, end, x, y, 1250 paint); 1251 } else { 1252 char[] buf = TemporaryBuffer.obtain(end - start); 1253 TextUtils.getChars(text, start, end, buf, 0); 1254 nDrawText(mRenderer, buf, 0, end - start, x, y, 1255 paint.mBidiFlags, paint.mNativePaint); 1256 TemporaryBuffer.recycle(buf); 1257 } 1258 } finally { 1259 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1260 } 1261 } 1262 1263 @Override 1264 public void drawText(String text, int start, int end, float x, float y, Paint paint) { 1265 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1266 throw new IndexOutOfBoundsException(); 1267 } 1268 1269 int modifiers = setupModifiers(paint); 1270 try { 1271 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); 1272 } finally { 1273 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1274 } 1275 } 1276 1277 private static native void nDrawText(long renderer, String text, int start, int end, 1278 float x, float y, int bidiFlags, long paint); 1279 1280 @Override 1281 public void drawText(String text, float x, float y, Paint paint) { 1282 int modifiers = setupModifiers(paint); 1283 try { 1284 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, 1285 paint.mNativePaint); 1286 } finally { 1287 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1288 } 1289 } 1290 1291 @Override 1292 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, 1293 float vOffset, Paint paint) { 1294 if (index < 0 || index + count > text.length) { 1295 throw new ArrayIndexOutOfBoundsException(); 1296 } 1297 1298 int modifiers = setupModifiers(paint); 1299 try { 1300 nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset, 1301 paint.mBidiFlags, paint.mNativePaint); 1302 } finally { 1303 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1304 } 1305 } 1306 1307 private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count, 1308 long path, float hOffset, float vOffset, int bidiFlags, long nativePaint); 1309 1310 @Override 1311 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { 1312 if (text.length() == 0) return; 1313 1314 int modifiers = setupModifiers(paint); 1315 try { 1316 nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset, 1317 paint.mBidiFlags, paint.mNativePaint); 1318 } finally { 1319 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1320 } 1321 } 1322 1323 private static native void nDrawTextOnPath(long renderer, String text, int start, int end, 1324 long path, float hOffset, float vOffset, int bidiFlags, long nativePaint); 1325 1326 @Override 1327 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, 1328 float x, float y, int dir, Paint paint) { 1329 if ((index | count | text.length - index - count) < 0) { 1330 throw new IndexOutOfBoundsException(); 1331 } 1332 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) { 1333 throw new IllegalArgumentException("Unknown direction: " + dir); 1334 } 1335 1336 int modifiers = setupModifiers(paint); 1337 try { 1338 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir, 1339 paint.mNativePaint); 1340 } finally { 1341 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1342 } 1343 } 1344 1345 private static native void nDrawTextRun(long renderer, char[] text, int index, int count, 1346 int contextIndex, int contextCount, float x, float y, int dir, long nativePaint); 1347 1348 @Override 1349 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, 1350 float x, float y, int dir, Paint paint) { 1351 if ((start | end | end - start | text.length() - end) < 0) { 1352 throw new IndexOutOfBoundsException(); 1353 } 1354 1355 int modifiers = setupModifiers(paint); 1356 try { 1357 int flags = dir == 0 ? 0 : 1; 1358 if (text instanceof String || text instanceof SpannedString || 1359 text instanceof SpannableString) { 1360 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart, 1361 contextEnd, x, y, flags, paint.mNativePaint); 1362 } else if (text instanceof GraphicsOperations) { 1363 ((GraphicsOperations) text).drawTextRun(this, start, end, 1364 contextStart, contextEnd, x, y, flags, paint); 1365 } else { 1366 int contextLen = contextEnd - contextStart; 1367 int len = end - start; 1368 char[] buf = TemporaryBuffer.obtain(contextLen); 1369 TextUtils.getChars(text, contextStart, contextEnd, buf, 0); 1370 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen, 1371 x, y, flags, paint.mNativePaint); 1372 TemporaryBuffer.recycle(buf); 1373 } 1374 } finally { 1375 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1376 } 1377 } 1378 1379 private static native void nDrawTextRun(long renderer, String text, int start, int end, 1380 int contextStart, int contextEnd, float x, float y, int flags, long nativePaint); 1381 1382 @Override 1383 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, 1384 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, 1385 int indexOffset, int indexCount, Paint paint) { 1386 // TODO: Implement 1387 } 1388 1389 private int setupModifiers(Bitmap b, Paint paint) { 1390 if (b.getConfig() != Bitmap.Config.ALPHA_8) { 1391 final ColorFilter filter = paint.getColorFilter(); 1392 if (filter != null) { 1393 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1394 return MODIFIER_COLOR_FILTER; 1395 } 1396 1397 return MODIFIER_NONE; 1398 } else { 1399 return setupModifiers(paint); 1400 } 1401 } 1402 1403 private int setupModifiers(Paint paint) { 1404 int modifiers = MODIFIER_NONE; 1405 1406 if (paint.hasShadow) { 1407 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy, 1408 paint.shadowColor); 1409 modifiers |= MODIFIER_SHADOW; 1410 } 1411 1412 final Shader shader = paint.getShader(); 1413 if (shader != null) { 1414 nSetupShader(mRenderer, shader.native_shader); 1415 modifiers |= MODIFIER_SHADER; 1416 } 1417 1418 final ColorFilter filter = paint.getColorFilter(); 1419 if (filter != null) { 1420 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1421 modifiers |= MODIFIER_COLOR_FILTER; 1422 } 1423 1424 return modifiers; 1425 } 1426 1427 private int setupModifiers(Paint paint, int flags) { 1428 int modifiers = MODIFIER_NONE; 1429 1430 if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) { 1431 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy, 1432 paint.shadowColor); 1433 modifiers |= MODIFIER_SHADOW; 1434 } 1435 1436 final Shader shader = paint.getShader(); 1437 if (shader != null && (flags & MODIFIER_SHADER) != 0) { 1438 nSetupShader(mRenderer, shader.native_shader); 1439 modifiers |= MODIFIER_SHADER; 1440 } 1441 1442 final ColorFilter filter = paint.getColorFilter(); 1443 if (filter != null && (flags & MODIFIER_COLOR_FILTER) != 0) { 1444 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1445 modifiers |= MODIFIER_COLOR_FILTER; 1446 } 1447 1448 return modifiers; 1449 } 1450 1451 private int setupColorFilter(Paint paint) { 1452 final ColorFilter filter = paint.getColorFilter(); 1453 if (filter != null) { 1454 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1455 return MODIFIER_COLOR_FILTER; 1456 } 1457 return MODIFIER_NONE; 1458 } 1459 1460 private static native void nSetupShader(long renderer, long shader); 1461 private static native void nSetupColorFilter(long renderer, long colorFilter); 1462 private static native void nSetupShadow(long renderer, float radius, 1463 float dx, float dy, int color); 1464 1465 private static native void nResetModifiers(long renderer, int modifiers); 1466} 1467