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