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