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