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