Paint.java revision c39a6e0c51e182338deb8b63d07933b585134929
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.SpannableString; 21import android.text.SpannedString; 22import android.text.GraphicsOperations; 23 24/** 25 * The Paint class holds the style and color information about how to draw 26 * geometries, text and bitmaps. 27 */ 28public class Paint { 29 30 /*package*/ int mNativePaint; 31 private ColorFilter mColorFilter; 32 private MaskFilter mMaskFilter; 33 private PathEffect mPathEffect; 34 private Rasterizer mRasterizer; 35 private Shader mShader; 36 private Typeface mTypeface; 37 private Xfermode mXfermode; 38 39 private static final Style[] sStyleArray = { 40 Style.FILL, Style.STROKE, Style.FILL_AND_STROKE 41 }; 42 private static final Cap[] sCapArray = { 43 Cap.BUTT, Cap.ROUND, Cap.SQUARE 44 }; 45 private static final Join[] sJoinArray = { 46 Join.MITER, Join.ROUND, Join.BEVEL 47 }; 48 private static final Align[] sAlignArray = { 49 Align.LEFT, Align.CENTER, Align.RIGHT 50 }; 51 52 /** bit mask for the flag enabling antialiasing */ 53 public static final int ANTI_ALIAS_FLAG = 0x01; 54 /** bit mask for the flag enabling bitmap filtering */ 55 public static final int FILTER_BITMAP_FLAG = 0x02; 56 /** bit mask for the flag enabling dithering */ 57 public static final int DITHER_FLAG = 0x04; 58 /** bit mask for the flag enabling underline text */ 59 public static final int UNDERLINE_TEXT_FLAG = 0x08; 60 /** bit mask for the flag enabling strike-thru text */ 61 public static final int STRIKE_THRU_TEXT_FLAG = 0x10; 62 /** bit mask for the flag enabling fake-bold text */ 63 public static final int FAKE_BOLD_TEXT_FLAG = 0x20; 64 /** bit mask for the flag enabling linear-text (no caching) */ 65 public static final int LINEAR_TEXT_FLAG = 0x40; 66 /** bit mask for the flag enabling subpixel-text */ 67 public static final int SUBPIXEL_TEXT_FLAG = 0x80; 68 /** bit mask for the flag enabling device kerning for text */ 69 public static final int DEV_KERN_TEXT_FLAG = 0x100; 70 71 // we use this when we first create a paint 72 private static final int DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG; 73 74 /** 75 * The Style specifies if the primitive being drawn is filled, 76 * stroked, or both (in the same color). The default is FILL. 77 */ 78 public enum Style { 79 /** 80 * Geometry and text drawn with this style will be filled, ignoring all 81 * stroke-related settings in the paint. 82 */ 83 FILL (0), 84 /** 85 * Geometry and text drawn with this style will be stroked, respecting 86 * the stroke-related fields on the paint. 87 */ 88 STROKE (1), 89 /** 90 * Geometry and text drawn with this style will be both filled and 91 * stroked at the same time, respecting the stroke-related fields on 92 * the paint. 93 */ 94 FILL_AND_STROKE (2); 95 96 Style(int nativeInt) { 97 this.nativeInt = nativeInt; 98 } 99 final int nativeInt; 100 } 101 102 /** 103 * The Cap specifies the treatment for the beginning and ending of 104 * stroked lines and paths. The default is BUTT. 105 */ 106 public enum Cap { 107 /** 108 * The stroke ends with the path, and does not project beyond it. 109 */ 110 BUTT (0), 111 /** 112 * The stroke projects out as a semicircle, with the center at the 113 * end of the path. 114 */ 115 ROUND (1), 116 /** 117 * The stroke projects out as a square, with the center at the end 118 * of the path. 119 */ 120 SQUARE (2); 121 122 private Cap(int nativeInt) { 123 this.nativeInt = nativeInt; 124 } 125 final int nativeInt; 126 } 127 128 /** 129 * The Join specifies the treatment where lines and curve segments 130 * join on a stroked path. The default is MITER. 131 */ 132 public enum Join { 133 /** 134 * The outer edges of a join meet at a sharp angle 135 */ 136 MITER (0), 137 /** 138 * The outer edges of a join meet in a circular arc. 139 */ 140 ROUND (1), 141 /** 142 * The outer edges of a join meet with a straight line 143 */ 144 BEVEL (2); 145 146 private Join(int nativeInt) { 147 this.nativeInt = nativeInt; 148 } 149 final int nativeInt; 150 } 151 152 /** 153 * Align specifies how drawText aligns its text relative to the 154 * [x,y] coordinates. The default is LEFT. 155 */ 156 public enum Align { 157 /** 158 * The text is drawn to the right of the x,y origin 159 */ 160 LEFT (0), 161 /** 162 * The text is drawn centered horizontally on the x,y origin 163 */ 164 CENTER (1), 165 /** 166 * The text is drawn to the left of the x,y origin 167 */ 168 RIGHT (2); 169 170 private Align(int nativeInt) { 171 this.nativeInt = nativeInt; 172 } 173 final int nativeInt; 174 } 175 176 /** 177 * Create a new paint with default settings. 178 */ 179 public Paint() { 180 this(0); 181 } 182 183 /** 184 * Create a new paint with the specified flags. Use setFlags() to change 185 * these after the paint is created. 186 * 187 * @param flags initial flag bits, as if they were passed via setFlags(). 188 */ 189 public Paint(int flags) { 190 mNativePaint = native_init(); 191 setFlags(flags | DEFAULT_PAINT_FLAGS); 192 } 193 194 /** 195 * Create a new paint, initialized with the attributes in the specified 196 * paint parameter. 197 * 198 * @param paint Existing paint used to initialized the attributes of the 199 * new paint. 200 */ 201 public Paint(Paint paint) { 202 mNativePaint = native_initWithPaint(paint.mNativePaint); 203 } 204 205 /** Restores the paint to its default settings. */ 206 public void reset() { 207 native_reset(mNativePaint); 208 setFlags(DEFAULT_PAINT_FLAGS); 209 } 210 211 /** 212 * Copy the fields from src into this paint. This is equivalent to calling 213 * get() on all of the src fields, and calling the corresponding set() 214 * methods on this. 215 */ 216 public void set(Paint src) { 217 if (this != src) { 218 // copy over the native settings 219 native_set(mNativePaint, src.mNativePaint); 220 // copy over our java settings 221 mColorFilter = src.mColorFilter; 222 mMaskFilter = src.mMaskFilter; 223 mPathEffect = src.mPathEffect; 224 mRasterizer = src.mRasterizer; 225 mShader = src.mShader; 226 mTypeface = src.mTypeface; 227 mXfermode = src.mXfermode; 228 } 229 } 230 231 /** 232 * Return the paint's flags. Use the Flag enum to test flag values. 233 * 234 * @return the paint's flags (see enums ending in _Flag for bit masks) 235 */ 236 public native int getFlags(); 237 238 /** 239 * Set the paint's flags. Use the Flag enum to specific flag values. 240 * 241 * @param flags The new flag bits for the paint 242 */ 243 public native void setFlags(int flags); 244 245 /** 246 * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set 247 * AntiAliasing smooths out the edges of what is being drawn, but is has 248 * no impact on the interior of the shape. See setDither() and 249 * setFilterBitmap() to affect how colors are treated. 250 * 251 * @return true if the antialias bit is set in the paint's flags. 252 */ 253 public final boolean isAntiAlias() { 254 return (getFlags() & ANTI_ALIAS_FLAG) != 0; 255 } 256 257 /** 258 * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit 259 * AntiAliasing smooths out the edges of what is being drawn, but is has 260 * no impact on the interior of the shape. See setDither() and 261 * setFilterBitmap() to affect how colors are treated. 262 * 263 * @param aa true to set the antialias bit in the flags, false to clear it 264 */ 265 public native void setAntiAlias(boolean aa); 266 267 /** 268 * Helper for getFlags(), returning true if DITHER_FLAG bit is set 269 * Dithering affects how colors that are higher precision than the device 270 * are down-sampled. No dithering is generally faster, but higher precision 271 * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to 272 * distribute the error inherent in this process, to reduce the visual 273 * artifacts. 274 * 275 * @return true if the dithering bit is set in the paint's flags. 276 */ 277 public final boolean isDither() { 278 return (getFlags() & DITHER_FLAG) != 0; 279 } 280 281 /** 282 * Helper for setFlags(), setting or clearing the DITHER_FLAG bit 283 * Dithering affects how colors that are higher precision than the device 284 * are down-sampled. No dithering is generally faster, but higher precision 285 * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to 286 * distribute the error inherent in this process, to reduce the visual 287 * artifacts. 288 * 289 * @param dither true to set the dithering bit in flags, false to clear it 290 */ 291 public native void setDither(boolean dither); 292 293 /** 294 * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set 295 * 296 * @return true if the lineartext bit is set in the paint's flags 297 */ 298 public final boolean isLinearText() { 299 return (getFlags() & LINEAR_TEXT_FLAG) != 0; 300 } 301 302 /** 303 * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit 304 * 305 * @param linearText true to set the linearText bit in the paint's flags, 306 * false to clear it. 307 */ 308 public native void setLinearText(boolean linearText); 309 310 /** 311 * Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set 312 * 313 * @return true if the subpixel bit is set in the paint's flags 314 */ 315 public final boolean isSubpixelText() { 316 return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0; 317 } 318 319 /** 320 * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit 321 * 322 * @param subpixelText true to set the subpixelText bit in the paint's 323 * flags, false to clear it. 324 */ 325 public native void setSubpixelText(boolean subpixelText); 326 327 /** 328 * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set 329 * 330 * @return true if the underlineText bit is set in the paint's flags. 331 */ 332 public final boolean isUnderlineText() { 333 return (getFlags() & UNDERLINE_TEXT_FLAG) != 0; 334 } 335 336 /** 337 * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit 338 * 339 * @param underlineText true to set the underlineText bit in the paint's 340 * flags, false to clear it. 341 */ 342 public native void setUnderlineText(boolean underlineText); 343 344 /** 345 * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set 346 * 347 * @return true if the strikeThruText bit is set in the paint's flags. 348 */ 349 public final boolean isStrikeThruText() { 350 return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0; 351 } 352 353 /** 354 * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit 355 * 356 * @param strikeThruText true to set the strikeThruText bit in the paint's 357 * flags, false to clear it. 358 */ 359 public native void setStrikeThruText(boolean strikeThruText); 360 361 /** 362 * Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set 363 * 364 * @return true if the fakeBoldText bit is set in the paint's flags. 365 */ 366 public final boolean isFakeBoldText() { 367 return (getFlags() & FAKE_BOLD_TEXT_FLAG) != 0; 368 } 369 370 /** 371 * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit 372 * 373 * @param fakeBoldText true to set the fakeBoldText bit in the paint's 374 * flags, false to clear it. 375 */ 376 public native void setFakeBoldText(boolean fakeBoldText); 377 378 /** 379 * Whether or not the bitmap filter is activated. 380 * Filtering affects the sampling of bitmaps when they are transformed. 381 * Filtering does not affect how the colors in the bitmap are converted into 382 * device pixels. That is dependent on dithering and xfermodes. 383 * 384 * @see #setFilterBitmap(boolean) setFilterBitmap() 385 */ 386 public final boolean isFilterBitmap() { 387 return (getFlags() & FILTER_BITMAP_FLAG) != 0; 388 } 389 390 /** 391 * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit. 392 * Filtering affects the sampling of bitmaps when they are transformed. 393 * Filtering does not affect how the colors in the bitmap are converted into 394 * device pixels. That is dependent on dithering and xfermodes. 395 * 396 * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's 397 * flags, false to clear it. 398 */ 399 public native void setFilterBitmap(boolean filter); 400 401 /** 402 * Return the paint's style, used for controlling how primitives' 403 * geometries are interpreted (except for drawBitmap, which always assumes 404 * FILL_STYLE). 405 * 406 * @return the paint's style setting (Fill, Stroke, StrokeAndFill) 407 */ 408 public Style getStyle() { 409 return sStyleArray[native_getStyle(mNativePaint)]; 410 } 411 412 /** 413 * Set the paint's style, used for controlling how primitives' 414 * geometries are interpreted (except for drawBitmap, which always assumes 415 * Fill). 416 * 417 * @param style The new style to set in the paint 418 */ 419 public void setStyle(Style style) { 420 native_setStyle(mNativePaint, style.nativeInt); 421 } 422 423 /** 424 * Return the paint's color. Note that the color is a 32bit value 425 * containing alpha as well as r,g,b. This 32bit value is not premultiplied, 426 * meaning that its alpha can be any value, regardless of the values of 427 * r,g,b. See the Color class for more details. 428 * 429 * @return the paint's color (and alpha). 430 */ 431 public native int getColor(); 432 433 /** 434 * Set the paint's color. Note that the color is an int containing alpha 435 * as well as r,g,b. This 32bit value is not premultiplied, meaning that 436 * its alpha can be any value, regardless of the values of r,g,b. 437 * See the Color class for more details. 438 * 439 * @param color The new color (including alpha) to set in the paint. 440 */ 441 public native void setColor(int color); 442 443 /** 444 * Helper to getColor() that just returns the color's alpha value. This is 445 * the same as calling getColor() >>> 24. It always returns a value between 446 * 0 (completely transparent) and 255 (completely opaque). 447 * 448 * @return the alpha component of the paint's color. 449 */ 450 public native int getAlpha(); 451 452 /** 453 * Helper to setColor(), that only assigns the color's alpha value, 454 * leaving its r,g,b values unchanged. Results are undefined if the alpha 455 * value is outside of the range [0..255] 456 * 457 * @param a set the alpha component [0..255] of the paint's color. 458 */ 459 public native void setAlpha(int a); 460 461 /** 462 * Helper to setColor(), that takes a,r,g,b and constructs the color int 463 * 464 * @param a The new alpha component (0..255) of the paint's color. 465 * @param r The new red component (0..255) of the paint's color. 466 * @param g The new green component (0..255) of the paint's color. 467 * @param b The new blue component (0..255) of the paint's color. 468 */ 469 public void setARGB(int a, int r, int g, int b) { 470 setColor((a << 24) | (r << 16) | (g << 8) | b); 471 } 472 473 /** 474 * Return the width for stroking. 475 * <p /> 476 * A value of 0 strokes in hairline mode. 477 * Hairlines always draws a single pixel independent of the canva's matrix. 478 * 479 * @return the paint's stroke width, used whenever the paint's style is 480 * Stroke or StrokeAndFill. 481 */ 482 public native float getStrokeWidth(); 483 484 /** 485 * Set the width for stroking. 486 * Pass 0 to stroke in hairline mode. 487 * Hairlines always draws a single pixel independent of the canva's matrix. 488 * 489 * @param width set the paint's stroke width, used whenever the paint's 490 * style is Stroke or StrokeAndFill. 491 */ 492 public native void setStrokeWidth(float width); 493 494 /** 495 * Return the paint's stroke miter value. Used to control the behavior 496 * of miter joins when the joins angle is sharp. 497 * 498 * @return the paint's miter limit, used whenever the paint's style is 499 * Stroke or StrokeAndFill. 500 */ 501 public native float getStrokeMiter(); 502 503 /** 504 * Set the paint's stroke miter value. This is used to control the behavior 505 * of miter joins when the joins angle is sharp. This value must be >= 0. 506 * 507 * @param miter set the miter limit on the paint, used whenever the paint's 508 * style is Stroke or StrokeAndFill. 509 */ 510 public native void setStrokeMiter(float miter); 511 512 /** 513 * Return the paint's Cap, controlling how the start and end of stroked 514 * lines and paths are treated. 515 * 516 * @return the line cap style for the paint, used whenever the paint's 517 * style is Stroke or StrokeAndFill. 518 */ 519 public Cap getStrokeCap() { 520 return sCapArray[native_getStrokeCap(mNativePaint)]; 521 } 522 523 /** 524 * Set the paint's Cap. 525 * 526 * @param cap set the paint's line cap style, used whenever the paint's 527 * style is Stroke or StrokeAndFill. 528 */ 529 public void setStrokeCap(Cap cap) { 530 native_setStrokeCap(mNativePaint, cap.nativeInt); 531 } 532 533 /** 534 * Return the paint's stroke join type. 535 * 536 * @return the paint's Join. 537 */ 538 public Join getStrokeJoin() { 539 return sJoinArray[native_getStrokeJoin(mNativePaint)]; 540 } 541 542 /** 543 * Set the paint's Join. 544 * 545 * @param join set the paint's Join, used whenever the paint's style is 546 * Stroke or StrokeAndFill. 547 */ 548 public void setStrokeJoin(Join join) { 549 native_setStrokeJoin(mNativePaint, join.nativeInt); 550 } 551 552 /** 553 * Applies any/all effects (patheffect, stroking) to src, returning the 554 * result in dst. The result is that drawing src with this paint will be 555 * the same as drawing dst with a default paint (at least from the 556 * geometric perspective). 557 * 558 * @param src input path 559 * @param dst output path (may be the same as src) 560 * @return true if the path should be filled, or false if it should be 561 * drawn with a hairline (width == 0) 562 */ 563 public boolean getFillPath(Path src, Path dst) { 564 return native_getFillPath(mNativePaint, src.ni(), dst.ni()); 565 } 566 567 /** 568 * Get the paint's shader object. 569 * 570 * @return the paint's shader (or null) 571 */ 572 public Shader getShader() { 573 return mShader; 574 } 575 576 /** 577 * Set or clear the shader object. 578 * <p /> 579 * Pass null to clear any previous shader. 580 * As a convenience, the parameter passed is also returned. 581 * 582 * @param shader May be null. the new shader to be installed in the paint 583 * @return shader 584 */ 585 public Shader setShader(Shader shader) { 586 int shaderNative = 0; 587 if (shader != null) 588 shaderNative = shader.native_instance; 589 native_setShader(mNativePaint, shaderNative); 590 mShader = shader; 591 return shader; 592 } 593 594 /** 595 * Get the paint's colorfilter (maybe be null). 596 * 597 * @return the paint's colorfilter (maybe be null) 598 */ 599 public ColorFilter getColorFilter() { 600 return mColorFilter; 601 } 602 603 /** 604 * Set or clear the paint's colorfilter, returning the parameter. 605 * 606 * @param filter May be null. The new filter to be installed in the paint 607 * @return filter 608 */ 609 public ColorFilter setColorFilter(ColorFilter filter) { 610 int filterNative = 0; 611 if (filter != null) 612 filterNative = filter.native_instance; 613 native_setColorFilter(mNativePaint, filterNative); 614 mColorFilter = filter; 615 return filter; 616 } 617 618 /** 619 * Get the paint's xfermode object. 620 * 621 * @return the paint's xfermode (or null) 622 */ 623 public Xfermode getXfermode() { 624 return mXfermode; 625 } 626 627 /** 628 * Set or clear the xfermode object. 629 * <p /> 630 * Pass null to clear any previous xfermode. 631 * As a convenience, the parameter passed is also returned. 632 * 633 * @param xfermode May be null. The xfermode to be installed in the paint 634 * @return xfermode 635 */ 636 public Xfermode setXfermode(Xfermode xfermode) { 637 int xfermodeNative = 0; 638 if (xfermode != null) 639 xfermodeNative = xfermode.native_instance; 640 native_setXfermode(mNativePaint, xfermodeNative); 641 mXfermode = xfermode; 642 return xfermode; 643 } 644 645 /** 646 * Get the paint's patheffect object. 647 * 648 * @return the paint's patheffect (or null) 649 */ 650 public PathEffect getPathEffect() { 651 return mPathEffect; 652 } 653 654 /** 655 * Set or clear the patheffect object. 656 * <p /> 657 * Pass null to clear any previous patheffect. 658 * As a convenience, the parameter passed is also returned. 659 * 660 * @param effect May be null. The patheffect to be installed in the paint 661 * @return effect 662 */ 663 public PathEffect setPathEffect(PathEffect effect) { 664 int effectNative = 0; 665 if (effect != null) { 666 effectNative = effect.native_instance; 667 } 668 native_setPathEffect(mNativePaint, effectNative); 669 mPathEffect = effect; 670 return effect; 671 } 672 673 /** 674 * Get the paint's maskfilter object. 675 * 676 * @return the paint's maskfilter (or null) 677 */ 678 public MaskFilter getMaskFilter() { 679 return mMaskFilter; 680 } 681 682 /** 683 * Set or clear the maskfilter object. 684 * <p /> 685 * Pass null to clear any previous maskfilter. 686 * As a convenience, the parameter passed is also returned. 687 * 688 * @param maskfilter May be null. The maskfilter to be installed in the 689 * paint 690 * @return maskfilter 691 */ 692 public MaskFilter setMaskFilter(MaskFilter maskfilter) { 693 int maskfilterNative = 0; 694 if (maskfilter != null) { 695 maskfilterNative = maskfilter.native_instance; 696 } 697 native_setMaskFilter(mNativePaint, maskfilterNative); 698 mMaskFilter = maskfilter; 699 return maskfilter; 700 } 701 702 /** 703 * Get the paint's typeface object. 704 * <p /> 705 * The typeface object identifies which font to use when drawing or 706 * measuring text. 707 * 708 * @return the paint's typeface (or null) 709 */ 710 public Typeface getTypeface() { 711 return mTypeface; 712 } 713 714 /** 715 * Set or clear the typeface object. 716 * <p /> 717 * Pass null to clear any previous typeface. 718 * As a convenience, the parameter passed is also returned. 719 * 720 * @param typeface May be null. The typeface to be installed in the paint 721 * @return typeface 722 */ 723 public Typeface setTypeface(Typeface typeface) { 724 int typefaceNative = 0; 725 if (typeface != null) { 726 typefaceNative = typeface.native_instance; 727 } 728 native_setTypeface(mNativePaint, typefaceNative); 729 mTypeface = typeface; 730 return typeface; 731 } 732 733 /** 734 * Get the paint's rasterizer (or null). 735 * <p /> 736 * The raster controls/modifies how paths/text are turned into alpha masks. 737 * 738 * @return the paint's rasterizer (or null) 739 */ 740 public Rasterizer getRasterizer() { 741 return mRasterizer; 742 } 743 744 /** 745 * Set or clear the rasterizer object. 746 * <p /> 747 * Pass null to clear any previous rasterizer. 748 * As a convenience, the parameter passed is also returned. 749 * 750 * @param rasterizer May be null. The new rasterizer to be installed in 751 * the paint. 752 * @return rasterizer 753 */ 754 public Rasterizer setRasterizer(Rasterizer rasterizer) { 755 int rasterizerNative = 0; 756 if (rasterizer != null) { 757 rasterizerNative = rasterizer.native_instance; 758 } 759 native_setRasterizer(mNativePaint, rasterizerNative); 760 mRasterizer = rasterizer; 761 return rasterizer; 762 } 763 764 /** 765 * Temporary API to expose layer drawing. This draws a shadow layer below 766 * the main layer, with the specified offset and color, and blur radius. 767 * If radius is 0, then the shadow layer is removed. 768 */ 769 public native void setShadowLayer(float radius, float dx, float dy, 770 int color); 771 772 /** 773 * Temporary API to clear the shadow layer. 774 */ 775 public void clearShadowLayer() { 776 setShadowLayer(0, 0, 0, 0); 777 } 778 779 /** 780 * Return the paint's Align value for drawing text. This controls how the 781 * text is positioned relative to its origin. LEFT align means that all of 782 * the text will be drawn to the right of its origin (i.e. the origin 783 * specifieds the LEFT edge of the text) and so on. 784 * 785 * @return the paint's Align value for drawing text. 786 */ 787 public Align getTextAlign() { 788 return sAlignArray[native_getTextAlign(mNativePaint)]; 789 } 790 791 /** 792 * Set the paint's text alignment. This controls how the 793 * text is positioned relative to its origin. LEFT align means that all of 794 * the text will be drawn to the right of its origin (i.e. the origin 795 * specifieds the LEFT edge of the text) and so on. 796 * 797 * @param align set the paint's Align value for drawing text. 798 */ 799 public void setTextAlign(Align align) { 800 native_setTextAlign(mNativePaint, align.nativeInt); 801 } 802 803 /** 804 * Return the paint's text size. 805 * 806 * @return the paint's text size. 807 */ 808 public native float getTextSize(); 809 810 /** 811 * Set the paint's text size. This value must be > 0 812 * 813 * @param textSize set the paint's text size. 814 */ 815 public native void setTextSize(float textSize); 816 817 /** 818 * Return the paint's horizontal scale factor for text. The default value 819 * is 1.0. 820 * 821 * @return the paint's scale factor in X for drawing/measuring text 822 */ 823 public native float getTextScaleX(); 824 825 /** 826 * Set the paint's horizontal scale factor for text. The default value 827 * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will 828 * stretch the text narrower. 829 * 830 * @param scaleX set the paint's scale in X for drawing/measuring text. 831 */ 832 public native void setTextScaleX(float scaleX); 833 834 /** 835 * Return the paint's horizontal skew factor for text. The default value 836 * is 0. 837 * 838 * @return the paint's skew factor in X for drawing text. 839 */ 840 public native float getTextSkewX(); 841 842 /** 843 * Set the paint's horizontal skew factor for text. The default value 844 * is 0. For approximating oblique text, use values around -0.25. 845 * 846 * @param skewX set the paint's skew factor in X for drawing text. 847 */ 848 public native void setTextSkewX(float skewX); 849 850 /** 851 * Return the distance above (negative) the baseline (ascent) based on the 852 * current typeface and text size. 853 * 854 * @return the distance above (negative) the baseline (ascent) based on the 855 * current typeface and text size. 856 */ 857 public native float ascent(); 858 859 /** 860 * Return the distance below (positive) the baseline (descent) based on the 861 * current typeface and text size. 862 * 863 * @return the distance below (positive) the baseline (descent) based on 864 * the current typeface and text size. 865 */ 866 public native float descent(); 867 868 /** 869 * Class that describes the various metrics for a font at a given text size. 870 * Remember, Y values increase going down, so those values will be positive, 871 * and values that measure distances going up will be negative. This class 872 * is returned by getFontMetrics(). 873 */ 874 public static class FontMetrics { 875 /** 876 * The maximum distance above the baseline for the tallest glyph in 877 * the font at a given text size. 878 */ 879 public float top; 880 /** 881 * The recommended distance above the baseline for singled spaced text. 882 */ 883 public float ascent; 884 /** 885 * The recommended distance below the baseline for singled spaced text. 886 */ 887 public float descent; 888 /** 889 * The maximum distance below the baseline for the lowest glyph in 890 * the font at a given text size. 891 */ 892 public float bottom; 893 /** 894 * The recommended additional space to add between lines of text. 895 */ 896 public float leading; 897 } 898 899 /** 900 * Return the font's recommended interline spacing, given the Paint's 901 * settings for typeface, textSize, etc. If metrics is not null, return the 902 * fontmetric values in it. 903 * 904 * @param metrics If this object is not null, its fields are filled with 905 * the appropriate values given the paint's text attributes. 906 * @return the font's recommended interline spacing. 907 */ 908 public native float getFontMetrics(FontMetrics metrics); 909 910 /** 911 * Allocates a new FontMetrics object, and then calls getFontMetrics(fm) 912 * with it, returning the object. 913 */ 914 public FontMetrics getFontMetrics() { 915 FontMetrics fm = new FontMetrics(); 916 getFontMetrics(fm); 917 return fm; 918 } 919 920 /** 921 * Convenience method for callers that want to have FontMetrics values as 922 * integers. 923 */ 924 public static class FontMetricsInt { 925 public int top; 926 public int ascent; 927 public int descent; 928 public int bottom; 929 public int leading; 930 931 @Override public String toString() { 932 return "FontMetricsInt: top=" + top + " ascent=" + ascent + 933 " descent=" + descent + " bottom=" + bottom + 934 " leading=" + leading; 935 } 936 } 937 938 /** 939 * Return the font's interline spacing, given the Paint's settings for 940 * typeface, textSize, etc. If metrics is not null, return the fontmetric 941 * values in it. Note: all values have been converted to integers from 942 * floats, in such a way has to make the answers useful for both spacing 943 * and clipping. If you want more control over the rounding, call 944 * getFontMetrics(). 945 * 946 * @return the font's interline spacing. 947 */ 948 public native int getFontMetricsInt(FontMetricsInt fmi); 949 950 public FontMetricsInt getFontMetricsInt() { 951 FontMetricsInt fm = new FontMetricsInt(); 952 getFontMetricsInt(fm); 953 return fm; 954 } 955 956 /** 957 * Return the recommend line spacing based on the current typeface and 958 * text size. 959 * 960 * @return recommend line spacing based on the current typeface and 961 * text size. 962 */ 963 public float getFontSpacing() { 964 return getFontMetrics(null); 965 } 966 967 /** 968 * Return the width of the text. 969 * 970 * @param text The text to measure 971 * @param index The index of the first character to start measuring 972 * @param count THe number of characters to measure, beginning with start 973 * @return The width of the text 974 */ 975 public native float measureText(char[] text, int index, int count); 976 977 /** 978 * Return the width of the text. 979 * 980 * @param text The text to measure 981 * @param start The index of the first character to start measuring 982 * @param end 1 beyond the index of the last character to measure 983 * @return The width of the text 984 */ 985 public native float measureText(String text, int start, int end); 986 987 /** 988 * Return the width of the text. 989 * 990 * @param text The text to measure 991 * @return The width of the text 992 */ 993 public native float measureText(String text); 994 995 /** 996 * Return the width of the text. 997 * 998 * @param text The text to measure 999 * @param start The index of the first character to start measuring 1000 * @param end 1 beyond the index of the last character to measure 1001 * @return The width of the text 1002 */ 1003 public float measureText(CharSequence text, int start, int end) { 1004 if (text instanceof String) { 1005 return measureText((String)text, start, end); 1006 } 1007 if (text instanceof SpannedString || 1008 text instanceof SpannableString) { 1009 return measureText(text.toString(), start, end); 1010 } 1011 if (text instanceof GraphicsOperations) { 1012 return ((GraphicsOperations)text).measureText(start, end, this); 1013 } 1014 1015 char[] buf = TemporaryBuffer.obtain(end - start); 1016 TextUtils.getChars(text, start, end, buf, 0); 1017 float result = measureText(buf, 0, end - start); 1018 TemporaryBuffer.recycle(buf); 1019 return result; 1020 } 1021 1022 /** 1023 * Measure the text, stopping early if the measured width exceeds maxWidth. 1024 * Return the number of chars that were measured, and if measuredWidth is 1025 * not null, return in it the actual width measured. 1026 * 1027 * @param text The text to measure 1028 * @param index The offset into text to begin measuring at 1029 * @param count The number of maximum number of entries to measure. If count 1030 * is negative, then the characters before index are measured 1031 * in reverse order. This allows for measuring the end of 1032 * string. 1033 * @param maxWidth The maximum width to accumulate. 1034 * @param measuredWidth Optional. If not null, returns the actual width 1035 * measured. 1036 * @return The number of chars that were measured. Will always be <= 1037 * abs(count). 1038 */ 1039 public native int breakText(char[] text, int index, int count, 1040 float maxWidth, float[] measuredWidth); 1041 1042 /** 1043 * Measure the text, stopping early if the measured width exceeds maxWidth. 1044 * Return the number of chars that were measured, and if measuredWidth is 1045 * not null, return in it the actual width measured. 1046 * 1047 * @param text The text to measure 1048 * @param start The offset into text to begin measuring at 1049 * @param end The end of the text slice to measure. 1050 * @param measureForwards If true, measure forwards, starting at start. 1051 * Otherwise, measure backwards, starting with end. 1052 * @param maxWidth The maximum width to accumulate. 1053 * @param measuredWidth Optional. If not null, returns the actual width 1054 * measured. 1055 * @return The number of chars that were measured. Will always be <= 1056 * abs(end - start). 1057 */ 1058 public int breakText(CharSequence text, int start, int end, 1059 boolean measureForwards, 1060 float maxWidth, float[] measuredWidth) { 1061 if (start == 0 && text instanceof String && end == text.length()) { 1062 return breakText((String) text, measureForwards, maxWidth, 1063 measuredWidth); 1064 } 1065 1066 char[] buf = TemporaryBuffer.obtain(end - start); 1067 int result; 1068 1069 TextUtils.getChars(text, start, end, buf, 0); 1070 1071 if (measureForwards) { 1072 result = breakText(buf, 0, end - start, maxWidth, measuredWidth); 1073 } else { 1074 result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth); 1075 } 1076 1077 TemporaryBuffer.recycle(buf); 1078 return result; 1079 } 1080 1081 /** 1082 * Measure the text, stopping early if the measured width exceeds maxWidth. 1083 * Return the number of chars that were measured, and if measuredWidth is 1084 * not null, return in it the actual width measured. 1085 * 1086 * @param text The text to measure 1087 * @param measureForwards If true, measure forwards, starting at index. 1088 * Otherwise, measure backwards, starting with the 1089 * last character in the string. 1090 * @param maxWidth The maximum width to accumulate. 1091 * @param measuredWidth Optional. If not null, returns the actual width 1092 * measured. 1093 * @return The number of chars that were measured. Will always be <= 1094 * abs(count). 1095 */ 1096 public native int breakText(String text, boolean measureForwards, 1097 float maxWidth, float[] measuredWidth); 1098 1099 /** 1100 * Return the advance widths for the characters in the string. 1101 * 1102 * @param text The text to measure 1103 * @param index The index of the first char to to measure 1104 * @param count The number of chars starting with index to measure 1105 * @param widths array to receive the advance widths of the characters. 1106 * Must be at least a large as count. 1107 * @return the actual number of widths returned. 1108 */ 1109 public int getTextWidths(char[] text, int index, int count, 1110 float[] widths) { 1111 if ((index | count) < 0 || index + count > text.length 1112 || count > widths.length) { 1113 throw new ArrayIndexOutOfBoundsException(); 1114 } 1115 return native_getTextWidths(mNativePaint, text, index, count, widths); 1116 } 1117 1118 /** 1119 * Return the advance widths for the characters in the string. 1120 * 1121 * @param text The text to measure 1122 * @param start The index of the first char to to measure 1123 * @param end The end of the text slice to measure 1124 * @param widths array to receive the advance widths of the characters. 1125 * Must be at least a large as (end - start). 1126 * @return the actual number of widths returned. 1127 */ 1128 public int getTextWidths(CharSequence text, int start, int end, 1129 float[] widths) { 1130 if (text instanceof String) { 1131 return getTextWidths((String) text, start, end, widths); 1132 } 1133 if (text instanceof SpannedString || 1134 text instanceof SpannableString) { 1135 return getTextWidths(text.toString(), start, end, widths); 1136 } 1137 if (text instanceof GraphicsOperations) { 1138 return ((GraphicsOperations) text).getTextWidths(start, end, 1139 widths, this); 1140 } 1141 1142 char[] buf = TemporaryBuffer.obtain(end - start); 1143 TextUtils.getChars(text, start, end, buf, 0); 1144 int result = getTextWidths(buf, 0, end - start, widths); 1145 TemporaryBuffer.recycle(buf); 1146 return result; 1147 } 1148 1149 /** 1150 * Return the advance widths for the characters in the string. 1151 * 1152 * @param text The text to measure 1153 * @param start The index of the first char to to measure 1154 * @param end The end of the text slice to measure 1155 * @param widths array to receive the advance widths of the characters. 1156 * Must be at least a large as the text. 1157 * @return the number of unichars in the specified text. 1158 */ 1159 public int getTextWidths(String text, int start, int end, float[] widths) { 1160 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1161 throw new IndexOutOfBoundsException(); 1162 } 1163 if (end - start > widths.length) { 1164 throw new ArrayIndexOutOfBoundsException(); 1165 } 1166 return native_getTextWidths(mNativePaint, text, start, end, widths); 1167 } 1168 1169 /** 1170 * Return the advance widths for the characters in the string. 1171 * 1172 * @param text The text to measure 1173 * @param widths array to receive the advance widths of the characters. 1174 * Must be at least a large as the text. 1175 * @return the number of unichars in the specified text. 1176 */ 1177 public int getTextWidths(String text, float[] widths) { 1178 return getTextWidths(text, 0, text.length(), widths); 1179 } 1180 1181 /** 1182 * Return the path (outline) for the specified text. 1183 * Note: just like Canvas.drawText, this will respect the Align setting in 1184 * the paint. 1185 * 1186 * @param text The text to retrieve the path from 1187 * @param index The index of the first character in text 1188 * @param count The number of characterss starting with index 1189 * @param x The x coordinate of the text's origin 1190 * @param y The y coordinate of the text's origin 1191 * @param path The path to receive the data describing the text. Must 1192 * be allocated by the caller. 1193 */ 1194 public void getTextPath(char[] text, int index, int count, 1195 float x, float y, Path path) { 1196 if ((index | count) < 0 || index + count > text.length) { 1197 throw new ArrayIndexOutOfBoundsException(); 1198 } 1199 native_getTextPath(mNativePaint, text, index, count, x, y, path.ni()); 1200 } 1201 1202 /** 1203 * Return the path (outline) for the specified text. 1204 * Note: just like Canvas.drawText, this will respect the Align setting 1205 * in the paint. 1206 * 1207 * @param text The text to retrieve the path from 1208 * @param start The first character in the text 1209 * @param end 1 past the last charcter in the text 1210 * @param x The x coordinate of the text's origin 1211 * @param y The y coordinate of the text's origin 1212 * @param path The path to receive the data describing the text. Must 1213 * be allocated by the caller. 1214 */ 1215 public void getTextPath(String text, int start, int end, 1216 float x, float y, Path path) { 1217 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1218 throw new IndexOutOfBoundsException(); 1219 } 1220 native_getTextPath(mNativePaint, text, start, end, x, y, path.ni()); 1221 } 1222 1223 /** 1224 * Return in bounds (allocated by the caller) the smallest rectangle that 1225 * encloses all of the characters, with an implied origin at (0,0). 1226 * 1227 * @param text String to measure and return its bounds 1228 * @param start Index of the first char in the string to measure 1229 * @param end 1 past the last char in the string measure 1230 * @param bounds Returns the unioned bounds of all the text. Must be 1231 * allocated by the caller. 1232 */ 1233 public void getTextBounds(String text, int start, int end, Rect bounds) { 1234 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1235 throw new IndexOutOfBoundsException(); 1236 } 1237 if (bounds == null) { 1238 throw new NullPointerException("need bounds Rect"); 1239 } 1240 nativeGetStringBounds(mNativePaint, text, start, end, bounds); 1241 } 1242 1243 /** 1244 * Return in bounds (allocated by the caller) the smallest rectangle that 1245 * encloses all of the characters, with an implied origin at (0,0). 1246 * 1247 * @param text Array of chars to measure and return their unioned bounds 1248 * @param index Index of the first char in the array to measure 1249 * @param count The number of chars, beginning at index, to measure 1250 * @param bounds Returns the unioned bounds of all the text. Must be 1251 * allocated by the caller. 1252 */ 1253 public void getTextBounds(char[] text, int index, int count, Rect bounds) { 1254 if ((index | count) < 0 || index + count > text.length) { 1255 throw new ArrayIndexOutOfBoundsException(); 1256 } 1257 if (bounds == null) { 1258 throw new NullPointerException("need bounds Rect"); 1259 } 1260 nativeGetCharArrayBounds(mNativePaint, text, index, count, bounds); 1261 } 1262 1263 protected void finalize() throws Throwable { 1264 finalizer(mNativePaint); 1265 } 1266 1267 private static native int native_init(); 1268 private static native int native_initWithPaint(int paint); 1269 private static native void native_reset(int native_object); 1270 private static native void native_set(int native_dst, int native_src); 1271 private static native int native_getStyle(int native_object); 1272 private static native void native_setStyle(int native_object, int style); 1273 private static native int native_getStrokeCap(int native_object); 1274 private static native void native_setStrokeCap(int native_object, int cap); 1275 private static native int native_getStrokeJoin(int native_object); 1276 private static native void native_setStrokeJoin(int native_object, 1277 int join); 1278 private static native boolean native_getFillPath(int native_object, 1279 int src, int dst); 1280 private static native int native_setShader(int native_object, int shader); 1281 private static native int native_setColorFilter(int native_object, 1282 int filter); 1283 private static native int native_setXfermode(int native_object, 1284 int xfermode); 1285 private static native int native_setPathEffect(int native_object, 1286 int effect); 1287 private static native int native_setMaskFilter(int native_object, 1288 int maskfilter); 1289 private static native int native_setTypeface(int native_object, 1290 int typeface); 1291 private static native int native_setRasterizer(int native_object, 1292 int rasterizer); 1293 1294 private static native int native_getTextAlign(int native_object); 1295 private static native void native_setTextAlign(int native_object, 1296 int align); 1297 1298 private static native float native_getFontMetrics(int native_paint, 1299 FontMetrics metrics); 1300 private static native int native_getTextWidths(int native_object, 1301 char[] text, int index, int count, float[] widths); 1302 private static native int native_getTextWidths(int native_object, 1303 String text, int start, int end, float[] widths); 1304 private static native void native_getTextPath(int native_object, 1305 char[] text, int index, int count, float x, float y, int path); 1306 private static native void native_getTextPath(int native_object, 1307 String text, int start, int end, float x, float y, int path); 1308 private static native void nativeGetStringBounds(int nativePaint, 1309 String text, int start, int end, Rect bounds); 1310 private static native void nativeGetCharArrayBounds(int nativePaint, 1311 char[] text, int index, int count, Rect bounds); 1312 private static native void finalizer(int nativePaint); 1313} 1314 1315