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