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