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