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