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