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