Canvas.java revision b8201195dfb2bae05faaf91b9b3d065e2f199929
1/* 2 * Copyright (C) 2006 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.graphics; 18 19import android.annotation.ColorInt; 20import android.annotation.IntDef; 21import android.annotation.NonNull; 22import android.annotation.Nullable; 23import android.annotation.Size; 24import android.os.Build; 25 26import dalvik.annotation.optimization.CriticalNative; 27import dalvik.annotation.optimization.FastNative; 28 29import libcore.util.NativeAllocationRegistry; 30 31import java.lang.annotation.Retention; 32import java.lang.annotation.RetentionPolicy; 33 34import javax.microedition.khronos.opengles.GL; 35 36/** 37 * The Canvas class holds the "draw" calls. To draw something, you need 38 * 4 basic components: A Bitmap to hold the pixels, a Canvas to host 39 * the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, 40 * Path, text, Bitmap), and a paint (to describe the colors and styles for the 41 * drawing). 42 * 43 * <div class="special reference"> 44 * <h3>Developer Guides</h3> 45 * <p>For more information about how to use Canvas, read the 46 * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html"> 47 * Canvas and Drawables</a> developer guide.</p></div> 48 */ 49public class Canvas extends BaseCanvas { 50 /** @hide */ 51 public static boolean sCompatibilityRestore = false; 52 53 /** @hide */ 54 public long getNativeCanvasWrapper() { 55 return mNativeCanvasWrapper; 56 } 57 58 /** @hide */ 59 public boolean isRecordingFor(Object o) { return false; } 60 61 // may be null 62 private Bitmap mBitmap; 63 64 // optional field set by the caller 65 private DrawFilter mDrawFilter; 66 67 // Maximum bitmap size as defined in Skia's native code 68 // (see SkCanvas.cpp, SkDraw.cpp) 69 private static final int MAXMIMUM_BITMAP_SIZE = 32766; 70 71 // The approximate size of the native allocation associated with 72 // a Canvas object. 73 private static final long NATIVE_ALLOCATION_SIZE = 525; 74 75 // Use a Holder to allow static initialization of Canvas in the boot image. 76 private static class NoImagePreloadHolder { 77 public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( 78 Canvas.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE); 79 } 80 81 // This field is used to finalize the native Canvas properly 82 private Runnable mFinalizer; 83 84 /** 85 * Construct an empty raster canvas. Use setBitmap() to specify a bitmap to 86 * draw into. The initial target density is {@link Bitmap#DENSITY_NONE}; 87 * this will typically be replaced when a target bitmap is set for the 88 * canvas. 89 */ 90 public Canvas() { 91 if (!isHardwareAccelerated()) { 92 // 0 means no native bitmap 93 mNativeCanvasWrapper = nInitRaster(null); 94 mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( 95 this, mNativeCanvasWrapper); 96 } else { 97 mFinalizer = null; 98 } 99 } 100 101 /** 102 * Construct a canvas with the specified bitmap to draw into. The bitmap 103 * must be mutable. 104 * 105 * <p>The initial target density of the canvas is the same as the given 106 * bitmap's density. 107 * 108 * @param bitmap Specifies a mutable bitmap for the canvas to draw into. 109 */ 110 public Canvas(@NonNull Bitmap bitmap) { 111 if (!bitmap.isMutable()) { 112 throw new IllegalStateException("Immutable bitmap passed to Canvas constructor"); 113 } 114 throwIfCannotDraw(bitmap); 115 mNativeCanvasWrapper = nInitRaster(bitmap); 116 mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( 117 this, mNativeCanvasWrapper); 118 mBitmap = bitmap; 119 mDensity = bitmap.mDensity; 120 } 121 122 /** @hide */ 123 public Canvas(long nativeCanvas) { 124 if (nativeCanvas == 0) { 125 throw new IllegalStateException(); 126 } 127 mNativeCanvasWrapper = nativeCanvas; 128 mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation( 129 this, mNativeCanvasWrapper); 130 mDensity = Bitmap.getDefaultDensity(); 131 } 132 133 /** 134 * Returns null. 135 * 136 * @deprecated This method is not supported and should not be invoked. 137 * 138 * @hide 139 */ 140 @Deprecated 141 protected GL getGL() { 142 return null; 143 } 144 145 /** 146 * Indicates whether this Canvas uses hardware acceleration. 147 * 148 * Note that this method does not define what type of hardware acceleration 149 * may or may not be used. 150 * 151 * @return True if drawing operations are hardware accelerated, 152 * false otherwise. 153 */ 154 public boolean isHardwareAccelerated() { 155 return false; 156 } 157 158 /** 159 * Specify a bitmap for the canvas to draw into. All canvas state such as 160 * layers, filters, and the save/restore stack are reset with the exception 161 * of the current matrix and clip stack. Additionally, as a side-effect 162 * the canvas' target density is updated to match that of the bitmap. 163 * 164 * @param bitmap Specifies a mutable bitmap for the canvas to draw into. 165 * @see #setDensity(int) 166 * @see #getDensity() 167 */ 168 public void setBitmap(@Nullable Bitmap bitmap) { 169 if (isHardwareAccelerated()) { 170 throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas"); 171 } 172 173 if (bitmap == null) { 174 nSetBitmap(mNativeCanvasWrapper, null); 175 mDensity = Bitmap.DENSITY_NONE; 176 } else { 177 if (!bitmap.isMutable()) { 178 throw new IllegalStateException(); 179 } 180 throwIfCannotDraw(bitmap); 181 182 nSetBitmap(mNativeCanvasWrapper, bitmap); 183 mDensity = bitmap.mDensity; 184 } 185 186 mBitmap = bitmap; 187 } 188 189 /** @hide */ 190 public void setHighContrastText(boolean highContrastText) { 191 nSetHighContrastText(mNativeCanvasWrapper, highContrastText); 192 } 193 194 /** @hide */ 195 public void insertReorderBarrier() {} 196 197 /** @hide */ 198 public void insertInorderBarrier() {} 199 200 /** 201 * Return true if the device that the current layer draws into is opaque 202 * (i.e. does not support per-pixel alpha). 203 * 204 * @return true if the device that the current layer draws into is opaque 205 */ 206 public boolean isOpaque() { 207 return nIsOpaque(mNativeCanvasWrapper); 208 } 209 210 /** 211 * Returns the width of the current drawing layer 212 * 213 * @return the width of the current drawing layer 214 */ 215 public int getWidth() { 216 return nGetWidth(mNativeCanvasWrapper); 217 } 218 219 /** 220 * Returns the height of the current drawing layer 221 * 222 * @return the height of the current drawing layer 223 */ 224 public int getHeight() { 225 return nGetHeight(mNativeCanvasWrapper); 226 } 227 228 /** 229 * <p>Returns the target density of the canvas. The default density is 230 * derived from the density of its backing bitmap, or 231 * {@link Bitmap#DENSITY_NONE} if there is not one.</p> 232 * 233 * @return Returns the current target density of the canvas, which is used 234 * to determine the scaling factor when drawing a bitmap into it. 235 * 236 * @see #setDensity(int) 237 * @see Bitmap#getDensity() 238 */ 239 public int getDensity() { 240 return mDensity; 241 } 242 243 /** 244 * <p>Specifies the density for this Canvas' backing bitmap. This modifies 245 * the target density of the canvas itself, as well as the density of its 246 * backing bitmap via {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}. 247 * 248 * @param density The new target density of the canvas, which is used 249 * to determine the scaling factor when drawing a bitmap into it. Use 250 * {@link Bitmap#DENSITY_NONE} to disable bitmap scaling. 251 * 252 * @see #getDensity() 253 * @see Bitmap#setDensity(int) 254 */ 255 public void setDensity(int density) { 256 if (mBitmap != null) { 257 mBitmap.setDensity(density); 258 } 259 mDensity = density; 260 } 261 262 /** @hide */ 263 public void setScreenDensity(int density) { 264 mScreenDensity = density; 265 } 266 267 /** 268 * Returns the maximum allowed width for bitmaps drawn with this canvas. 269 * Attempting to draw with a bitmap wider than this value will result 270 * in an error. 271 * 272 * @see #getMaximumBitmapHeight() 273 */ 274 public int getMaximumBitmapWidth() { 275 return MAXMIMUM_BITMAP_SIZE; 276 } 277 278 /** 279 * Returns the maximum allowed height for bitmaps drawn with this canvas. 280 * Attempting to draw with a bitmap taller than this value will result 281 * in an error. 282 * 283 * @see #getMaximumBitmapWidth() 284 */ 285 public int getMaximumBitmapHeight() { 286 return MAXMIMUM_BITMAP_SIZE; 287 } 288 289 // the SAVE_FLAG constants must match their native equivalents 290 291 /** @hide */ 292 @IntDef(flag = true, 293 value = { 294 ALL_SAVE_FLAG 295 }) 296 @Retention(RetentionPolicy.SOURCE) 297 public @interface Saveflags {} 298 299 /** 300 * Restore the current matrix when restore() is called. 301 * 302 * @deprecated Use the flagless version of {@link #save()}, {@link #saveLayer(RectF, Paint)} or 303 * {@link #saveLayerAlpha(RectF, int)}. For saveLayer() calls the matrix 304 * was always restored for {@link #isHardwareAccelerated() Hardware accelerated} 305 * canvases and as of API level {@value Build.VERSION_CODES#O} that is the default 306 * behavior for all canvas types. 307 */ 308 public static final int MATRIX_SAVE_FLAG = 0x01; 309 310 /** 311 * Restore the current clip when restore() is called. 312 * 313 * @deprecated Use the flagless version of {@link #save()}, {@link #saveLayer(RectF, Paint)} or 314 * {@link #saveLayerAlpha(RectF, int)}. For saveLayer() calls the clip 315 * was always restored for {@link #isHardwareAccelerated() Hardware accelerated} 316 * canvases and as of API level {@value Build.VERSION_CODES#O} that is the default 317 * behavior for all canvas types. 318 */ 319 public static final int CLIP_SAVE_FLAG = 0x02; 320 321 /** 322 * The layer requires a per-pixel alpha channel. 323 * 324 * @deprecated This flag is ignored. Use the flagless version of {@link #saveLayer(RectF, Paint)} 325 * {@link #saveLayerAlpha(RectF, int)}. 326 */ 327 public static final int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04; 328 329 /** 330 * The layer requires full 8-bit precision for each color channel. 331 * 332 * @deprecated This flag is ignored. Use the flagless version of {@link #saveLayer(RectF, Paint)} 333 * {@link #saveLayerAlpha(RectF, int)}. 334 */ 335 public static final int FULL_COLOR_LAYER_SAVE_FLAG = 0x08; 336 337 /** 338 * Clip drawing to the bounds of the offscreen layer, omit at your own peril. 339 * <p class="note"><strong>Note:</strong> it is strongly recommended to not 340 * omit this flag for any call to <code>saveLayer()</code> and 341 * <code>saveLayerAlpha()</code> variants. Not passing this flag generally 342 * triggers extremely poor performance with hardware accelerated rendering. 343 * 344 * @deprecated This flag results in poor performance and the same effect can be achieved with 345 * a single layer or multiple draw commands with different clips. 346 * 347 */ 348 public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10; 349 350 /** 351 * Restore everything when restore() is called (standard save flags). 352 * <p class="note"><strong>Note:</strong> for performance reasons, it is 353 * strongly recommended to pass this - the complete set of flags - to any 354 * call to <code>saveLayer()</code> and <code>saveLayerAlpha()</code> 355 * variants. 356 * 357 * <p class="note"><strong>Note:</strong> all methods that accept this flag 358 * have flagless versions that are equivalent to passing this flag. 359 */ 360 public static final int ALL_SAVE_FLAG = 0x1F; 361 362 /** 363 * Saves the current matrix and clip onto a private stack. 364 * <p> 365 * Subsequent calls to translate,scale,rotate,skew,concat or clipRect, 366 * clipPath will all operate as usual, but when the balancing call to 367 * restore() is made, those calls will be forgotten, and the settings that 368 * existed before the save() will be reinstated. 369 * 370 * @return The value to pass to restoreToCount() to balance this save() 371 */ 372 public int save() { 373 return nSave(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG); 374 } 375 376 /** 377 * Based on saveFlags, can save the current matrix and clip onto a private 378 * stack. 379 * <p class="note"><strong>Note:</strong> if possible, use the 380 * parameter-less save(). It is simpler and faster than individually 381 * disabling the saving of matrix or clip with this method. 382 * <p> 383 * Subsequent calls to translate,scale,rotate,skew,concat or clipRect, 384 * clipPath will all operate as usual, but when the balancing call to 385 * restore() is made, those calls will be forgotten, and the settings that 386 * existed before the save() will be reinstated. 387 * 388 * @deprecated Use {@link #save()} instead. 389 * @param saveFlags flag bits that specify which parts of the Canvas state 390 * to save/restore 391 * @return The value to pass to restoreToCount() to balance this save() 392 */ 393 public int save(@Saveflags int saveFlags) { 394 return nSave(mNativeCanvasWrapper, saveFlags); 395 } 396 397 /** 398 * This behaves the same as save(), but in addition it allocates and 399 * redirects drawing to an offscreen bitmap. 400 * <p class="note"><strong>Note:</strong> this method is very expensive, 401 * incurring more than double rendering cost for contained content. Avoid 402 * using this method, especially if the bounds provided are large, or if 403 * the {@link #CLIP_TO_LAYER_SAVE_FLAG} is omitted from the 404 * {@code saveFlags} parameter. It is recommended to use a 405 * {@link android.view.View#LAYER_TYPE_HARDWARE hardware layer} on a View 406 * to apply an xfermode, color filter, or alpha, as it will perform much 407 * better than this method. 408 * <p> 409 * All drawing calls are directed to a newly allocated offscreen bitmap. 410 * Only when the balancing call to restore() is made, is that offscreen 411 * buffer drawn back to the current target of the Canvas (either the 412 * screen, it's target Bitmap, or the previous layer). 413 * <p> 414 * Attributes of the Paint - {@link Paint#getAlpha() alpha}, 415 * {@link Paint#getXfermode() Xfermode}, and 416 * {@link Paint#getColorFilter() ColorFilter} are applied when the 417 * offscreen bitmap is drawn back when restore() is called. 418 * 419 * @deprecated Use {@link #saveLayer(RectF, Paint)} instead. 420 * @param bounds May be null. The maximum size the offscreen bitmap 421 * needs to be (in local coordinates) 422 * @param paint This is copied, and is applied to the offscreen when 423 * restore() is called. 424 * @param saveFlags see _SAVE_FLAG constants, generally {@link #ALL_SAVE_FLAG} is recommended 425 * for performance reasons. 426 * @return value to pass to restoreToCount() to balance this save() 427 */ 428 public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, @Saveflags int saveFlags) { 429 if (bounds == null) { 430 bounds = new RectF(getClipBounds()); 431 } 432 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags); 433 } 434 435 /** 436 * This behaves the same as save(), but in addition it allocates and 437 * redirects drawing to an offscreen rendering target. 438 * <p class="note"><strong>Note:</strong> this method is very expensive, 439 * incurring more than double rendering cost for contained content. Avoid 440 * using this method when possible and instead use a 441 * {@link android.view.View#LAYER_TYPE_HARDWARE hardware layer} on a View 442 * to apply an xfermode, color filter, or alpha, as it will perform much 443 * better than this method. 444 * <p> 445 * All drawing calls are directed to a newly allocated offscreen rendering target. 446 * Only when the balancing call to restore() is made, is that offscreen 447 * buffer drawn back to the current target of the Canvas (which can potentially be a previous 448 * layer if these calls are nested). 449 * <p> 450 * Attributes of the Paint - {@link Paint#getAlpha() alpha}, 451 * {@link Paint#getXfermode() Xfermode}, and 452 * {@link Paint#getColorFilter() ColorFilter} are applied when the 453 * offscreen rendering target is drawn back when restore() is called. 454 * 455 * @param bounds May be null. The maximum size the offscreen render target 456 * needs to be (in local coordinates) 457 * @param paint This is copied, and is applied to the offscreen when 458 * restore() is called. 459 * @return value to pass to restoreToCount() to balance this save() 460 */ 461 public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint) { 462 return saveLayer(bounds, paint, ALL_SAVE_FLAG); 463 } 464 465 /** 466 * Helper version of saveLayer() that takes 4 values rather than a RectF. 467 * 468 * @deprecated Use {@link #saveLayer(float, float, float, float, Paint)} instead. 469 */ 470 public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint, 471 @Saveflags int saveFlags) { 472 return nSaveLayer(mNativeCanvasWrapper, left, top, right, bottom, 473 paint != null ? paint.getNativeInstance() : 0, 474 saveFlags); 475 } 476 477 /** 478 * Convenience for {@link #saveLayer(RectF, Paint)} that takes the four float coordinates of the 479 * bounds rectangle. 480 */ 481 public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint) { 482 return saveLayer(left, top, right, bottom, paint, ALL_SAVE_FLAG); 483 } 484 485 /** 486 * This behaves the same as save(), but in addition it allocates and 487 * redirects drawing to an offscreen bitmap. 488 * <p class="note"><strong>Note:</strong> this method is very expensive, 489 * incurring more than double rendering cost for contained content. Avoid 490 * using this method, especially if the bounds provided are large, or if 491 * the {@link #CLIP_TO_LAYER_SAVE_FLAG} is omitted from the 492 * {@code saveFlags} parameter. It is recommended to use a 493 * {@link android.view.View#LAYER_TYPE_HARDWARE hardware layer} on a View 494 * to apply an xfermode, color filter, or alpha, as it will perform much 495 * better than this method. 496 * <p> 497 * All drawing calls are directed to a newly allocated offscreen bitmap. 498 * Only when the balancing call to restore() is made, is that offscreen 499 * buffer drawn back to the current target of the Canvas (either the 500 * screen, it's target Bitmap, or the previous layer). 501 * <p> 502 * The {@code alpha} parameter is applied when the offscreen bitmap is 503 * drawn back when restore() is called. 504 * 505 * @deprecated Use {@link #saveLayerAlpha(RectF, int)} instead. 506 * @param bounds The maximum size the offscreen bitmap needs to be 507 * (in local coordinates) 508 * @param alpha The alpha to apply to the offscreen when it is 509 drawn during restore() 510 * @param saveFlags see _SAVE_FLAG constants, generally {@link #ALL_SAVE_FLAG} is recommended 511 * for performance reasons. 512 * @return value to pass to restoreToCount() to balance this call 513 */ 514 public int saveLayerAlpha(@Nullable RectF bounds, int alpha, @Saveflags int saveFlags) { 515 if (bounds == null) { 516 bounds = new RectF(getClipBounds()); 517 } 518 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, alpha, saveFlags); 519 } 520 521 /** 522 * Convenience for {@link #saveLayer(RectF, Paint)} but instead of taking a entire Paint object 523 * it takes only the {@code alpha} parameter. 524 * 525 * @param bounds The maximum size the offscreen bitmap needs to be 526 * (in local coordinates) 527 * @param alpha The alpha to apply to the offscreen when it is 528 drawn during restore() 529 */ 530 public int saveLayerAlpha(@Nullable RectF bounds, int alpha) { 531 return saveLayerAlpha(bounds, alpha, ALL_SAVE_FLAG); 532 } 533 534 /** 535 * Helper for saveLayerAlpha() that takes 4 values instead of a RectF. 536 * 537 * @deprecated Use {@link #saveLayerAlpha(float, float, float, float, int)} instead. 538 */ 539 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, 540 @Saveflags int saveFlags) { 541 alpha = Math.min(255, Math.max(0, alpha)); 542 return nSaveLayerAlpha(mNativeCanvasWrapper, left, top, right, bottom, 543 alpha, saveFlags); 544 } 545 546 /** 547 * Convenience for {@link #saveLayerAlpha(RectF, int)} that takes the four float coordinates of 548 * the bounds rectangle. 549 */ 550 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) { 551 return saveLayerAlpha(left, top, right, bottom, alpha, ALL_SAVE_FLAG); 552 } 553 554 /** 555 * This call balances a previous call to save(), and is used to remove all 556 * modifications to the matrix/clip state since the last save call. It is 557 * an error to call restore() more times than save() was called. 558 */ 559 public void restore() { 560 if (!nRestore(mNativeCanvasWrapper) 561 && (!sCompatibilityRestore || !isHardwareAccelerated())) { 562 throw new IllegalStateException("Underflow in restore - more restores than saves"); 563 } 564 } 565 566 /** 567 * Returns the number of matrix/clip states on the Canvas' private stack. 568 * This will equal # save() calls - # restore() calls. 569 */ 570 public int getSaveCount() { 571 return nGetSaveCount(mNativeCanvasWrapper); 572 } 573 574 /** 575 * Efficient way to pop any calls to save() that happened after the save 576 * count reached saveCount. It is an error for saveCount to be less than 1. 577 * 578 * Example: 579 * int count = canvas.save(); 580 * ... // more calls potentially to save() 581 * canvas.restoreToCount(count); 582 * // now the canvas is back in the same state it was before the initial 583 * // call to save(). 584 * 585 * @param saveCount The save level to restore to. 586 */ 587 public void restoreToCount(int saveCount) { 588 if (saveCount < 1) { 589 if (!sCompatibilityRestore || !isHardwareAccelerated()) { 590 // do nothing and throw without restoring 591 throw new IllegalArgumentException( 592 "Underflow in restoreToCount - more restores than saves"); 593 } 594 // compat behavior - restore as far as possible 595 saveCount = 1; 596 } 597 nRestoreToCount(mNativeCanvasWrapper, saveCount); 598 } 599 600 /** 601 * Preconcat the current matrix with the specified translation 602 * 603 * @param dx The distance to translate in X 604 * @param dy The distance to translate in Y 605 */ 606 public void translate(float dx, float dy) { 607 if (dx == 0.0f && dy == 0.0f) return; 608 nTranslate(mNativeCanvasWrapper, dx, dy); 609 } 610 611 /** 612 * Preconcat the current matrix with the specified scale. 613 * 614 * @param sx The amount to scale in X 615 * @param sy The amount to scale in Y 616 */ 617 public void scale(float sx, float sy) { 618 if (sx == 1.0f && sy == 1.0f) return; 619 nScale(mNativeCanvasWrapper, sx, sy); 620 } 621 622 /** 623 * Preconcat the current matrix with the specified scale. 624 * 625 * @param sx The amount to scale in X 626 * @param sy The amount to scale in Y 627 * @param px The x-coord for the pivot point (unchanged by the scale) 628 * @param py The y-coord for the pivot point (unchanged by the scale) 629 */ 630 public final void scale(float sx, float sy, float px, float py) { 631 if (sx == 1.0f && sy == 1.0f) return; 632 translate(px, py); 633 scale(sx, sy); 634 translate(-px, -py); 635 } 636 637 /** 638 * Preconcat the current matrix with the specified rotation. 639 * 640 * @param degrees The amount to rotate, in degrees 641 */ 642 public void rotate(float degrees) { 643 if (degrees == 0.0f) return; 644 nRotate(mNativeCanvasWrapper, degrees); 645 } 646 647 /** 648 * Preconcat the current matrix with the specified rotation. 649 * 650 * @param degrees The amount to rotate, in degrees 651 * @param px The x-coord for the pivot point (unchanged by the rotation) 652 * @param py The y-coord for the pivot point (unchanged by the rotation) 653 */ 654 public final void rotate(float degrees, float px, float py) { 655 if (degrees == 0.0f) return; 656 translate(px, py); 657 rotate(degrees); 658 translate(-px, -py); 659 } 660 661 /** 662 * Preconcat the current matrix with the specified skew. 663 * 664 * @param sx The amount to skew in X 665 * @param sy The amount to skew in Y 666 */ 667 public void skew(float sx, float sy) { 668 if (sx == 0.0f && sy == 0.0f) return; 669 nSkew(mNativeCanvasWrapper, sx, sy); 670 } 671 672 /** 673 * Preconcat the current matrix with the specified matrix. If the specified 674 * matrix is null, this method does nothing. 675 * 676 * @param matrix The matrix to preconcatenate with the current matrix 677 */ 678 public void concat(@Nullable Matrix matrix) { 679 if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.native_instance); 680 } 681 682 /** 683 * Completely replace the current matrix with the specified matrix. If the 684 * matrix parameter is null, then the current matrix is reset to identity. 685 * 686 * <strong>Note:</strong> it is recommended to use {@link #concat(Matrix)}, 687 * {@link #scale(float, float)}, {@link #translate(float, float)} and 688 * {@link #rotate(float)} instead of this method. 689 * 690 * @param matrix The matrix to replace the current matrix with. If it is 691 * null, set the current matrix to identity. 692 * 693 * @see #concat(Matrix) 694 */ 695 public void setMatrix(@Nullable Matrix matrix) { 696 nSetMatrix(mNativeCanvasWrapper, 697 matrix == null ? 0 : matrix.native_instance); 698 } 699 700 /** 701 * Return, in ctm, the current transformation matrix. This does not alter 702 * the matrix in the canvas, but just returns a copy of it. 703 * 704 * @deprecated {@link #isHardwareAccelerated() Hardware accelerated} canvases may have any 705 * matrix when passed to a View or Drawable, as it is implementation defined where in the 706 * hierarchy such canvases are created. It is recommended in such cases to either draw contents 707 * irrespective of the current matrix, or to track relevant transform state outside of the 708 * canvas. 709 */ 710 @Deprecated 711 public void getMatrix(@NonNull Matrix ctm) { 712 nGetMatrix(mNativeCanvasWrapper, ctm.native_instance); 713 } 714 715 /** 716 * Return a new matrix with a copy of the canvas' current transformation 717 * matrix. 718 * 719 * @deprecated {@link #isHardwareAccelerated() Hardware accelerated} canvases may have any 720 * matrix when passed to a View or Drawable, as it is implementation defined where in the 721 * hierarchy such canvases are created. It is recommended in such cases to either draw contents 722 * irrespective of the current matrix, or to track relevant transform state outside of the 723 * canvas. 724 */ 725 @Deprecated 726 public final @NonNull Matrix getMatrix() { 727 Matrix m = new Matrix(); 728 //noinspection deprecation 729 getMatrix(m); 730 return m; 731 } 732 733 /** 734 * Modify the current clip with the specified rectangle. 735 * 736 * @param rect The rect to intersect with the current clip 737 * @param op How the clip is modified 738 * @return true if the resulting clip is non-empty 739 */ 740 public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) { 741 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 742 op.nativeInt); 743 } 744 745 /** 746 * Modify the current clip with the specified rectangle, which is 747 * expressed in local coordinates. 748 * 749 * @param rect The rectangle to intersect with the current clip. 750 * @param op How the clip is modified 751 * @return true if the resulting clip is non-empty 752 */ 753 public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) { 754 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 755 op.nativeInt); 756 } 757 758 /** 759 * Intersect the current clip with the specified rectangle, which is 760 * expressed in local coordinates. 761 * 762 * @param rect The rectangle to intersect with the current clip. 763 * @return true if the resulting clip is non-empty 764 */ 765 public boolean clipRect(@NonNull RectF rect) { 766 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 767 Region.Op.INTERSECT.nativeInt); 768 } 769 770 /** 771 * Intersect the current clip with the specified rectangle, which is 772 * expressed in local coordinates. 773 * 774 * @param rect The rectangle to intersect with the current clip. 775 * @return true if the resulting clip is non-empty 776 */ 777 public boolean clipRect(@NonNull Rect rect) { 778 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 779 Region.Op.INTERSECT.nativeInt); 780 } 781 782 /** 783 * Modify the current clip with the specified rectangle, which is 784 * expressed in local coordinates. 785 * 786 * @param left The left side of the rectangle to intersect with the 787 * current clip 788 * @param top The top of the rectangle to intersect with the current 789 * clip 790 * @param right The right side of the rectangle to intersect with the 791 * current clip 792 * @param bottom The bottom of the rectangle to intersect with the current 793 * clip 794 * @param op How the clip is modified 795 * @return true if the resulting clip is non-empty 796 */ 797 public boolean clipRect(float left, float top, float right, float bottom, 798 @NonNull Region.Op op) { 799 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt); 800 } 801 802 /** 803 * Intersect the current clip with the specified rectangle, which is 804 * expressed in local coordinates. 805 * 806 * @param left The left side of the rectangle to intersect with the 807 * current clip 808 * @param top The top of the rectangle to intersect with the current clip 809 * @param right The right side of the rectangle to intersect with the 810 * current clip 811 * @param bottom The bottom of the rectangle to intersect with the current 812 * clip 813 * @return true if the resulting clip is non-empty 814 */ 815 public boolean clipRect(float left, float top, float right, float bottom) { 816 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, 817 Region.Op.INTERSECT.nativeInt); 818 } 819 820 /** 821 * Intersect the current clip with the specified rectangle, which is 822 * expressed in local coordinates. 823 * 824 * @param left The left side of the rectangle to intersect with the 825 * current clip 826 * @param top The top of the rectangle to intersect with the current clip 827 * @param right The right side of the rectangle to intersect with the 828 * current clip 829 * @param bottom The bottom of the rectangle to intersect with the current 830 * clip 831 * @return true if the resulting clip is non-empty 832 */ 833 public boolean clipRect(int left, int top, int right, int bottom) { 834 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, 835 Region.Op.INTERSECT.nativeInt); 836 } 837 838 /** 839 * Modify the current clip with the specified path. 840 * 841 * @param path The path to operate on the current clip 842 * @param op How the clip is modified 843 * @return true if the resulting is non-empty 844 */ 845 public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) { 846 return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt); 847 } 848 849 /** 850 * Intersect the current clip with the specified path. 851 * 852 * @param path The path to intersect with the current clip 853 * @return true if the resulting is non-empty 854 */ 855 public boolean clipPath(@NonNull Path path) { 856 return clipPath(path, Region.Op.INTERSECT); 857 } 858 859 /** 860 * Modify the current clip with the specified region. Note that unlike 861 * clipRect() and clipPath() which transform their arguments by the 862 * current matrix, clipRegion() assumes its argument is already in the 863 * coordinate system of the current layer's bitmap, and so not 864 * transformation is performed. 865 * 866 * @param region The region to operate on the current clip, based on op 867 * @param op How the clip is modified 868 * @return true if the resulting is non-empty 869 * 870 * @removed 871 * @deprecated Unlike all other clip calls this API does not respect the 872 * current matrix. Use {@link #clipRect(Rect)} as an alternative. 873 */ 874 @Deprecated 875 public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) { 876 return false; 877 } 878 879 /** 880 * Intersect the current clip with the specified region. Note that unlike 881 * clipRect() and clipPath() which transform their arguments by the 882 * current matrix, clipRegion() assumes its argument is already in the 883 * coordinate system of the current layer's bitmap, and so not 884 * transformation is performed. 885 * 886 * @param region The region to operate on the current clip, based on op 887 * @return true if the resulting is non-empty 888 * 889 * @removed 890 * @deprecated Unlike all other clip calls this API does not respect the 891 * current matrix. Use {@link #clipRect(Rect)} as an alternative. 892 */ 893 @Deprecated 894 public boolean clipRegion(@NonNull Region region) { 895 return false; 896 } 897 898 public @Nullable DrawFilter getDrawFilter() { 899 return mDrawFilter; 900 } 901 902 public void setDrawFilter(@Nullable DrawFilter filter) { 903 long nativeFilter = 0; 904 if (filter != null) { 905 nativeFilter = filter.mNativeInt; 906 } 907 mDrawFilter = filter; 908 nSetDrawFilter(mNativeCanvasWrapper, nativeFilter); 909 } 910 911 /** 912 * Constant values used as parameters to {@code quickReject()} calls. These values 913 * specify how much space around the shape should be accounted for, depending on whether 914 * the shaped area is antialiased or not. 915 * 916 * @see #quickReject(float, float, float, float, EdgeType) 917 * @see #quickReject(Path, EdgeType) 918 * @see #quickReject(RectF, EdgeType) 919 */ 920 public enum EdgeType { 921 922 /** 923 * Black-and-White: Treat edges by just rounding to nearest pixel boundary 924 */ 925 BW(0), //!< treat edges by just rounding to nearest pixel boundary 926 927 /** 928 * Antialiased: Treat edges by rounding-out, since they may be antialiased 929 */ 930 AA(1); 931 932 EdgeType(int nativeInt) { 933 this.nativeInt = nativeInt; 934 } 935 936 /** 937 * @hide 938 */ 939 public final int nativeInt; 940 } 941 942 /** 943 * Return true if the specified rectangle, after being transformed by the 944 * current matrix, would lie completely outside of the current clip. Call 945 * this to check if an area you intend to draw into is clipped out (and 946 * therefore you can skip making the draw calls). 947 * 948 * @param rect the rect to compare with the current clip 949 * @param type {@link Canvas.EdgeType#AA} if the path should be considered antialiased, 950 * since that means it may affect a larger area (more pixels) than 951 * non-antialiased ({@link Canvas.EdgeType#BW}). 952 * @return true if the rect (transformed by the canvas' matrix) 953 * does not intersect with the canvas' clip 954 */ 955 public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) { 956 return nQuickReject(mNativeCanvasWrapper, 957 rect.left, rect.top, rect.right, rect.bottom); 958 } 959 960 /** 961 * Return true if the specified path, after being transformed by the 962 * current matrix, would lie completely outside of the current clip. Call 963 * this to check if an area you intend to draw into is clipped out (and 964 * therefore you can skip making the draw calls). Note: for speed it may 965 * return false even if the path itself might not intersect the clip 966 * (i.e. the bounds of the path intersects, but the path does not). 967 * 968 * @param path The path to compare with the current clip 969 * @param type {@link Canvas.EdgeType#AA} if the path should be considered antialiased, 970 * since that means it may affect a larger area (more pixels) than 971 * non-antialiased ({@link Canvas.EdgeType#BW}). 972 * @return true if the path (transformed by the canvas' matrix) 973 * does not intersect with the canvas' clip 974 */ 975 public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) { 976 return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI()); 977 } 978 979 /** 980 * Return true if the specified rectangle, after being transformed by the 981 * current matrix, would lie completely outside of the current clip. Call 982 * this to check if an area you intend to draw into is clipped out (and 983 * therefore you can skip making the draw calls). 984 * 985 * @param left The left side of the rectangle to compare with the 986 * current clip 987 * @param top The top of the rectangle to compare with the current 988 * clip 989 * @param right The right side of the rectangle to compare with the 990 * current clip 991 * @param bottom The bottom of the rectangle to compare with the 992 * current clip 993 * @param type {@link Canvas.EdgeType#AA} if the path should be considered antialiased, 994 * since that means it may affect a larger area (more pixels) than 995 * non-antialiased ({@link Canvas.EdgeType#BW}). 996 * @return true if the rect (transformed by the canvas' matrix) 997 * does not intersect with the canvas' clip 998 */ 999 public boolean quickReject(float left, float top, float right, float bottom, 1000 @NonNull EdgeType type) { 1001 return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom); 1002 } 1003 1004 /** 1005 * Return the bounds of the current clip (in local coordinates) in the 1006 * bounds parameter, and return true if it is non-empty. This can be useful 1007 * in a way similar to quickReject, in that it tells you that drawing 1008 * outside of these bounds will be clipped out. 1009 * 1010 * @param bounds Return the clip bounds here. If it is null, ignore it but 1011 * still return true if the current clip is non-empty. 1012 * @return true if the current clip is non-empty. 1013 */ 1014 public boolean getClipBounds(@Nullable Rect bounds) { 1015 return nGetClipBounds(mNativeCanvasWrapper, bounds); 1016 } 1017 1018 /** 1019 * Retrieve the bounds of the current clip (in local coordinates). 1020 * 1021 * @return the clip bounds, or [0, 0, 0, 0] if the clip is empty. 1022 */ 1023 public final @NonNull Rect getClipBounds() { 1024 Rect r = new Rect(); 1025 getClipBounds(r); 1026 return r; 1027 } 1028 1029 /** 1030 * Save the canvas state, draw the picture, and restore the canvas state. 1031 * This differs from picture.draw(canvas), which does not perform any 1032 * save/restore. 1033 * 1034 * <p> 1035 * <strong>Note:</strong> This forces the picture to internally call 1036 * {@link Picture#endRecording} in order to prepare for playback. 1037 * 1038 * @param picture The picture to be drawn 1039 */ 1040 public void drawPicture(@NonNull Picture picture) { 1041 picture.endRecording(); 1042 int restoreCount = save(); 1043 picture.draw(this); 1044 restoreToCount(restoreCount); 1045 } 1046 1047 /** 1048 * Draw the picture, stretched to fit into the dst rectangle. 1049 */ 1050 public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) { 1051 save(); 1052 translate(dst.left, dst.top); 1053 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1054 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight()); 1055 } 1056 drawPicture(picture); 1057 restore(); 1058 } 1059 1060 /** 1061 * Draw the picture, stretched to fit into the dst rectangle. 1062 */ 1063 public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) { 1064 save(); 1065 translate(dst.left, dst.top); 1066 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1067 scale((float) dst.width() / picture.getWidth(), 1068 (float) dst.height() / picture.getHeight()); 1069 } 1070 drawPicture(picture); 1071 restore(); 1072 } 1073 1074 public enum VertexMode { 1075 TRIANGLES(0), 1076 TRIANGLE_STRIP(1), 1077 TRIANGLE_FAN(2); 1078 1079 VertexMode(int nativeInt) { 1080 this.nativeInt = nativeInt; 1081 } 1082 1083 /** 1084 * @hide 1085 */ 1086 public final int nativeInt; 1087 } 1088 1089 /** 1090 * Releases the resources associated with this canvas. 1091 * 1092 * @hide 1093 */ 1094 public void release() { 1095 mNativeCanvasWrapper = 0; 1096 if (mFinalizer != null) { 1097 mFinalizer.run(); 1098 mFinalizer = null; 1099 } 1100 } 1101 1102 /** 1103 * Free up as much memory as possible from private caches (e.g. fonts, images) 1104 * 1105 * @hide 1106 */ 1107 public static void freeCaches() { 1108 nFreeCaches(); 1109 } 1110 1111 /** 1112 * Free up text layout caches 1113 * 1114 * @hide 1115 */ 1116 public static void freeTextLayoutCaches() { 1117 nFreeTextLayoutCaches(); 1118 } 1119 1120 private static native void nFreeCaches(); 1121 private static native void nFreeTextLayoutCaches(); 1122 private static native long nInitRaster(Bitmap bitmap); 1123 private static native long nGetNativeFinalizer(); 1124 1125 // ---------------- @FastNative ------------------- 1126 1127 @FastNative 1128 private static native void nSetBitmap(long canvasHandle, Bitmap bitmap); 1129 1130 @FastNative 1131 private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds); 1132 1133 // ---------------- @CriticalNative ------------------- 1134 1135 @CriticalNative 1136 private static native boolean nIsOpaque(long canvasHandle); 1137 @CriticalNative 1138 private static native void nSetHighContrastText(long renderer, boolean highContrastText); 1139 @CriticalNative 1140 private static native int nGetWidth(long canvasHandle); 1141 @CriticalNative 1142 private static native int nGetHeight(long canvasHandle); 1143 1144 @CriticalNative 1145 private static native int nSave(long canvasHandle, int saveFlags); 1146 @CriticalNative 1147 private static native int nSaveLayer(long nativeCanvas, float l, float t, float r, float b, 1148 long nativePaint, int layerFlags); 1149 @CriticalNative 1150 private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b, 1151 int alpha, int layerFlags); 1152 @CriticalNative 1153 private static native boolean nRestore(long canvasHandle); 1154 @CriticalNative 1155 private static native void nRestoreToCount(long canvasHandle, int saveCount); 1156 @CriticalNative 1157 private static native int nGetSaveCount(long canvasHandle); 1158 1159 @CriticalNative 1160 private static native void nTranslate(long canvasHandle, float dx, float dy); 1161 @CriticalNative 1162 private static native void nScale(long canvasHandle, float sx, float sy); 1163 @CriticalNative 1164 private static native void nRotate(long canvasHandle, float degrees); 1165 @CriticalNative 1166 private static native void nSkew(long canvasHandle, float sx, float sy); 1167 @CriticalNative 1168 private static native void nConcat(long nativeCanvas, long nativeMatrix); 1169 @CriticalNative 1170 private static native void nSetMatrix(long nativeCanvas, long nativeMatrix); 1171 @CriticalNative 1172 private static native boolean nClipRect(long nativeCanvas, 1173 float left, float top, float right, float bottom, int regionOp); 1174 @CriticalNative 1175 private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp); 1176 @CriticalNative 1177 private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter); 1178 @CriticalNative 1179 private static native void nGetMatrix(long nativeCanvas, long nativeMatrix); 1180 @CriticalNative 1181 private static native boolean nQuickReject(long nativeCanvas, long nativePath); 1182 @CriticalNative 1183 private static native boolean nQuickReject(long nativeCanvas, float left, float top, 1184 float right, float bottom); 1185 1186 1187 // ---------------- Draw Methods ------------------- 1188 1189 /** 1190 * <p> 1191 * Draw the specified arc, which will be scaled to fit inside the specified oval. 1192 * </p> 1193 * <p> 1194 * If the start angle is negative or >= 360, the start angle is treated as start angle modulo 1195 * 360. 1196 * </p> 1197 * <p> 1198 * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs 1199 * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is 1200 * negative, the sweep angle is treated as sweep angle modulo 360 1201 * </p> 1202 * <p> 1203 * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0 1204 * degrees (3 o'clock on a watch.) 1205 * </p> 1206 * 1207 * @param oval The bounds of oval used to define the shape and size of the arc 1208 * @param startAngle Starting angle (in degrees) where the arc begins 1209 * @param sweepAngle Sweep angle (in degrees) measured clockwise 1210 * @param useCenter If true, include the center of the oval in the arc, and close it if it is 1211 * being stroked. This will draw a wedge 1212 * @param paint The paint used to draw the arc 1213 */ 1214 public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, 1215 @NonNull Paint paint) { 1216 super.drawArc(oval, startAngle, sweepAngle, useCenter, paint); 1217 } 1218 1219 /** 1220 * <p> 1221 * Draw the specified arc, which will be scaled to fit inside the specified oval. 1222 * </p> 1223 * <p> 1224 * If the start angle is negative or >= 360, the start angle is treated as start angle modulo 1225 * 360. 1226 * </p> 1227 * <p> 1228 * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs 1229 * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is 1230 * negative, the sweep angle is treated as sweep angle modulo 360 1231 * </p> 1232 * <p> 1233 * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0 1234 * degrees (3 o'clock on a watch.) 1235 * </p> 1236 * 1237 * @param startAngle Starting angle (in degrees) where the arc begins 1238 * @param sweepAngle Sweep angle (in degrees) measured clockwise 1239 * @param useCenter If true, include the center of the oval in the arc, and close it if it is 1240 * being stroked. This will draw a wedge 1241 * @param paint The paint used to draw the arc 1242 */ 1243 public void drawArc(float left, float top, float right, float bottom, float startAngle, 1244 float sweepAngle, boolean useCenter, @NonNull Paint paint) { 1245 super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); 1246 } 1247 1248 /** 1249 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified ARGB 1250 * color, using srcover porterduff mode. 1251 * 1252 * @param a alpha component (0..255) of the color to draw onto the canvas 1253 * @param r red component (0..255) of the color to draw onto the canvas 1254 * @param g green component (0..255) of the color to draw onto the canvas 1255 * @param b blue component (0..255) of the color to draw onto the canvas 1256 */ 1257 public void drawARGB(int a, int r, int g, int b) { 1258 super.drawARGB(a, r, g, b); 1259 } 1260 1261 /** 1262 * Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint, 1263 * transformed by the current matrix. 1264 * <p> 1265 * Note: if the paint contains a maskfilter that generates a mask which extends beyond the 1266 * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it 1267 * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be 1268 * the edge color replicated. 1269 * <p> 1270 * If the bitmap and canvas have different densities, this function will take care of 1271 * automatically scaling the bitmap to draw at the same density as the canvas. 1272 * 1273 * @param bitmap The bitmap to be drawn 1274 * @param left The position of the left side of the bitmap being drawn 1275 * @param top The position of the top side of the bitmap being drawn 1276 * @param paint The paint used to draw the bitmap (may be null) 1277 */ 1278 public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { 1279 super.drawBitmap(bitmap, left, top, paint); 1280 } 1281 1282 /** 1283 * Draw the specified bitmap, scaling/translating automatically to fill the destination 1284 * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to 1285 * draw. 1286 * <p> 1287 * Note: if the paint contains a maskfilter that generates a mask which extends beyond the 1288 * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it 1289 * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be 1290 * the edge color replicated. 1291 * <p> 1292 * This function <em>ignores the density associated with the bitmap</em>. This is because the 1293 * source and destination rectangle coordinate spaces are in their respective densities, so must 1294 * already have the appropriate scaling factor applied. 1295 * 1296 * @param bitmap The bitmap to be drawn 1297 * @param src May be null. The subset of the bitmap to be drawn 1298 * @param dst The rectangle that the bitmap will be scaled/translated to fit into 1299 * @param paint May be null. The paint used to draw the bitmap 1300 */ 1301 public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, 1302 @Nullable Paint paint) { 1303 super.drawBitmap(bitmap, src, dst, paint); 1304 } 1305 1306 /** 1307 * Draw the specified bitmap, scaling/translating automatically to fill the destination 1308 * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to 1309 * draw. 1310 * <p> 1311 * Note: if the paint contains a maskfilter that generates a mask which extends beyond the 1312 * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it 1313 * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be 1314 * the edge color replicated. 1315 * <p> 1316 * This function <em>ignores the density associated with the bitmap</em>. This is because the 1317 * source and destination rectangle coordinate spaces are in their respective densities, so must 1318 * already have the appropriate scaling factor applied. 1319 * 1320 * @param bitmap The bitmap to be drawn 1321 * @param src May be null. The subset of the bitmap to be drawn 1322 * @param dst The rectangle that the bitmap will be scaled/translated to fit into 1323 * @param paint May be null. The paint used to draw the bitmap 1324 */ 1325 public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, 1326 @Nullable Paint paint) { 1327 super.drawBitmap(bitmap, src, dst, paint); 1328 } 1329 1330 /** 1331 * Treat the specified array of colors as a bitmap, and draw it. This gives the same result as 1332 * first creating a bitmap from the array, and then drawing it, but this method avoids 1333 * explicitly creating a bitmap object which can be more efficient if the colors are changing 1334 * often. 1335 * 1336 * @param colors Array of colors representing the pixels of the bitmap 1337 * @param offset Offset into the array of colors for the first pixel 1338 * @param stride The number of colors in the array between rows (must be >= width or <= -width). 1339 * @param x The X coordinate for where to draw the bitmap 1340 * @param y The Y coordinate for where to draw the bitmap 1341 * @param width The width of the bitmap 1342 * @param height The height of the bitmap 1343 * @param hasAlpha True if the alpha channel of the colors contains valid values. If false, the 1344 * alpha byte is ignored (assumed to be 0xFF for every pixel). 1345 * @param paint May be null. The paint used to draw the bitmap 1346 * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas 1347 * requires an internal copy of color buffer contents every time this method is 1348 * called. Using a Bitmap avoids this copy, and allows the application to more 1349 * explicitly control the lifetime and copies of pixel data. 1350 */ 1351 @Deprecated 1352 public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y, 1353 int width, int height, boolean hasAlpha, @Nullable Paint paint) { 1354 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 1355 } 1356 1357 /** 1358 * Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y 1359 * 1360 * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas 1361 * requires an internal copy of color buffer contents every time this method is 1362 * called. Using a Bitmap avoids this copy, and allows the application to more 1363 * explicitly control the lifetime and copies of pixel data. 1364 */ 1365 @Deprecated 1366 public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y, 1367 int width, int height, boolean hasAlpha, @Nullable Paint paint) { 1368 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 1369 } 1370 1371 /** 1372 * Draw the bitmap using the specified matrix. 1373 * 1374 * @param bitmap The bitmap to draw 1375 * @param matrix The matrix used to transform the bitmap when it is drawn 1376 * @param paint May be null. The paint used to draw the bitmap 1377 */ 1378 public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { 1379 super.drawBitmap(bitmap, matrix, paint); 1380 } 1381 1382 /** 1383 * Draw the bitmap through the mesh, where mesh vertices are evenly distributed across the 1384 * bitmap. There are meshWidth+1 vertices across, and meshHeight+1 vertices down. The verts 1385 * array is accessed in row-major order, so that the first meshWidth+1 vertices are distributed 1386 * across the top of the bitmap from left to right. A more general version of this method is 1387 * drawVertices(). 1388 * 1389 * @param bitmap The bitmap to draw using the mesh 1390 * @param meshWidth The number of columns in the mesh. Nothing is drawn if this is 0 1391 * @param meshHeight The number of rows in the mesh. Nothing is drawn if this is 0 1392 * @param verts Array of x,y pairs, specifying where the mesh should be drawn. There must be at 1393 * least (meshWidth+1) * (meshHeight+1) * 2 + vertOffset values in the array 1394 * @param vertOffset Number of verts elements to skip before drawing 1395 * @param colors May be null. Specifies a color at each vertex, which is interpolated across the 1396 * cell, and whose values are multiplied by the corresponding bitmap colors. If not 1397 * null, there must be at least (meshWidth+1) * (meshHeight+1) + colorOffset values 1398 * in the array. 1399 * @param colorOffset Number of color elements to skip before drawing 1400 * @param paint May be null. The paint used to draw the bitmap 1401 */ 1402 public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight, 1403 @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset, 1404 @Nullable Paint paint) { 1405 super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, 1406 paint); 1407 } 1408 1409 /** 1410 * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be 1411 * drawn. The circle will be filled or framed based on the Style in the paint. 1412 * 1413 * @param cx The x-coordinate of the center of the cirle to be drawn 1414 * @param cy The y-coordinate of the center of the cirle to be drawn 1415 * @param radius The radius of the cirle to be drawn 1416 * @param paint The paint used to draw the circle 1417 */ 1418 public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) { 1419 super.drawCircle(cx, cy, radius, paint); 1420 } 1421 1422 /** 1423 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color, 1424 * using srcover porterduff mode. 1425 * 1426 * @param color the color to draw onto the canvas 1427 */ 1428 public void drawColor(@ColorInt int color) { 1429 super.drawColor(color); 1430 } 1431 1432 /** 1433 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and 1434 * porter-duff xfermode. 1435 * 1436 * @param color the color to draw with 1437 * @param mode the porter-duff mode to apply to the color 1438 */ 1439 public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) { 1440 super.drawColor(color, mode); 1441 } 1442 1443 /** 1444 * Draw a line segment with the specified start and stop x,y coordinates, using the specified 1445 * paint. 1446 * <p> 1447 * Note that since a line is always "framed", the Style is ignored in the paint. 1448 * </p> 1449 * <p> 1450 * Degenerate lines (length is 0) will not be drawn. 1451 * </p> 1452 * 1453 * @param startX The x-coordinate of the start point of the line 1454 * @param startY The y-coordinate of the start point of the line 1455 * @param paint The paint used to draw the line 1456 */ 1457 public void drawLine(float startX, float startY, float stopX, float stopY, 1458 @NonNull Paint paint) { 1459 super.drawLine(startX, startY, stopX, stopY, paint); 1460 } 1461 1462 /** 1463 * Draw a series of lines. Each line is taken from 4 consecutive values in the pts array. Thus 1464 * to draw 1 line, the array must contain at least 4 values. This is logically the same as 1465 * drawing the array as follows: drawLine(pts[0], pts[1], pts[2], pts[3]) followed by 1466 * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on. 1467 * 1468 * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...] 1469 * @param offset Number of values in the array to skip before drawing. 1470 * @param count The number of values in the array to process, after skipping "offset" of them. 1471 * Since each line uses 4 values, the number of "lines" that are drawn is really 1472 * (count >> 2). 1473 * @param paint The paint used to draw the points 1474 */ 1475 public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count, 1476 @NonNull Paint paint) { 1477 super.drawLines(pts, offset, count, paint); 1478 } 1479 1480 public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) { 1481 super.drawLines(pts, paint); 1482 } 1483 1484 /** 1485 * Draw the specified oval using the specified paint. The oval will be filled or framed based on 1486 * the Style in the paint. 1487 * 1488 * @param oval The rectangle bounds of the oval to be drawn 1489 */ 1490 public void drawOval(@NonNull RectF oval, @NonNull Paint paint) { 1491 super.drawOval(oval, paint); 1492 } 1493 1494 /** 1495 * Draw the specified oval using the specified paint. The oval will be filled or framed based on 1496 * the Style in the paint. 1497 */ 1498 public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) { 1499 super.drawOval(left, top, right, bottom, paint); 1500 } 1501 1502 /** 1503 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint. 1504 * This is equivalent (but faster) to drawing an infinitely large rectangle with the specified 1505 * paint. 1506 * 1507 * @param paint The paint used to draw onto the canvas 1508 */ 1509 public void drawPaint(@NonNull Paint paint) { 1510 super.drawPaint(paint); 1511 } 1512 1513 /** 1514 * Draws the specified bitmap as an N-patch (most often, a 9-patches.) 1515 * 1516 * @param patch The ninepatch object to render 1517 * @param dst The destination rectangle. 1518 * @param paint The paint to draw the bitmap with. may be null 1519 * @hide 1520 */ 1521 public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) { 1522 super.drawPatch(patch, dst, paint); 1523 } 1524 1525 /** 1526 * Draws the specified bitmap as an N-patch (most often, a 9-patches.) 1527 * 1528 * @param patch The ninepatch object to render 1529 * @param dst The destination rectangle. 1530 * @param paint The paint to draw the bitmap with. may be null 1531 * @hide 1532 */ 1533 public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) { 1534 super.drawPatch(patch, dst, paint); 1535 } 1536 1537 /** 1538 * Draw the specified path using the specified paint. The path will be filled or framed based on 1539 * the Style in the paint. 1540 * 1541 * @param path The path to be drawn 1542 * @param paint The paint used to draw the path 1543 */ 1544 public void drawPath(@NonNull Path path, @NonNull Paint paint) { 1545 super.drawPath(path, paint); 1546 } 1547 1548 /** 1549 * Helper for drawPoints() for drawing a single point. 1550 */ 1551 public void drawPoint(float x, float y, @NonNull Paint paint) { 1552 super.drawPoint(x, y, paint); 1553 } 1554 1555 /** 1556 * Draw a series of points. Each point is centered at the coordinate specified by pts[], and its 1557 * diameter is specified by the paint's stroke width (as transformed by the canvas' CTM), with 1558 * special treatment for a stroke width of 0, which always draws exactly 1 pixel (or at most 4 1559 * if antialiasing is enabled). The shape of the point is controlled by the paint's Cap type. 1560 * The shape is a square, unless the cap type is Round, in which case the shape is a circle. 1561 * 1562 * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...] 1563 * @param offset Number of values to skip before starting to draw. 1564 * @param count The number of values to process, after skipping offset of them. Since one point 1565 * uses two values, the number of "points" that are drawn is really (count >> 1). 1566 * @param paint The paint used to draw the points 1567 */ 1568 public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count, 1569 @NonNull Paint paint) { 1570 super.drawPoints(pts, offset, count, paint); 1571 } 1572 1573 /** 1574 * Helper for drawPoints() that assumes you want to draw the entire array 1575 */ 1576 public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) { 1577 super.drawPoints(pts, paint); 1578 } 1579 1580 /** 1581 * Draw the text in the array, with each character's origin specified by the pos array. 1582 * 1583 * @param text The text to be drawn 1584 * @param index The index of the first character to draw 1585 * @param count The number of characters to draw, starting from index. 1586 * @param pos Array of [x,y] positions, used to position each character 1587 * @param paint The paint used for the text (e.g. color, size, style) 1588 * @deprecated This method does not support glyph composition and decomposition and should 1589 * therefore not be used to render complex scripts. It also doesn't handle 1590 * supplementary characters (eg emoji). 1591 */ 1592 @Deprecated 1593 public void drawPosText(@NonNull char[] text, int index, int count, 1594 @NonNull @Size(multiple = 2) float[] pos, 1595 @NonNull Paint paint) { 1596 super.drawPosText(text, index, count, pos, paint); 1597 } 1598 1599 /** 1600 * Draw the text in the array, with each character's origin specified by the pos array. 1601 * 1602 * @param text The text to be drawn 1603 * @param pos Array of [x,y] positions, used to position each character 1604 * @param paint The paint used for the text (e.g. color, size, style) 1605 * @deprecated This method does not support glyph composition and decomposition and should 1606 * therefore not be used to render complex scripts. It also doesn't handle 1607 * supplementary characters (eg emoji). 1608 */ 1609 @Deprecated 1610 public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos, 1611 @NonNull Paint paint) { 1612 super.drawPosText(text, pos, paint); 1613 } 1614 1615 /** 1616 * Draw the specified Rect using the specified paint. The rectangle will be filled or framed 1617 * based on the Style in the paint. 1618 * 1619 * @param rect The rect to be drawn 1620 * @param paint The paint used to draw the rect 1621 */ 1622 public void drawRect(@NonNull RectF rect, @NonNull Paint paint) { 1623 super.drawRect(rect, paint); 1624 } 1625 1626 /** 1627 * Draw the specified Rect using the specified Paint. The rectangle will be filled or framed 1628 * based on the Style in the paint. 1629 * 1630 * @param r The rectangle to be drawn. 1631 * @param paint The paint used to draw the rectangle 1632 */ 1633 public void drawRect(@NonNull Rect r, @NonNull Paint paint) { 1634 super.drawRect(r, paint); 1635 } 1636 1637 /** 1638 * Draw the specified Rect using the specified paint. The rectangle will be filled or framed 1639 * based on the Style in the paint. 1640 * 1641 * @param left The left side of the rectangle to be drawn 1642 * @param top The top side of the rectangle to be drawn 1643 * @param right The right side of the rectangle to be drawn 1644 * @param bottom The bottom side of the rectangle to be drawn 1645 * @param paint The paint used to draw the rect 1646 */ 1647 public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) { 1648 super.drawRect(left, top, right, bottom, paint); 1649 } 1650 1651 /** 1652 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified RGB color, 1653 * using srcover porterduff mode. 1654 * 1655 * @param r red component (0..255) of the color to draw onto the canvas 1656 * @param g green component (0..255) of the color to draw onto the canvas 1657 * @param b blue component (0..255) of the color to draw onto the canvas 1658 */ 1659 public void drawRGB(int r, int g, int b) { 1660 super.drawRGB(r, g, b); 1661 } 1662 1663 /** 1664 * Draw the specified round-rect using the specified paint. The roundrect will be filled or 1665 * framed based on the Style in the paint. 1666 * 1667 * @param rect The rectangular bounds of the roundRect to be drawn 1668 * @param rx The x-radius of the oval used to round the corners 1669 * @param ry The y-radius of the oval used to round the corners 1670 * @param paint The paint used to draw the roundRect 1671 */ 1672 public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) { 1673 super.drawRoundRect(rect, rx, ry, paint); 1674 } 1675 1676 /** 1677 * Draw the specified round-rect using the specified paint. The roundrect will be filled or 1678 * framed based on the Style in the paint. 1679 * 1680 * @param rx The x-radius of the oval used to round the corners 1681 * @param ry The y-radius of the oval used to round the corners 1682 * @param paint The paint used to draw the roundRect 1683 */ 1684 public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, 1685 @NonNull Paint paint) { 1686 super.drawRoundRect(left, top, right, bottom, rx, ry, paint); 1687 } 1688 1689 /** 1690 * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted 1691 * based on the Align setting in the paint. 1692 * 1693 * @param text The text to be drawn 1694 * @param x The x-coordinate of the origin of the text being drawn 1695 * @param y The y-coordinate of the baseline of the text being drawn 1696 * @param paint The paint used for the text (e.g. color, size, style) 1697 */ 1698 public void drawText(@NonNull char[] text, int index, int count, float x, float y, 1699 @NonNull Paint paint) { 1700 super.drawText(text, index, count, x, y, paint); 1701 } 1702 1703 /** 1704 * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted 1705 * based on the Align setting in the paint. 1706 * 1707 * @param text The text to be drawn 1708 * @param x The x-coordinate of the origin of the text being drawn 1709 * @param y The y-coordinate of the baseline of the text being drawn 1710 * @param paint The paint used for the text (e.g. color, size, style) 1711 */ 1712 public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) { 1713 super.drawText(text, x, y, paint); 1714 } 1715 1716 /** 1717 * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted 1718 * based on the Align setting in the paint. 1719 * 1720 * @param text The text to be drawn 1721 * @param start The index of the first character in text to draw 1722 * @param end (end - 1) is the index of the last character in text to draw 1723 * @param x The x-coordinate of the origin of the text being drawn 1724 * @param y The y-coordinate of the baseline of the text being drawn 1725 * @param paint The paint used for the text (e.g. color, size, style) 1726 */ 1727 public void drawText(@NonNull String text, int start, int end, float x, float y, 1728 @NonNull Paint paint) { 1729 super.drawText(text, start, end, x, y, paint); 1730 } 1731 1732 /** 1733 * Draw the specified range of text, specified by start/end, with its origin at (x,y), in the 1734 * specified Paint. The origin is interpreted based on the Align setting in the Paint. 1735 * 1736 * @param text The text to be drawn 1737 * @param start The index of the first character in text to draw 1738 * @param end (end - 1) is the index of the last character in text to draw 1739 * @param x The x-coordinate of origin for where to draw the text 1740 * @param y The y-coordinate of origin for where to draw the text 1741 * @param paint The paint used for the text (e.g. color, size, style) 1742 */ 1743 public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, 1744 @NonNull Paint paint) { 1745 super.drawText(text, start, end, x, y, paint); 1746 } 1747 1748 /** 1749 * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The 1750 * paint's Align setting determins where along the path to start the text. 1751 * 1752 * @param text The text to be drawn 1753 * @param path The path the text should follow for its baseline 1754 * @param hOffset The distance along the path to add to the text's starting position 1755 * @param vOffset The distance above(-) or below(+) the path to position the text 1756 * @param paint The paint used for the text (e.g. color, size, style) 1757 */ 1758 public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, 1759 float hOffset, float vOffset, @NonNull Paint paint) { 1760 super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint); 1761 } 1762 1763 /** 1764 * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The 1765 * paint's Align setting determins where along the path to start the text. 1766 * 1767 * @param text The text to be drawn 1768 * @param path The path the text should follow for its baseline 1769 * @param hOffset The distance along the path to add to the text's starting position 1770 * @param vOffset The distance above(-) or below(+) the path to position the text 1771 * @param paint The paint used for the text (e.g. color, size, style) 1772 */ 1773 public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, 1774 float vOffset, @NonNull Paint paint) { 1775 super.drawTextOnPath(text, path, hOffset, vOffset, paint); 1776 } 1777 1778 /** 1779 * Draw a run of text, all in a single direction, with optional context for complex text 1780 * shaping. 1781 * <p> 1782 * See {@link #drawTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)} for 1783 * more details. This method uses a character array rather than CharSequence to represent the 1784 * string. Also, to be consistent with the pattern established in {@link #drawText}, in this 1785 * method {@code count} and {@code contextCount} are used rather than offsets of the end 1786 * position; {@code count = end - start, contextCount = contextEnd - 1787 * contextStart}. 1788 * 1789 * @param text the text to render 1790 * @param index the start of the text to render 1791 * @param count the count of chars to render 1792 * @param contextIndex the start of the context for shaping. Must be no greater than index. 1793 * @param contextCount the number of characters in the context for shaping. contexIndex + 1794 * contextCount must be no less than index + count. 1795 * @param x the x position at which to draw the text 1796 * @param y the y position at which to draw the text 1797 * @param isRtl whether the run is in RTL direction 1798 * @param paint the paint 1799 */ 1800 public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, 1801 int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) { 1802 super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint); 1803 } 1804 1805 /** 1806 * Draw a run of text, all in a single direction, with optional context for complex text 1807 * shaping. 1808 * <p> 1809 * The run of text includes the characters from {@code start} to {@code end} in the text. In 1810 * addition, the range {@code contextStart} to {@code contextEnd} is used as context for the 1811 * purpose of complex text shaping, such as Arabic text potentially shaped differently based on 1812 * the text next to it. 1813 * <p> 1814 * All text outside the range {@code contextStart..contextEnd} is ignored. The text between 1815 * {@code start} and {@code end} will be laid out and drawn. 1816 * <p> 1817 * The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is 1818 * suitable only for runs of a single direction. Alignment of the text is as determined by the 1819 * Paint's TextAlign value. Further, {@code 0 <= contextStart <= start <= end <= contextEnd 1820 * <= text.length} must hold on entry. 1821 * <p> 1822 * Also see {@link android.graphics.Paint#getRunAdvance} for a corresponding method to measure 1823 * the text; the advance width of the text drawn matches the value obtained from that method. 1824 * 1825 * @param text the text to render 1826 * @param start the start of the text to render. Data before this position can be used for 1827 * shaping context. 1828 * @param end the end of the text to render. Data at or after this position can be used for 1829 * shaping context. 1830 * @param contextStart the index of the start of the shaping context 1831 * @param contextEnd the index of the end of the shaping context 1832 * @param x the x position at which to draw the text 1833 * @param y the y position at which to draw the text 1834 * @param isRtl whether the run is in RTL direction 1835 * @param paint the paint 1836 * @see #drawTextRun(char[], int, int, int, int, float, float, boolean, Paint) 1837 */ 1838 public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, 1839 int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) { 1840 super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint); 1841 } 1842 1843 /** 1844 * Draw the array of vertices, interpreted as triangles (based on mode). The verts array is 1845 * required, and specifies the x,y pairs for each vertex. If texs is non-null, then it is used 1846 * to specify the coordinate in shader coordinates to use at each vertex (the paint must have a 1847 * shader in this case). If there is no texs array, but there is a color array, then each color 1848 * is interpolated across its corresponding triangle in a gradient. If both texs and colors 1849 * arrays are present, then they behave as before, but the resulting color at each pixels is the 1850 * result of multiplying the colors from the shader and the color-gradient together. The indices 1851 * array is optional, but if it is present, then it is used to specify the index of each 1852 * triangle, rather than just walking through the arrays in order. 1853 * 1854 * @param mode How to interpret the array of vertices 1855 * @param vertexCount The number of values in the vertices array (and corresponding texs and 1856 * colors arrays if non-null). Each logical vertex is two values (x, y), vertexCount 1857 * must be a multiple of 2. 1858 * @param verts Array of vertices for the mesh 1859 * @param vertOffset Number of values in the verts to skip before drawing. 1860 * @param texs May be null. If not null, specifies the coordinates to sample into the current 1861 * shader (e.g. bitmap tile or gradient) 1862 * @param texOffset Number of values in texs to skip before drawing. 1863 * @param colors May be null. If not null, specifies a color for each vertex, to be interpolated 1864 * across the triangle. 1865 * @param colorOffset Number of values in colors to skip before drawing. 1866 * @param indices If not null, array of indices to reference into the vertex (texs, colors) 1867 * array. 1868 * @param indexCount number of entries in the indices array (if not null). 1869 * @param paint Specifies the shader to use if the texs array is non-null. 1870 */ 1871 public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts, 1872 int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors, 1873 int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount, 1874 @NonNull Paint paint) { 1875 super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, 1876 colors, colorOffset, indices, indexOffset, indexCount, paint); 1877 } 1878} 1879