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