Canvas.java revision 4f641d1e4586b027969052cc0ad6b65c1158e72e
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 * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and 741 * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs 742 * are intended to only expand the clip as a result of a restore operation. This enables a view 743 * parent to clip a canvas to clearly define the maximal drawing area of its children. The 744 * recommended alternative calls are {@link #clipRect(RectF)} and {@link #clipOutRect(RectF)}; 745 */ 746 @Deprecated 747 public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) { 748 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 749 op.nativeInt); 750 } 751 752 /** 753 * Modify the current clip with the specified rectangle, which is 754 * expressed in local coordinates. 755 * 756 * @param rect The rectangle to intersect with the current clip. 757 * @param op How the clip is modified 758 * @return true if the resulting clip is non-empty 759 * 760 * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and 761 * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs 762 * are intended to only expand the clip as a result of a restore operation. This enables a view 763 * parent to clip a canvas to clearly define the maximal drawing area of its children. The 764 * recommended alternative calls are {@link #clipRect(Rect)} and {@link #clipOutRect(Rect)}; 765 */ 766 @Deprecated 767 public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) { 768 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 769 op.nativeInt); 770 } 771 772 /** 773 * Intersect the current clip with the specified rectangle, which is 774 * expressed in local coordinates. 775 * 776 * @param rect The rectangle to intersect with the current clip. 777 * @return true if the resulting clip is non-empty 778 */ 779 public boolean clipRect(@NonNull RectF rect) { 780 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 781 Region.Op.INTERSECT.nativeInt); 782 } 783 784 /** 785 * Set the clip to the difference of the current clip and the specified rectangle, which is 786 * expressed in local coordinates. 787 * 788 * @param rect The rectangle to perform a difference op with the current clip. 789 * @return true if the resulting clip is non-empty 790 */ 791 public boolean clipOutRect(@NonNull RectF rect) { 792 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 793 Region.Op.DIFFERENCE.nativeInt); 794 } 795 796 /** 797 * Intersect the current clip with the specified rectangle, which is 798 * expressed in local coordinates. 799 * 800 * @param rect The rectangle to intersect with the current clip. 801 * @return true if the resulting clip is non-empty 802 */ 803 public boolean clipRect(@NonNull Rect rect) { 804 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 805 Region.Op.INTERSECT.nativeInt); 806 } 807 808 /** 809 * Set the clip to the difference of the current clip and the specified rectangle, which is 810 * expressed in local coordinates. 811 * 812 * @param rect The rectangle to perform a difference op with the current clip. 813 * @return true if the resulting clip is non-empty 814 */ 815 public boolean clipOutRect(@NonNull Rect rect) { 816 return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, 817 Region.Op.DIFFERENCE.nativeInt); 818 } 819 820 /** 821 * Modify 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 827 * clip 828 * @param right The right side of the rectangle to intersect with the 829 * current clip 830 * @param bottom The bottom of the rectangle to intersect with the current 831 * clip 832 * @param op How the clip is modified 833 * @return true if the resulting clip is non-empty 834 * 835 * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and 836 * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs 837 * are intended to only expand the clip as a result of a restore operation. This enables a view 838 * parent to clip a canvas to clearly define the maximal drawing area of its children. The 839 * recommended alternative calls are {@link #clipRect(float,float,float,float)} and 840 * {@link #clipOutRect(float,float,float,float)}; 841 */ 842 @Deprecated 843 public boolean clipRect(float left, float top, float right, float bottom, 844 @NonNull Region.Op op) { 845 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt); 846 } 847 848 /** 849 * Intersect the current clip with the specified rectangle, which is 850 * expressed in local coordinates. 851 * 852 * @param left The left side of the rectangle to intersect with the 853 * current clip 854 * @param top The top of the rectangle to intersect with the current clip 855 * @param right The right side of the rectangle to intersect with the 856 * current clip 857 * @param bottom The bottom of the rectangle to intersect with the current 858 * clip 859 * @return true if the resulting clip is non-empty 860 */ 861 public boolean clipRect(float left, float top, float right, float bottom) { 862 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, 863 Region.Op.INTERSECT.nativeInt); 864 } 865 866 /** 867 * Set the clip to the difference of the current clip and the specified rectangle, which is 868 * expressed in local coordinates. 869 * 870 * @param left The left side of the rectangle used in the difference operation 871 * @param top The top of the rectangle used in the difference operation 872 * @param right The right side of the rectangle used in the difference operation 873 * @param bottom The bottom of the rectangle used in the difference operation 874 * @return true if the resulting clip is non-empty 875 */ 876 public boolean clipOutRect(float left, float top, float right, float bottom) { 877 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, 878 Region.Op.DIFFERENCE.nativeInt); 879 } 880 881 /** 882 * Intersect the current clip with the specified rectangle, which is 883 * expressed in local coordinates. 884 * 885 * @param left The left side of the rectangle to intersect with the 886 * current clip 887 * @param top The top of the rectangle to intersect with the current clip 888 * @param right The right side of the rectangle to intersect with the 889 * current clip 890 * @param bottom The bottom of the rectangle to intersect with the current 891 * clip 892 * @return true if the resulting clip is non-empty 893 */ 894 public boolean clipRect(int left, int top, int right, int bottom) { 895 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, 896 Region.Op.INTERSECT.nativeInt); 897 } 898 899 /** 900 * Set the clip to the difference of the current clip and the specified rectangle, which is 901 * expressed in local coordinates. 902 * 903 * @param left The left side of the rectangle used in the difference operation 904 * @param top The top of the rectangle used in the difference operation 905 * @param right The right side of the rectangle used in the difference operation 906 * @param bottom The bottom of the rectangle used in the difference operation 907 * @return true if the resulting clip is non-empty 908 */ 909 public boolean clipOutRect(int left, int top, int right, int bottom) { 910 return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, 911 Region.Op.DIFFERENCE.nativeInt); 912 } 913 914 /** 915 * Modify the current clip with the specified path. 916 * 917 * @param path The path to operate on the current clip 918 * @param op How the clip is modified 919 * @return true if the resulting is non-empty 920 * 921 * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and 922 * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs 923 * are intended to only expand the clip as a result of a restore operation. This enables a view 924 * parent to clip a canvas to clearly define the maximal drawing area of its children. The 925 * recommended alternative calls are {@link #clipPath(Path)} and 926 * {@link #clipOutPath(Path)}; 927 */ 928 @Deprecated 929 public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) { 930 return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt); 931 } 932 933 /** 934 * Intersect the current clip with the specified path. 935 * 936 * @param path The path to intersect with the current clip 937 * @return true if the resulting clip is non-empty 938 */ 939 public boolean clipPath(@NonNull Path path) { 940 return clipPath(path, Region.Op.INTERSECT); 941 } 942 943 /** 944 * Set the clip to the difference of the current clip and the specified path. 945 * 946 * @param path The path used in the difference operation 947 * @return true if the resulting clip is non-empty 948 */ 949 public boolean clipOutPath(@NonNull Path path) { 950 return clipPath(path, Region.Op.DIFFERENCE); 951 } 952 953 /** 954 * Modify the current clip with the specified region. Note that unlike 955 * clipRect() and clipPath() which transform their arguments by the 956 * current matrix, clipRegion() assumes its argument is already in the 957 * coordinate system of the current layer's bitmap, and so not 958 * transformation is performed. 959 * 960 * @param region The region to operate on the current clip, based on op 961 * @param op How the clip is modified 962 * @return true if the resulting is non-empty 963 * 964 * @removed 965 * @deprecated Unlike all other clip calls this API does not respect the 966 * current matrix. Use {@link #clipRect(Rect)} as an alternative. 967 */ 968 @Deprecated 969 public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) { 970 return false; 971 } 972 973 /** 974 * Intersect the current clip with the specified region. Note that unlike 975 * clipRect() and clipPath() which transform their arguments by the 976 * current matrix, clipRegion() assumes its argument is already in the 977 * coordinate system of the current layer's bitmap, and so not 978 * transformation is performed. 979 * 980 * @param region The region to operate on the current clip, based on op 981 * @return true if the resulting is non-empty 982 * 983 * @removed 984 * @deprecated Unlike all other clip calls this API does not respect the 985 * current matrix. Use {@link #clipRect(Rect)} as an alternative. 986 */ 987 @Deprecated 988 public boolean clipRegion(@NonNull Region region) { 989 return false; 990 } 991 992 public @Nullable DrawFilter getDrawFilter() { 993 return mDrawFilter; 994 } 995 996 public void setDrawFilter(@Nullable DrawFilter filter) { 997 long nativeFilter = 0; 998 if (filter != null) { 999 nativeFilter = filter.mNativeInt; 1000 } 1001 mDrawFilter = filter; 1002 nSetDrawFilter(mNativeCanvasWrapper, nativeFilter); 1003 } 1004 1005 /** 1006 * Constant values used as parameters to {@code quickReject()} calls. These values 1007 * specify how much space around the shape should be accounted for, depending on whether 1008 * the shaped area is antialiased or not. 1009 * 1010 * @see #quickReject(float, float, float, float, EdgeType) 1011 * @see #quickReject(Path, EdgeType) 1012 * @see #quickReject(RectF, EdgeType) 1013 */ 1014 public enum EdgeType { 1015 1016 /** 1017 * Black-and-White: Treat edges by just rounding to nearest pixel boundary 1018 */ 1019 BW(0), //!< treat edges by just rounding to nearest pixel boundary 1020 1021 /** 1022 * Antialiased: Treat edges by rounding-out, since they may be antialiased 1023 */ 1024 AA(1); 1025 1026 EdgeType(int nativeInt) { 1027 this.nativeInt = nativeInt; 1028 } 1029 1030 /** 1031 * @hide 1032 */ 1033 public final int nativeInt; 1034 } 1035 1036 /** 1037 * Return true if the specified rectangle, after being transformed by the 1038 * current matrix, would lie completely outside of the current clip. Call 1039 * this to check if an area you intend to draw into is clipped out (and 1040 * therefore you can skip making the draw calls). 1041 * 1042 * @param rect the rect to compare with the current clip 1043 * @param type {@link Canvas.EdgeType#AA} if the path should be considered antialiased, 1044 * since that means it may affect a larger area (more pixels) than 1045 * non-antialiased ({@link Canvas.EdgeType#BW}). 1046 * @return true if the rect (transformed by the canvas' matrix) 1047 * does not intersect with the canvas' clip 1048 */ 1049 public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) { 1050 return nQuickReject(mNativeCanvasWrapper, 1051 rect.left, rect.top, rect.right, rect.bottom); 1052 } 1053 1054 /** 1055 * Return true if the specified path, after being transformed by the 1056 * current matrix, would lie completely outside of the current clip. Call 1057 * this to check if an area you intend to draw into is clipped out (and 1058 * therefore you can skip making the draw calls). Note: for speed it may 1059 * return false even if the path itself might not intersect the clip 1060 * (i.e. the bounds of the path intersects, but the path does not). 1061 * 1062 * @param path The path to compare with the current clip 1063 * @param type {@link Canvas.EdgeType#AA} if the path should be considered antialiased, 1064 * since that means it may affect a larger area (more pixels) than 1065 * non-antialiased ({@link Canvas.EdgeType#BW}). 1066 * @return true if the path (transformed by the canvas' matrix) 1067 * does not intersect with the canvas' clip 1068 */ 1069 public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) { 1070 return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI()); 1071 } 1072 1073 /** 1074 * Return true if the specified rectangle, after being transformed by the 1075 * current matrix, would lie completely outside of the current clip. Call 1076 * this to check if an area you intend to draw into is clipped out (and 1077 * therefore you can skip making the draw calls). 1078 * 1079 * @param left The left side of the rectangle to compare with the 1080 * current clip 1081 * @param top The top of the rectangle to compare with the current 1082 * clip 1083 * @param right The right side of the rectangle to compare with the 1084 * current clip 1085 * @param bottom The bottom of the rectangle to compare with the 1086 * current clip 1087 * @param type {@link Canvas.EdgeType#AA} if the path should be considered antialiased, 1088 * since that means it may affect a larger area (more pixels) than 1089 * non-antialiased ({@link Canvas.EdgeType#BW}). 1090 * @return true if the rect (transformed by the canvas' matrix) 1091 * does not intersect with the canvas' clip 1092 */ 1093 public boolean quickReject(float left, float top, float right, float bottom, 1094 @NonNull EdgeType type) { 1095 return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom); 1096 } 1097 1098 /** 1099 * Return the bounds of the current clip (in local coordinates) in the 1100 * bounds parameter, and return true if it is non-empty. This can be useful 1101 * in a way similar to quickReject, in that it tells you that drawing 1102 * outside of these bounds will be clipped out. 1103 * 1104 * @param bounds Return the clip bounds here. If it is null, ignore it but 1105 * still return true if the current clip is non-empty. 1106 * @return true if the current clip is non-empty. 1107 */ 1108 public boolean getClipBounds(@Nullable Rect bounds) { 1109 return nGetClipBounds(mNativeCanvasWrapper, bounds); 1110 } 1111 1112 /** 1113 * Retrieve the bounds of the current clip (in local coordinates). 1114 * 1115 * @return the clip bounds, or [0, 0, 0, 0] if the clip is empty. 1116 */ 1117 public final @NonNull Rect getClipBounds() { 1118 Rect r = new Rect(); 1119 getClipBounds(r); 1120 return r; 1121 } 1122 1123 /** 1124 * Save the canvas state, draw the picture, and restore the canvas state. 1125 * This differs from picture.draw(canvas), which does not perform any 1126 * save/restore. 1127 * 1128 * <p> 1129 * <strong>Note:</strong> This forces the picture to internally call 1130 * {@link Picture#endRecording} in order to prepare for playback. 1131 * 1132 * @param picture The picture to be drawn 1133 */ 1134 public void drawPicture(@NonNull Picture picture) { 1135 picture.endRecording(); 1136 int restoreCount = save(); 1137 picture.draw(this); 1138 restoreToCount(restoreCount); 1139 } 1140 1141 /** 1142 * Draw the picture, stretched to fit into the dst rectangle. 1143 */ 1144 public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) { 1145 save(); 1146 translate(dst.left, dst.top); 1147 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1148 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight()); 1149 } 1150 drawPicture(picture); 1151 restore(); 1152 } 1153 1154 /** 1155 * Draw the picture, stretched to fit into the dst rectangle. 1156 */ 1157 public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) { 1158 save(); 1159 translate(dst.left, dst.top); 1160 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1161 scale((float) dst.width() / picture.getWidth(), 1162 (float) dst.height() / picture.getHeight()); 1163 } 1164 drawPicture(picture); 1165 restore(); 1166 } 1167 1168 public enum VertexMode { 1169 TRIANGLES(0), 1170 TRIANGLE_STRIP(1), 1171 TRIANGLE_FAN(2); 1172 1173 VertexMode(int nativeInt) { 1174 this.nativeInt = nativeInt; 1175 } 1176 1177 /** 1178 * @hide 1179 */ 1180 public final int nativeInt; 1181 } 1182 1183 /** 1184 * Releases the resources associated with this canvas. 1185 * 1186 * @hide 1187 */ 1188 public void release() { 1189 mNativeCanvasWrapper = 0; 1190 if (mFinalizer != null) { 1191 mFinalizer.run(); 1192 mFinalizer = null; 1193 } 1194 } 1195 1196 /** 1197 * Free up as much memory as possible from private caches (e.g. fonts, images) 1198 * 1199 * @hide 1200 */ 1201 public static void freeCaches() { 1202 nFreeCaches(); 1203 } 1204 1205 /** 1206 * Free up text layout caches 1207 * 1208 * @hide 1209 */ 1210 public static void freeTextLayoutCaches() { 1211 nFreeTextLayoutCaches(); 1212 } 1213 1214 private static native void nFreeCaches(); 1215 private static native void nFreeTextLayoutCaches(); 1216 private static native long nInitRaster(Bitmap bitmap); 1217 private static native long nGetNativeFinalizer(); 1218 1219 // ---------------- @FastNative ------------------- 1220 1221 @FastNative 1222 private static native void nSetBitmap(long canvasHandle, Bitmap bitmap); 1223 1224 @FastNative 1225 private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds); 1226 1227 // ---------------- @CriticalNative ------------------- 1228 1229 @CriticalNative 1230 private static native boolean nIsOpaque(long canvasHandle); 1231 @CriticalNative 1232 private static native void nSetHighContrastText(long renderer, boolean highContrastText); 1233 @CriticalNative 1234 private static native int nGetWidth(long canvasHandle); 1235 @CriticalNative 1236 private static native int nGetHeight(long canvasHandle); 1237 1238 @CriticalNative 1239 private static native int nSave(long canvasHandle, int saveFlags); 1240 @CriticalNative 1241 private static native int nSaveLayer(long nativeCanvas, float l, float t, float r, float b, 1242 long nativePaint, int layerFlags); 1243 @CriticalNative 1244 private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b, 1245 int alpha, int layerFlags); 1246 @CriticalNative 1247 private static native boolean nRestore(long canvasHandle); 1248 @CriticalNative 1249 private static native void nRestoreToCount(long canvasHandle, int saveCount); 1250 @CriticalNative 1251 private static native int nGetSaveCount(long canvasHandle); 1252 1253 @CriticalNative 1254 private static native void nTranslate(long canvasHandle, float dx, float dy); 1255 @CriticalNative 1256 private static native void nScale(long canvasHandle, float sx, float sy); 1257 @CriticalNative 1258 private static native void nRotate(long canvasHandle, float degrees); 1259 @CriticalNative 1260 private static native void nSkew(long canvasHandle, float sx, float sy); 1261 @CriticalNative 1262 private static native void nConcat(long nativeCanvas, long nativeMatrix); 1263 @CriticalNative 1264 private static native void nSetMatrix(long nativeCanvas, long nativeMatrix); 1265 @CriticalNative 1266 private static native boolean nClipRect(long nativeCanvas, 1267 float left, float top, float right, float bottom, int regionOp); 1268 @CriticalNative 1269 private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp); 1270 @CriticalNative 1271 private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter); 1272 @CriticalNative 1273 private static native void nGetMatrix(long nativeCanvas, long nativeMatrix); 1274 @CriticalNative 1275 private static native boolean nQuickReject(long nativeCanvas, long nativePath); 1276 @CriticalNative 1277 private static native boolean nQuickReject(long nativeCanvas, float left, float top, 1278 float right, float bottom); 1279 1280 1281 // ---------------- Draw Methods ------------------- 1282 1283 /** 1284 * <p> 1285 * Draw the specified arc, which will be scaled to fit inside the specified oval. 1286 * </p> 1287 * <p> 1288 * If the start angle is negative or >= 360, the start angle is treated as start angle modulo 1289 * 360. 1290 * </p> 1291 * <p> 1292 * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs 1293 * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is 1294 * negative, the sweep angle is treated as sweep angle modulo 360 1295 * </p> 1296 * <p> 1297 * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0 1298 * degrees (3 o'clock on a watch.) 1299 * </p> 1300 * 1301 * @param oval The bounds of oval used to define the shape and size of the arc 1302 * @param startAngle Starting angle (in degrees) where the arc begins 1303 * @param sweepAngle Sweep angle (in degrees) measured clockwise 1304 * @param useCenter If true, include the center of the oval in the arc, and close it if it is 1305 * being stroked. This will draw a wedge 1306 * @param paint The paint used to draw the arc 1307 */ 1308 public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, 1309 @NonNull Paint paint) { 1310 super.drawArc(oval, startAngle, sweepAngle, useCenter, paint); 1311 } 1312 1313 /** 1314 * <p> 1315 * Draw the specified arc, which will be scaled to fit inside the specified oval. 1316 * </p> 1317 * <p> 1318 * If the start angle is negative or >= 360, the start angle is treated as start angle modulo 1319 * 360. 1320 * </p> 1321 * <p> 1322 * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs 1323 * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is 1324 * negative, the sweep angle is treated as sweep angle modulo 360 1325 * </p> 1326 * <p> 1327 * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0 1328 * degrees (3 o'clock on a watch.) 1329 * </p> 1330 * 1331 * @param startAngle Starting angle (in degrees) where the arc begins 1332 * @param sweepAngle Sweep angle (in degrees) measured clockwise 1333 * @param useCenter If true, include the center of the oval in the arc, and close it if it is 1334 * being stroked. This will draw a wedge 1335 * @param paint The paint used to draw the arc 1336 */ 1337 public void drawArc(float left, float top, float right, float bottom, float startAngle, 1338 float sweepAngle, boolean useCenter, @NonNull Paint paint) { 1339 super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); 1340 } 1341 1342 /** 1343 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified ARGB 1344 * color, using srcover porterduff mode. 1345 * 1346 * @param a alpha component (0..255) of the color to draw onto the canvas 1347 * @param r red component (0..255) of the color to draw onto the canvas 1348 * @param g green component (0..255) of the color to draw onto the canvas 1349 * @param b blue component (0..255) of the color to draw onto the canvas 1350 */ 1351 public void drawARGB(int a, int r, int g, int b) { 1352 super.drawARGB(a, r, g, b); 1353 } 1354 1355 /** 1356 * Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint, 1357 * transformed by the current matrix. 1358 * <p> 1359 * Note: if the paint contains a maskfilter that generates a mask which extends beyond the 1360 * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it 1361 * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be 1362 * the edge color replicated. 1363 * <p> 1364 * If the bitmap and canvas have different densities, this function will take care of 1365 * automatically scaling the bitmap to draw at the same density as the canvas. 1366 * 1367 * @param bitmap The bitmap to be drawn 1368 * @param left The position of the left side of the bitmap being drawn 1369 * @param top The position of the top side of the bitmap being drawn 1370 * @param paint The paint used to draw the bitmap (may be null) 1371 */ 1372 public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { 1373 super.drawBitmap(bitmap, left, top, paint); 1374 } 1375 1376 /** 1377 * Draw the specified bitmap, scaling/translating automatically to fill the destination 1378 * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to 1379 * draw. 1380 * <p> 1381 * Note: if the paint contains a maskfilter that generates a mask which extends beyond the 1382 * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it 1383 * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be 1384 * the edge color replicated. 1385 * <p> 1386 * This function <em>ignores the density associated with the bitmap</em>. This is because the 1387 * source and destination rectangle coordinate spaces are in their respective densities, so must 1388 * already have the appropriate scaling factor applied. 1389 * 1390 * @param bitmap The bitmap to be drawn 1391 * @param src May be null. The subset of the bitmap to be drawn 1392 * @param dst The rectangle that the bitmap will be scaled/translated to fit into 1393 * @param paint May be null. The paint used to draw the bitmap 1394 */ 1395 public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, 1396 @Nullable Paint paint) { 1397 super.drawBitmap(bitmap, src, dst, paint); 1398 } 1399 1400 /** 1401 * Draw the specified bitmap, scaling/translating automatically to fill the destination 1402 * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to 1403 * draw. 1404 * <p> 1405 * Note: if the paint contains a maskfilter that generates a mask which extends beyond the 1406 * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it 1407 * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be 1408 * the edge color replicated. 1409 * <p> 1410 * This function <em>ignores the density associated with the bitmap</em>. This is because the 1411 * source and destination rectangle coordinate spaces are in their respective densities, so must 1412 * already have the appropriate scaling factor applied. 1413 * 1414 * @param bitmap The bitmap to be drawn 1415 * @param src May be null. The subset of the bitmap to be drawn 1416 * @param dst The rectangle that the bitmap will be scaled/translated to fit into 1417 * @param paint May be null. The paint used to draw the bitmap 1418 */ 1419 public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, 1420 @Nullable Paint paint) { 1421 super.drawBitmap(bitmap, src, dst, paint); 1422 } 1423 1424 /** 1425 * Treat the specified array of colors as a bitmap, and draw it. This gives the same result as 1426 * first creating a bitmap from the array, and then drawing it, but this method avoids 1427 * explicitly creating a bitmap object which can be more efficient if the colors are changing 1428 * often. 1429 * 1430 * @param colors Array of colors representing the pixels of the bitmap 1431 * @param offset Offset into the array of colors for the first pixel 1432 * @param stride The number of colors in the array between rows (must be >= width or <= -width). 1433 * @param x The X coordinate for where to draw the bitmap 1434 * @param y The Y coordinate for where to draw the bitmap 1435 * @param width The width of the bitmap 1436 * @param height The height of the bitmap 1437 * @param hasAlpha True if the alpha channel of the colors contains valid values. If false, the 1438 * alpha byte is ignored (assumed to be 0xFF for every pixel). 1439 * @param paint May be null. The paint used to draw the bitmap 1440 * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas 1441 * requires an internal copy of color buffer contents every time this method is 1442 * called. Using a Bitmap avoids this copy, and allows the application to more 1443 * explicitly control the lifetime and copies of pixel data. 1444 */ 1445 @Deprecated 1446 public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y, 1447 int width, int height, boolean hasAlpha, @Nullable Paint paint) { 1448 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 1449 } 1450 1451 /** 1452 * Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y 1453 * 1454 * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas 1455 * requires an internal copy of color buffer contents every time this method is 1456 * called. Using a Bitmap avoids this copy, and allows the application to more 1457 * explicitly control the lifetime and copies of pixel data. 1458 */ 1459 @Deprecated 1460 public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y, 1461 int width, int height, boolean hasAlpha, @Nullable Paint paint) { 1462 super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); 1463 } 1464 1465 /** 1466 * Draw the bitmap using the specified matrix. 1467 * 1468 * @param bitmap The bitmap to draw 1469 * @param matrix The matrix used to transform the bitmap when it is drawn 1470 * @param paint May be null. The paint used to draw the bitmap 1471 */ 1472 public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { 1473 super.drawBitmap(bitmap, matrix, paint); 1474 } 1475 1476 /** 1477 * Draw the bitmap through the mesh, where mesh vertices are evenly distributed across the 1478 * bitmap. There are meshWidth+1 vertices across, and meshHeight+1 vertices down. The verts 1479 * array is accessed in row-major order, so that the first meshWidth+1 vertices are distributed 1480 * across the top of the bitmap from left to right. A more general version of this method is 1481 * drawVertices(). 1482 * 1483 * @param bitmap The bitmap to draw using the mesh 1484 * @param meshWidth The number of columns in the mesh. Nothing is drawn if this is 0 1485 * @param meshHeight The number of rows in the mesh. Nothing is drawn if this is 0 1486 * @param verts Array of x,y pairs, specifying where the mesh should be drawn. There must be at 1487 * least (meshWidth+1) * (meshHeight+1) * 2 + vertOffset values in the array 1488 * @param vertOffset Number of verts elements to skip before drawing 1489 * @param colors May be null. Specifies a color at each vertex, which is interpolated across the 1490 * cell, and whose values are multiplied by the corresponding bitmap colors. If not 1491 * null, there must be at least (meshWidth+1) * (meshHeight+1) + colorOffset values 1492 * in the array. 1493 * @param colorOffset Number of color elements to skip before drawing 1494 * @param paint May be null. The paint used to draw the bitmap 1495 */ 1496 public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight, 1497 @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset, 1498 @Nullable Paint paint) { 1499 super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, 1500 paint); 1501 } 1502 1503 /** 1504 * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be 1505 * drawn. The circle will be filled or framed based on the Style in the paint. 1506 * 1507 * @param cx The x-coordinate of the center of the cirle to be drawn 1508 * @param cy The y-coordinate of the center of the cirle to be drawn 1509 * @param radius The radius of the cirle to be drawn 1510 * @param paint The paint used to draw the circle 1511 */ 1512 public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) { 1513 super.drawCircle(cx, cy, radius, paint); 1514 } 1515 1516 /** 1517 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color, 1518 * using srcover porterduff mode. 1519 * 1520 * @param color the color to draw onto the canvas 1521 */ 1522 public void drawColor(@ColorInt int color) { 1523 super.drawColor(color); 1524 } 1525 1526 /** 1527 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and 1528 * porter-duff xfermode. 1529 * 1530 * @param color the color to draw with 1531 * @param mode the porter-duff mode to apply to the color 1532 */ 1533 public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) { 1534 super.drawColor(color, mode); 1535 } 1536 1537 /** 1538 * Draw a line segment with the specified start and stop x,y coordinates, using the specified 1539 * paint. 1540 * <p> 1541 * Note that since a line is always "framed", the Style is ignored in the paint. 1542 * </p> 1543 * <p> 1544 * Degenerate lines (length is 0) will not be drawn. 1545 * </p> 1546 * 1547 * @param startX The x-coordinate of the start point of the line 1548 * @param startY The y-coordinate of the start point of the line 1549 * @param paint The paint used to draw the line 1550 */ 1551 public void drawLine(float startX, float startY, float stopX, float stopY, 1552 @NonNull Paint paint) { 1553 super.drawLine(startX, startY, stopX, stopY, paint); 1554 } 1555 1556 /** 1557 * Draw a series of lines. Each line is taken from 4 consecutive values in the pts array. Thus 1558 * to draw 1 line, the array must contain at least 4 values. This is logically the same as 1559 * drawing the array as follows: drawLine(pts[0], pts[1], pts[2], pts[3]) followed by 1560 * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on. 1561 * 1562 * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...] 1563 * @param offset Number of values in the array to skip before drawing. 1564 * @param count The number of values in the array to process, after skipping "offset" of them. 1565 * Since each line uses 4 values, the number of "lines" that are drawn is really 1566 * (count >> 2). 1567 * @param paint The paint used to draw the points 1568 */ 1569 public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count, 1570 @NonNull Paint paint) { 1571 super.drawLines(pts, offset, count, paint); 1572 } 1573 1574 public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) { 1575 super.drawLines(pts, paint); 1576 } 1577 1578 /** 1579 * Draw the specified oval using the specified paint. The oval will be filled or framed based on 1580 * the Style in the paint. 1581 * 1582 * @param oval The rectangle bounds of the oval to be drawn 1583 */ 1584 public void drawOval(@NonNull RectF oval, @NonNull Paint paint) { 1585 super.drawOval(oval, paint); 1586 } 1587 1588 /** 1589 * Draw the specified oval using the specified paint. The oval will be filled or framed based on 1590 * the Style in the paint. 1591 */ 1592 public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) { 1593 super.drawOval(left, top, right, bottom, paint); 1594 } 1595 1596 /** 1597 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint. 1598 * This is equivalent (but faster) to drawing an infinitely large rectangle with the specified 1599 * paint. 1600 * 1601 * @param paint The paint used to draw onto the canvas 1602 */ 1603 public void drawPaint(@NonNull Paint paint) { 1604 super.drawPaint(paint); 1605 } 1606 1607 /** 1608 * Draws the specified bitmap as an N-patch (most often, a 9-patches.) 1609 * 1610 * @param patch The ninepatch object to render 1611 * @param dst The destination rectangle. 1612 * @param paint The paint to draw the bitmap with. may be null 1613 * @hide 1614 */ 1615 public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) { 1616 super.drawPatch(patch, dst, paint); 1617 } 1618 1619 /** 1620 * Draws the specified bitmap as an N-patch (most often, a 9-patches.) 1621 * 1622 * @param patch The ninepatch object to render 1623 * @param dst The destination rectangle. 1624 * @param paint The paint to draw the bitmap with. may be null 1625 * @hide 1626 */ 1627 public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) { 1628 super.drawPatch(patch, dst, paint); 1629 } 1630 1631 /** 1632 * Draw the specified path using the specified paint. The path will be filled or framed based on 1633 * the Style in the paint. 1634 * 1635 * @param path The path to be drawn 1636 * @param paint The paint used to draw the path 1637 */ 1638 public void drawPath(@NonNull Path path, @NonNull Paint paint) { 1639 super.drawPath(path, paint); 1640 } 1641 1642 /** 1643 * Helper for drawPoints() for drawing a single point. 1644 */ 1645 public void drawPoint(float x, float y, @NonNull Paint paint) { 1646 super.drawPoint(x, y, paint); 1647 } 1648 1649 /** 1650 * Draw a series of points. Each point is centered at the coordinate specified by pts[], and its 1651 * diameter is specified by the paint's stroke width (as transformed by the canvas' CTM), with 1652 * special treatment for a stroke width of 0, which always draws exactly 1 pixel (or at most 4 1653 * if antialiasing is enabled). The shape of the point is controlled by the paint's Cap type. 1654 * The shape is a square, unless the cap type is Round, in which case the shape is a circle. 1655 * 1656 * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...] 1657 * @param offset Number of values to skip before starting to draw. 1658 * @param count The number of values to process, after skipping offset of them. Since one point 1659 * uses two values, the number of "points" that are drawn is really (count >> 1). 1660 * @param paint The paint used to draw the points 1661 */ 1662 public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count, 1663 @NonNull Paint paint) { 1664 super.drawPoints(pts, offset, count, paint); 1665 } 1666 1667 /** 1668 * Helper for drawPoints() that assumes you want to draw the entire array 1669 */ 1670 public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) { 1671 super.drawPoints(pts, paint); 1672 } 1673 1674 /** 1675 * Draw the text in the array, with each character's origin specified by the pos array. 1676 * 1677 * @param text The text to be drawn 1678 * @param index The index of the first character to draw 1679 * @param count The number of characters to draw, starting from index. 1680 * @param pos Array of [x,y] positions, used to position each character 1681 * @param paint The paint used for the text (e.g. color, size, style) 1682 * @deprecated This method does not support glyph composition and decomposition and should 1683 * therefore not be used to render complex scripts. It also doesn't handle 1684 * supplementary characters (eg emoji). 1685 */ 1686 @Deprecated 1687 public void drawPosText(@NonNull char[] text, int index, int count, 1688 @NonNull @Size(multiple = 2) float[] pos, 1689 @NonNull Paint paint) { 1690 super.drawPosText(text, index, count, pos, paint); 1691 } 1692 1693 /** 1694 * Draw the text in the array, with each character's origin specified by the pos array. 1695 * 1696 * @param text The text to be drawn 1697 * @param pos Array of [x,y] positions, used to position each character 1698 * @param paint The paint used for the text (e.g. color, size, style) 1699 * @deprecated This method does not support glyph composition and decomposition and should 1700 * therefore not be used to render complex scripts. It also doesn't handle 1701 * supplementary characters (eg emoji). 1702 */ 1703 @Deprecated 1704 public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos, 1705 @NonNull Paint paint) { 1706 super.drawPosText(text, pos, paint); 1707 } 1708 1709 /** 1710 * Draw the specified Rect using the specified paint. The rectangle will be filled or framed 1711 * based on the Style in the paint. 1712 * 1713 * @param rect The rect to be drawn 1714 * @param paint The paint used to draw the rect 1715 */ 1716 public void drawRect(@NonNull RectF rect, @NonNull Paint paint) { 1717 super.drawRect(rect, paint); 1718 } 1719 1720 /** 1721 * Draw the specified Rect using the specified Paint. The rectangle will be filled or framed 1722 * based on the Style in the paint. 1723 * 1724 * @param r The rectangle to be drawn. 1725 * @param paint The paint used to draw the rectangle 1726 */ 1727 public void drawRect(@NonNull Rect r, @NonNull Paint paint) { 1728 super.drawRect(r, paint); 1729 } 1730 1731 /** 1732 * Draw the specified Rect using the specified paint. The rectangle will be filled or framed 1733 * based on the Style in the paint. 1734 * 1735 * @param left The left side of the rectangle to be drawn 1736 * @param top The top side of the rectangle to be drawn 1737 * @param right The right side of the rectangle to be drawn 1738 * @param bottom The bottom side of the rectangle to be drawn 1739 * @param paint The paint used to draw the rect 1740 */ 1741 public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) { 1742 super.drawRect(left, top, right, bottom, paint); 1743 } 1744 1745 /** 1746 * Fill the entire canvas' bitmap (restricted to the current clip) with the specified RGB color, 1747 * using srcover porterduff mode. 1748 * 1749 * @param r red component (0..255) of the color to draw onto the canvas 1750 * @param g green component (0..255) of the color to draw onto the canvas 1751 * @param b blue component (0..255) of the color to draw onto the canvas 1752 */ 1753 public void drawRGB(int r, int g, int b) { 1754 super.drawRGB(r, g, b); 1755 } 1756 1757 /** 1758 * Draw the specified round-rect using the specified paint. The roundrect will be filled or 1759 * framed based on the Style in the paint. 1760 * 1761 * @param rect The rectangular bounds of the roundRect to be drawn 1762 * @param rx The x-radius of the oval used to round the corners 1763 * @param ry The y-radius of the oval used to round the corners 1764 * @param paint The paint used to draw the roundRect 1765 */ 1766 public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) { 1767 super.drawRoundRect(rect, rx, ry, paint); 1768 } 1769 1770 /** 1771 * Draw the specified round-rect using the specified paint. The roundrect will be filled or 1772 * framed based on the Style in the paint. 1773 * 1774 * @param rx The x-radius of the oval used to round the corners 1775 * @param ry The y-radius of the oval used to round the corners 1776 * @param paint The paint used to draw the roundRect 1777 */ 1778 public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, 1779 @NonNull Paint paint) { 1780 super.drawRoundRect(left, top, right, bottom, rx, ry, paint); 1781 } 1782 1783 /** 1784 * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted 1785 * based on the Align setting in the paint. 1786 * 1787 * @param text The text to be drawn 1788 * @param x The x-coordinate of the origin of the text being drawn 1789 * @param y The y-coordinate of the baseline of the text being drawn 1790 * @param paint The paint used for the text (e.g. color, size, style) 1791 */ 1792 public void drawText(@NonNull char[] text, int index, int count, float x, float y, 1793 @NonNull Paint paint) { 1794 super.drawText(text, index, count, x, y, paint); 1795 } 1796 1797 /** 1798 * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted 1799 * based on the Align setting in the paint. 1800 * 1801 * @param text The text to be drawn 1802 * @param x The x-coordinate of the origin of the text being drawn 1803 * @param y The y-coordinate of the baseline of the text being drawn 1804 * @param paint The paint used for the text (e.g. color, size, style) 1805 */ 1806 public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) { 1807 super.drawText(text, x, y, paint); 1808 } 1809 1810 /** 1811 * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted 1812 * based on the Align setting in the paint. 1813 * 1814 * @param text The text to be drawn 1815 * @param start The index of the first character in text to draw 1816 * @param end (end - 1) is the index of the last character in text to draw 1817 * @param x The x-coordinate of the origin of the text being drawn 1818 * @param y The y-coordinate of the baseline of the text being drawn 1819 * @param paint The paint used for the text (e.g. color, size, style) 1820 */ 1821 public void drawText(@NonNull String text, int start, int end, float x, float y, 1822 @NonNull Paint paint) { 1823 super.drawText(text, start, end, x, y, paint); 1824 } 1825 1826 /** 1827 * Draw the specified range of text, specified by start/end, with its origin at (x,y), in the 1828 * specified Paint. The origin is interpreted based on the Align setting in the Paint. 1829 * 1830 * @param text The text to be drawn 1831 * @param start The index of the first character in text to draw 1832 * @param end (end - 1) is the index of the last character in text to draw 1833 * @param x The x-coordinate of origin for where to draw the text 1834 * @param y The y-coordinate of origin for where to draw the text 1835 * @param paint The paint used for the text (e.g. color, size, style) 1836 */ 1837 public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, 1838 @NonNull Paint paint) { 1839 super.drawText(text, start, end, x, y, paint); 1840 } 1841 1842 /** 1843 * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The 1844 * paint's Align setting determins where along the path to start the text. 1845 * 1846 * @param text The text to be drawn 1847 * @param path The path the text should follow for its baseline 1848 * @param hOffset The distance along the path to add to the text's starting position 1849 * @param vOffset The distance above(-) or below(+) the path to position the text 1850 * @param paint The paint used for the text (e.g. color, size, style) 1851 */ 1852 public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, 1853 float hOffset, float vOffset, @NonNull Paint paint) { 1854 super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint); 1855 } 1856 1857 /** 1858 * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The 1859 * paint's Align setting determins where along the path to start the text. 1860 * 1861 * @param text The text to be drawn 1862 * @param path The path the text should follow for its baseline 1863 * @param hOffset The distance along the path to add to the text's starting position 1864 * @param vOffset The distance above(-) or below(+) the path to position the text 1865 * @param paint The paint used for the text (e.g. color, size, style) 1866 */ 1867 public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, 1868 float vOffset, @NonNull Paint paint) { 1869 super.drawTextOnPath(text, path, hOffset, vOffset, paint); 1870 } 1871 1872 /** 1873 * Draw a run of text, all in a single direction, with optional context for complex text 1874 * shaping. 1875 * <p> 1876 * See {@link #drawTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)} for 1877 * more details. This method uses a character array rather than CharSequence to represent the 1878 * string. Also, to be consistent with the pattern established in {@link #drawText}, in this 1879 * method {@code count} and {@code contextCount} are used rather than offsets of the end 1880 * position; {@code count = end - start, contextCount = contextEnd - 1881 * contextStart}. 1882 * 1883 * @param text the text to render 1884 * @param index the start of the text to render 1885 * @param count the count of chars to render 1886 * @param contextIndex the start of the context for shaping. Must be no greater than index. 1887 * @param contextCount the number of characters in the context for shaping. contexIndex + 1888 * contextCount must be no less than index + count. 1889 * @param x the x position at which to draw the text 1890 * @param y the y position at which to draw the text 1891 * @param isRtl whether the run is in RTL direction 1892 * @param paint the paint 1893 */ 1894 public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, 1895 int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) { 1896 super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint); 1897 } 1898 1899 /** 1900 * Draw a run of text, all in a single direction, with optional context for complex text 1901 * shaping. 1902 * <p> 1903 * The run of text includes the characters from {@code start} to {@code end} in the text. In 1904 * addition, the range {@code contextStart} to {@code contextEnd} is used as context for the 1905 * purpose of complex text shaping, such as Arabic text potentially shaped differently based on 1906 * the text next to it. 1907 * <p> 1908 * All text outside the range {@code contextStart..contextEnd} is ignored. The text between 1909 * {@code start} and {@code end} will be laid out and drawn. 1910 * <p> 1911 * The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is 1912 * suitable only for runs of a single direction. Alignment of the text is as determined by the 1913 * Paint's TextAlign value. Further, {@code 0 <= contextStart <= start <= end <= contextEnd 1914 * <= text.length} must hold on entry. 1915 * <p> 1916 * Also see {@link android.graphics.Paint#getRunAdvance} for a corresponding method to measure 1917 * the text; the advance width of the text drawn matches the value obtained from that method. 1918 * 1919 * @param text the text to render 1920 * @param start the start of the text to render. Data before this position can be used for 1921 * shaping context. 1922 * @param end the end of the text to render. Data at or after this position can be used for 1923 * shaping context. 1924 * @param contextStart the index of the start of the shaping context 1925 * @param contextEnd the index of the end of the shaping context 1926 * @param x the x position at which to draw the text 1927 * @param y the y position at which to draw the text 1928 * @param isRtl whether the run is in RTL direction 1929 * @param paint the paint 1930 * @see #drawTextRun(char[], int, int, int, int, float, float, boolean, Paint) 1931 */ 1932 public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, 1933 int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) { 1934 super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint); 1935 } 1936 1937 /** 1938 * Draw the array of vertices, interpreted as triangles (based on mode). The verts array is 1939 * required, and specifies the x,y pairs for each vertex. If texs is non-null, then it is used 1940 * to specify the coordinate in shader coordinates to use at each vertex (the paint must have a 1941 * shader in this case). If there is no texs array, but there is a color array, then each color 1942 * is interpolated across its corresponding triangle in a gradient. If both texs and colors 1943 * arrays are present, then they behave as before, but the resulting color at each pixels is the 1944 * result of multiplying the colors from the shader and the color-gradient together. The indices 1945 * array is optional, but if it is present, then it is used to specify the index of each 1946 * triangle, rather than just walking through the arrays in order. 1947 * 1948 * @param mode How to interpret the array of vertices 1949 * @param vertexCount The number of values in the vertices array (and corresponding texs and 1950 * colors arrays if non-null). Each logical vertex is two values (x, y), vertexCount 1951 * must be a multiple of 2. 1952 * @param verts Array of vertices for the mesh 1953 * @param vertOffset Number of values in the verts to skip before drawing. 1954 * @param texs May be null. If not null, specifies the coordinates to sample into the current 1955 * shader (e.g. bitmap tile or gradient) 1956 * @param texOffset Number of values in texs to skip before drawing. 1957 * @param colors May be null. If not null, specifies a color for each vertex, to be interpolated 1958 * across the triangle. 1959 * @param colorOffset Number of values in colors to skip before drawing. 1960 * @param indices If not null, array of indices to reference into the vertex (texs, colors) 1961 * array. 1962 * @param indexCount number of entries in the indices array (if not null). 1963 * @param paint Specifies the shader to use if the texs array is non-null. 1964 */ 1965 public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts, 1966 int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors, 1967 int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount, 1968 @NonNull Paint paint) { 1969 super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, 1970 colors, colorOffset, indices, indexOffset, indexCount, paint); 1971 } 1972} 1973