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