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