Paint.java revision a1db574036c9bc2d397b69f8200594027e1fff16
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.graphics; 18 19import android.text.GraphicsOperations; 20import android.text.SpannableString; 21import android.text.SpannedString; 22import android.text.TextUtils; 23 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 /** 31 * @hide 32 */ 33 public int mNativePaint; 34 35 private ColorFilter mColorFilter; 36 private MaskFilter mMaskFilter; 37 private PathEffect mPathEffect; 38 private Rasterizer mRasterizer; 39 private Shader mShader; 40 private Typeface mTypeface; 41 private Xfermode mXfermode; 42 43 private boolean mHasCompatScaling; 44 private float mCompatScaling; 45 private float mInvCompatScaling; 46 /** 47 * @hide 48 */ 49 public int mBidiFlags = BIDI_DEFAULT_LTR; 50 51 private static final Style[] sStyleArray = { 52 Style.FILL, Style.STROKE, Style.FILL_AND_STROKE 53 }; 54 private static final Cap[] sCapArray = { 55 Cap.BUTT, Cap.ROUND, Cap.SQUARE 56 }; 57 private static final Join[] sJoinArray = { 58 Join.MITER, Join.ROUND, Join.BEVEL 59 }; 60 private static final Align[] sAlignArray = { 61 Align.LEFT, Align.CENTER, Align.RIGHT 62 }; 63 64 /** bit mask for the flag enabling antialiasing */ 65 public static final int ANTI_ALIAS_FLAG = 0x01; 66 /** bit mask for the flag enabling bitmap filtering */ 67 public static final int FILTER_BITMAP_FLAG = 0x02; 68 /** bit mask for the flag enabling dithering */ 69 public static final int DITHER_FLAG = 0x04; 70 /** bit mask for the flag enabling underline text */ 71 public static final int UNDERLINE_TEXT_FLAG = 0x08; 72 /** bit mask for the flag enabling strike-thru text */ 73 public static final int STRIKE_THRU_TEXT_FLAG = 0x10; 74 /** bit mask for the flag enabling fake-bold text */ 75 public static final int FAKE_BOLD_TEXT_FLAG = 0x20; 76 /** bit mask for the flag enabling linear-text (no caching) */ 77 public static final int LINEAR_TEXT_FLAG = 0x40; 78 /** bit mask for the flag enabling subpixel-text */ 79 public static final int SUBPIXEL_TEXT_FLAG = 0x80; 80 /** bit mask for the flag enabling device kerning for text */ 81 public static final int DEV_KERN_TEXT_FLAG = 0x100; 82 83 // we use this when we first create a paint 84 private static final int DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG; 85 86 /** 87 * Bidi flag to set LTR paragraph direction. 88 * 89 * @hide 90 */ 91 public static final int BIDI_LTR = 0x0; 92 93 /** 94 * Bidi flag to set RTL paragraph direction. 95 * 96 * @hide 97 */ 98 public static final int BIDI_RTL = 0x1; 99 100 /** 101 * Bidi flag to detect paragraph direction via heuristics, defaulting to 102 * LTR. 103 * 104 * @hide 105 */ 106 public static final int BIDI_DEFAULT_LTR = 0x2; 107 108 /** 109 * Bidi flag to detect paragraph direction via heuristics, defaulting to 110 * RTL. 111 * 112 * @hide 113 */ 114 public static final int BIDI_DEFAULT_RTL = 0x3; 115 116 /** 117 * Bidi flag to override direction to all LTR (ignore bidi). 118 * 119 * @hide 120 */ 121 public static final int BIDI_FORCE_LTR = 0x4; 122 123 /** 124 * Bidi flag to override direction to all RTL (ignore bidi). 125 * 126 * @hide 127 */ 128 public static final int BIDI_FORCE_RTL = 0x5; 129 130 /** 131 * Maximum Bidi flag value. 132 * @hide 133 */ 134 private static final int BIDI_MAX_FLAG_VALUE = BIDI_FORCE_RTL; 135 136 /** 137 * Mask for bidi flags. 138 * @hide 139 */ 140 private static final int BIDI_FLAG_MASK = 0x7; 141 142 /** 143 * Flag for getTextRunAdvances indicating left-to-right run direction. 144 * @hide 145 */ 146 public static final int DIRECTION_LTR = 0; 147 148 /** 149 * Flag for getTextRunAdvances indicating right-to-left run direction. 150 * @hide 151 */ 152 public static final int DIRECTION_RTL = 1; 153 154 /** 155 * Option for getTextRunCursor to compute the valid cursor after 156 * offset or the limit of the context, whichever is less. 157 * @hide 158 */ 159 public static final int CURSOR_AFTER = 0; 160 161 /** 162 * Option for getTextRunCursor to compute the valid cursor at or after 163 * the offset or the limit of the context, whichever is less. 164 * @hide 165 */ 166 public static final int CURSOR_AT_OR_AFTER = 1; 167 168 /** 169 * Option for getTextRunCursor to compute the valid cursor before 170 * offset or the start of the context, whichever is greater. 171 * @hide 172 */ 173 public static final int CURSOR_BEFORE = 2; 174 175 /** 176 * Option for getTextRunCursor to compute the valid cursor at or before 177 * offset or the start of the context, whichever is greater. 178 * @hide 179 */ 180 public static final int CURSOR_AT_OR_BEFORE = 3; 181 182 /** 183 * Option for getTextRunCursor to return offset if the cursor at offset 184 * is valid, or -1 if it isn't. 185 * @hide 186 */ 187 public static final int CURSOR_AT = 4; 188 189 /** 190 * Maximum cursor option value. 191 */ 192 private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT; 193 194 /** 195 * The Style specifies if the primitive being drawn is filled, stroked, or 196 * both (in the same color). The default is FILL. 197 */ 198 public enum Style { 199 /** 200 * Geometry and text drawn with this style will be filled, ignoring all 201 * stroke-related settings in the paint. 202 */ 203 FILL (0), 204 /** 205 * Geometry and text drawn with this style will be stroked, respecting 206 * the stroke-related fields on the paint. 207 */ 208 STROKE (1), 209 /** 210 * Geometry and text drawn with this style will be both filled and 211 * stroked at the same time, respecting the stroke-related fields on 212 * the paint. This mode can give unexpected results if the geometry 213 * is oriented counter-clockwise. This restriction does not apply to 214 * either FILL or STROKE. 215 */ 216 FILL_AND_STROKE (2); 217 218 Style(int nativeInt) { 219 this.nativeInt = nativeInt; 220 } 221 final int nativeInt; 222 } 223 224 /** 225 * The Cap specifies the treatment for the beginning and ending of 226 * stroked lines and paths. The default is BUTT. 227 */ 228 public enum Cap { 229 /** 230 * The stroke ends with the path, and does not project beyond it. 231 */ 232 BUTT (0), 233 /** 234 * The stroke projects out as a semicircle, with the center at the 235 * end of the path. 236 */ 237 ROUND (1), 238 /** 239 * The stroke projects out as a square, with the center at the end 240 * of the path. 241 */ 242 SQUARE (2); 243 244 private Cap(int nativeInt) { 245 this.nativeInt = nativeInt; 246 } 247 final int nativeInt; 248 } 249 250 /** 251 * The Join specifies the treatment where lines and curve segments 252 * join on a stroked path. The default is MITER. 253 */ 254 public enum Join { 255 /** 256 * The outer edges of a join meet at a sharp angle 257 */ 258 MITER (0), 259 /** 260 * The outer edges of a join meet in a circular arc. 261 */ 262 ROUND (1), 263 /** 264 * The outer edges of a join meet with a straight line 265 */ 266 BEVEL (2); 267 268 private Join(int nativeInt) { 269 this.nativeInt = nativeInt; 270 } 271 final int nativeInt; 272 } 273 274 /** 275 * Align specifies how drawText aligns its text relative to the 276 * [x,y] coordinates. The default is LEFT. 277 */ 278 public enum Align { 279 /** 280 * The text is drawn to the right of the x,y origin 281 */ 282 LEFT (0), 283 /** 284 * The text is drawn centered horizontally on the x,y origin 285 */ 286 CENTER (1), 287 /** 288 * The text is drawn to the left of the x,y origin 289 */ 290 RIGHT (2); 291 292 private Align(int nativeInt) { 293 this.nativeInt = nativeInt; 294 } 295 final int nativeInt; 296 } 297 298 /** 299 * Create a new paint with default settings. 300 */ 301 public Paint() { 302 this(0); 303 } 304 305 /** 306 * Create a new paint with the specified flags. Use setFlags() to change 307 * these after the paint is created. 308 * 309 * @param flags initial flag bits, as if they were passed via setFlags(). 310 */ 311 public Paint(int flags) { 312 mNativePaint = native_init(); 313 setFlags(flags | DEFAULT_PAINT_FLAGS); 314 mCompatScaling = mInvCompatScaling = 1; 315 } 316 317 /** 318 * Create a new paint, initialized with the attributes in the specified 319 * paint parameter. 320 * 321 * @param paint Existing paint used to initialized the attributes of the 322 * new paint. 323 */ 324 public Paint(Paint paint) { 325 mNativePaint = native_initWithPaint(paint.mNativePaint); 326 mHasCompatScaling = paint.mHasCompatScaling; 327 mCompatScaling = paint.mCompatScaling; 328 mInvCompatScaling = paint.mInvCompatScaling; 329 mBidiFlags = paint.mBidiFlags; 330 } 331 332 /** Restores the paint to its default settings. */ 333 public void reset() { 334 native_reset(mNativePaint); 335 setFlags(DEFAULT_PAINT_FLAGS); 336 mHasCompatScaling = false; 337 mCompatScaling = mInvCompatScaling = 1; 338 mBidiFlags = BIDI_DEFAULT_LTR; 339 } 340 341 /** 342 * Copy the fields from src into this paint. This is equivalent to calling 343 * get() on all of the src fields, and calling the corresponding set() 344 * methods on this. 345 */ 346 public void set(Paint src) { 347 if (this != src) { 348 // copy over the native settings 349 native_set(mNativePaint, src.mNativePaint); 350 // copy over our java settings 351 mColorFilter = src.mColorFilter; 352 mMaskFilter = src.mMaskFilter; 353 mPathEffect = src.mPathEffect; 354 mRasterizer = src.mRasterizer; 355 mShader = src.mShader; 356 mTypeface = src.mTypeface; 357 mXfermode = src.mXfermode; 358 mHasCompatScaling = src.mHasCompatScaling; 359 mCompatScaling = src.mCompatScaling; 360 mInvCompatScaling = src.mInvCompatScaling; 361 mBidiFlags = src.mBidiFlags; 362 } 363 } 364 365 /** @hide */ 366 public void setCompatibilityScaling(float factor) { 367 if (factor == 1.0) { 368 mHasCompatScaling = false; 369 mCompatScaling = mInvCompatScaling = 1.0f; 370 } else { 371 mHasCompatScaling = true; 372 mCompatScaling = factor; 373 mInvCompatScaling = 1.0f/factor; 374 } 375 } 376 377 /** 378 * Return the bidi flags on the paint. 379 * 380 * @return the bidi flags on the paint 381 * @hide 382 */ 383 public int getBidiFlags() { 384 return mBidiFlags; 385 } 386 387 /** 388 * Set the bidi flags on the paint. 389 * @hide 390 */ 391 public void setBidiFlags(int flags) { 392 // only flag value is the 3-bit BIDI control setting 393 flags &= BIDI_FLAG_MASK; 394 if (flags > BIDI_MAX_FLAG_VALUE) { 395 throw new IllegalArgumentException("unknown bidi flag: " + flags); 396 } 397 mBidiFlags = flags; 398 } 399 400 /** 401 * Return the paint's flags. Use the Flag enum to test flag values. 402 * 403 * @return the paint's flags (see enums ending in _Flag for bit masks) 404 */ 405 public native int getFlags(); 406 407 /** 408 * Set the paint's flags. Use the Flag enum to specific flag values. 409 * 410 * @param flags The new flag bits for the paint 411 */ 412 public native void setFlags(int flags); 413 414 /** 415 * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set 416 * AntiAliasing smooths out the edges of what is being drawn, but is has 417 * no impact on the interior of the shape. See setDither() and 418 * setFilterBitmap() to affect how colors are treated. 419 * 420 * @return true if the antialias bit is set in the paint's flags. 421 */ 422 public final boolean isAntiAlias() { 423 return (getFlags() & ANTI_ALIAS_FLAG) != 0; 424 } 425 426 /** 427 * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit 428 * AntiAliasing smooths out the edges of what is being drawn, but is has 429 * no impact on the interior of the shape. See setDither() and 430 * setFilterBitmap() to affect how colors are treated. 431 * 432 * @param aa true to set the antialias bit in the flags, false to clear it 433 */ 434 public native void setAntiAlias(boolean aa); 435 436 /** 437 * Helper for getFlags(), returning true if DITHER_FLAG bit is set 438 * Dithering affects how colors that are higher precision than the device 439 * are down-sampled. No dithering is generally faster, but higher precision 440 * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to 441 * distribute the error inherent in this process, to reduce the visual 442 * artifacts. 443 * 444 * @return true if the dithering bit is set in the paint's flags. 445 */ 446 public final boolean isDither() { 447 return (getFlags() & DITHER_FLAG) != 0; 448 } 449 450 /** 451 * Helper for setFlags(), setting or clearing the DITHER_FLAG bit 452 * Dithering affects how colors that are higher precision than the device 453 * are down-sampled. No dithering is generally faster, but higher precision 454 * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to 455 * distribute the error inherent in this process, to reduce the visual 456 * artifacts. 457 * 458 * @param dither true to set the dithering bit in flags, false to clear it 459 */ 460 public native void setDither(boolean dither); 461 462 /** 463 * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set 464 * 465 * @return true if the lineartext bit is set in the paint's flags 466 */ 467 public final boolean isLinearText() { 468 return (getFlags() & LINEAR_TEXT_FLAG) != 0; 469 } 470 471 /** 472 * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit 473 * 474 * @param linearText true to set the linearText bit in the paint's flags, 475 * false to clear it. 476 */ 477 public native void setLinearText(boolean linearText); 478 479 /** 480 * Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set 481 * 482 * @return true if the subpixel bit is set in the paint's flags 483 */ 484 public final boolean isSubpixelText() { 485 return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0; 486 } 487 488 /** 489 * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit 490 * 491 * @param subpixelText true to set the subpixelText bit in the paint's 492 * flags, false to clear it. 493 */ 494 public native void setSubpixelText(boolean subpixelText); 495 496 /** 497 * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set 498 * 499 * @return true if the underlineText bit is set in the paint's flags. 500 */ 501 public final boolean isUnderlineText() { 502 return (getFlags() & UNDERLINE_TEXT_FLAG) != 0; 503 } 504 505 /** 506 * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit 507 * 508 * @param underlineText true to set the underlineText bit in the paint's 509 * flags, false to clear it. 510 */ 511 public native void setUnderlineText(boolean underlineText); 512 513 /** 514 * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set 515 * 516 * @return true if the strikeThruText bit is set in the paint's flags. 517 */ 518 public final boolean isStrikeThruText() { 519 return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0; 520 } 521 522 /** 523 * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit 524 * 525 * @param strikeThruText true to set the strikeThruText bit in the paint's 526 * flags, false to clear it. 527 */ 528 public native void setStrikeThruText(boolean strikeThruText); 529 530 /** 531 * Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set 532 * 533 * @return true if the fakeBoldText bit is set in the paint's flags. 534 */ 535 public final boolean isFakeBoldText() { 536 return (getFlags() & FAKE_BOLD_TEXT_FLAG) != 0; 537 } 538 539 /** 540 * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit 541 * 542 * @param fakeBoldText true to set the fakeBoldText bit in the paint's 543 * flags, false to clear it. 544 */ 545 public native void setFakeBoldText(boolean fakeBoldText); 546 547 /** 548 * Whether or not the bitmap filter is activated. 549 * Filtering affects the sampling of bitmaps when they are transformed. 550 * Filtering does not affect how the colors in the bitmap are converted into 551 * device pixels. That is dependent on dithering and xfermodes. 552 * 553 * @see #setFilterBitmap(boolean) setFilterBitmap() 554 */ 555 public final boolean isFilterBitmap() { 556 return (getFlags() & FILTER_BITMAP_FLAG) != 0; 557 } 558 559 /** 560 * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit. 561 * Filtering affects the sampling of bitmaps when they are transformed. 562 * Filtering does not affect how the colors in the bitmap are converted into 563 * device pixels. That is dependent on dithering and xfermodes. 564 * 565 * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's 566 * flags, false to clear it. 567 */ 568 public native void setFilterBitmap(boolean filter); 569 570 /** 571 * Return the paint's style, used for controlling how primitives' 572 * geometries are interpreted (except for drawBitmap, which always assumes 573 * FILL_STYLE). 574 * 575 * @return the paint's style setting (Fill, Stroke, StrokeAndFill) 576 */ 577 public Style getStyle() { 578 return sStyleArray[native_getStyle(mNativePaint)]; 579 } 580 581 /** 582 * Set the paint's style, used for controlling how primitives' 583 * geometries are interpreted (except for drawBitmap, which always assumes 584 * Fill). 585 * 586 * @param style The new style to set in the paint 587 */ 588 public void setStyle(Style style) { 589 native_setStyle(mNativePaint, style.nativeInt); 590 } 591 592 /** 593 * Return the paint's color. Note that the color is a 32bit value 594 * containing alpha as well as r,g,b. This 32bit value is not premultiplied, 595 * meaning that its alpha can be any value, regardless of the values of 596 * r,g,b. See the Color class for more details. 597 * 598 * @return the paint's color (and alpha). 599 */ 600 public native int getColor(); 601 602 /** 603 * Set the paint's color. Note that the color is an int containing alpha 604 * as well as r,g,b. This 32bit value is not premultiplied, meaning that 605 * its alpha can be any value, regardless of the values of r,g,b. 606 * See the Color class for more details. 607 * 608 * @param color The new color (including alpha) to set in the paint. 609 */ 610 public native void setColor(int color); 611 612 /** 613 * Helper to getColor() that just returns the color's alpha value. This is 614 * the same as calling getColor() >>> 24. It always returns a value between 615 * 0 (completely transparent) and 255 (completely opaque). 616 * 617 * @return the alpha component of the paint's color. 618 */ 619 public native int getAlpha(); 620 621 /** 622 * Helper to setColor(), that only assigns the color's alpha value, 623 * leaving its r,g,b values unchanged. Results are undefined if the alpha 624 * value is outside of the range [0..255] 625 * 626 * @param a set the alpha component [0..255] of the paint's color. 627 */ 628 public native void setAlpha(int a); 629 630 /** 631 * Helper to setColor(), that takes a,r,g,b and constructs the color int 632 * 633 * @param a The new alpha component (0..255) of the paint's color. 634 * @param r The new red component (0..255) of the paint's color. 635 * @param g The new green component (0..255) of the paint's color. 636 * @param b The new blue component (0..255) of the paint's color. 637 */ 638 public void setARGB(int a, int r, int g, int b) { 639 setColor((a << 24) | (r << 16) | (g << 8) | b); 640 } 641 642 /** 643 * Return the width for stroking. 644 * <p /> 645 * A value of 0 strokes in hairline mode. 646 * Hairlines always draws a single pixel independent of the canva's matrix. 647 * 648 * @return the paint's stroke width, used whenever the paint's style is 649 * Stroke or StrokeAndFill. 650 */ 651 public native float getStrokeWidth(); 652 653 /** 654 * Set the width for stroking. 655 * Pass 0 to stroke in hairline mode. 656 * Hairlines always draws a single pixel independent of the canva's matrix. 657 * 658 * @param width set the paint's stroke width, used whenever the paint's 659 * style is Stroke or StrokeAndFill. 660 */ 661 public native void setStrokeWidth(float width); 662 663 /** 664 * Return the paint's stroke miter value. Used to control the behavior 665 * of miter joins when the joins angle is sharp. 666 * 667 * @return the paint's miter limit, used whenever the paint's style is 668 * Stroke or StrokeAndFill. 669 */ 670 public native float getStrokeMiter(); 671 672 /** 673 * Set the paint's stroke miter value. This is used to control the behavior 674 * of miter joins when the joins angle is sharp. This value must be >= 0. 675 * 676 * @param miter set the miter limit on the paint, used whenever the paint's 677 * style is Stroke or StrokeAndFill. 678 */ 679 public native void setStrokeMiter(float miter); 680 681 /** 682 * Return the paint's Cap, controlling how the start and end of stroked 683 * lines and paths are treated. 684 * 685 * @return the line cap style for the paint, used whenever the paint's 686 * style is Stroke or StrokeAndFill. 687 */ 688 public Cap getStrokeCap() { 689 return sCapArray[native_getStrokeCap(mNativePaint)]; 690 } 691 692 /** 693 * Set the paint's Cap. 694 * 695 * @param cap set the paint's line cap style, used whenever the paint's 696 * style is Stroke or StrokeAndFill. 697 */ 698 public void setStrokeCap(Cap cap) { 699 native_setStrokeCap(mNativePaint, cap.nativeInt); 700 } 701 702 /** 703 * Return the paint's stroke join type. 704 * 705 * @return the paint's Join. 706 */ 707 public Join getStrokeJoin() { 708 return sJoinArray[native_getStrokeJoin(mNativePaint)]; 709 } 710 711 /** 712 * Set the paint's Join. 713 * 714 * @param join set the paint's Join, used whenever the paint's style is 715 * Stroke or StrokeAndFill. 716 */ 717 public void setStrokeJoin(Join join) { 718 native_setStrokeJoin(mNativePaint, join.nativeInt); 719 } 720 721 /** 722 * Applies any/all effects (patheffect, stroking) to src, returning the 723 * result in dst. The result is that drawing src with this paint will be 724 * the same as drawing dst with a default paint (at least from the 725 * geometric perspective). 726 * 727 * @param src input path 728 * @param dst output path (may be the same as src) 729 * @return true if the path should be filled, or false if it should be 730 * drawn with a hairline (width == 0) 731 */ 732 public boolean getFillPath(Path src, Path dst) { 733 return native_getFillPath(mNativePaint, src.ni(), dst.ni()); 734 } 735 736 /** 737 * Get the paint's shader object. 738 * 739 * @return the paint's shader (or null) 740 */ 741 public Shader getShader() { 742 return mShader; 743 } 744 745 /** 746 * Set or clear the shader object. 747 * <p /> 748 * Pass null to clear any previous shader. 749 * As a convenience, the parameter passed is also returned. 750 * 751 * @param shader May be null. the new shader to be installed in the paint 752 * @return shader 753 */ 754 public Shader setShader(Shader shader) { 755 int shaderNative = 0; 756 if (shader != null) 757 shaderNative = shader.native_instance; 758 native_setShader(mNativePaint, shaderNative); 759 mShader = shader; 760 return shader; 761 } 762 763 /** 764 * Get the paint's colorfilter (maybe be null). 765 * 766 * @return the paint's colorfilter (maybe be null) 767 */ 768 public ColorFilter getColorFilter() { 769 return mColorFilter; 770 } 771 772 /** 773 * Set or clear the paint's colorfilter, returning the parameter. 774 * 775 * @param filter May be null. The new filter to be installed in the paint 776 * @return filter 777 */ 778 public ColorFilter setColorFilter(ColorFilter filter) { 779 int filterNative = 0; 780 if (filter != null) 781 filterNative = filter.native_instance; 782 native_setColorFilter(mNativePaint, filterNative); 783 mColorFilter = filter; 784 return filter; 785 } 786 787 /** 788 * Get the paint's xfermode object. 789 * 790 * @return the paint's xfermode (or null) 791 */ 792 public Xfermode getXfermode() { 793 return mXfermode; 794 } 795 796 /** 797 * Set or clear the xfermode object. 798 * <p /> 799 * Pass null to clear any previous xfermode. 800 * As a convenience, the parameter passed is also returned. 801 * 802 * @param xfermode May be null. The xfermode to be installed in the paint 803 * @return xfermode 804 */ 805 public Xfermode setXfermode(Xfermode xfermode) { 806 int xfermodeNative = 0; 807 if (xfermode != null) 808 xfermodeNative = xfermode.native_instance; 809 native_setXfermode(mNativePaint, xfermodeNative); 810 mXfermode = xfermode; 811 return xfermode; 812 } 813 814 /** 815 * Get the paint's patheffect object. 816 * 817 * @return the paint's patheffect (or null) 818 */ 819 public PathEffect getPathEffect() { 820 return mPathEffect; 821 } 822 823 /** 824 * Set or clear the patheffect object. 825 * <p /> 826 * Pass null to clear any previous patheffect. 827 * As a convenience, the parameter passed is also returned. 828 * 829 * @param effect May be null. The patheffect to be installed in the paint 830 * @return effect 831 */ 832 public PathEffect setPathEffect(PathEffect effect) { 833 int effectNative = 0; 834 if (effect != null) { 835 effectNative = effect.native_instance; 836 } 837 native_setPathEffect(mNativePaint, effectNative); 838 mPathEffect = effect; 839 return effect; 840 } 841 842 /** 843 * Get the paint's maskfilter object. 844 * 845 * @return the paint's maskfilter (or null) 846 */ 847 public MaskFilter getMaskFilter() { 848 return mMaskFilter; 849 } 850 851 /** 852 * Set or clear the maskfilter object. 853 * <p /> 854 * Pass null to clear any previous maskfilter. 855 * As a convenience, the parameter passed is also returned. 856 * 857 * @param maskfilter May be null. The maskfilter to be installed in the 858 * paint 859 * @return maskfilter 860 */ 861 public MaskFilter setMaskFilter(MaskFilter maskfilter) { 862 int maskfilterNative = 0; 863 if (maskfilter != null) { 864 maskfilterNative = maskfilter.native_instance; 865 } 866 native_setMaskFilter(mNativePaint, maskfilterNative); 867 mMaskFilter = maskfilter; 868 return maskfilter; 869 } 870 871 /** 872 * Get the paint's typeface object. 873 * <p /> 874 * The typeface object identifies which font to use when drawing or 875 * measuring text. 876 * 877 * @return the paint's typeface (or null) 878 */ 879 public Typeface getTypeface() { 880 return mTypeface; 881 } 882 883 /** 884 * Set or clear the typeface object. 885 * <p /> 886 * Pass null to clear any previous typeface. 887 * As a convenience, the parameter passed is also returned. 888 * 889 * @param typeface May be null. The typeface to be installed in the paint 890 * @return typeface 891 */ 892 public Typeface setTypeface(Typeface typeface) { 893 int typefaceNative = 0; 894 if (typeface != null) { 895 typefaceNative = typeface.native_instance; 896 } 897 native_setTypeface(mNativePaint, typefaceNative); 898 mTypeface = typeface; 899 return typeface; 900 } 901 902 /** 903 * Get the paint's rasterizer (or null). 904 * <p /> 905 * The raster controls/modifies how paths/text are turned into alpha masks. 906 * 907 * @return the paint's rasterizer (or null) 908 */ 909 public Rasterizer getRasterizer() { 910 return mRasterizer; 911 } 912 913 /** 914 * Set or clear the rasterizer object. 915 * <p /> 916 * Pass null to clear any previous rasterizer. 917 * As a convenience, the parameter passed is also returned. 918 * 919 * @param rasterizer May be null. The new rasterizer to be installed in 920 * the paint. 921 * @return rasterizer 922 */ 923 public Rasterizer setRasterizer(Rasterizer rasterizer) { 924 int rasterizerNative = 0; 925 if (rasterizer != null) { 926 rasterizerNative = rasterizer.native_instance; 927 } 928 native_setRasterizer(mNativePaint, rasterizerNative); 929 mRasterizer = rasterizer; 930 return rasterizer; 931 } 932 933 /** 934 * Temporary API to expose layer drawing. This draws a shadow layer below 935 * the main layer, with the specified offset and color, and blur radius. 936 * If radius is 0, then the shadow layer is removed. 937 */ 938 public native void setShadowLayer(float radius, float dx, float dy, 939 int color); 940 941 /** 942 * Temporary API to clear the shadow layer. 943 */ 944 public void clearShadowLayer() { 945 setShadowLayer(0, 0, 0, 0); 946 } 947 948 /** 949 * Return the paint's Align value for drawing text. This controls how the 950 * text is positioned relative to its origin. LEFT align means that all of 951 * the text will be drawn to the right of its origin (i.e. the origin 952 * specifieds the LEFT edge of the text) and so on. 953 * 954 * @return the paint's Align value for drawing text. 955 */ 956 public Align getTextAlign() { 957 return sAlignArray[native_getTextAlign(mNativePaint)]; 958 } 959 960 /** 961 * Set the paint's text alignment. This controls how the 962 * text is positioned relative to its origin. LEFT align means that all of 963 * the text will be drawn to the right of its origin (i.e. the origin 964 * specifieds the LEFT edge of the text) and so on. 965 * 966 * @param align set the paint's Align value for drawing text. 967 */ 968 public void setTextAlign(Align align) { 969 native_setTextAlign(mNativePaint, align.nativeInt); 970 } 971 972 /** 973 * Return the paint's text size. 974 * 975 * @return the paint's text size. 976 */ 977 public native float getTextSize(); 978 979 /** 980 * Set the paint's text size. This value must be > 0 981 * 982 * @param textSize set the paint's text size. 983 */ 984 public native void setTextSize(float textSize); 985 986 /** 987 * Return the paint's horizontal scale factor for text. The default value 988 * is 1.0. 989 * 990 * @return the paint's scale factor in X for drawing/measuring text 991 */ 992 public native float getTextScaleX(); 993 994 /** 995 * Set the paint's horizontal scale factor for text. The default value 996 * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will 997 * stretch the text narrower. 998 * 999 * @param scaleX set the paint's scale in X for drawing/measuring text. 1000 */ 1001 public native void setTextScaleX(float scaleX); 1002 1003 /** 1004 * Return the paint's horizontal skew factor for text. The default value 1005 * is 0. 1006 * 1007 * @return the paint's skew factor in X for drawing text. 1008 */ 1009 public native float getTextSkewX(); 1010 1011 /** 1012 * Set the paint's horizontal skew factor for text. The default value 1013 * is 0. For approximating oblique text, use values around -0.25. 1014 * 1015 * @param skewX set the paint's skew factor in X for drawing text. 1016 */ 1017 public native void setTextSkewX(float skewX); 1018 1019 /** 1020 * Return the distance above (negative) the baseline (ascent) based on the 1021 * current typeface and text size. 1022 * 1023 * @return the distance above (negative) the baseline (ascent) based on the 1024 * current typeface and text size. 1025 */ 1026 public native float ascent(); 1027 1028 /** 1029 * Return the distance below (positive) the baseline (descent) based on the 1030 * current typeface and text size. 1031 * 1032 * @return the distance below (positive) the baseline (descent) based on 1033 * the current typeface and text size. 1034 */ 1035 public native float descent(); 1036 1037 /** 1038 * Class that describes the various metrics for a font at a given text size. 1039 * Remember, Y values increase going down, so those values will be positive, 1040 * and values that measure distances going up will be negative. This class 1041 * is returned by getFontMetrics(). 1042 */ 1043 public static class FontMetrics { 1044 /** 1045 * The maximum distance above the baseline for the tallest glyph in 1046 * the font at a given text size. 1047 */ 1048 public float top; 1049 /** 1050 * The recommended distance above the baseline for singled spaced text. 1051 */ 1052 public float ascent; 1053 /** 1054 * The recommended distance below the baseline for singled spaced text. 1055 */ 1056 public float descent; 1057 /** 1058 * The maximum distance below the baseline for the lowest glyph in 1059 * the font at a given text size. 1060 */ 1061 public float bottom; 1062 /** 1063 * The recommended additional space to add between lines of text. 1064 */ 1065 public float leading; 1066 } 1067 1068 /** 1069 * Return the font's recommended interline spacing, given the Paint's 1070 * settings for typeface, textSize, etc. If metrics is not null, return the 1071 * fontmetric values in it. 1072 * 1073 * @param metrics If this object is not null, its fields are filled with 1074 * the appropriate values given the paint's text attributes. 1075 * @return the font's recommended interline spacing. 1076 */ 1077 public native float getFontMetrics(FontMetrics metrics); 1078 1079 /** 1080 * Allocates a new FontMetrics object, and then calls getFontMetrics(fm) 1081 * with it, returning the object. 1082 */ 1083 public FontMetrics getFontMetrics() { 1084 FontMetrics fm = new FontMetrics(); 1085 getFontMetrics(fm); 1086 return fm; 1087 } 1088 1089 /** 1090 * Convenience method for callers that want to have FontMetrics values as 1091 * integers. 1092 */ 1093 public static class FontMetricsInt { 1094 public int top; 1095 public int ascent; 1096 public int descent; 1097 public int bottom; 1098 public int leading; 1099 1100 @Override public String toString() { 1101 return "FontMetricsInt: top=" + top + " ascent=" + ascent + 1102 " descent=" + descent + " bottom=" + bottom + 1103 " leading=" + leading; 1104 } 1105 } 1106 1107 /** 1108 * Return the font's interline spacing, given the Paint's settings for 1109 * typeface, textSize, etc. If metrics is not null, return the fontmetric 1110 * values in it. Note: all values have been converted to integers from 1111 * floats, in such a way has to make the answers useful for both spacing 1112 * and clipping. If you want more control over the rounding, call 1113 * getFontMetrics(). 1114 * 1115 * @return the font's interline spacing. 1116 */ 1117 public native int getFontMetricsInt(FontMetricsInt fmi); 1118 1119 public FontMetricsInt getFontMetricsInt() { 1120 FontMetricsInt fm = new FontMetricsInt(); 1121 getFontMetricsInt(fm); 1122 return fm; 1123 } 1124 1125 /** 1126 * Return the recommend line spacing based on the current typeface and 1127 * text size. 1128 * 1129 * @return recommend line spacing based on the current typeface and 1130 * text size. 1131 */ 1132 public float getFontSpacing() { 1133 return getFontMetrics(null); 1134 } 1135 1136 /** 1137 * Return the width of the text. 1138 * 1139 * @param text The text to measure 1140 * @param index The index of the first character to start measuring 1141 * @param count THe number of characters to measure, beginning with start 1142 * @return The width of the text 1143 */ 1144 public float measureText(char[] text, int index, int count) { 1145 if (!mHasCompatScaling) return native_measureText(text, index, count); 1146 final float oldSize = getTextSize(); 1147 setTextSize(oldSize*mCompatScaling); 1148 float w = native_measureText(text, index, count); 1149 setTextSize(oldSize); 1150 return w*mInvCompatScaling; 1151 } 1152 1153 private native float native_measureText(char[] text, int index, int count); 1154 1155 /** 1156 * Return the width of the text. 1157 * 1158 * @param text The text to measure 1159 * @param start The index of the first character to start measuring 1160 * @param end 1 beyond the index of the last character to measure 1161 * @return The width of the text 1162 */ 1163 public float measureText(String text, int start, int end) { 1164 if (!mHasCompatScaling) return native_measureText(text, start, end); 1165 final float oldSize = getTextSize(); 1166 setTextSize(oldSize*mCompatScaling); 1167 float w = native_measureText(text, start, end); 1168 setTextSize(oldSize); 1169 return w*mInvCompatScaling; 1170 } 1171 1172 private native float native_measureText(String text, int start, int end); 1173 1174 /** 1175 * Return the width of the text. 1176 * 1177 * @param text The text to measure 1178 * @return The width of the text 1179 */ 1180 public float measureText(String text) { 1181 if (!mHasCompatScaling) return native_measureText(text); 1182 final float oldSize = getTextSize(); 1183 setTextSize(oldSize*mCompatScaling); 1184 float w = native_measureText(text); 1185 setTextSize(oldSize); 1186 return w*mInvCompatScaling; 1187 } 1188 1189 private native float native_measureText(String text); 1190 1191 /** 1192 * Return the width of the text. 1193 * 1194 * @param text The text to measure 1195 * @param start The index of the first character to start measuring 1196 * @param end 1 beyond the index of the last character to measure 1197 * @return The width of the text 1198 */ 1199 public float measureText(CharSequence text, int start, int end) { 1200 if (text instanceof String) { 1201 return measureText((String)text, start, end); 1202 } 1203 if (text instanceof SpannedString || 1204 text instanceof SpannableString) { 1205 return measureText(text.toString(), start, end); 1206 } 1207 if (text instanceof GraphicsOperations) { 1208 return ((GraphicsOperations)text).measureText(start, end, this); 1209 } 1210 1211 char[] buf = TemporaryBuffer.obtain(end - start); 1212 TextUtils.getChars(text, start, end, buf, 0); 1213 float result = measureText(buf, 0, end - start); 1214 TemporaryBuffer.recycle(buf); 1215 return result; 1216 } 1217 1218 /** 1219 * Measure the text, stopping early if the measured width exceeds maxWidth. 1220 * Return the number of chars that were measured, and if measuredWidth is 1221 * not null, return in it the actual width measured. 1222 * 1223 * @param text The text to measure 1224 * @param index The offset into text to begin measuring at 1225 * @param count The number of maximum number of entries to measure. If count 1226 * is negative, then the characters before index are measured 1227 * in reverse order. This allows for measuring the end of 1228 * string. 1229 * @param maxWidth The maximum width to accumulate. 1230 * @param measuredWidth Optional. If not null, returns the actual width 1231 * measured. 1232 * @return The number of chars that were measured. Will always be <= 1233 * abs(count). 1234 */ 1235 public int breakText(char[] text, int index, int count, 1236 float maxWidth, float[] measuredWidth) { 1237 if (!mHasCompatScaling) { 1238 return native_breakText(text, index, count, maxWidth, measuredWidth); 1239 } 1240 final float oldSize = getTextSize(); 1241 setTextSize(oldSize*mCompatScaling); 1242 int res = native_breakText(text, index, count, maxWidth*mCompatScaling, 1243 measuredWidth); 1244 setTextSize(oldSize); 1245 if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling; 1246 return res; 1247 } 1248 1249 private native int native_breakText(char[] text, int index, int count, 1250 float maxWidth, float[] measuredWidth); 1251 1252 /** 1253 * Measure the text, stopping early if the measured width exceeds maxWidth. 1254 * Return the number of chars that were measured, and if measuredWidth is 1255 * not null, return in it the actual width measured. 1256 * 1257 * @param text The text to measure 1258 * @param start The offset into text to begin measuring at 1259 * @param end The end of the text slice to measure. 1260 * @param measureForwards If true, measure forwards, starting at start. 1261 * Otherwise, measure backwards, starting with end. 1262 * @param maxWidth The maximum width to accumulate. 1263 * @param measuredWidth Optional. If not null, returns the actual width 1264 * measured. 1265 * @return The number of chars that were measured. Will always be <= 1266 * abs(end - start). 1267 */ 1268 public int breakText(CharSequence text, int start, int end, 1269 boolean measureForwards, 1270 float maxWidth, float[] measuredWidth) { 1271 if (start == 0 && text instanceof String && end == text.length()) { 1272 return breakText((String) text, measureForwards, maxWidth, 1273 measuredWidth); 1274 } 1275 1276 char[] buf = TemporaryBuffer.obtain(end - start); 1277 int result; 1278 1279 TextUtils.getChars(text, start, end, buf, 0); 1280 1281 if (measureForwards) { 1282 result = breakText(buf, 0, end - start, maxWidth, measuredWidth); 1283 } else { 1284 result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth); 1285 } 1286 1287 TemporaryBuffer.recycle(buf); 1288 return result; 1289 } 1290 1291 /** 1292 * Measure the text, stopping early if the measured width exceeds maxWidth. 1293 * Return the number of chars that were measured, and if measuredWidth is 1294 * not null, return in it the actual width measured. 1295 * 1296 * @param text The text to measure 1297 * @param measureForwards If true, measure forwards, starting with the 1298 * first character in the string. Otherwise, 1299 * measure backwards, starting with the 1300 * last character in the string. 1301 * @param maxWidth The maximum width to accumulate. 1302 * @param measuredWidth Optional. If not null, returns the actual width 1303 * measured. 1304 * @return The number of chars that were measured. Will always be <= 1305 * abs(count). 1306 */ 1307 public int breakText(String text, boolean measureForwards, 1308 float maxWidth, float[] measuredWidth) { 1309 if (!mHasCompatScaling) { 1310 return native_breakText(text, measureForwards, maxWidth, measuredWidth); 1311 } 1312 final float oldSize = getTextSize(); 1313 setTextSize(oldSize*mCompatScaling); 1314 int res = native_breakText(text, measureForwards, maxWidth*mCompatScaling, 1315 measuredWidth); 1316 setTextSize(oldSize); 1317 if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling; 1318 return res; 1319 } 1320 1321 private native int native_breakText(String text, boolean measureForwards, 1322 float maxWidth, float[] measuredWidth); 1323 1324 /** 1325 * Return the advance widths for the characters in the string. 1326 * 1327 * @param text The text to measure 1328 * @param index The index of the first char to to measure 1329 * @param count The number of chars starting with index to measure 1330 * @param widths array to receive the advance widths of the characters. 1331 * Must be at least a large as count. 1332 * @return the actual number of widths returned. 1333 */ 1334 public int getTextWidths(char[] text, int index, int count, 1335 float[] widths) { 1336 if ((index | count) < 0 || index + count > text.length 1337 || count > widths.length) { 1338 throw new ArrayIndexOutOfBoundsException(); 1339 } 1340 1341 if (!mHasCompatScaling) { 1342 return native_getTextWidths(mNativePaint, text, index, count, widths); 1343 } 1344 final float oldSize = getTextSize(); 1345 setTextSize(oldSize*mCompatScaling); 1346 int res = native_getTextWidths(mNativePaint, text, index, count, widths); 1347 setTextSize(oldSize); 1348 for (int i=0; i<res; i++) { 1349 widths[i] *= mInvCompatScaling; 1350 } 1351 return res; 1352 } 1353 1354 /** 1355 * Return the advance widths for the characters in the string. 1356 * 1357 * @param text The text to measure 1358 * @param start The index of the first char to to measure 1359 * @param end The end of the text slice to measure 1360 * @param widths array to receive the advance widths of the characters. 1361 * Must be at least a large as (end - start). 1362 * @return the actual number of widths returned. 1363 */ 1364 public int getTextWidths(CharSequence text, int start, int end, 1365 float[] widths) { 1366 if (text instanceof String) { 1367 return getTextWidths((String) text, start, end, widths); 1368 } 1369 if (text instanceof SpannedString || 1370 text instanceof SpannableString) { 1371 return getTextWidths(text.toString(), start, end, widths); 1372 } 1373 if (text instanceof GraphicsOperations) { 1374 return ((GraphicsOperations) text).getTextWidths(start, end, 1375 widths, this); 1376 } 1377 1378 char[] buf = TemporaryBuffer.obtain(end - start); 1379 TextUtils.getChars(text, start, end, buf, 0); 1380 int result = getTextWidths(buf, 0, end - start, widths); 1381 TemporaryBuffer.recycle(buf); 1382 return result; 1383 } 1384 1385 /** 1386 * Return the advance widths for the characters in the string. 1387 * 1388 * @param text The text to measure 1389 * @param start The index of the first char to to measure 1390 * @param end The end of the text slice to measure 1391 * @param widths array to receive the advance widths of the characters. 1392 * Must be at least a large as the text. 1393 * @return the number of unichars in the specified text. 1394 */ 1395 public int getTextWidths(String text, int start, int end, float[] widths) { 1396 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1397 throw new IndexOutOfBoundsException(); 1398 } 1399 if (end - start > widths.length) { 1400 throw new ArrayIndexOutOfBoundsException(); 1401 } 1402 1403 if (!mHasCompatScaling) { 1404 return native_getTextWidths(mNativePaint, text, start, end, widths); 1405 } 1406 final float oldSize = getTextSize(); 1407 setTextSize(oldSize*mCompatScaling); 1408 int res = native_getTextWidths(mNativePaint, text, start, end, widths); 1409 setTextSize(oldSize); 1410 for (int i=0; i<res; i++) { 1411 widths[i] *= mInvCompatScaling; 1412 } 1413 return res; 1414 } 1415 1416 /** 1417 * Return the advance widths for the characters in the string. 1418 * 1419 * @param text The text to measure 1420 * @param widths array to receive the advance widths of the characters. 1421 * Must be at least a large as the text. 1422 * @return the number of unichars in the specified text. 1423 */ 1424 public int getTextWidths(String text, float[] widths) { 1425 return getTextWidths(text, 0, text.length(), widths); 1426 } 1427 1428 /** 1429 * Convenience overload that takes a char array instead of a 1430 * String. 1431 * 1432 * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int) 1433 * @hide 1434 */ 1435 public float getTextRunAdvances(char[] chars, int index, int count, 1436 int contextIndex, int contextCount, int flags, float[] advances, 1437 int advancesIndex) { 1438 1439 if ((index | count | contextIndex | contextCount | advancesIndex 1440 | (index - contextIndex) 1441 | ((contextIndex + contextCount) - (index + count)) 1442 | (chars.length - (contextIndex + contextCount)) 1443 | (advances == null ? 0 : 1444 (advances.length - (advancesIndex + count)))) < 0) { 1445 throw new IndexOutOfBoundsException(); 1446 } 1447 if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) { 1448 throw new IllegalArgumentException("unknown flags value: " + flags); 1449 } 1450 1451 if (!mHasCompatScaling) { 1452 return native_getTextRunAdvances(mNativePaint, chars, index, count, 1453 contextIndex, contextCount, flags, advances, advancesIndex); 1454 } 1455 1456 final float oldSize = getTextSize(); 1457 setTextSize(oldSize * mCompatScaling); 1458 float res = native_getTextRunAdvances(mNativePaint, chars, index, count, 1459 contextIndex, contextCount, flags, advances, advancesIndex); 1460 setTextSize(oldSize); 1461 1462 if (advances != null) { 1463 for (int i = advancesIndex, e = i + count; i < e; i++) { 1464 advances[i] *= mInvCompatScaling; 1465 } 1466 } 1467 return res * mInvCompatScaling; // assume errors are not significant 1468 } 1469 1470 /** 1471 * Convenience overload that takes a CharSequence instead of a 1472 * String. 1473 * 1474 * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int) 1475 * @hide 1476 */ 1477 public float getTextRunAdvances(CharSequence text, int start, int end, 1478 int contextStart, int contextEnd, int flags, float[] advances, 1479 int advancesIndex) { 1480 1481 if (text instanceof String) { 1482 return getTextRunAdvances((String) text, start, end, 1483 contextStart, contextEnd, flags, advances, advancesIndex); 1484 } 1485 if (text instanceof SpannedString || 1486 text instanceof SpannableString) { 1487 return getTextRunAdvances(text.toString(), start, end, 1488 contextStart, contextEnd, flags, advances, advancesIndex); 1489 } 1490 if (text instanceof GraphicsOperations) { 1491 return ((GraphicsOperations) text).getTextRunAdvances(start, end, 1492 contextStart, contextEnd, flags, advances, advancesIndex, this); 1493 } 1494 1495 int contextLen = contextEnd - contextStart; 1496 int len = end - start; 1497 char[] buf = TemporaryBuffer.obtain(contextLen); 1498 TextUtils.getChars(text, start, end, buf, 0); 1499 float result = getTextRunAdvances(buf, start - contextStart, len, 1500 0, contextLen, flags, advances, advancesIndex); 1501 TemporaryBuffer.recycle(buf); 1502 return result; 1503 } 1504 1505 /** 1506 * Returns the total advance width for the characters in the run 1507 * between start and end, and if advances is not null, the advance 1508 * assigned to each of these characters (java chars). 1509 * 1510 * <p>The trailing surrogate in a valid surrogate pair is assigned 1511 * an advance of 0. Thus the number of returned advances is 1512 * always equal to count, not to the number of unicode codepoints 1513 * represented by the run. 1514 * 1515 * <p>In the case of conjuncts or combining marks, the total 1516 * advance is assigned to the first logical character, and the 1517 * following characters are assigned an advance of 0. 1518 * 1519 * <p>This generates the sum of the advances of glyphs for 1520 * characters in a reordered cluster as the width of the first 1521 * logical character in the cluster, and 0 for the widths of all 1522 * other characters in the cluster. In effect, such clusters are 1523 * treated like conjuncts. 1524 * 1525 * <p>The shaping bounds limit the amount of context available 1526 * outside start and end that can be used for shaping analysis. 1527 * These bounds typically reflect changes in bidi level or font 1528 * metrics across which shaping does not occur. 1529 * 1530 * @param text the text to measure 1531 * @param start the index of the first character to measure 1532 * @param end the index past the last character to measure 1533 * @param contextStart the index of the first character to use for shaping context, 1534 * must be <= start 1535 * @param contextEnd the index past the last character to use for shaping context, 1536 * must be >= end 1537 * @param flags the flags to control the advances, either {@link #DIRECTION_LTR} 1538 * or {@link #DIRECTION_RTL} 1539 * @param advances array to receive the advances, must have room for all advances, 1540 * can be null if only total advance is needed 1541 * @param advancesIndex the position in advances at which to put the 1542 * advance corresponding to the character at start 1543 * @return the total advance 1544 * 1545 * @hide 1546 */ 1547 public float getTextRunAdvances(String text, int start, int end, int contextStart, 1548 int contextEnd, int flags, float[] advances, int advancesIndex) { 1549 1550 if ((start | end | contextStart | contextEnd | advancesIndex | (end - start) 1551 | (start - contextStart) | (contextEnd - end) 1552 | (text.length() - contextEnd) 1553 | (advances == null ? 0 : 1554 (advances.length - advancesIndex - (end - start)))) < 0) { 1555 throw new IndexOutOfBoundsException(); 1556 } 1557 if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) { 1558 throw new IllegalArgumentException("unknown flags value: " + flags); 1559 } 1560 1561 if (!mHasCompatScaling) { 1562 return native_getTextRunAdvances(mNativePaint, text, start, end, 1563 contextStart, contextEnd, flags, advances, advancesIndex); 1564 } 1565 1566 final float oldSize = getTextSize(); 1567 setTextSize(oldSize * mCompatScaling); 1568 float totalAdvance = native_getTextRunAdvances(mNativePaint, text, start, end, 1569 contextStart, contextEnd, flags, advances, advancesIndex); 1570 setTextSize(oldSize); 1571 1572 if (advances != null) { 1573 for (int i = advancesIndex, e = i + (end - start); i < e; i++) { 1574 advances[i] *= mInvCompatScaling; 1575 } 1576 } 1577 return totalAdvance * mInvCompatScaling; // assume errors are insignificant 1578 } 1579 1580 /** 1581 * Returns the next cursor position in the run. This avoids placing the 1582 * cursor between surrogates, between characters that form conjuncts, 1583 * between base characters and combining marks, or within a reordering 1584 * cluster. 1585 * 1586 * <p>ContextStart and offset are relative to the start of text. 1587 * The context is the shaping context for cursor movement, generally 1588 * the bounds of the metric span enclosing the cursor in the direction of 1589 * movement. 1590 * 1591 * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid 1592 * cursor position, this returns -1. Otherwise this will never return a 1593 * value before contextStart or after contextStart + contextLength. 1594 * 1595 * @param text the text 1596 * @param contextStart the start of the context 1597 * @param contextLength the length of the context 1598 * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR} 1599 * @param offset the cursor position to move from 1600 * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER}, 1601 * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE}, 1602 * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT} 1603 * @return the offset of the next position, or -1 1604 * @hide 1605 */ 1606 public int getTextRunCursor(char[] text, int contextStart, int contextLength, 1607 int flags, int offset, int cursorOpt) { 1608 int contextEnd = contextStart + contextLength; 1609 if (((contextStart | contextEnd | offset | (contextEnd - contextStart) 1610 | (offset - contextStart) | (contextEnd - offset) 1611 | (text.length - contextEnd) | cursorOpt) < 0) 1612 || cursorOpt > CURSOR_OPT_MAX_VALUE) { 1613 throw new IndexOutOfBoundsException(); 1614 } 1615 1616 return native_getTextRunCursor(mNativePaint, text, 1617 contextStart, contextLength, flags, offset, cursorOpt); 1618 } 1619 1620 /** 1621 * Returns the next cursor position in the run. This avoids placing the 1622 * cursor between surrogates, between characters that form conjuncts, 1623 * between base characters and combining marks, or within a reordering 1624 * cluster. 1625 * 1626 * <p>ContextStart, contextEnd, and offset are relative to the start of 1627 * text. The context is the shaping context for cursor movement, generally 1628 * the bounds of the metric span enclosing the cursor in the direction of 1629 * movement. 1630 * 1631 * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid 1632 * cursor position, this returns -1. Otherwise this will never return a 1633 * value before contextStart or after contextEnd. 1634 * 1635 * @param text the text 1636 * @param contextStart the start of the context 1637 * @param contextEnd the end of the context 1638 * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR} 1639 * @param offset the cursor position to move from 1640 * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER}, 1641 * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE}, 1642 * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT} 1643 * @return the offset of the next position, or -1 1644 * @hide 1645 */ 1646 public int getTextRunCursor(CharSequence text, int contextStart, 1647 int contextEnd, int flags, int offset, int cursorOpt) { 1648 1649 if (text instanceof String || text instanceof SpannedString || 1650 text instanceof SpannableString) { 1651 return getTextRunCursor(text.toString(), contextStart, contextEnd, 1652 flags, offset, cursorOpt); 1653 } 1654 if (text instanceof GraphicsOperations) { 1655 return ((GraphicsOperations) text).getTextRunCursor( 1656 contextStart, contextEnd, flags, offset, cursorOpt, this); 1657 } 1658 1659 int contextLen = contextEnd - contextStart; 1660 char[] buf = TemporaryBuffer.obtain(contextLen); 1661 TextUtils.getChars(text, contextStart, contextEnd, buf, 0); 1662 int result = getTextRunCursor(buf, 0, contextLen, flags, offset, cursorOpt); 1663 TemporaryBuffer.recycle(buf); 1664 return result; 1665 } 1666 1667 /** 1668 * Returns the next cursor position in the run. This avoids placing the 1669 * cursor between surrogates, between characters that form conjuncts, 1670 * between base characters and combining marks, or within a reordering 1671 * cluster. 1672 * 1673 * <p>ContextStart, contextEnd, and offset are relative to the start of 1674 * text. The context is the shaping context for cursor movement, generally 1675 * the bounds of the metric span enclosing the cursor in the direction of 1676 * movement. 1677 * 1678 * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid 1679 * cursor position, this returns -1. Otherwise this will never return a 1680 * value before contextStart or after contextEnd. 1681 * 1682 * @param text the text 1683 * @param contextStart the start of the context 1684 * @param contextEnd the end of the context 1685 * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR} 1686 * @param offset the cursor position to move from 1687 * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER}, 1688 * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE}, 1689 * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT} 1690 * @return the offset of the next position, or -1 1691 * @hide 1692 */ 1693 public int getTextRunCursor(String text, int contextStart, int contextEnd, 1694 int flags, int offset, int cursorOpt) { 1695 if (((contextStart | contextEnd | offset | (contextEnd - contextStart) 1696 | (offset - contextStart) | (contextEnd - offset) 1697 | (text.length() - contextEnd) | cursorOpt) < 0) 1698 || cursorOpt > CURSOR_OPT_MAX_VALUE) { 1699 throw new IndexOutOfBoundsException(); 1700 } 1701 1702 return native_getTextRunCursor(mNativePaint, text, 1703 contextStart, contextEnd, flags, offset, cursorOpt); 1704 } 1705 1706 /** 1707 * Return the path (outline) for the specified text. 1708 * Note: just like Canvas.drawText, this will respect the Align setting in 1709 * the paint. 1710 * 1711 * @param text The text to retrieve the path from 1712 * @param index The index of the first character in text 1713 * @param count The number of characterss starting with index 1714 * @param x The x coordinate of the text's origin 1715 * @param y The y coordinate of the text's origin 1716 * @param path The path to receive the data describing the text. Must 1717 * be allocated by the caller. 1718 */ 1719 public void getTextPath(char[] text, int index, int count, 1720 float x, float y, Path path) { 1721 if ((index | count) < 0 || index + count > text.length) { 1722 throw new ArrayIndexOutOfBoundsException(); 1723 } 1724 native_getTextPath(mNativePaint, mBidiFlags, text, index, count, x, y, 1725 path.ni()); 1726 } 1727 1728 /** 1729 * Return the path (outline) for the specified text. 1730 * Note: just like Canvas.drawText, this will respect the Align setting 1731 * in the paint. 1732 * 1733 * @param text The text to retrieve the path from 1734 * @param start The first character in the text 1735 * @param end 1 past the last charcter in the text 1736 * @param x The x coordinate of the text's origin 1737 * @param y The y coordinate of the text's origin 1738 * @param path The path to receive the data describing the text. Must 1739 * be allocated by the caller. 1740 */ 1741 public void getTextPath(String text, int start, int end, 1742 float x, float y, Path path) { 1743 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1744 throw new IndexOutOfBoundsException(); 1745 } 1746 native_getTextPath(mNativePaint, mBidiFlags, text, start, end, x, y, 1747 path.ni()); 1748 } 1749 1750 /** 1751 * Return in bounds (allocated by the caller) the smallest rectangle that 1752 * encloses all of the characters, with an implied origin at (0,0). 1753 * 1754 * @param text String to measure and return its bounds 1755 * @param start Index of the first char in the string to measure 1756 * @param end 1 past the last char in the string measure 1757 * @param bounds Returns the unioned bounds of all the text. Must be 1758 * allocated by the caller. 1759 */ 1760 public void getTextBounds(String text, int start, int end, Rect bounds) { 1761 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1762 throw new IndexOutOfBoundsException(); 1763 } 1764 if (bounds == null) { 1765 throw new NullPointerException("need bounds Rect"); 1766 } 1767 nativeGetStringBounds(mNativePaint, text, start, end, bounds); 1768 } 1769 1770 /** 1771 * Return in bounds (allocated by the caller) the smallest rectangle that 1772 * encloses all of the characters, with an implied origin at (0,0). 1773 * 1774 * @param text Array of chars to measure and return their unioned bounds 1775 * @param index Index of the first char in the array to measure 1776 * @param count The number of chars, beginning at index, to measure 1777 * @param bounds Returns the unioned bounds of all the text. Must be 1778 * allocated by the caller. 1779 */ 1780 public void getTextBounds(char[] text, int index, int count, Rect bounds) { 1781 if ((index | count) < 0 || index + count > text.length) { 1782 throw new ArrayIndexOutOfBoundsException(); 1783 } 1784 if (bounds == null) { 1785 throw new NullPointerException("need bounds Rect"); 1786 } 1787 nativeGetCharArrayBounds(mNativePaint, text, index, count, bounds); 1788 } 1789 1790 protected void finalize() throws Throwable { 1791 finalizer(mNativePaint); 1792 } 1793 1794 private static native int native_init(); 1795 private static native int native_initWithPaint(int paint); 1796 private static native void native_reset(int native_object); 1797 private static native void native_set(int native_dst, int native_src); 1798 private static native int native_getStyle(int native_object); 1799 private static native void native_setStyle(int native_object, int style); 1800 private static native int native_getStrokeCap(int native_object); 1801 private static native void native_setStrokeCap(int native_object, int cap); 1802 private static native int native_getStrokeJoin(int native_object); 1803 private static native void native_setStrokeJoin(int native_object, 1804 int join); 1805 private static native boolean native_getFillPath(int native_object, 1806 int src, int dst); 1807 private static native int native_setShader(int native_object, int shader); 1808 private static native int native_setColorFilter(int native_object, 1809 int filter); 1810 private static native int native_setXfermode(int native_object, 1811 int xfermode); 1812 private static native int native_setPathEffect(int native_object, 1813 int effect); 1814 private static native int native_setMaskFilter(int native_object, 1815 int maskfilter); 1816 private static native int native_setTypeface(int native_object, 1817 int typeface); 1818 private static native int native_setRasterizer(int native_object, 1819 int rasterizer); 1820 1821 private static native int native_getTextAlign(int native_object); 1822 private static native void native_setTextAlign(int native_object, 1823 int align); 1824 1825 private static native float native_getFontMetrics(int native_paint, 1826 FontMetrics metrics); 1827 private static native int native_getTextWidths(int native_object, 1828 char[] text, int index, int count, float[] widths); 1829 private static native int native_getTextWidths(int native_object, 1830 String text, int start, int end, float[] widths); 1831 1832 private static native float native_getTextRunAdvances(int native_object, 1833 char[] text, int index, int count, int contextIndex, int contextCount, 1834 int flags, float[] advances, int advancesIndex); 1835 private static native float native_getTextRunAdvances(int native_object, 1836 String text, int start, int end, int contextStart, int contextEnd, 1837 int flags, float[] advances, int advancesIndex); 1838 1839 private native int native_getTextRunCursor(int native_object, char[] text, 1840 int contextStart, int contextLength, int flags, int offset, int cursorOpt); 1841 private native int native_getTextRunCursor(int native_object, String text, 1842 int contextStart, int contextEnd, int flags, int offset, int cursorOpt); 1843 1844 private static native void native_getTextPath(int native_object, int bidiFlags, 1845 char[] text, int index, int count, float x, float y, int path); 1846 private static native void native_getTextPath(int native_object, int bidiFlags, 1847 String text, int start, int end, float x, float y, int path); 1848 private static native void nativeGetStringBounds(int nativePaint, 1849 String text, int start, int end, Rect bounds); 1850 private static native void nativeGetCharArrayBounds(int nativePaint, 1851 char[] text, int index, int count, Rect bounds); 1852 private static native void finalizer(int nativePaint); 1853} 1854