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