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.annotation.ColorLong;
21 import android.annotation.IntDef;
22 import android.annotation.IntRange;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.Px;
26 import android.annotation.Size;
27 import android.compat.annotation.UnsupportedAppUsage;
28 import android.graphics.fonts.FontVariationAxis;
29 import android.os.Build;
30 import android.os.LocaleList;
31 import android.text.GraphicsOperations;
32 import android.text.SpannableString;
33 import android.text.SpannedString;
34 import android.text.TextUtils;
35 
36 import com.android.internal.annotations.GuardedBy;
37 
38 import dalvik.annotation.optimization.CriticalNative;
39 import dalvik.annotation.optimization.FastNative;
40 
41 import libcore.util.NativeAllocationRegistry;
42 
43 import java.lang.annotation.Retention;
44 import java.lang.annotation.RetentionPolicy;
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.Locale;
49 
50 /**
51  * The Paint class holds the style and color information about how to draw
52  * geometries, text and bitmaps.
53  */
54 public class Paint {
55 
56     @UnsupportedAppUsage
57     private long mNativePaint;
58     private long mNativeShader;
59     private long mNativeColorFilter;
60 
61     // Use a Holder to allow static initialization of Paint in the boot image.
62     private static class NoImagePreloadHolder {
63         public static final NativeAllocationRegistry sRegistry =
64                 NativeAllocationRegistry.createMalloced(
65                 Paint.class.getClassLoader(), nGetNativeFinalizer());
66     }
67 
68     @ColorLong private long mColor;
69     private ColorFilter     mColorFilter;
70     private MaskFilter      mMaskFilter;
71     private PathEffect      mPathEffect;
72     private Shader          mShader;
73     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
74     private Typeface        mTypeface;
75     private Xfermode        mXfermode;
76 
77     private boolean         mHasCompatScaling;
78     private float           mCompatScaling;
79     private float           mInvCompatScaling;
80 
81     private LocaleList      mLocales;
82     private String          mFontFeatureSettings;
83     private String          mFontVariationSettings;
84 
85     private float           mShadowLayerRadius;
86     private float           mShadowLayerDx;
87     private float           mShadowLayerDy;
88     @ColorLong private long mShadowLayerColor;
89 
90     private static final Object sCacheLock = new Object();
91 
92     /**
93      * Cache for the Minikin language list ID.
94      *
95      * A map from a string representation of the LocaleList to Minikin's language list ID.
96      */
97     @GuardedBy("sCacheLock")
98     private static final HashMap<String, Integer> sMinikinLocaleListIdCache = new HashMap<>();
99 
100     /**
101      * @hide
102      */
103     public  int         mBidiFlags = BIDI_DEFAULT_LTR;
104 
105     static final Style[] sStyleArray = {
106         Style.FILL, Style.STROKE, Style.FILL_AND_STROKE
107     };
108     static final Cap[] sCapArray = {
109         Cap.BUTT, Cap.ROUND, Cap.SQUARE
110     };
111     static final Join[] sJoinArray = {
112         Join.MITER, Join.ROUND, Join.BEVEL
113     };
114     static final Align[] sAlignArray = {
115         Align.LEFT, Align.CENTER, Align.RIGHT
116     };
117 
118     /**
119      * Paint flag that enables antialiasing when drawing.
120      *
121      * <p>Enabling this flag will cause all draw operations that support
122      * antialiasing to use it.</p>
123      *
124      * @see #Paint(int)
125      * @see #setFlags(int)
126      */
127     public static final int ANTI_ALIAS_FLAG     = 0x01;
128     /**
129      * Paint flag that enables bilinear sampling on scaled bitmaps.
130      *
131      * <p>If cleared, scaled bitmaps will be drawn with nearest neighbor
132      * sampling, likely resulting in artifacts. This should generally be on
133      * when drawing bitmaps, unless performance-bound (rendering to software
134      * canvas) or preferring pixelation artifacts to blurriness when scaling
135      * significantly.</p>
136      *
137      * <p>If bitmaps are scaled for device density at creation time (as
138      * resource bitmaps often are) the filtering will already have been
139      * done.</p>
140      *
141      * @see #Paint(int)
142      * @see #setFlags(int)
143      */
144     public static final int FILTER_BITMAP_FLAG  = 0x02;
145     /**
146      * Paint flag that enables dithering when blitting.
147      *
148      * <p>Enabling this flag applies a dither to any blit operation where the
149      * target's colour space is more constrained than the source.
150      *
151      * @see #Paint(int)
152      * @see #setFlags(int)
153      */
154     public static final int DITHER_FLAG         = 0x04;
155     /**
156      * Paint flag that applies an underline decoration to drawn text.
157      *
158      * @see #Paint(int)
159      * @see #setFlags(int)
160      */
161     public static final int UNDERLINE_TEXT_FLAG = 0x08;
162     /**
163      * Paint flag that applies a strike-through decoration to drawn text.
164      *
165      * @see #Paint(int)
166      * @see #setFlags(int)
167      */
168     public static final int STRIKE_THRU_TEXT_FLAG = 0x10;
169     /**
170      * Paint flag that applies a synthetic bolding effect to drawn text.
171      *
172      * <p>Enabling this flag will cause text draw operations to apply a
173      * simulated bold effect when drawing a {@link Typeface} that is not
174      * already bold.</p>
175      *
176      * @see #Paint(int)
177      * @see #setFlags(int)
178      */
179     public static final int FAKE_BOLD_TEXT_FLAG = 0x20;
180     /**
181      * Paint flag that enables smooth linear scaling of text.
182      *
183      * <p>Enabling this flag does not actually scale text, but rather adjusts
184      * text draw operations to deal gracefully with smooth adjustment of scale.
185      * When this flag is enabled, font hinting is disabled to prevent shape
186      * deformation between scale factors, and glyph caching is disabled due to
187      * the large number of glyph images that will be generated.</p>
188      *
189      * <p>{@link #SUBPIXEL_TEXT_FLAG} should be used in conjunction with this
190      * flag to prevent glyph positions from snapping to whole pixel values as
191      * scale factor is adjusted.</p>
192      *
193      * @see #Paint(int)
194      * @see #setFlags(int)
195      */
196     public static final int LINEAR_TEXT_FLAG    = 0x40;
197     /**
198      * Paint flag that enables subpixel positioning of text.
199      *
200      * <p>Enabling this flag causes glyph advances to be computed with subpixel
201      * accuracy.</p>
202      *
203      * <p>This can be used with {@link #LINEAR_TEXT_FLAG} to prevent text from
204      * jittering during smooth scale transitions.</p>
205      *
206      * @see #Paint(int)
207      * @see #setFlags(int)
208      */
209     public static final int SUBPIXEL_TEXT_FLAG  = 0x80;
210     /** Legacy Paint flag, no longer used. */
211     public static final int DEV_KERN_TEXT_FLAG  = 0x100;
212     /** @hide bit mask for the flag enabling subpixel glyph rendering for text */
213     public static final int LCD_RENDER_TEXT_FLAG = 0x200;
214     /**
215      * Paint flag that enables the use of bitmap fonts when drawing text.
216      *
217      * <p>Disabling this flag will prevent text draw operations from using
218      * embedded bitmap strikes in fonts, causing fonts with both scalable
219      * outlines and bitmap strikes to draw only the scalable outlines, and
220      * fonts with only bitmap strikes to not draw at all.</p>
221      *
222      * @see #Paint(int)
223      * @see #setFlags(int)
224      */
225     public static final int EMBEDDED_BITMAP_TEXT_FLAG = 0x400;
226     /** @hide bit mask for the flag forcing freetype's autohinter on for text */
227     public static final int AUTO_HINTING_TEXT_FLAG = 0x800;
228     /** @hide bit mask for the flag enabling vertical rendering for text */
229     public static final int VERTICAL_TEXT_FLAG = 0x1000;
230 
231     // These flags are always set on a new/reset paint, even if flags 0 is passed.
232     static final int HIDDEN_DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG | EMBEDDED_BITMAP_TEXT_FLAG
233             | FILTER_BITMAP_FLAG;
234 
235     /**
236      * Font hinter option that disables font hinting.
237      *
238      * @see #setHinting(int)
239      */
240     public static final int HINTING_OFF = 0x0;
241 
242     /**
243      * Font hinter option that enables font hinting.
244      *
245      * @see #setHinting(int)
246      */
247     public static final int HINTING_ON = 0x1;
248 
249     /**
250      * Bidi flag to set LTR paragraph direction.
251      *
252      * @hide
253      */
254     public static final int BIDI_LTR = 0x0;
255 
256     /**
257      * Bidi flag to set RTL paragraph direction.
258      *
259      * @hide
260      */
261     public static final int BIDI_RTL = 0x1;
262 
263     /**
264      * Bidi flag to detect paragraph direction via heuristics, defaulting to
265      * LTR.
266      *
267      * @hide
268      */
269     public static final int BIDI_DEFAULT_LTR = 0x2;
270 
271     /**
272      * Bidi flag to detect paragraph direction via heuristics, defaulting to
273      * RTL.
274      *
275      * @hide
276      */
277     public static final int BIDI_DEFAULT_RTL = 0x3;
278 
279     /**
280      * Bidi flag to override direction to all LTR (ignore bidi).
281      *
282      * @hide
283      */
284     public static final int BIDI_FORCE_LTR = 0x4;
285 
286     /**
287      * Bidi flag to override direction to all RTL (ignore bidi).
288      *
289      * @hide
290      */
291     public static final int BIDI_FORCE_RTL = 0x5;
292 
293     /**
294      * Maximum Bidi flag value.
295      * @hide
296      */
297     private static final int BIDI_MAX_FLAG_VALUE = BIDI_FORCE_RTL;
298 
299     /**
300      * Mask for bidi flags.
301      * @hide
302      */
303     private static final int BIDI_FLAG_MASK = 0x7;
304 
305     /**
306      * Flag for getTextRunAdvances indicating left-to-right run direction.
307      * @hide
308      */
309     public static final int DIRECTION_LTR = 0;
310 
311     /**
312      * Flag for getTextRunAdvances indicating right-to-left run direction.
313      * @hide
314      */
315     public static final int DIRECTION_RTL = 1;
316 
317     /** @hide */
318     @IntDef(prefix = { "CURSOR_" }, value = {
319         CURSOR_AFTER, CURSOR_AT_OR_AFTER, CURSOR_BEFORE, CURSOR_AT_OR_BEFORE
320     })
321     @Retention(RetentionPolicy.SOURCE)
322     public @interface CursorOption {}
323 
324     /**
325      * Option for getTextRunCursor.
326      *
327      * Compute the valid cursor after offset or the limit of the context, whichever is less.
328      */
329     public static final int CURSOR_AFTER = 0;
330 
331     /**
332      * Option for getTextRunCursor.
333      *
334      * Compute the valid cursor at or after the offset or the limit of the context, whichever is
335      * less.
336      */
337     public static final int CURSOR_AT_OR_AFTER = 1;
338 
339      /**
340      * Option for getTextRunCursor.
341      *
342      * Compute the valid cursor before offset or the start of the context, whichever is greater.
343      */
344     public static final int CURSOR_BEFORE = 2;
345 
346    /**
347      * Option for getTextRunCursor.
348      *
349      * Compute the valid cursor at or before offset or the start of the context, whichever is
350      * greater.
351      */
352     public static final int CURSOR_AT_OR_BEFORE = 3;
353 
354     /**
355      * Option for getTextRunCursor.
356      *
357      * Return offset if the cursor at offset is valid, or -1 if it isn't.
358      */
359     public static final int CURSOR_AT = 4;
360 
361     /**
362      * Maximum cursor option value.
363      */
364     private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
365 
366     /** @hide */
367     @IntDef(prefix = { "START_HYPHEN_EDIT_" }, value = {
368         START_HYPHEN_EDIT_NO_EDIT,
369         START_HYPHEN_EDIT_INSERT_HYPHEN,
370         START_HYPHEN_EDIT_INSERT_ZWJ
371     })
372     @Retention(RetentionPolicy.SOURCE)
373     public @interface StartHyphenEdit {}
374 
375     /**
376      * An integer representing the starting of the line has no modification for hyphenation.
377      */
378     public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
379 
380     /**
381      * An integer representing the starting of the line has normal hyphen character (U+002D).
382      */
383     public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 0x01;
384 
385     /**
386      * An integer representing the starting of the line has Zero-Width-Joiner (U+200D).
387      */
388     public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 0x02;
389 
390     /** @hide */
391     @IntDef(prefix = { "END_HYPHEN_EDIT_" }, value = {
392         END_HYPHEN_EDIT_NO_EDIT,
393         END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN,
394         END_HYPHEN_EDIT_INSERT_HYPHEN,
395         END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN,
396         END_HYPHEN_EDIT_INSERT_MAQAF,
397         END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN,
398         END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN
399     })
400     @Retention(RetentionPolicy.SOURCE)
401     public @interface EndHyphenEdit {}
402 
403     /**
404      * An integer representing the end of the line has no modification for hyphenation.
405      */
406     public static final int END_HYPHEN_EDIT_NO_EDIT = 0x00;
407 
408     /**
409      * An integer representing the character at the end of the line is replaced with hyphen
410      * character (U+002D).
411      */
412     public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0x01;
413 
414     /**
415      * An integer representing the end of the line has normal hyphen character (U+002D).
416      */
417     public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 0x02;
418 
419     /**
420      * An integer representing the end of the line has Armentian hyphen (U+058A).
421      */
422     public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0x03;
423 
424     /**
425      * An integer representing the end of the line has maqaf (Hebrew hyphen, U+05BE).
426      */
427     public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 0x04;
428 
429     /**
430      * An integer representing the end of the line has Canadian Syllabics hyphen (U+1400).
431      */
432     public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0x05;
433 
434     /**
435      * An integer representing the end of the line has Zero-Width-Joiner (U+200D) followed by normal
436      * hyphen character (U+002D).
437      */
438     public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0x06;
439 
440     /**
441      * The Style specifies if the primitive being drawn is filled, stroked, or
442      * both (in the same color). The default is FILL.
443      */
444     public enum Style {
445         /**
446          * Geometry and text drawn with this style will be filled, ignoring all
447          * stroke-related settings in the paint.
448          */
449         FILL            (0),
450         /**
451          * Geometry and text drawn with this style will be stroked, respecting
452          * the stroke-related fields on the paint.
453          */
454         STROKE          (1),
455         /**
456          * Geometry and text drawn with this style will be both filled and
457          * stroked at the same time, respecting the stroke-related fields on
458          * the paint. This mode can give unexpected results if the geometry
459          * is oriented counter-clockwise. This restriction does not apply to
460          * either FILL or STROKE.
461          */
462         FILL_AND_STROKE (2);
463 
Style(int nativeInt)464         Style(int nativeInt) {
465             this.nativeInt = nativeInt;
466         }
467         final int nativeInt;
468     }
469 
470     /**
471      * The Cap specifies the treatment for the beginning and ending of
472      * stroked lines and paths. The default is BUTT.
473      */
474     public enum Cap {
475         /**
476          * The stroke ends with the path, and does not project beyond it.
477          */
478         BUTT    (0),
479         /**
480          * The stroke projects out as a semicircle, with the center at the
481          * end of the path.
482          */
483         ROUND   (1),
484         /**
485          * The stroke projects out as a square, with the center at the end
486          * of the path.
487          */
488         SQUARE  (2);
489 
Cap(int nativeInt)490         private Cap(int nativeInt) {
491             this.nativeInt = nativeInt;
492         }
493         final int nativeInt;
494     }
495 
496     /**
497      * The Join specifies the treatment where lines and curve segments
498      * join on a stroked path. The default is MITER.
499      */
500     public enum Join {
501         /**
502          * The outer edges of a join meet at a sharp angle
503          */
504         MITER   (0),
505         /**
506          * The outer edges of a join meet in a circular arc.
507          */
508         ROUND   (1),
509         /**
510          * The outer edges of a join meet with a straight line
511          */
512         BEVEL   (2);
513 
Join(int nativeInt)514         private Join(int nativeInt) {
515             this.nativeInt = nativeInt;
516         }
517         final int nativeInt;
518     }
519 
520     /**
521      * Align specifies how drawText aligns its text relative to the
522      * [x,y] coordinates. The default is LEFT.
523      */
524     public enum Align {
525         /**
526          * The text is drawn to the right of the x,y origin
527          */
528         LEFT    (0),
529         /**
530          * The text is drawn centered horizontally on the x,y origin
531          */
532         CENTER  (1),
533         /**
534          * The text is drawn to the left of the x,y origin
535          */
536         RIGHT   (2);
537 
Align(int nativeInt)538         private Align(int nativeInt) {
539             this.nativeInt = nativeInt;
540         }
541         final int nativeInt;
542     }
543 
544     /**
545      * Create a new paint with default settings.
546      */
Paint()547     public Paint() {
548         this(0);
549     }
550 
551     /**
552      * Create a new paint with the specified flags. Use setFlags() to change
553      * these after the paint is created.
554      *
555      * @param flags initial flag bits, as if they were passed via setFlags().
556      */
Paint(int flags)557     public Paint(int flags) {
558         mNativePaint = nInit();
559         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
560         setFlags(flags | HIDDEN_DEFAULT_PAINT_FLAGS);
561         // TODO: Turning off hinting has undesirable side effects, we need to
562         //       revisit hinting once we add support for subpixel positioning
563         // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
564         //        ? HINTING_OFF : HINTING_ON);
565         mCompatScaling = mInvCompatScaling = 1;
566         setTextLocales(LocaleList.getAdjustedDefault());
567         mColor = Color.pack(Color.BLACK);
568     }
569 
570     /**
571      * Create a new paint, initialized with the attributes in the specified
572      * paint parameter.
573      *
574      * @param paint Existing paint used to initialized the attributes of the
575      *              new paint.
576      */
Paint(Paint paint)577     public Paint(Paint paint) {
578         mNativePaint = nInitWithPaint(paint.getNativeInstance());
579         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
580         setClassVariablesFrom(paint);
581     }
582 
583     /** Restores the paint to its default settings. */
reset()584     public void reset() {
585         nReset(mNativePaint);
586         setFlags(HIDDEN_DEFAULT_PAINT_FLAGS);
587 
588         // TODO: Turning off hinting has undesirable side effects, we need to
589         //       revisit hinting once we add support for subpixel positioning
590         // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
591         //        ? HINTING_OFF : HINTING_ON);
592 
593         mColor = Color.pack(Color.BLACK);
594         mColorFilter = null;
595         mMaskFilter = null;
596         mPathEffect = null;
597         mShader = null;
598         mNativeShader = 0;
599         mTypeface = null;
600         mXfermode = null;
601 
602         mHasCompatScaling = false;
603         mCompatScaling = 1;
604         mInvCompatScaling = 1;
605 
606         mBidiFlags = BIDI_DEFAULT_LTR;
607         setTextLocales(LocaleList.getAdjustedDefault());
608         setElegantTextHeight(false);
609         mFontFeatureSettings = null;
610         mFontVariationSettings = null;
611 
612         mShadowLayerRadius = 0.0f;
613         mShadowLayerDx = 0.0f;
614         mShadowLayerDy = 0.0f;
615         mShadowLayerColor = Color.pack(0);
616     }
617 
618     /**
619      * Copy the fields from src into this paint. This is equivalent to calling
620      * get() on all of the src fields, and calling the corresponding set()
621      * methods on this.
622      */
set(Paint src)623     public void set(Paint src) {
624         if (this != src) {
625             // copy over the native settings
626             nSet(mNativePaint, src.mNativePaint);
627             setClassVariablesFrom(src);
628         }
629     }
630 
631     /**
632      * Set all class variables using current values from the given
633      * {@link Paint}.
634      */
setClassVariablesFrom(Paint paint)635     private void setClassVariablesFrom(Paint paint) {
636         mColor = paint.mColor;
637         mColorFilter = paint.mColorFilter;
638         mMaskFilter = paint.mMaskFilter;
639         mPathEffect = paint.mPathEffect;
640         mShader = paint.mShader;
641         mNativeShader = paint.mNativeShader;
642         mTypeface = paint.mTypeface;
643         mXfermode = paint.mXfermode;
644 
645         mHasCompatScaling = paint.mHasCompatScaling;
646         mCompatScaling = paint.mCompatScaling;
647         mInvCompatScaling = paint.mInvCompatScaling;
648 
649         mBidiFlags = paint.mBidiFlags;
650         mLocales = paint.mLocales;
651         mFontFeatureSettings = paint.mFontFeatureSettings;
652         mFontVariationSettings = paint.mFontVariationSettings;
653 
654         mShadowLayerRadius = paint.mShadowLayerRadius;
655         mShadowLayerDx = paint.mShadowLayerDx;
656         mShadowLayerDy = paint.mShadowLayerDy;
657         mShadowLayerColor = paint.mShadowLayerColor;
658     }
659 
660     /** @hide */
661     @UnsupportedAppUsage
setCompatibilityScaling(float factor)662     public void setCompatibilityScaling(float factor) {
663         if (factor == 1.0) {
664             mHasCompatScaling = false;
665             mCompatScaling = mInvCompatScaling = 1.0f;
666         } else {
667             mHasCompatScaling = true;
668             mCompatScaling = factor;
669             mInvCompatScaling = 1.0f/factor;
670         }
671     }
672 
673     /**
674      * Return the pointer to the native object while ensuring that any
675      * mutable objects that are attached to the paint are also up-to-date.
676      *
677      * @hide
678      */
679     @UnsupportedAppUsage
getNativeInstance()680     public long getNativeInstance() {
681         long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
682         if (newNativeShader != mNativeShader) {
683             mNativeShader = newNativeShader;
684             nSetShader(mNativePaint, mNativeShader);
685         }
686         long newNativeColorFilter = mColorFilter == null ? 0 : mColorFilter.getNativeInstance();
687         if (newNativeColorFilter != mNativeColorFilter) {
688             mNativeColorFilter = newNativeColorFilter;
689             nSetColorFilter(mNativePaint, mNativeColorFilter);
690         }
691         return mNativePaint;
692     }
693 
694     /**
695      * Return the bidi flags on the paint.
696      *
697      * @return the bidi flags on the paint
698      * @hide
699      */
getBidiFlags()700     public int getBidiFlags() {
701         return mBidiFlags;
702     }
703 
704     /**
705      * Set the bidi flags on the paint.
706      * @hide
707      */
setBidiFlags(int flags)708     public void setBidiFlags(int flags) {
709         // only flag value is the 3-bit BIDI control setting
710         flags &= BIDI_FLAG_MASK;
711         if (flags > BIDI_MAX_FLAG_VALUE) {
712             throw new IllegalArgumentException("unknown bidi flag: " + flags);
713         }
714         mBidiFlags = flags;
715     }
716 
717     /**
718      * Return the paint's flags. Use the Flag enum to test flag values.
719      *
720      * @return the paint's flags (see enums ending in _Flag for bit masks)
721      */
getFlags()722     public int getFlags() {
723         return nGetFlags(mNativePaint);
724     }
725 
726     /**
727      * Set the paint's flags. Use the Flag enum to specific flag values.
728      *
729      * @param flags The new flag bits for the paint
730      */
setFlags(int flags)731     public void setFlags(int flags) {
732         nSetFlags(mNativePaint, flags);
733     }
734 
735     /**
736      * Return the paint's hinting mode.  Returns either
737      * {@link #HINTING_OFF} or {@link #HINTING_ON}.
738      */
getHinting()739     public int getHinting() {
740         return nGetHinting(mNativePaint);
741     }
742 
743     /**
744      * Set the paint's hinting mode.  May be either
745      * {@link #HINTING_OFF} or {@link #HINTING_ON}.
746      */
setHinting(int mode)747     public void setHinting(int mode) {
748         nSetHinting(mNativePaint, mode);
749     }
750 
751     /**
752      * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set
753      * AntiAliasing smooths out the edges of what is being drawn, but is has
754      * no impact on the interior of the shape. See setDither() and
755      * setFilterBitmap() to affect how colors are treated.
756      *
757      * @return true if the antialias bit is set in the paint's flags.
758      */
isAntiAlias()759     public final boolean isAntiAlias() {
760         return (getFlags() & ANTI_ALIAS_FLAG) != 0;
761     }
762 
763     /**
764      * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit
765      * AntiAliasing smooths out the edges of what is being drawn, but is has
766      * no impact on the interior of the shape. See setDither() and
767      * setFilterBitmap() to affect how colors are treated.
768      *
769      * @param aa true to set the antialias bit in the flags, false to clear it
770      */
setAntiAlias(boolean aa)771     public void setAntiAlias(boolean aa) {
772         nSetAntiAlias(mNativePaint, aa);
773     }
774 
775     /**
776      * Helper for getFlags(), returning true if DITHER_FLAG bit is set
777      * Dithering affects how colors that are higher precision than the device
778      * are down-sampled. No dithering is generally faster, but higher precision
779      * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
780      * distribute the error inherent in this process, to reduce the visual
781      * artifacts.
782      *
783      * @return true if the dithering bit is set in the paint's flags.
784      */
isDither()785     public final boolean isDither() {
786         return (getFlags() & DITHER_FLAG) != 0;
787     }
788 
789     /**
790      * Helper for setFlags(), setting or clearing the DITHER_FLAG bit
791      * Dithering affects how colors that are higher precision than the device
792      * are down-sampled. No dithering is generally faster, but higher precision
793      * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
794      * distribute the error inherent in this process, to reduce the visual
795      * artifacts.
796      *
797      * @param dither true to set the dithering bit in flags, false to clear it
798      */
setDither(boolean dither)799     public void setDither(boolean dither) {
800         nSetDither(mNativePaint, dither);
801     }
802 
803     /**
804      * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set
805      *
806      * @return true if the lineartext bit is set in the paint's flags
807      */
isLinearText()808     public final boolean isLinearText() {
809         return (getFlags() & LINEAR_TEXT_FLAG) != 0;
810     }
811 
812     /**
813      * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit
814      *
815      * @param linearText true to set the linearText bit in the paint's flags,
816      *                   false to clear it.
817      */
setLinearText(boolean linearText)818     public void setLinearText(boolean linearText) {
819         nSetLinearText(mNativePaint, linearText);
820     }
821 
822     /**
823      * Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set
824      *
825      * @return true if the subpixel bit is set in the paint's flags
826      */
isSubpixelText()827     public final boolean isSubpixelText() {
828         return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0;
829     }
830 
831     /**
832      * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit
833      *
834      * @param subpixelText true to set the subpixelText bit in the paint's
835      *                     flags, false to clear it.
836      */
setSubpixelText(boolean subpixelText)837     public void setSubpixelText(boolean subpixelText) {
838         nSetSubpixelText(mNativePaint, subpixelText);
839     }
840 
841     /**
842      * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
843      *
844      * @return true if the underlineText bit is set in the paint's flags.
845      * @see #getUnderlinePosition()
846      * @see #getUnderlineThickness()
847      * @see #setUnderlineText(boolean)
848      */
isUnderlineText()849     public final boolean isUnderlineText() {
850         return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
851     }
852 
853     /**
854      * Returns the distance from top of the underline to the baseline in pixels.
855      *
856      * The result is positive for positions that are below the baseline.
857      * This method returns where the underline should be drawn independent of if the {@link
858      * #UNDERLINE_TEXT_FLAG} bit is set.
859      *
860      * @return the position of the underline in pixels
861      * @see #isUnderlineText()
862      * @see #getUnderlineThickness()
863      * @see #setUnderlineText(boolean)
864      */
getUnderlinePosition()865     public @Px float getUnderlinePosition() {
866         return nGetUnderlinePosition(mNativePaint);
867     }
868 
869     /**
870      * Returns the thickness of the underline in pixels.
871      *
872      * @return the thickness of the underline in pixels
873      * @see #isUnderlineText()
874      * @see #getUnderlinePosition()
875      * @see #setUnderlineText(boolean)
876      */
getUnderlineThickness()877     public @Px float getUnderlineThickness() {
878         return nGetUnderlineThickness(mNativePaint);
879     }
880 
881     /**
882      * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit
883      *
884      * @param underlineText true to set the underlineText bit in the paint's
885      *                      flags, false to clear it.
886      * @see #isUnderlineText()
887      * @see #getUnderlinePosition()
888      * @see #getUnderlineThickness()
889      */
setUnderlineText(boolean underlineText)890     public void setUnderlineText(boolean underlineText) {
891         nSetUnderlineText(mNativePaint, underlineText);
892     }
893 
894     /**
895      * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
896      *
897      * @return true if the {@link #STRIKE_THRU_TEXT_FLAG} bit is set in the paint's flags.
898      * @see #getStrikeThruPosition()
899      * @see #getStrikeThruThickness()
900      * @see #setStrikeThruText(boolean)
901      */
isStrikeThruText()902     public final boolean isStrikeThruText() {
903         return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
904     }
905 
906     /**
907      * Distance from top of the strike-through line to the baseline in pixels.
908      *
909      * The result is negative for positions that are above the baseline.
910      * This method returns where the strike-through line should be drawn independent of if the
911      * {@link #STRIKE_THRU_TEXT_FLAG} bit is set.
912      *
913      * @return the position of the strike-through line in pixels
914      * @see #getStrikeThruThickness()
915      * @see #setStrikeThruText(boolean)
916      * @see #isStrikeThruText()
917      */
getStrikeThruPosition()918     public @Px float getStrikeThruPosition() {
919         return nGetStrikeThruPosition(mNativePaint);
920     }
921 
922     /**
923      * Returns the thickness of the strike-through line in pixels.
924      *
925      * @return the position of the strike-through line in pixels
926      * @see #getStrikeThruPosition()
927      * @see #setStrikeThruText(boolean)
928      * @see #isStrikeThruText()
929      */
getStrikeThruThickness()930     public @Px float getStrikeThruThickness() {
931         return nGetStrikeThruThickness(mNativePaint);
932     }
933 
934     /**
935      * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
936      *
937      * @param strikeThruText true to set the strikeThruText bit in the paint's
938      *                       flags, false to clear it.
939      * @see #getStrikeThruPosition()
940      * @see #getStrikeThruThickness()
941      * @see #isStrikeThruText()
942      */
setStrikeThruText(boolean strikeThruText)943     public void setStrikeThruText(boolean strikeThruText) {
944         nSetStrikeThruText(mNativePaint, strikeThruText);
945     }
946 
947     /**
948      * Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set
949      *
950      * @return true if the fakeBoldText bit is set in the paint's flags.
951      */
isFakeBoldText()952     public final boolean isFakeBoldText() {
953         return (getFlags() & FAKE_BOLD_TEXT_FLAG) != 0;
954     }
955 
956     /**
957      * Helper for setFlags(), setting or clearing the FAKE_BOLD_TEXT_FLAG bit
958      *
959      * @param fakeBoldText true to set the fakeBoldText bit in the paint's
960      *                     flags, false to clear it.
961      */
setFakeBoldText(boolean fakeBoldText)962     public void setFakeBoldText(boolean fakeBoldText) {
963         nSetFakeBoldText(mNativePaint, fakeBoldText);
964     }
965 
966     /**
967      * Whether or not the bitmap filter is activated.
968      * Filtering affects the sampling of bitmaps when they are transformed.
969      * Filtering does not affect how the colors in the bitmap are converted into
970      * device pixels. That is dependent on dithering and xfermodes.
971      *
972      * @see #setFilterBitmap(boolean) setFilterBitmap()
973      */
isFilterBitmap()974     public final boolean isFilterBitmap() {
975         return (getFlags() & FILTER_BITMAP_FLAG) != 0;
976     }
977 
978     /**
979      * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit.
980      * Filtering affects the sampling of bitmaps when they are transformed.
981      * Filtering does not affect how the colors in the bitmap are converted into
982      * device pixels. That is dependent on dithering and xfermodes.
983      *
984      * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
985      *               flags, false to clear it.
986      */
setFilterBitmap(boolean filter)987     public void setFilterBitmap(boolean filter) {
988         nSetFilterBitmap(mNativePaint, filter);
989     }
990 
991     /**
992      * Return the paint's style, used for controlling how primitives'
993      * geometries are interpreted (except for drawBitmap, which always assumes
994      * FILL_STYLE).
995      *
996      * @return the paint's style setting (Fill, Stroke, StrokeAndFill)
997      */
getStyle()998     public Style getStyle() {
999         return sStyleArray[nGetStyle(mNativePaint)];
1000     }
1001 
1002     /**
1003      * Set the paint's style, used for controlling how primitives'
1004      * geometries are interpreted (except for drawBitmap, which always assumes
1005      * Fill).
1006      *
1007      * @param style The new style to set in the paint
1008      */
setStyle(Style style)1009     public void setStyle(Style style) {
1010         nSetStyle(mNativePaint, style.nativeInt);
1011     }
1012 
1013     /**
1014      * Return the paint's color in sRGB. Note that the color is a 32bit value
1015      * containing alpha as well as r,g,b. This 32bit value is not premultiplied,
1016      * meaning that its alpha can be any value, regardless of the values of
1017      * r,g,b. See the Color class for more details.
1018      *
1019      * @return the paint's color (and alpha).
1020      */
1021     @ColorInt
getColor()1022     public int getColor() {
1023         return Color.toArgb(mColor);
1024     }
1025 
1026     /**
1027      * Return the paint's color. Note that the color is a long with an encoded
1028      * {@link ColorSpace} as well as alpha and r,g,b. These values are not
1029      * premultiplied, meaning that alpha can be any value, regardless of the
1030      * values of r,g,b. See the {@link Color} class for more details.
1031      *
1032      * @return the paint's color, alpha, and {@code ColorSpace} encoded as a
1033      *      {@code ColorLong}
1034      */
1035     @ColorLong
getColorLong()1036     public long getColorLong() {
1037         return mColor;
1038     }
1039 
1040     /**
1041      * Set the paint's color. Note that the color is an int containing alpha
1042      * as well as r,g,b. This 32bit value is not premultiplied, meaning that
1043      * its alpha can be any value, regardless of the values of r,g,b.
1044      * See the Color class for more details.
1045      *
1046      * @param color The new color (including alpha) to set in the paint.
1047      */
setColor(@olorInt int color)1048     public void setColor(@ColorInt int color) {
1049         nSetColor(mNativePaint, color);
1050         mColor = Color.pack(color);
1051     }
1052 
1053     /**
1054      * Set the paint's color with a {@code ColorLong}. Note that the color is
1055      * a long with an encoded {@link ColorSpace} as well as alpha and r,g,b.
1056      * These values are not premultiplied, meaning that alpha can be any value,
1057      * regardless of the values of r,g,b. See the {@link Color} class for more
1058      * details.
1059      *
1060      * @param color The new color (including alpha and {@link ColorSpace})
1061      *      to set in the paint.
1062      * @throws IllegalArgumentException if the color space encoded in the
1063      *      {@code ColorLong} is invalid or unknown.
1064      */
setColor(@olorLong long color)1065     public void setColor(@ColorLong long color) {
1066         ColorSpace cs = Color.colorSpace(color);
1067 
1068         nSetColor(mNativePaint, cs.getNativeInstance(), color);
1069         mColor = color;
1070     }
1071 
1072     /**
1073      * Helper to getColor() that just returns the color's alpha value. This is
1074      * the same as calling getColor() >>> 24. It always returns a value between
1075      * 0 (completely transparent) and 255 (completely opaque).
1076      *
1077      * @return the alpha component of the paint's color.
1078      */
getAlpha()1079     public int getAlpha() {
1080         return Math.round(Color.alpha(mColor) * 255.0f);
1081     }
1082 
1083     /**
1084      * Helper to setColor(), that only assigns the color's alpha value,
1085      * leaving its r,g,b values unchanged. Results are undefined if the alpha
1086      * value is outside of the range [0..255]
1087      *
1088      * @param a set the alpha component [0..255] of the paint's color.
1089      */
setAlpha(int a)1090     public void setAlpha(int a) {
1091         // FIXME: No need to unpack this. Instead, just update the alpha bits.
1092         // b/122959599
1093         ColorSpace cs = Color.colorSpace(mColor);
1094         float r = Color.red(mColor);
1095         float g = Color.green(mColor);
1096         float b = Color.blue(mColor);
1097         mColor = Color.pack(r, g, b, a * (1.0f / 255), cs);
1098         nSetAlpha(mNativePaint, a);
1099     }
1100 
1101     /**
1102      * Helper to setColor(), that takes a,r,g,b and constructs the color int
1103      *
1104      * @param a The new alpha component (0..255) of the paint's color.
1105      * @param r The new red component (0..255) of the paint's color.
1106      * @param g The new green component (0..255) of the paint's color.
1107      * @param b The new blue component (0..255) of the paint's color.
1108      */
setARGB(int a, int r, int g, int b)1109     public void setARGB(int a, int r, int g, int b) {
1110         setColor((a << 24) | (r << 16) | (g << 8) | b);
1111     }
1112 
1113     /**
1114      * Return the width for stroking.
1115      * <p />
1116      * A value of 0 strokes in hairline mode.
1117      * Hairlines always draws a single pixel independent of the canvas's matrix.
1118      *
1119      * @return the paint's stroke width, used whenever the paint's style is
1120      *         Stroke or StrokeAndFill.
1121      */
getStrokeWidth()1122     public float getStrokeWidth() {
1123         return nGetStrokeWidth(mNativePaint);
1124     }
1125 
1126     /**
1127      * Set the width for stroking.
1128      * Pass 0 to stroke in hairline mode.
1129      * Hairlines always draws a single pixel independent of the canvas's matrix.
1130      *
1131      * @param width set the paint's stroke width, used whenever the paint's
1132      *              style is Stroke or StrokeAndFill.
1133      */
setStrokeWidth(float width)1134     public void setStrokeWidth(float width) {
1135         nSetStrokeWidth(mNativePaint, width);
1136     }
1137 
1138     /**
1139      * Return the paint's stroke miter value. Used to control the behavior
1140      * of miter joins when the joins angle is sharp.
1141      *
1142      * @return the paint's miter limit, used whenever the paint's style is
1143      *         Stroke or StrokeAndFill.
1144      */
getStrokeMiter()1145     public float getStrokeMiter() {
1146         return nGetStrokeMiter(mNativePaint);
1147     }
1148 
1149     /**
1150      * Set the paint's stroke miter value. This is used to control the behavior
1151      * of miter joins when the joins angle is sharp. This value must be >= 0.
1152      *
1153      * @param miter set the miter limit on the paint, used whenever the paint's
1154      *              style is Stroke or StrokeAndFill.
1155      */
setStrokeMiter(float miter)1156     public void setStrokeMiter(float miter) {
1157         nSetStrokeMiter(mNativePaint, miter);
1158     }
1159 
1160     /**
1161      * Return the paint's Cap, controlling how the start and end of stroked
1162      * lines and paths are treated.
1163      *
1164      * @return the line cap style for the paint, used whenever the paint's
1165      *         style is Stroke or StrokeAndFill.
1166      */
getStrokeCap()1167     public Cap getStrokeCap() {
1168         return sCapArray[nGetStrokeCap(mNativePaint)];
1169     }
1170 
1171     /**
1172      * Set the paint's Cap.
1173      *
1174      * @param cap set the paint's line cap style, used whenever the paint's
1175      *            style is Stroke or StrokeAndFill.
1176      */
setStrokeCap(Cap cap)1177     public void setStrokeCap(Cap cap) {
1178         nSetStrokeCap(mNativePaint, cap.nativeInt);
1179     }
1180 
1181     /**
1182      * Return the paint's stroke join type.
1183      *
1184      * @return the paint's Join.
1185      */
getStrokeJoin()1186     public Join getStrokeJoin() {
1187         return sJoinArray[nGetStrokeJoin(mNativePaint)];
1188     }
1189 
1190     /**
1191      * Set the paint's Join.
1192      *
1193      * @param join set the paint's Join, used whenever the paint's style is
1194      *             Stroke or StrokeAndFill.
1195      */
setStrokeJoin(Join join)1196     public void setStrokeJoin(Join join) {
1197         nSetStrokeJoin(mNativePaint, join.nativeInt);
1198     }
1199 
1200     /**
1201      * Applies any/all effects (patheffect, stroking) to src, returning the
1202      * result in dst. The result is that drawing src with this paint will be
1203      * the same as drawing dst with a default paint (at least from the
1204      * geometric perspective).
1205      *
1206      * @param src input path
1207      * @param dst output path (may be the same as src)
1208      * @return    true if the path should be filled, or false if it should be
1209      *                 drawn with a hairline (width == 0)
1210      */
getFillPath(Path src, Path dst)1211     public boolean getFillPath(Path src, Path dst) {
1212         return nGetFillPath(mNativePaint, src.readOnlyNI(), dst.mutateNI());
1213     }
1214 
1215     /**
1216      * Get the paint's shader object.
1217      *
1218      * @return the paint's shader (or null)
1219      */
getShader()1220     public Shader getShader() {
1221         return mShader;
1222     }
1223 
1224     /**
1225      * Set or clear the shader object.
1226      * <p />
1227      * Pass null to clear any previous shader.
1228      * As a convenience, the parameter passed is also returned.
1229      *
1230      * @param shader May be null. the new shader to be installed in the paint
1231      * @return       shader
1232      */
setShader(Shader shader)1233     public Shader setShader(Shader shader) {
1234         // If mShader changes, cached value of native shader aren't valid, since
1235         // old shader's pointer may be reused by another shader allocation later
1236         if (mShader != shader) {
1237             mNativeShader = -1;
1238             // Release any native references to the old shader content
1239             nSetShader(mNativePaint, 0);
1240         }
1241         // Defer setting the shader natively until getNativeInstance() is called
1242         mShader = shader;
1243         return shader;
1244     }
1245 
1246     /**
1247      * Get the paint's colorfilter (maybe be null).
1248      *
1249      * @return the paint's colorfilter (maybe be null)
1250      */
getColorFilter()1251     public ColorFilter getColorFilter() {
1252         return mColorFilter;
1253     }
1254 
1255     /**
1256      * Set or clear the paint's colorfilter, returning the parameter.
1257      *
1258      * @param filter May be null. The new filter to be installed in the paint
1259      * @return       filter
1260      */
setColorFilter(ColorFilter filter)1261     public ColorFilter setColorFilter(ColorFilter filter) {
1262         // If mColorFilter changes, cached value of native shader aren't valid, since
1263         // old shader's pointer may be reused by another shader allocation later
1264         if (mColorFilter != filter) {
1265             mNativeColorFilter = -1;
1266         }
1267 
1268         // Defer setting the filter natively until getNativeInstance() is called
1269         mColorFilter = filter;
1270         return filter;
1271     }
1272 
1273     /**
1274      * Get the paint's transfer mode object.
1275      *
1276      * @return the paint's transfer mode (or null)
1277      */
getXfermode()1278     public Xfermode getXfermode() {
1279         return mXfermode;
1280     }
1281 
1282     /**
1283      * Get the paint's blend mode object.
1284      *
1285      * @return the paint's blend mode (or null)
1286      */
1287     @Nullable
getBlendMode()1288     public BlendMode getBlendMode() {
1289         if (mXfermode == null) {
1290             return null;
1291         } else {
1292             return BlendMode.fromValue(mXfermode.porterDuffMode);
1293         }
1294     }
1295 
1296     /**
1297      * Set or clear the transfer mode object. A transfer mode defines how
1298      * source pixels (generate by a drawing command) are composited with
1299      * the destination pixels (content of the render target).
1300      * <p />
1301      * Pass null to clear any previous transfer mode.
1302      * As a convenience, the parameter passed is also returned.
1303      * <p />
1304      * {@link PorterDuffXfermode} is the most common transfer mode.
1305      *
1306      * @param xfermode May be null. The xfermode to be installed in the paint
1307      * @return         xfermode
1308      */
setXfermode(Xfermode xfermode)1309     public Xfermode setXfermode(Xfermode xfermode) {
1310         return installXfermode(xfermode);
1311     }
1312 
1313     @Nullable
installXfermode(Xfermode xfermode)1314     private Xfermode installXfermode(Xfermode xfermode) {
1315         int newMode = xfermode != null ? xfermode.porterDuffMode : Xfermode.DEFAULT;
1316         int curMode = mXfermode != null ? mXfermode.porterDuffMode : Xfermode.DEFAULT;
1317         if (newMode != curMode) {
1318             nSetXfermode(mNativePaint, newMode);
1319         }
1320         mXfermode = xfermode;
1321         return xfermode;
1322     }
1323 
1324     /**
1325      * Set or clear the blend mode. A blend mode defines how source pixels
1326      * (generated by a drawing command) are composited with the destination pixels
1327      * (content of the render target).
1328      * <p />
1329      * Pass null to clear any previous blend mode.
1330      * <p />
1331      *
1332      * @see BlendMode
1333      *
1334      * @param blendmode May be null. The blend mode to be installed in the paint
1335      */
setBlendMode(@ullable BlendMode blendmode)1336     public void setBlendMode(@Nullable BlendMode blendmode) {
1337         installXfermode(blendmode != null ? blendmode.getXfermode() : null);
1338     }
1339 
1340     /**
1341      * Get the paint's patheffect object.
1342      *
1343      * @return the paint's patheffect (or null)
1344      */
getPathEffect()1345     public PathEffect getPathEffect() {
1346         return mPathEffect;
1347     }
1348 
1349     /**
1350      * Set or clear the patheffect object.
1351      * <p />
1352      * Pass null to clear any previous patheffect.
1353      * As a convenience, the parameter passed is also returned.
1354      *
1355      * @param effect May be null. The patheffect to be installed in the paint
1356      * @return       effect
1357      */
setPathEffect(PathEffect effect)1358     public PathEffect setPathEffect(PathEffect effect) {
1359         long effectNative = 0;
1360         if (effect != null) {
1361             effectNative = effect.native_instance;
1362         }
1363         nSetPathEffect(mNativePaint, effectNative);
1364         mPathEffect = effect;
1365         return effect;
1366     }
1367 
1368     /**
1369      * Get the paint's maskfilter object.
1370      *
1371      * @return the paint's maskfilter (or null)
1372      */
getMaskFilter()1373     public MaskFilter getMaskFilter() {
1374         return mMaskFilter;
1375     }
1376 
1377     /**
1378      * Set or clear the maskfilter object.
1379      * <p />
1380      * Pass null to clear any previous maskfilter.
1381      * As a convenience, the parameter passed is also returned.
1382      *
1383      * @param maskfilter May be null. The maskfilter to be installed in the
1384      *                   paint
1385      * @return           maskfilter
1386      */
setMaskFilter(MaskFilter maskfilter)1387     public MaskFilter setMaskFilter(MaskFilter maskfilter) {
1388         long maskfilterNative = 0;
1389         if (maskfilter != null) {
1390             maskfilterNative = maskfilter.native_instance;
1391         }
1392         nSetMaskFilter(mNativePaint, maskfilterNative);
1393         mMaskFilter = maskfilter;
1394         return maskfilter;
1395     }
1396 
1397     /**
1398      * Get the paint's typeface object.
1399      * <p />
1400      * The typeface object identifies which font to use when drawing or
1401      * measuring text.
1402      *
1403      * @return the paint's typeface (or null)
1404      */
getTypeface()1405     public Typeface getTypeface() {
1406         return mTypeface;
1407     }
1408 
1409     /**
1410      * Set or clear the typeface object.
1411      * <p />
1412      * Pass null to clear any previous typeface.
1413      * As a convenience, the parameter passed is also returned.
1414      *
1415      * @param typeface May be null. The typeface to be installed in the paint
1416      * @return         typeface
1417      */
setTypeface(Typeface typeface)1418     public Typeface setTypeface(Typeface typeface) {
1419         final long typefaceNative = typeface == null ? 0 : typeface.native_instance;
1420         nSetTypeface(mNativePaint, typefaceNative);
1421         mTypeface = typeface;
1422         return typeface;
1423     }
1424 
1425     /**
1426      * Get the paint's rasterizer (or null).
1427      * <p />
1428      * The raster controls/modifies how paths/text are turned into alpha masks.
1429      *
1430      * @return         the paint's rasterizer (or null)
1431      *
1432      * @deprecated Rasterizer is not supported by either the HW or PDF backends.
1433      * @removed
1434      */
1435     @Deprecated
getRasterizer()1436     public Rasterizer getRasterizer() {
1437         return null;
1438     }
1439 
1440     /**
1441      * Set or clear the rasterizer object.
1442      * <p />
1443      * Pass null to clear any previous rasterizer.
1444      * As a convenience, the parameter passed is also returned.
1445      *
1446      * @param rasterizer May be null. The new rasterizer to be installed in
1447      *                   the paint.
1448      * @return           rasterizer
1449      *
1450      * @deprecated Rasterizer is not supported by either the HW or PDF backends.
1451      * @removed
1452      */
1453     @Deprecated
setRasterizer(Rasterizer rasterizer)1454     public Rasterizer setRasterizer(Rasterizer rasterizer) {
1455         return rasterizer;
1456     }
1457 
1458     /**
1459      * This draws a shadow layer below the main layer, with the specified
1460      * offset and color, and blur radius. If radius is 0, then the shadow
1461      * layer is removed.
1462      * <p>
1463      * Can be used to create a blurred shadow underneath text. Support for use
1464      * with other drawing operations is constrained to the software rendering
1465      * pipeline.
1466      * <p>
1467      * The alpha of the shadow will be the paint's alpha if the shadow color is
1468      * opaque, or the alpha from the shadow color if not.
1469      */
setShadowLayer(float radius, float dx, float dy, @ColorInt int shadowColor)1470     public void setShadowLayer(float radius, float dx, float dy, @ColorInt int shadowColor) {
1471         setShadowLayer(radius, dx, dy, Color.pack(shadowColor));
1472     }
1473 
1474     /**
1475      * This draws a shadow layer below the main layer, with the specified
1476      * offset and color, and blur radius. If radius is 0, then the shadow
1477      * layer is removed.
1478      * <p>
1479      * Can be used to create a blurred shadow underneath text. Support for use
1480      * with other drawing operations is constrained to the software rendering
1481      * pipeline.
1482      * <p>
1483      * The alpha of the shadow will be the paint's alpha if the shadow color is
1484      * opaque, or the alpha from the shadow color if not.
1485      *
1486      * @throws IllegalArgumentException if the color space encoded in the
1487      *      {@code ColorLong} is invalid or unknown.
1488      */
setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor)1489     public void setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor) {
1490         ColorSpace cs = Color.colorSpace(shadowColor);
1491         nSetShadowLayer(mNativePaint, radius, dx, dy, cs.getNativeInstance(), shadowColor);
1492 
1493         mShadowLayerRadius = radius;
1494         mShadowLayerDx = dx;
1495         mShadowLayerDy = dy;
1496         mShadowLayerColor = shadowColor;
1497     }
1498 
1499     /**
1500      * Clear the shadow layer.
1501      */
clearShadowLayer()1502     public void clearShadowLayer() {
1503         setShadowLayer(0, 0, 0, 0);
1504     }
1505 
1506     /**
1507      * Checks if the paint has a shadow layer attached
1508      *
1509      * @return true if the paint has a shadow layer attached and false otherwise
1510      * @hide
1511      */
hasShadowLayer()1512     public boolean hasShadowLayer() {
1513         return nHasShadowLayer(mNativePaint);
1514     }
1515 
1516     /**
1517      * Returns the blur radius of the shadow layer.
1518      * @see #setShadowLayer(float,float,float,int)
1519      * @see #setShadowLayer(float,float,float,long)
1520      */
getShadowLayerRadius()1521     public float getShadowLayerRadius() {
1522         return mShadowLayerRadius;
1523     }
1524 
1525     /**
1526      * Returns the x offset of the shadow layer.
1527      * @see #setShadowLayer(float,float,float,int)
1528      * @see #setShadowLayer(float,float,float,long)
1529      */
getShadowLayerDx()1530     public float getShadowLayerDx() {
1531         return mShadowLayerDx;
1532     }
1533 
1534     /**
1535      * Returns the y offset of the shadow layer.
1536      * @see #setShadowLayer(float,float,float,int)
1537      * @see #setShadowLayer(float,float,float,long)
1538      */
getShadowLayerDy()1539     public float getShadowLayerDy() {
1540         return mShadowLayerDy;
1541     }
1542 
1543     /**
1544      * Returns the color of the shadow layer.
1545      * @see #setShadowLayer(float,float,float,int)
1546      * @see #setShadowLayer(float,float,float,long)
1547      */
getShadowLayerColor()1548     public @ColorInt int getShadowLayerColor() {
1549         return Color.toArgb(mShadowLayerColor);
1550     }
1551 
1552     /**
1553      * Returns the color of the shadow layer.
1554      *
1555      * @return the shadow layer's color encoded as a {@link ColorLong}.
1556      * @see #setShadowLayer(float,float,float,int)
1557      * @see #setShadowLayer(float,float,float,long)
1558      * @see Color
1559      */
getShadowLayerColorLong()1560     public @ColorLong long getShadowLayerColorLong() {
1561         return mShadowLayerColor;
1562     }
1563 
1564     /**
1565      * Return the paint's Align value for drawing text. This controls how the
1566      * text is positioned relative to its origin. LEFT align means that all of
1567      * the text will be drawn to the right of its origin (i.e. the origin
1568      * specifieds the LEFT edge of the text) and so on.
1569      *
1570      * @return the paint's Align value for drawing text.
1571      */
getTextAlign()1572     public Align getTextAlign() {
1573         return sAlignArray[nGetTextAlign(mNativePaint)];
1574     }
1575 
1576     /**
1577      * Set the paint's text alignment. This controls how the
1578      * text is positioned relative to its origin. LEFT align means that all of
1579      * the text will be drawn to the right of its origin (i.e. the origin
1580      * specifieds the LEFT edge of the text) and so on.
1581      *
1582      * @param align set the paint's Align value for drawing text.
1583      */
setTextAlign(Align align)1584     public void setTextAlign(Align align) {
1585         nSetTextAlign(mNativePaint, align.nativeInt);
1586     }
1587 
1588     /**
1589      * Get the text's primary Locale. Note that this is not all of the locale-related information
1590      * Paint has. Use {@link #getTextLocales()} to get the complete list.
1591      *
1592      * @return the paint's primary Locale used for drawing text, never null.
1593      */
1594     @NonNull
getTextLocale()1595     public Locale getTextLocale() {
1596         return mLocales.get(0);
1597     }
1598 
1599     /**
1600      * Get the text locale list.
1601      *
1602      * @return the paint's LocaleList used for drawing text, never null or empty.
1603      */
1604     @NonNull @Size(min=1)
getTextLocales()1605     public LocaleList getTextLocales() {
1606         return mLocales;
1607     }
1608 
1609     /**
1610      * Set the text locale list to a one-member list consisting of just the locale.
1611      *
1612      * See {@link #setTextLocales(LocaleList)} for how the locale list affects
1613      * the way the text is drawn for some languages.
1614      *
1615      * @param locale the paint's locale value for drawing text, must not be null.
1616      */
setTextLocale(@onNull Locale locale)1617     public void setTextLocale(@NonNull Locale locale) {
1618         if (locale == null) {
1619             throw new IllegalArgumentException("locale cannot be null");
1620         }
1621         if (mLocales != null && mLocales.size() == 1 && locale.equals(mLocales.get(0))) {
1622             return;
1623         }
1624         mLocales = new LocaleList(locale);
1625         syncTextLocalesWithMinikin();
1626     }
1627 
1628     /**
1629      * Set the text locale list.
1630      *
1631      * The text locale list affects how the text is drawn for some languages.
1632      *
1633      * For example, if the locale list contains {@link Locale#CHINESE} or {@link Locale#CHINA},
1634      * then the text renderer will prefer to draw text using a Chinese font. Likewise,
1635      * if the locale list contains {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text
1636      * renderer will prefer to draw text using a Japanese font. If the locale list contains both,
1637      * the order those locales appear in the list is considered for deciding the font.
1638      *
1639      * This distinction is important because Chinese and Japanese text both use many
1640      * of the same Unicode code points but their appearance is subtly different for
1641      * each language.
1642      *
1643      * By default, the text locale list is initialized to a one-member list just containing the
1644      * system locales. This assumes that the text to be rendered will most likely be in the user's
1645      * preferred language.
1646      *
1647      * If the actual language or languages of the text is/are known, then they can be provided to
1648      * the text renderer using this method. The text renderer may attempt to guess the
1649      * language script based on the contents of the text to be drawn independent of
1650      * the text locale here. Specifying the text locales just helps it do a better
1651      * job in certain ambiguous cases.
1652      *
1653      * @param locales the paint's locale list for drawing text, must not be null or empty.
1654      */
setTextLocales(@onNull @izemin=1) LocaleList locales)1655     public void setTextLocales(@NonNull @Size(min=1) LocaleList locales) {
1656         if (locales == null || locales.isEmpty()) {
1657             throw new IllegalArgumentException("locales cannot be null or empty");
1658         }
1659         if (locales.equals(mLocales)) return;
1660         mLocales = locales;
1661         syncTextLocalesWithMinikin();
1662     }
1663 
syncTextLocalesWithMinikin()1664     private void syncTextLocalesWithMinikin() {
1665         final String languageTags = mLocales.toLanguageTags();
1666         final Integer minikinLocaleListId;
1667         synchronized (sCacheLock) {
1668             minikinLocaleListId = sMinikinLocaleListIdCache.get(languageTags);
1669             if (minikinLocaleListId == null) {
1670                 final int newID = nSetTextLocales(mNativePaint, languageTags);
1671                 sMinikinLocaleListIdCache.put(languageTags, newID);
1672                 return;
1673             }
1674         }
1675         nSetTextLocalesByMinikinLocaleListId(mNativePaint, minikinLocaleListId.intValue());
1676     }
1677 
1678     /**
1679      * Get the elegant metrics flag.
1680      *
1681      * @return true if elegant metrics are enabled for text drawing.
1682      */
isElegantTextHeight()1683     public boolean isElegantTextHeight() {
1684         return nIsElegantTextHeight(mNativePaint);
1685     }
1686 
1687     /**
1688      * Set the paint's elegant height metrics flag. This setting selects font
1689      * variants that have not been compacted to fit Latin-based vertical
1690      * metrics, and also increases top and bottom bounds to provide more space.
1691      *
1692      * @param elegant set the paint's elegant metrics flag for drawing text.
1693      */
setElegantTextHeight(boolean elegant)1694     public void setElegantTextHeight(boolean elegant) {
1695         nSetElegantTextHeight(mNativePaint, elegant);
1696     }
1697 
1698     /**
1699      * Return the paint's text size.
1700      *
1701      * @return the paint's text size in pixel units.
1702      */
getTextSize()1703     public float getTextSize() {
1704         return nGetTextSize(mNativePaint);
1705     }
1706 
1707     /**
1708      * Set the paint's text size. This value must be > 0
1709      *
1710      * @param textSize set the paint's text size in pixel units.
1711      */
setTextSize(float textSize)1712     public void setTextSize(float textSize) {
1713         nSetTextSize(mNativePaint, textSize);
1714     }
1715 
1716     /**
1717      * Return the paint's horizontal scale factor for text. The default value
1718      * is 1.0.
1719      *
1720      * @return the paint's scale factor in X for drawing/measuring text
1721      */
getTextScaleX()1722     public float getTextScaleX() {
1723         return nGetTextScaleX(mNativePaint);
1724     }
1725 
1726     /**
1727      * Set the paint's horizontal scale factor for text. The default value
1728      * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
1729      * stretch the text narrower.
1730      *
1731      * @param scaleX set the paint's scale in X for drawing/measuring text.
1732      */
setTextScaleX(float scaleX)1733     public void setTextScaleX(float scaleX) {
1734         nSetTextScaleX(mNativePaint, scaleX);
1735     }
1736 
1737     /**
1738      * Return the paint's horizontal skew factor for text. The default value
1739      * is 0.
1740      *
1741      * @return         the paint's skew factor in X for drawing text.
1742      */
getTextSkewX()1743     public float getTextSkewX() {
1744         return nGetTextSkewX(mNativePaint);
1745     }
1746 
1747     /**
1748      * Set the paint's horizontal skew factor for text. The default value
1749      * is 0. For approximating oblique text, use values around -0.25.
1750      *
1751      * @param skewX set the paint's skew factor in X for drawing text.
1752      */
setTextSkewX(float skewX)1753     public void setTextSkewX(float skewX) {
1754         nSetTextSkewX(mNativePaint, skewX);
1755     }
1756 
1757     /**
1758      * Return the paint's letter-spacing for text. The default value
1759      * is 0.
1760      *
1761      * @return         the paint's letter-spacing for drawing text.
1762      */
getLetterSpacing()1763     public float getLetterSpacing() {
1764         return nGetLetterSpacing(mNativePaint);
1765     }
1766 
1767     /**
1768      * Set the paint's letter-spacing for text. The default value
1769      * is 0.  The value is in 'EM' units.  Typical values for slight
1770      * expansion will be around 0.05.  Negative values tighten text.
1771      *
1772      * @param letterSpacing set the paint's letter-spacing for drawing text.
1773      */
setLetterSpacing(float letterSpacing)1774     public void setLetterSpacing(float letterSpacing) {
1775         nSetLetterSpacing(mNativePaint, letterSpacing);
1776     }
1777 
1778     /**
1779      * Return the paint's extra word-spacing for text.
1780      *
1781      * The default value is 0.
1782      *
1783      * @return the paint's extra word-spacing for drawing text in pixels.
1784      * @see #setWordSpacing(float)
1785      */
getWordSpacing()1786     public @Px float getWordSpacing() {
1787         return nGetWordSpacing(mNativePaint);
1788     }
1789 
1790     /**
1791      * Set the paint's extra word-spacing for text.
1792      *
1793      * Increases the white space width between words with the given amount of pixels.
1794      * The default value is 0.
1795      *
1796      * @param wordSpacing set the paint's extra word-spacing for drawing text in pixels.
1797      * @see #getWordSpacing()
1798      */
setWordSpacing(@x float wordSpacing)1799     public void setWordSpacing(@Px float wordSpacing) {
1800         nSetWordSpacing(mNativePaint, wordSpacing);
1801     }
1802 
1803     /**
1804      * Returns the font feature settings. The format is the same as the CSS
1805      * font-feature-settings attribute:
1806      * <a href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
1807      *     https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop</a>
1808      *
1809      * @return the paint's currently set font feature settings. Default is null.
1810      *
1811      * @see #setFontFeatureSettings(String)
1812      */
getFontFeatureSettings()1813     public String getFontFeatureSettings() {
1814         return mFontFeatureSettings;
1815     }
1816 
1817     /**
1818      * Set font feature settings.
1819      *
1820      * The format is the same as the CSS font-feature-settings attribute:
1821      * <a href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
1822      *     https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop</a>
1823      *
1824      * @see #getFontFeatureSettings()
1825      *
1826      * @param settings the font feature settings string to use, may be null.
1827      */
setFontFeatureSettings(String settings)1828     public void setFontFeatureSettings(String settings) {
1829         if (settings != null && settings.equals("")) {
1830             settings = null;
1831         }
1832         if ((settings == null && mFontFeatureSettings == null)
1833                 || (settings != null && settings.equals(mFontFeatureSettings))) {
1834             return;
1835         }
1836         mFontFeatureSettings = settings;
1837         nSetFontFeatureSettings(mNativePaint, settings);
1838     }
1839 
1840     /**
1841      * Returns the font variation settings.
1842      *
1843      * @return the paint's currently set font variation settings. Default is null.
1844      *
1845      * @see #setFontVariationSettings(String)
1846      */
getFontVariationSettings()1847     public String getFontVariationSettings() {
1848         return mFontVariationSettings;
1849     }
1850 
1851     /**
1852      * Sets TrueType or OpenType font variation settings. The settings string is constructed from
1853      * multiple pairs of axis tag and style values. The axis tag must contain four ASCII characters
1854      * and must be wrapped with single quotes (U+0027) or double quotes (U+0022). Axis strings that
1855      * are longer or shorter than four characters, or contain characters outside of U+0020..U+007E
1856      * are invalid. If a specified axis name is not defined in the font, the settings will be
1857      * ignored.
1858      *
1859      * Examples,
1860      * <ul>
1861      * <li>Set font width to 150.
1862      * <pre>
1863      * <code>
1864      *   Paint paint = new Paint();
1865      *   paint.setFontVariationSettings("'wdth' 150");
1866      * </code>
1867      * </pre>
1868      * </li>
1869      *
1870      * <li>Set the font slant to 20 degrees and ask for italic style.
1871      * <pre>
1872      * <code>
1873      *   Paint paint = new Paint();
1874      *   paint.setFontVariationSettings("'slnt' 20, 'ital' 1");
1875      * </code>
1876      * </pre>
1877      * </li>
1878      * </ul>
1879      *
1880      * @param fontVariationSettings font variation settings. You can pass null or empty string as
1881      *                              no variation settings.
1882      *
1883      * @return true if the given settings is effective to at least one font file underlying this
1884      *         typeface. This function also returns true for empty settings string. Otherwise
1885      *         returns false
1886      *
1887      * @throws IllegalArgumentException If given string is not a valid font variation settings
1888      *                                  format
1889      *
1890      * @see #getFontVariationSettings()
1891      * @see FontVariationAxis
1892      */
setFontVariationSettings(String fontVariationSettings)1893     public boolean setFontVariationSettings(String fontVariationSettings) {
1894         final String settings = TextUtils.nullIfEmpty(fontVariationSettings);
1895         if (settings == mFontVariationSettings
1896                 || (settings != null && settings.equals(mFontVariationSettings))) {
1897             return true;
1898         }
1899 
1900         if (settings == null || settings.length() == 0) {
1901             mFontVariationSettings = null;
1902             setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface,
1903                       Collections.emptyList()));
1904             return true;
1905         }
1906 
1907         // The null typeface is valid and it is equivalent to Typeface.DEFAULT.
1908         // To call isSupportedAxes method, use Typeface.DEFAULT instance.
1909         Typeface targetTypeface = mTypeface == null ? Typeface.DEFAULT : mTypeface;
1910         FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings(settings);
1911         final ArrayList<FontVariationAxis> filteredAxes = new ArrayList<FontVariationAxis>();
1912         for (final FontVariationAxis axis : axes) {
1913             if (targetTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) {
1914                 filteredAxes.add(axis);
1915             }
1916         }
1917         if (filteredAxes.isEmpty()) {
1918             return false;
1919         }
1920         mFontVariationSettings = settings;
1921         setTypeface(Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes));
1922         return true;
1923     }
1924 
1925     /**
1926      * Get the current value of start hyphen edit.
1927      *
1928      * The default value is 0 which is equivalent to {@link #START_HYPHEN_EDIT_NO_EDIT}.
1929      *
1930      * @return the current starting hyphen edit value
1931      * @see #setStartHyphenEdit(int)
1932      */
getStartHyphenEdit()1933     public @StartHyphenEdit int getStartHyphenEdit() {
1934         return nGetStartHyphenEdit(mNativePaint);
1935     }
1936 
1937     /**
1938      * Get the current value of end hyphen edit.
1939      *
1940      * The default value is 0 which is equivalent to {@link #END_HYPHEN_EDIT_NO_EDIT}.
1941      *
1942      * @return the current starting hyphen edit value
1943      * @see #setStartHyphenEdit(int)
1944      */
getEndHyphenEdit()1945     public @EndHyphenEdit int getEndHyphenEdit() {
1946         return nGetEndHyphenEdit(mNativePaint);
1947     }
1948 
1949     /**
1950      * Set a start hyphen edit on the paint.
1951      *
1952      * By setting start hyphen edit, the measurement and drawing is performed with modifying
1953      * hyphenation at the start of line. For example, by passing
1954      * {@link #START_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
1955      * character is appended at the start of line.
1956      *
1957      * <pre>
1958      * <code>
1959      *   Paint paint = new Paint();
1960      *   paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
1961      *   paint.measureText("abc", 0, 3);  // Returns the width of "-abc"
1962      *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "-abc"
1963      * </code>
1964      * </pre>
1965      *
1966      * The default value is 0 which is equivalent to
1967      * {@link #START_HYPHEN_EDIT_NO_EDIT}.
1968      *
1969      * @param startHyphen a start hyphen edit value.
1970      * @see #getStartHyphenEdit()
1971      */
setStartHyphenEdit(@tartHyphenEdit int startHyphen)1972     public void setStartHyphenEdit(@StartHyphenEdit int startHyphen) {
1973         nSetStartHyphenEdit(mNativePaint, startHyphen);
1974     }
1975 
1976     /**
1977      * Set a end hyphen edit on the paint.
1978      *
1979      * By setting end hyphen edit, the measurement and drawing is performed with modifying
1980      * hyphenation at the end of line. For example, by passing
1981      * {@link #END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
1982      * character is appended at the end of line.
1983      *
1984      * <pre>
1985      * <code>
1986      *   Paint paint = new Paint();
1987      *   paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
1988      *   paint.measureText("abc", 0, 3);  // Returns the width of "abc-"
1989      *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "abc-"
1990      * </code>
1991      * </pre>
1992      *
1993      * The default value is 0 which is equivalent to {@link #END_HYPHEN_EDIT_NO_EDIT}.
1994      *
1995      * @param endHyphen a end hyphen edit value.
1996      * @see #getEndHyphenEdit()
1997      */
setEndHyphenEdit(@ndHyphenEdit int endHyphen)1998     public void setEndHyphenEdit(@EndHyphenEdit int endHyphen) {
1999         nSetEndHyphenEdit(mNativePaint, endHyphen);
2000     }
2001 
2002     /**
2003      * Return the distance above (negative) the baseline (ascent) based on the
2004      * current typeface and text size.
2005      *
2006      * <p>Note that this is the ascent of the main typeface, and actual text rendered may need a
2007      * larger ascent because fallback fonts may get used in rendering the text.
2008      *
2009      * @return the distance above (negative) the baseline (ascent) based on the
2010      *         current typeface and text size.
2011      */
ascent()2012     public float ascent() {
2013         return nAscent(mNativePaint);
2014     }
2015 
2016     /**
2017      * Return the distance below (positive) the baseline (descent) based on the
2018      * current typeface and text size.
2019      *
2020      * <p>Note that this is the descent of the main typeface, and actual text rendered may need a
2021      * larger descent because fallback fonts may get used in rendering the text.
2022      *
2023      * @return the distance below (positive) the baseline (descent) based on
2024      *         the current typeface and text size.
2025      */
descent()2026     public float descent() {
2027         return nDescent(mNativePaint);
2028     }
2029 
2030     /**
2031      * Class that describes the various metrics for a font at a given text size.
2032      * Remember, Y values increase going down, so those values will be positive,
2033      * and values that measure distances going up will be negative. This class
2034      * is returned by getFontMetrics().
2035      */
2036     public static class FontMetrics {
2037         /**
2038          * The maximum distance above the baseline for the tallest glyph in
2039          * the font at a given text size.
2040          */
2041         public float   top;
2042         /**
2043          * The recommended distance above the baseline for singled spaced text.
2044          */
2045         public float   ascent;
2046         /**
2047          * The recommended distance below the baseline for singled spaced text.
2048          */
2049         public float   descent;
2050         /**
2051          * The maximum distance below the baseline for the lowest glyph in
2052          * the font at a given text size.
2053          */
2054         public float   bottom;
2055         /**
2056          * The recommended additional space to add between lines of text.
2057          */
2058         public float   leading;
2059     }
2060 
2061     /**
2062      * Return the font's recommended interline spacing, given the Paint's
2063      * settings for typeface, textSize, etc. If metrics is not null, return the
2064      * fontmetric values in it.
2065      *
2066      * <p>Note that these are the values for the main typeface, and actual text rendered may need a
2067      * larger set of values because fallback fonts may get used in rendering the text.
2068      *
2069      * @param metrics If this object is not null, its fields are filled with
2070      *                the appropriate values given the paint's text attributes.
2071      * @return the font's recommended interline spacing.
2072      */
getFontMetrics(FontMetrics metrics)2073     public float getFontMetrics(FontMetrics metrics) {
2074         return nGetFontMetrics(mNativePaint, metrics);
2075     }
2076 
2077     /**
2078      * Allocates a new FontMetrics object, and then calls getFontMetrics(fm)
2079      * with it, returning the object.
2080      */
getFontMetrics()2081     public FontMetrics getFontMetrics() {
2082         FontMetrics fm = new FontMetrics();
2083         getFontMetrics(fm);
2084         return fm;
2085     }
2086 
2087     /**
2088      * Convenience method for callers that want to have FontMetrics values as
2089      * integers.
2090      */
2091     public static class FontMetricsInt {
2092         /**
2093          * The maximum distance above the baseline for the tallest glyph in
2094          * the font at a given text size.
2095          */
2096         public int   top;
2097         /**
2098          * The recommended distance above the baseline for singled spaced text.
2099          */
2100         public int   ascent;
2101         /**
2102          * The recommended distance below the baseline for singled spaced text.
2103          */
2104         public int   descent;
2105         /**
2106          * The maximum distance below the baseline for the lowest glyph in
2107          * the font at a given text size.
2108          */
2109         public int   bottom;
2110         /**
2111          * The recommended additional space to add between lines of text.
2112          */
2113         public int   leading;
2114 
toString()2115         @Override public String toString() {
2116             return "FontMetricsInt: top=" + top + " ascent=" + ascent +
2117                     " descent=" + descent + " bottom=" + bottom +
2118                     " leading=" + leading;
2119         }
2120     }
2121 
2122     /**
2123      * Return the font's interline spacing, given the Paint's settings for
2124      * typeface, textSize, etc. If metrics is not null, return the fontmetric
2125      * values in it. Note: all values have been converted to integers from
2126      * floats, in such a way has to make the answers useful for both spacing
2127      * and clipping. If you want more control over the rounding, call
2128      * getFontMetrics().
2129      *
2130      * <p>Note that these are the values for the main typeface, and actual text rendered may need a
2131      * larger set of values because fallback fonts may get used in rendering the text.
2132      *
2133      * @return the font's interline spacing.
2134      */
getFontMetricsInt(FontMetricsInt fmi)2135     public int getFontMetricsInt(FontMetricsInt fmi) {
2136         return nGetFontMetricsInt(mNativePaint, fmi);
2137     }
2138 
getFontMetricsInt()2139     public FontMetricsInt getFontMetricsInt() {
2140         FontMetricsInt fm = new FontMetricsInt();
2141         getFontMetricsInt(fm);
2142         return fm;
2143     }
2144 
2145     /**
2146      * Return the recommend line spacing based on the current typeface and
2147      * text size.
2148      *
2149      * <p>Note that this is the value for the main typeface, and actual text rendered may need a
2150      * larger value because fallback fonts may get used in rendering the text.
2151      *
2152      * @return  recommend line spacing based on the current typeface and
2153      *          text size.
2154      */
getFontSpacing()2155     public float getFontSpacing() {
2156         return getFontMetrics(null);
2157     }
2158 
2159     /**
2160      * Return the width of the text.
2161      *
2162      * @param text  The text to measure. Cannot be null.
2163      * @param index The index of the first character to start measuring
2164      * @param count THe number of characters to measure, beginning with start
2165      * @return      The width of the text
2166      */
measureText(char[] text, int index, int count)2167     public float measureText(char[] text, int index, int count) {
2168         if (text == null) {
2169             throw new IllegalArgumentException("text cannot be null");
2170         }
2171         if ((index | count) < 0 || index + count > text.length) {
2172             throw new ArrayIndexOutOfBoundsException();
2173         }
2174 
2175         if (text.length == 0 || count == 0) {
2176             return 0f;
2177         }
2178         if (!mHasCompatScaling) {
2179             return (float) Math.ceil(nGetTextAdvances(mNativePaint, text,
2180                     index, count, index, count, mBidiFlags, null, 0));
2181         }
2182 
2183         final float oldSize = getTextSize();
2184         setTextSize(oldSize * mCompatScaling);
2185         final float w = nGetTextAdvances(mNativePaint, text, index, count, index, count,
2186                 mBidiFlags, null, 0);
2187         setTextSize(oldSize);
2188         return (float) Math.ceil(w*mInvCompatScaling);
2189     }
2190 
2191     /**
2192      * Return the width of the text.
2193      *
2194      * @param text  The text to measure. Cannot be null.
2195      * @param start The index of the first character to start measuring
2196      * @param end   1 beyond the index of the last character to measure
2197      * @return      The width of the text
2198      */
measureText(String text, int start, int end)2199     public float measureText(String text, int start, int end) {
2200         if (text == null) {
2201             throw new IllegalArgumentException("text cannot be null");
2202         }
2203         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2204             throw new IndexOutOfBoundsException();
2205         }
2206 
2207         if (text.length() == 0 || start == end) {
2208             return 0f;
2209         }
2210         if (!mHasCompatScaling) {
2211             return (float) Math.ceil(nGetTextAdvances(mNativePaint, text,
2212                     start, end, start, end, mBidiFlags, null, 0));
2213         }
2214         final float oldSize = getTextSize();
2215         setTextSize(oldSize * mCompatScaling);
2216         final float w = nGetTextAdvances(mNativePaint, text, start, end, start, end, mBidiFlags,
2217                 null, 0);
2218         setTextSize(oldSize);
2219         return (float) Math.ceil(w * mInvCompatScaling);
2220     }
2221 
2222     /**
2223      * Return the width of the text.
2224      *
2225      * @param text  The text to measure. Cannot be null.
2226      * @return      The width of the text
2227      */
measureText(String text)2228     public float measureText(String text) {
2229         if (text == null) {
2230             throw new IllegalArgumentException("text cannot be null");
2231         }
2232         return measureText(text, 0, text.length());
2233     }
2234 
2235     /**
2236      * Return the width of the text.
2237      *
2238      * @param text  The text to measure
2239      * @param start The index of the first character to start measuring
2240      * @param end   1 beyond the index of the last character to measure
2241      * @return      The width of the text
2242      */
measureText(CharSequence text, int start, int end)2243     public float measureText(CharSequence text, int start, int end) {
2244         if (text == null) {
2245             throw new IllegalArgumentException("text cannot be null");
2246         }
2247         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2248             throw new IndexOutOfBoundsException();
2249         }
2250 
2251         if (text.length() == 0 || start == end) {
2252             return 0f;
2253         }
2254         if (text instanceof String) {
2255             return measureText((String)text, start, end);
2256         }
2257         if (text instanceof SpannedString ||
2258             text instanceof SpannableString) {
2259             return measureText(text.toString(), start, end);
2260         }
2261         if (text instanceof GraphicsOperations) {
2262             return ((GraphicsOperations)text).measureText(start, end, this);
2263         }
2264 
2265         char[] buf = TemporaryBuffer.obtain(end - start);
2266         TextUtils.getChars(text, start, end, buf, 0);
2267         float result = measureText(buf, 0, end - start);
2268         TemporaryBuffer.recycle(buf);
2269         return result;
2270     }
2271 
2272     /**
2273      * Measure the text, stopping early if the measured width exceeds maxWidth.
2274      * Return the number of chars that were measured, and if measuredWidth is
2275      * not null, return in it the actual width measured.
2276      *
2277      * @param text  The text to measure. Cannot be null.
2278      * @param index The offset into text to begin measuring at
2279      * @param count The number of maximum number of entries to measure. If count
2280      *              is negative, then the characters are measured in reverse order.
2281      * @param maxWidth The maximum width to accumulate.
2282      * @param measuredWidth Optional. If not null, returns the actual width
2283      *                     measured.
2284      * @return The number of chars that were measured. Will always be <=
2285      *         abs(count).
2286      */
breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth)2287     public int breakText(char[] text, int index, int count,
2288                                 float maxWidth, float[] measuredWidth) {
2289         if (text == null) {
2290             throw new IllegalArgumentException("text cannot be null");
2291         }
2292         if (index < 0 || text.length - index < Math.abs(count)) {
2293             throw new ArrayIndexOutOfBoundsException();
2294         }
2295 
2296         if (text.length == 0 || count == 0) {
2297             return 0;
2298         }
2299         if (!mHasCompatScaling) {
2300             return nBreakText(mNativePaint, text, index, count, maxWidth, mBidiFlags,
2301                     measuredWidth);
2302         }
2303 
2304         final float oldSize = getTextSize();
2305         setTextSize(oldSize * mCompatScaling);
2306         final int res = nBreakText(mNativePaint, text, index, count, maxWidth * mCompatScaling,
2307                 mBidiFlags, measuredWidth);
2308         setTextSize(oldSize);
2309         if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
2310         return res;
2311     }
2312 
2313     /**
2314      * Measure the text, stopping early if the measured width exceeds maxWidth.
2315      * Return the number of chars that were measured, and if measuredWidth is
2316      * not null, return in it the actual width measured.
2317      *
2318      * @param text  The text to measure. Cannot be null.
2319      * @param start The offset into text to begin measuring at
2320      * @param end   The end of the text slice to measure.
2321      * @param measureForwards If true, measure forwards, starting at start.
2322      *                        Otherwise, measure backwards, starting with end.
2323      * @param maxWidth The maximum width to accumulate.
2324      * @param measuredWidth Optional. If not null, returns the actual width
2325      *                     measured.
2326      * @return The number of chars that were measured. Will always be <=
2327      *         abs(end - start).
2328      */
breakText(CharSequence text, int start, int end, boolean measureForwards, float maxWidth, float[] measuredWidth)2329     public int breakText(CharSequence text, int start, int end,
2330                          boolean measureForwards,
2331                          float maxWidth, float[] measuredWidth) {
2332         if (text == null) {
2333             throw new IllegalArgumentException("text cannot be null");
2334         }
2335         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2336             throw new IndexOutOfBoundsException();
2337         }
2338 
2339         if (text.length() == 0 || start == end) {
2340             return 0;
2341         }
2342         if (start == 0 && text instanceof String && end == text.length()) {
2343             return breakText((String) text, measureForwards, maxWidth,
2344                              measuredWidth);
2345         }
2346 
2347         char[] buf = TemporaryBuffer.obtain(end - start);
2348         int result;
2349 
2350         TextUtils.getChars(text, start, end, buf, 0);
2351 
2352         if (measureForwards) {
2353             result = breakText(buf, 0, end - start, maxWidth, measuredWidth);
2354         } else {
2355             result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth);
2356         }
2357 
2358         TemporaryBuffer.recycle(buf);
2359         return result;
2360     }
2361 
2362     /**
2363      * Measure the text, stopping early if the measured width exceeds maxWidth.
2364      * Return the number of chars that were measured, and if measuredWidth is
2365      * not null, return in it the actual width measured.
2366      *
2367      * @param text  The text to measure. Cannot be null.
2368      * @param measureForwards If true, measure forwards, starting with the
2369      *                        first character in the string. Otherwise,
2370      *                        measure backwards, starting with the
2371      *                        last character in the string.
2372      * @param maxWidth The maximum width to accumulate.
2373      * @param measuredWidth Optional. If not null, returns the actual width
2374      *                     measured.
2375      * @return The number of chars that were measured. Will always be <=
2376      *         abs(count).
2377      */
breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth)2378     public int breakText(String text, boolean measureForwards,
2379                                 float maxWidth, float[] measuredWidth) {
2380         if (text == null) {
2381             throw new IllegalArgumentException("text cannot be null");
2382         }
2383 
2384         if (text.length() == 0) {
2385             return 0;
2386         }
2387         if (!mHasCompatScaling) {
2388             return nBreakText(mNativePaint, text, measureForwards,
2389                     maxWidth, mBidiFlags, measuredWidth);
2390         }
2391 
2392         final float oldSize = getTextSize();
2393         setTextSize(oldSize*mCompatScaling);
2394         final int res = nBreakText(mNativePaint, text, measureForwards, maxWidth*mCompatScaling,
2395                 mBidiFlags, measuredWidth);
2396         setTextSize(oldSize);
2397         if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
2398         return res;
2399     }
2400 
2401     /**
2402      * Return the advance widths for the characters in the string.
2403      *
2404      * @param text     The text to measure. Cannot be null.
2405      * @param index    The index of the first char to to measure
2406      * @param count    The number of chars starting with index to measure
2407      * @param widths   array to receive the advance widths of the characters.
2408      *                 Must be at least a large as count.
2409      * @return         the actual number of widths returned.
2410      */
getTextWidths(char[] text, int index, int count, float[] widths)2411     public int getTextWidths(char[] text, int index, int count,
2412                              float[] widths) {
2413         if (text == null) {
2414             throw new IllegalArgumentException("text cannot be null");
2415         }
2416         if ((index | count) < 0 || index + count > text.length
2417                 || count > widths.length) {
2418             throw new ArrayIndexOutOfBoundsException();
2419         }
2420 
2421         if (text.length == 0 || count == 0) {
2422             return 0;
2423         }
2424         if (!mHasCompatScaling) {
2425             nGetTextAdvances(mNativePaint, text, index, count, index, count, mBidiFlags, widths, 0);
2426             return count;
2427         }
2428 
2429         final float oldSize = getTextSize();
2430         setTextSize(oldSize * mCompatScaling);
2431         nGetTextAdvances(mNativePaint, text, index, count, index, count, mBidiFlags, widths, 0);
2432         setTextSize(oldSize);
2433         for (int i = 0; i < count; i++) {
2434             widths[i] *= mInvCompatScaling;
2435         }
2436         return count;
2437     }
2438 
2439     /**
2440      * Return the advance widths for the characters in the string.
2441      *
2442      * @param text     The text to measure. Cannot be null.
2443      * @param start    The index of the first char to to measure
2444      * @param end      The end of the text slice to measure
2445      * @param widths   array to receive the advance widths of the characters.
2446      *                 Must be at least a large as (end - start).
2447      * @return         the actual number of widths returned.
2448      */
getTextWidths(CharSequence text, int start, int end, float[] widths)2449     public int getTextWidths(CharSequence text, int start, int end,
2450                              float[] widths) {
2451         if (text == null) {
2452             throw new IllegalArgumentException("text cannot be null");
2453         }
2454         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2455             throw new IndexOutOfBoundsException();
2456         }
2457         if (end - start > widths.length) {
2458             throw new ArrayIndexOutOfBoundsException();
2459         }
2460 
2461         if (text.length() == 0 || start == end) {
2462             return 0;
2463         }
2464         if (text instanceof String) {
2465             return getTextWidths((String) text, start, end, widths);
2466         }
2467         if (text instanceof SpannedString ||
2468             text instanceof SpannableString) {
2469             return getTextWidths(text.toString(), start, end, widths);
2470         }
2471         if (text instanceof GraphicsOperations) {
2472             return ((GraphicsOperations) text).getTextWidths(start, end,
2473                                                                  widths, this);
2474         }
2475 
2476         char[] buf = TemporaryBuffer.obtain(end - start);
2477         TextUtils.getChars(text, start, end, buf, 0);
2478         int result = getTextWidths(buf, 0, end - start, widths);
2479         TemporaryBuffer.recycle(buf);
2480         return result;
2481     }
2482 
2483     /**
2484      * Return the advance widths for the characters in the string.
2485      *
2486      * @param text   The text to measure. Cannot be null.
2487      * @param start  The index of the first char to to measure
2488      * @param end    The end of the text slice to measure
2489      * @param widths array to receive the advance widths of the characters.
2490      *               Must be at least a large as the text.
2491      * @return       the number of code units in the specified text.
2492      */
getTextWidths(String text, int start, int end, float[] widths)2493     public int getTextWidths(String text, int start, int end, float[] widths) {
2494         if (text == null) {
2495             throw new IllegalArgumentException("text cannot be null");
2496         }
2497         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2498             throw new IndexOutOfBoundsException();
2499         }
2500         if (end - start > widths.length) {
2501             throw new ArrayIndexOutOfBoundsException();
2502         }
2503 
2504         if (text.length() == 0 || start == end) {
2505             return 0;
2506         }
2507         if (!mHasCompatScaling) {
2508             nGetTextAdvances(mNativePaint, text, start, end, start, end, mBidiFlags, widths, 0);
2509             return end - start;
2510         }
2511 
2512         final float oldSize = getTextSize();
2513         setTextSize(oldSize * mCompatScaling);
2514         nGetTextAdvances(mNativePaint, text, start, end, start, end, mBidiFlags, widths, 0);
2515         setTextSize(oldSize);
2516         for (int i = 0; i < end - start; i++) {
2517             widths[i] *= mInvCompatScaling;
2518         }
2519         return end - start;
2520     }
2521 
2522     /**
2523      * Return the advance widths for the characters in the string.
2524      *
2525      * @param text   The text to measure
2526      * @param widths array to receive the advance widths of the characters.
2527      *               Must be at least a large as the text.
2528      * @return       the number of code units in the specified text.
2529      */
getTextWidths(String text, float[] widths)2530     public int getTextWidths(String text, float[] widths) {
2531         return getTextWidths(text, 0, text.length(), widths);
2532     }
2533 
2534     /**
2535      * Retrieve the character advances of the text.
2536      *
2537      * Returns the total advance width for the characters in the run from {@code index} for
2538      * {@code count} of chars, and if {@code advances} is not null, the advance assigned to each of
2539      * these characters (java chars).
2540      *
2541      * <p>
2542      * The trailing surrogate in a valid surrogate pair is assigned an advance of 0.  Thus the
2543      * number of returned advances is always equal to count, not to the number of unicode codepoints
2544      * represented by the run.
2545      * </p>
2546      *
2547      * <p>
2548      * In the case of conjuncts or combining marks, the total advance is assigned to the first
2549      * logical character, and the following characters are assigned an advance of 0.
2550      * </p>
2551      *
2552      * <p>
2553      * This generates the sum of the advances of glyphs for characters in a reordered cluster as the
2554      * width of the first logical character in the cluster, and 0 for the widths of all other
2555      * characters in the cluster.  In effect, such clusters are treated like conjuncts.
2556      * </p>
2557      *
2558      * <p>
2559      * The shaping bounds limit the amount of context available outside start and end that can be
2560      * used for shaping analysis.  These bounds typically reflect changes in bidi level or font
2561      * metrics across which shaping does not occur.
2562      * </p>
2563      *
2564      * @param chars the text to measure.
2565      * @param index the index of the first character to measure
2566      * @param count the number of characters to measure
2567      * @param contextIndex the index of the first character to use for shaping context.
2568      *                     Context must cover the measureing target.
2569      * @param contextCount the number of character to use for shaping context.
2570      *                     Context must cover the measureing target.
2571      * @param isRtl whether the run is in RTL direction
2572      * @param advances array to receive the advances, must have room for all advances.
2573      *                 This can be null if only total advance is needed
2574      * @param advancesIndex the position in advances at which to put the advance corresponding to
2575      *                      the character at start
2576      * @return the total advance in pixels
2577      */
getTextRunAdvances(@onNull char[] chars, @IntRange(from = 0) int index, @IntRange(from = 0) int count, @IntRange(from = 0) int contextIndex, @IntRange(from = 0) int contextCount, boolean isRtl, @Nullable float[] advances, @IntRange(from = 0) int advancesIndex)2578     public float getTextRunAdvances(@NonNull char[] chars, @IntRange(from = 0) int index,
2579             @IntRange(from = 0) int count, @IntRange(from = 0) int contextIndex,
2580             @IntRange(from = 0) int contextCount, boolean isRtl, @Nullable float[] advances,
2581             @IntRange(from = 0) int advancesIndex) {
2582         if (chars == null) {
2583             throw new IllegalArgumentException("text cannot be null");
2584         }
2585         if ((index | count | contextIndex | contextCount | advancesIndex
2586                 | (index - contextIndex) | (contextCount - count)
2587                 | ((contextIndex + contextCount) - (index + count))
2588                 | (chars.length - (contextIndex + contextCount))
2589                 | (advances == null ? 0 :
2590                     (advances.length - (advancesIndex + count)))) < 0) {
2591             throw new IndexOutOfBoundsException();
2592         }
2593 
2594         if (chars.length == 0 || count == 0){
2595             return 0f;
2596         }
2597         if (!mHasCompatScaling) {
2598             return nGetTextAdvances(mNativePaint, chars, index, count, contextIndex, contextCount,
2599                     isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
2600                     advancesIndex);
2601         }
2602 
2603         final float oldSize = getTextSize();
2604         setTextSize(oldSize * mCompatScaling);
2605         final float res = nGetTextAdvances(mNativePaint, chars, index, count, contextIndex,
2606                 contextCount, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances, advancesIndex);
2607         setTextSize(oldSize);
2608 
2609         if (advances != null) {
2610             for (int i = advancesIndex, e = i + count; i < e; i++) {
2611                 advances[i] *= mInvCompatScaling;
2612             }
2613         }
2614         return res * mInvCompatScaling; // assume errors are not significant
2615     }
2616 
2617     /**
2618      * Returns the next cursor position in the run.
2619      *
2620      * This avoids placing the cursor between surrogates, between characters that form conjuncts,
2621      * between base characters and combining marks, or within a reordering cluster.
2622      *
2623      * <p>
2624      * ContextStart and offset are relative to the start of text.
2625      * The context is the shaping context for cursor movement, generally the bounds of the metric
2626      * span enclosing the cursor in the direction of movement.
2627      *
2628      * <p>
2629      * If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
2630      * returns -1.  Otherwise this will never return a value before contextStart or after
2631      * contextStart + contextLength.
2632      *
2633      * @param text the text
2634      * @param contextStart the start of the context
2635      * @param contextLength the length of the context
2636      * @param isRtl true if the paragraph context is RTL, otherwise false
2637      * @param offset the cursor position to move from
2638      * @param cursorOpt how to move the cursor
2639      * @return the offset of the next position, or -1
2640      */
getTextRunCursor(@onNull char[] text, @IntRange(from = 0) int contextStart, @IntRange(from = 0) int contextLength, boolean isRtl, @IntRange(from = 0) int offset, @CursorOption int cursorOpt)2641     public int getTextRunCursor(@NonNull char[] text, @IntRange(from = 0) int contextStart,
2642             @IntRange(from = 0) int contextLength, boolean isRtl, @IntRange(from = 0) int offset,
2643             @CursorOption int cursorOpt) {
2644         int contextEnd = contextStart + contextLength;
2645         if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
2646                 | (offset - contextStart) | (contextEnd - offset)
2647                 | (text.length - contextEnd) | cursorOpt) < 0)
2648                 || cursorOpt > CURSOR_OPT_MAX_VALUE) {
2649             throw new IndexOutOfBoundsException();
2650         }
2651 
2652         return nGetTextRunCursor(mNativePaint, text, contextStart, contextLength,
2653                 isRtl ? DIRECTION_RTL : DIRECTION_LTR, offset, cursorOpt);
2654     }
2655 
2656     /**
2657      * Returns the next cursor position in the run.
2658      *
2659      * This avoids placing the cursor between surrogates, between characters that form conjuncts,
2660      * between base characters and combining marks, or within a reordering cluster.
2661      *
2662      * <p>
2663      * ContextStart, contextEnd, and offset are relative to the start of
2664      * text.  The context is the shaping context for cursor movement, generally
2665      * the bounds of the metric span enclosing the cursor in the direction of
2666      * movement.
2667      *
2668      * <p>
2669      * If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
2670      * returns -1.  Otherwise this will never return a value before contextStart or after
2671      * contextEnd.
2672      *
2673      * @param text the text
2674      * @param contextStart the start of the context
2675      * @param contextEnd the end of the context
2676      * @param isRtl true if the paragraph context is RTL, otherwise false
2677      * @param offset the cursor position to move from
2678      * @param cursorOpt how to move the cursor
2679      * @return the offset of the next position, or -1
2680      */
getTextRunCursor(@onNull CharSequence text, @IntRange(from = 0) int contextStart, @IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset, @CursorOption int cursorOpt)2681     public int getTextRunCursor(@NonNull CharSequence text, @IntRange(from = 0) int contextStart,
2682             @IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset,
2683             @CursorOption int cursorOpt) {
2684 
2685         if (text instanceof String || text instanceof SpannedString ||
2686                 text instanceof SpannableString) {
2687             return getTextRunCursor(text.toString(), contextStart, contextEnd,
2688                     isRtl, offset, cursorOpt);
2689         }
2690         if (text instanceof GraphicsOperations) {
2691             return ((GraphicsOperations) text).getTextRunCursor(
2692                     contextStart, contextEnd, isRtl, offset, cursorOpt, this);
2693         }
2694 
2695         int contextLen = contextEnd - contextStart;
2696         char[] buf = TemporaryBuffer.obtain(contextLen);
2697         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
2698         int relPos = getTextRunCursor(buf, 0, contextLen, isRtl, offset - contextStart, cursorOpt);
2699         TemporaryBuffer.recycle(buf);
2700         return (relPos == -1) ? -1 : relPos + contextStart;
2701     }
2702 
2703     /**
2704      * Returns the next cursor position in the run.
2705      *
2706      * This avoids placing the cursor between surrogates, between characters that form conjuncts,
2707      * between base characters and combining marks, or within a reordering cluster.
2708      *
2709      * <p>
2710      * ContextStart, contextEnd, and offset are relative to the start of text.  The context is the
2711      * shaping context for cursor movement, generally the bounds of the metric span enclosing the
2712      * cursor in the direction of movement.
2713      * </p>
2714      *
2715      * <p>
2716      * If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
2717      * returns -1.  Otherwise this will never return a value before contextStart or after
2718      * contextEnd.
2719      * </p>
2720      *
2721      * @param text the text
2722      * @param contextStart the start of the context
2723      * @param contextEnd the end of the context
2724      * @param isRtl true if the paragraph context is RTL, otherwise false.
2725      * @param offset the cursor position to move from
2726      * @param cursorOpt how to move the cursor
2727      * @return the offset of the next position, or -1
2728      * @hide
2729      */
getTextRunCursor(@onNull String text, @IntRange(from = 0) int contextStart, @IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset, @CursorOption int cursorOpt)2730     public int getTextRunCursor(@NonNull String text, @IntRange(from = 0) int contextStart,
2731             @IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset,
2732             @CursorOption int cursorOpt) {
2733         if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
2734                 | (offset - contextStart) | (contextEnd - offset)
2735                 | (text.length() - contextEnd) | cursorOpt) < 0)
2736                 || cursorOpt > CURSOR_OPT_MAX_VALUE) {
2737             throw new IndexOutOfBoundsException();
2738         }
2739 
2740         return nGetTextRunCursor(mNativePaint, text, contextStart, contextEnd,
2741                 isRtl ? DIRECTION_RTL : DIRECTION_LTR, offset, cursorOpt);
2742     }
2743 
2744     /**
2745      * Return the path (outline) for the specified text.
2746      * Note: just like Canvas.drawText, this will respect the Align setting in
2747      * the paint.
2748      *
2749      * @param text the text to retrieve the path from
2750      * @param index the index of the first character in text
2751      * @param count the number of characters starting with index
2752      * @param x the x coordinate of the text's origin
2753      * @param y the y coordinate of the text's origin
2754      * @param path the path to receive the data describing the text. Must be allocated by the caller
2755      */
getTextPath(char[] text, int index, int count, float x, float y, Path path)2756     public void getTextPath(char[] text, int index, int count,
2757                             float x, float y, Path path) {
2758         if ((index | count) < 0 || index + count > text.length) {
2759             throw new ArrayIndexOutOfBoundsException();
2760         }
2761         nGetTextPath(mNativePaint, mBidiFlags, text, index, count, x, y, path.mutateNI());
2762     }
2763 
2764     /**
2765      * Return the path (outline) for the specified text.
2766      * Note: just like Canvas.drawText, this will respect the Align setting
2767      * in the paint.
2768      *
2769      * @param text the text to retrieve the path from
2770      * @param start the first character in the text
2771      * @param end 1 past the last character in the text
2772      * @param x the x coordinate of the text's origin
2773      * @param y the y coordinate of the text's origin
2774      * @param path the path to receive the data describing the text. Must be allocated by the caller
2775      */
getTextPath(String text, int start, int end, float x, float y, Path path)2776     public void getTextPath(String text, int start, int end,
2777                             float x, float y, Path path) {
2778         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2779             throw new IndexOutOfBoundsException();
2780         }
2781         nGetTextPath(mNativePaint, mBidiFlags, text, start, end, x, y, path.mutateNI());
2782     }
2783 
2784     /**
2785      * Retrieve the text boundary box and store to bounds.
2786      *
2787      * Return in bounds (allocated by the caller) the smallest rectangle that
2788      * encloses all of the characters, with an implied origin at (0,0).
2789      *
2790      * @param text string to measure and return its bounds
2791      * @param start index of the first char in the string to measure
2792      * @param end 1 past the last char in the string to measure
2793      * @param bounds returns the unioned bounds of all the text. Must be allocated by the caller
2794      */
getTextBounds(String text, int start, int end, Rect bounds)2795     public void getTextBounds(String text, int start, int end, Rect bounds) {
2796         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2797             throw new IndexOutOfBoundsException();
2798         }
2799         if (bounds == null) {
2800             throw new NullPointerException("need bounds Rect");
2801         }
2802         nGetStringBounds(mNativePaint, text, start, end, mBidiFlags, bounds);
2803     }
2804 
2805     /**
2806      * Retrieve the text boundary box and store to bounds.
2807      *
2808      * Return in bounds (allocated by the caller) the smallest rectangle that
2809      * encloses all of the characters, with an implied origin at (0,0).
2810      *
2811      * Note that styles are ignored even if you pass {@link android.text.Spanned} instance.
2812      * Use {@link android.text.StaticLayout} for measuring bounds of {@link android.text.Spanned}.
2813      *
2814      * @param text text to measure and return its bounds
2815      * @param start index of the first char in the text to measure
2816      * @param end 1 past the last char in the text to measure
2817      * @param bounds returns the unioned bounds of all the text. Must be allocated by the caller
2818      */
getTextBounds(@onNull CharSequence text, int start, int end, @NonNull Rect bounds)2819     public void getTextBounds(@NonNull CharSequence text, int start, int end,
2820             @NonNull Rect bounds) {
2821         if ((start | end | (end - start) | (text.length() - end)) < 0) {
2822             throw new IndexOutOfBoundsException();
2823         }
2824         if (bounds == null) {
2825             throw new NullPointerException("need bounds Rect");
2826         }
2827         char[] buf = TemporaryBuffer.obtain(end - start);
2828         TextUtils.getChars(text, start, end, buf, 0);
2829         getTextBounds(buf, 0, end - start, bounds);
2830         TemporaryBuffer.recycle(buf);
2831     }
2832 
2833     /**
2834      * Return in bounds (allocated by the caller) the smallest rectangle that
2835      * encloses all of the characters, with an implied origin at (0,0).
2836      *
2837      * @param text  array of chars to measure and return their unioned bounds
2838      * @param index index of the first char in the array to measure
2839      * @param count the number of chars, beginning at index, to measure
2840      * @param bounds returns the unioned bounds of all the text. Must be allocated by the caller
2841      */
getTextBounds(char[] text, int index, int count, Rect bounds)2842     public void getTextBounds(char[] text, int index, int count, Rect bounds) {
2843         if ((index | count) < 0 || index + count > text.length) {
2844             throw new ArrayIndexOutOfBoundsException();
2845         }
2846         if (bounds == null) {
2847             throw new NullPointerException("need bounds Rect");
2848         }
2849         nGetCharArrayBounds(mNativePaint, text, index, count, mBidiFlags,
2850             bounds);
2851     }
2852 
2853     /**
2854      * Determine whether the typeface set on the paint has a glyph supporting the string. The
2855      * simplest case is when the string contains a single character, in which this method
2856      * determines whether the font has the character. In the case of multiple characters, the
2857      * method returns true if there is a single glyph representing the ligature. For example, if
2858      * the input is a pair of regional indicator symbols, determine whether there is an emoji flag
2859      * for the pair.
2860      *
2861      * <p>Finally, if the string contains a variation selector, the method only returns true if
2862      * the fonts contains a glyph specific to that variation.
2863      *
2864      * <p>Checking is done on the entire fallback chain, not just the immediate font referenced.
2865      *
2866      * @param string the string to test whether there is glyph support
2867      * @return true if the typeface has a glyph for the string
2868      */
hasGlyph(String string)2869     public boolean hasGlyph(String string) {
2870         return nHasGlyph(mNativePaint, mBidiFlags, string);
2871     }
2872 
2873     /**
2874      * Measure cursor position within a run of text.
2875      *
2876      * <p>The run of text includes the characters from {@code start} to {@code end} in the text. In
2877      * addition, the range {@code contextStart} to {@code contextEnd} is used as context for the
2878      * purpose of complex text shaping, such as Arabic text potentially shaped differently based on
2879      * the text next to it.
2880      *
2881      * <p>All text outside the range {@code contextStart..contextEnd} is ignored. The text between
2882      * {@code start} and {@code end} will be laid out to be measured.
2883      *
2884      * <p>The returned width measurement is the advance from {@code start} to {@code offset}. It is
2885      * generally a positive value, no matter the direction of the run. If {@code offset == end},
2886      * the return value is simply the width of the whole run from {@code start} to {@code end}.
2887      *
2888      * <p>Ligatures are formed for characters in the range {@code start..end} (but not for
2889      * {@code start..contextStart} or {@code end..contextEnd}). If {@code offset} points to a
2890      * character in the middle of such a formed ligature, but at a grapheme cluster boundary, the
2891      * return value will also reflect an advance in the middle of the ligature. See
2892      * {@link #getOffsetForAdvance} for more discussion of grapheme cluster boundaries.
2893      *
2894      * <p>The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is
2895      * suitable only for runs of a single direction.
2896      *
2897      * <p>All indices are relative to the start of {@code text}. Further, {@code 0 <= contextStart
2898      * <= start <= offset <= end <= contextEnd <= text.length} must hold on entry.
2899      *
2900      * @param text the text to measure. Cannot be null.
2901      * @param start the index of the start of the range to measure
2902      * @param end the index + 1 of the end of the range to measure
2903      * @param contextStart the index of the start of the shaping context
2904      * @param contextEnd the index + 1 of the end of the shaping context
2905      * @param isRtl whether the run is in RTL direction
2906      * @param offset index of caret position
2907      * @return width measurement between start and offset
2908      */
getRunAdvance(char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)2909     public float getRunAdvance(char[] text, int start, int end, int contextStart, int contextEnd,
2910             boolean isRtl, int offset) {
2911         if (text == null) {
2912             throw new IllegalArgumentException("text cannot be null");
2913         }
2914         if ((contextStart | start | offset | end | contextEnd
2915                 | start - contextStart | offset - start | end - offset
2916                 | contextEnd - end | text.length - contextEnd) < 0) {
2917             throw new IndexOutOfBoundsException();
2918         }
2919         if (end == start) {
2920             return 0.0f;
2921         }
2922         // TODO: take mCompatScaling into account (or eliminate compat scaling)?
2923         return nGetRunAdvance(mNativePaint, text, start, end, contextStart, contextEnd, isRtl,
2924                 offset);
2925     }
2926 
2927     /**
2928      * @see #getRunAdvance(char[], int, int, int, int, boolean, int)
2929      *
2930      * @param text the text to measure. Cannot be null.
2931      * @param start the index of the start of the range to measure
2932      * @param end the index + 1 of the end of the range to measure
2933      * @param contextStart the index of the start of the shaping context
2934      * @param contextEnd the index + 1 of the end of the shaping context
2935      * @param isRtl whether the run is in RTL direction
2936      * @param offset index of caret position
2937      * @return width measurement between start and offset
2938      */
getRunAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)2939     public float getRunAdvance(CharSequence text, int start, int end, int contextStart,
2940             int contextEnd, boolean isRtl, int offset) {
2941         if (text == null) {
2942             throw new IllegalArgumentException("text cannot be null");
2943         }
2944         if ((contextStart | start | offset | end | contextEnd
2945                 | start - contextStart | offset - start | end - offset
2946                 | contextEnd - end | text.length() - contextEnd) < 0) {
2947             throw new IndexOutOfBoundsException();
2948         }
2949         if (end == start) {
2950             return 0.0f;
2951         }
2952         // TODO performance: specialized alternatives to avoid buffer copy, if win is significant
2953         char[] buf = TemporaryBuffer.obtain(contextEnd - contextStart);
2954         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
2955         float result = getRunAdvance(buf, start - contextStart, end - contextStart, 0,
2956                 contextEnd - contextStart, isRtl, offset - contextStart);
2957         TemporaryBuffer.recycle(buf);
2958         return result;
2959     }
2960 
2961     /**
2962      * Get the character offset within the string whose position is closest to the specified
2963      * horizontal position.
2964      *
2965      * <p>The returned value is generally the value of {@code offset} for which
2966      * {@link #getRunAdvance} yields a result most closely approximating {@code advance},
2967      * and which is also on a grapheme cluster boundary. As such, it is the preferred method
2968      * for positioning a cursor in response to a touch or pointer event. The grapheme cluster
2969      * boundaries are based on
2970      * <a href="http://unicode.org/reports/tr29/">Unicode Standard Annex #29</a> but with some
2971      * tailoring for better user experience.
2972      *
2973      * <p>Note that {@code advance} is a (generally positive) width measurement relative to the start
2974      * of the run. Thus, for RTL runs it the distance from the point to the right edge.
2975      *
2976      * <p>All indices are relative to the start of {@code text}. Further, {@code 0 <= contextStart
2977      * <= start <= end <= contextEnd <= text.length} must hold on entry, and {@code start <= result
2978      * <= end} will hold on return.
2979      *
2980      * @param text the text to measure. Cannot be null.
2981      * @param start the index of the start of the range to measure
2982      * @param end the index + 1 of the end of the range to measure
2983      * @param contextStart the index of the start of the shaping context
2984      * @param contextEnd the index + 1 of the end of the range to measure
2985      * @param isRtl whether the run is in RTL direction
2986      * @param advance width relative to start of run
2987      * @return index of offset
2988      */
getOffsetForAdvance(char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance)2989     public int getOffsetForAdvance(char[] text, int start, int end, int contextStart,
2990             int contextEnd, boolean isRtl, float advance) {
2991         if (text == null) {
2992             throw new IllegalArgumentException("text cannot be null");
2993         }
2994         if ((contextStart | start | end | contextEnd
2995                 | start - contextStart | end - start | contextEnd - end
2996                 | text.length - contextEnd) < 0) {
2997             throw new IndexOutOfBoundsException();
2998         }
2999         // TODO: take mCompatScaling into account (or eliminate compat scaling)?
3000         return nGetOffsetForAdvance(mNativePaint, text, start, end, contextStart, contextEnd,
3001                 isRtl, advance);
3002     }
3003 
3004     /**
3005      * @see #getOffsetForAdvance(char[], int, int, int, int, boolean, float)
3006      *
3007      * @param text the text to measure. Cannot be null.
3008      * @param start the index of the start of the range to measure
3009      * @param end the index + 1 of the end of the range to measure
3010      * @param contextStart the index of the start of the shaping context
3011      * @param contextEnd the index + 1 of the end of the range to measure
3012      * @param isRtl whether the run is in RTL direction
3013      * @param advance width relative to start of run
3014      * @return index of offset
3015      */
getOffsetForAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance)3016     public int getOffsetForAdvance(CharSequence text, int start, int end, int contextStart,
3017             int contextEnd, boolean isRtl, float advance) {
3018         if (text == null) {
3019             throw new IllegalArgumentException("text cannot be null");
3020         }
3021         if ((contextStart | start | end | contextEnd
3022                 | start - contextStart | end - start | contextEnd - end
3023                 | text.length() - contextEnd) < 0) {
3024             throw new IndexOutOfBoundsException();
3025         }
3026         // TODO performance: specialized alternatives to avoid buffer copy, if win is significant
3027         char[] buf = TemporaryBuffer.obtain(contextEnd - contextStart);
3028         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
3029         int result = getOffsetForAdvance(buf, start - contextStart, end - contextStart, 0,
3030                 contextEnd - contextStart, isRtl, advance) + contextStart;
3031         TemporaryBuffer.recycle(buf);
3032         return result;
3033     }
3034 
3035     /**
3036      * Returns true of the passed {@link Paint} will have the same effect on text measurement
3037      *
3038      * @param other A {@link Paint} object.
3039      * @return true if the other {@link Paint} has the same effect on text measurement.
3040      */
equalsForTextMeasurement(@onNull Paint other)3041     public boolean equalsForTextMeasurement(@NonNull Paint other) {
3042         return nEqualsForTextMeasurement(mNativePaint, other.mNativePaint);
3043     }
3044 
3045     // regular JNI
nGetNativeFinalizer()3046     private static native long nGetNativeFinalizer();
nInit()3047     private static native long nInit();
nInitWithPaint(long paint)3048     private static native long nInitWithPaint(long paint);
nBreakText(long nObject, char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth)3049     private static native int nBreakText(long nObject, char[] text, int index, int count,
3050             float maxWidth, int bidiFlags, float[] measuredWidth);
nBreakText(long nObject, String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth)3051     private static native int nBreakText(long nObject, String text, boolean measureForwards,
3052             float maxWidth, int bidiFlags, float[] measuredWidth);
nGetTextAdvances(long paintPtr, char[] text, int index, int count, int contextIndex, int contextCount, int bidiFlags, float[] advances, int advancesIndex)3053     private static native float nGetTextAdvances(long paintPtr, char[] text, int index, int count,
3054             int contextIndex, int contextCount, int bidiFlags, float[] advances, int advancesIndex);
nGetTextAdvances(long paintPtr, String text, int start, int end, int contextStart, int contextEnd, int bidiFlags, float[] advances, int advancesIndex)3055     private static native float nGetTextAdvances(long paintPtr, String text, int start, int end,
3056             int contextStart, int contextEnd, int bidiFlags, float[] advances, int advancesIndex);
nGetTextRunCursor(long paintPtr, char[] text, int contextStart, int contextLength, int dir, int offset, int cursorOpt)3057     private native int nGetTextRunCursor(long paintPtr, char[] text, int contextStart,
3058             int contextLength, int dir, int offset, int cursorOpt);
nGetTextRunCursor(long paintPtr, String text, int contextStart, int contextEnd, int dir, int offset, int cursorOpt)3059     private native int nGetTextRunCursor(long paintPtr, String text, int contextStart,
3060             int contextEnd, int dir, int offset, int cursorOpt);
nGetTextPath(long paintPtr, int bidiFlags, char[] text, int index, int count, float x, float y, long path)3061     private static native void nGetTextPath(long paintPtr, int bidiFlags, char[] text, int index,
3062             int count, float x, float y, long path);
nGetTextPath(long paintPtr, int bidiFlags, String text, int start, int end, float x, float y, long path)3063     private static native void nGetTextPath(long paintPtr, int bidiFlags, String text, int start,
3064             int end, float x, float y, long path);
nGetStringBounds(long nativePaint, String text, int start, int end, int bidiFlags, Rect bounds)3065     private static native void nGetStringBounds(long nativePaint, String text, int start, int end,
3066             int bidiFlags, Rect bounds);
nGetCharArrayBounds(long nativePaint, char[] text, int index, int count, int bidiFlags, Rect bounds)3067     private static native void nGetCharArrayBounds(long nativePaint, char[] text, int index,
3068             int count, int bidiFlags, Rect bounds);
nHasGlyph(long paintPtr, int bidiFlags, String string)3069     private static native boolean nHasGlyph(long paintPtr, int bidiFlags, String string);
nGetRunAdvance(long paintPtr, char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)3070     private static native float nGetRunAdvance(long paintPtr, char[] text, int start, int end,
3071             int contextStart, int contextEnd, boolean isRtl, int offset);
nGetOffsetForAdvance(long paintPtr, char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance)3072     private static native int nGetOffsetForAdvance(long paintPtr, char[] text, int start, int end,
3073             int contextStart, int contextEnd, boolean isRtl, float advance);
3074 
3075 
3076     // ---------------- @FastNative ------------------------
3077 
3078     @FastNative
nSetTextLocales(long paintPtr, String locales)3079     private static native int nSetTextLocales(long paintPtr, String locales);
3080     @FastNative
nSetFontFeatureSettings(long paintPtr, String settings)3081     private static native void nSetFontFeatureSettings(long paintPtr, String settings);
3082     @FastNative
nGetFontMetrics(long paintPtr, FontMetrics metrics)3083     private static native float nGetFontMetrics(long paintPtr, FontMetrics metrics);
3084     @FastNative
nGetFontMetricsInt(long paintPtr, FontMetricsInt fmi)3085     private static native int nGetFontMetricsInt(long paintPtr, FontMetricsInt fmi);
3086 
3087 
3088     // ---------------- @CriticalNative ------------------------
3089 
3090     @CriticalNative
nReset(long paintPtr)3091     private static native void nReset(long paintPtr);
3092     @CriticalNative
nSet(long paintPtrDest, long paintPtrSrc)3093     private static native void nSet(long paintPtrDest, long paintPtrSrc);
3094     @CriticalNative
nGetStyle(long paintPtr)3095     private static native int nGetStyle(long paintPtr);
3096     @CriticalNative
nSetStyle(long paintPtr, int style)3097     private static native void nSetStyle(long paintPtr, int style);
3098     @CriticalNative
nGetStrokeCap(long paintPtr)3099     private static native int nGetStrokeCap(long paintPtr);
3100     @CriticalNative
nSetStrokeCap(long paintPtr, int cap)3101     private static native void nSetStrokeCap(long paintPtr, int cap);
3102     @CriticalNative
nGetStrokeJoin(long paintPtr)3103     private static native int nGetStrokeJoin(long paintPtr);
3104     @CriticalNative
nSetStrokeJoin(long paintPtr, int join)3105     private static native void nSetStrokeJoin(long paintPtr, int join);
3106     @CriticalNative
nGetFillPath(long paintPtr, long src, long dst)3107     private static native boolean nGetFillPath(long paintPtr, long src, long dst);
3108     @CriticalNative
nSetShader(long paintPtr, long shader)3109     private static native long nSetShader(long paintPtr, long shader);
3110     @CriticalNative
nSetColorFilter(long paintPtr, long filter)3111     private static native long nSetColorFilter(long paintPtr, long filter);
3112     @CriticalNative
nSetXfermode(long paintPtr, int xfermode)3113     private static native void nSetXfermode(long paintPtr, int xfermode);
3114     @CriticalNative
nSetPathEffect(long paintPtr, long effect)3115     private static native long nSetPathEffect(long paintPtr, long effect);
3116     @CriticalNative
nSetMaskFilter(long paintPtr, long maskfilter)3117     private static native long nSetMaskFilter(long paintPtr, long maskfilter);
3118     @CriticalNative
nSetTypeface(long paintPtr, long typeface)3119     private static native void nSetTypeface(long paintPtr, long typeface);
3120     @CriticalNative
nGetTextAlign(long paintPtr)3121     private static native int nGetTextAlign(long paintPtr);
3122     @CriticalNative
nSetTextAlign(long paintPtr, int align)3123     private static native void nSetTextAlign(long paintPtr, int align);
3124     @CriticalNative
nSetTextLocalesByMinikinLocaleListId(long paintPtr, int mMinikinLocaleListId)3125     private static native void nSetTextLocalesByMinikinLocaleListId(long paintPtr,
3126             int mMinikinLocaleListId);
3127     @CriticalNative
nSetShadowLayer(long paintPtr, float radius, float dx, float dy, long colorSpaceHandle, @ColorLong long shadowColor)3128     private static native void nSetShadowLayer(long paintPtr,
3129             float radius, float dx, float dy, long colorSpaceHandle,
3130             @ColorLong long shadowColor);
3131     @CriticalNative
nHasShadowLayer(long paintPtr)3132     private static native boolean nHasShadowLayer(long paintPtr);
3133     @CriticalNative
nGetLetterSpacing(long paintPtr)3134     private static native float nGetLetterSpacing(long paintPtr);
3135     @CriticalNative
nSetLetterSpacing(long paintPtr, float letterSpacing)3136     private static native void nSetLetterSpacing(long paintPtr, float letterSpacing);
3137     @CriticalNative
nGetWordSpacing(long paintPtr)3138     private static native float nGetWordSpacing(long paintPtr);
3139     @CriticalNative
nSetWordSpacing(long paintPtr, float wordSpacing)3140     private static native void nSetWordSpacing(long paintPtr, float wordSpacing);
3141     @CriticalNative
nGetStartHyphenEdit(long paintPtr)3142     private static native int nGetStartHyphenEdit(long paintPtr);
3143     @CriticalNative
nGetEndHyphenEdit(long paintPtr)3144     private static native int nGetEndHyphenEdit(long paintPtr);
3145     @CriticalNative
nSetStartHyphenEdit(long paintPtr, int hyphen)3146     private static native void nSetStartHyphenEdit(long paintPtr, int hyphen);
3147     @CriticalNative
nSetEndHyphenEdit(long paintPtr, int hyphen)3148     private static native void nSetEndHyphenEdit(long paintPtr, int hyphen);
3149     @CriticalNative
nSetStrokeMiter(long paintPtr, float miter)3150     private static native void nSetStrokeMiter(long paintPtr, float miter);
3151     @CriticalNative
nGetStrokeMiter(long paintPtr)3152     private static native float nGetStrokeMiter(long paintPtr);
3153     @CriticalNative
nSetStrokeWidth(long paintPtr, float width)3154     private static native void nSetStrokeWidth(long paintPtr, float width);
3155     @CriticalNative
nGetStrokeWidth(long paintPtr)3156     private static native float nGetStrokeWidth(long paintPtr);
3157     @CriticalNative
nSetAlpha(long paintPtr, int a)3158     private static native void nSetAlpha(long paintPtr, int a);
3159     @CriticalNative
nSetDither(long paintPtr, boolean dither)3160     private static native void nSetDither(long paintPtr, boolean dither);
3161     @CriticalNative
nGetFlags(long paintPtr)3162     private static native int nGetFlags(long paintPtr);
3163     @CriticalNative
nSetFlags(long paintPtr, int flags)3164     private static native void nSetFlags(long paintPtr, int flags);
3165     @CriticalNative
nGetHinting(long paintPtr)3166     private static native int nGetHinting(long paintPtr);
3167     @CriticalNative
nSetHinting(long paintPtr, int mode)3168     private static native void nSetHinting(long paintPtr, int mode);
3169     @CriticalNative
nSetAntiAlias(long paintPtr, boolean aa)3170     private static native void nSetAntiAlias(long paintPtr, boolean aa);
3171     @CriticalNative
nSetLinearText(long paintPtr, boolean linearText)3172     private static native void nSetLinearText(long paintPtr, boolean linearText);
3173     @CriticalNative
nSetSubpixelText(long paintPtr, boolean subpixelText)3174     private static native void nSetSubpixelText(long paintPtr, boolean subpixelText);
3175     @CriticalNative
nSetUnderlineText(long paintPtr, boolean underlineText)3176     private static native void nSetUnderlineText(long paintPtr, boolean underlineText);
3177     @CriticalNative
nSetFakeBoldText(long paintPtr, boolean fakeBoldText)3178     private static native void nSetFakeBoldText(long paintPtr, boolean fakeBoldText);
3179     @CriticalNative
nSetFilterBitmap(long paintPtr, boolean filter)3180     private static native void nSetFilterBitmap(long paintPtr, boolean filter);
3181     @CriticalNative
nSetColor(long paintPtr, long colorSpaceHandle, @ColorLong long color)3182     private static native void nSetColor(long paintPtr, long colorSpaceHandle,
3183             @ColorLong long color);
3184     @CriticalNative
nSetColor(long paintPtr, @ColorInt int color)3185     private static native void nSetColor(long paintPtr, @ColorInt int color);
3186     @CriticalNative
nSetStrikeThruText(long paintPtr, boolean strikeThruText)3187     private static native void nSetStrikeThruText(long paintPtr, boolean strikeThruText);
3188     @CriticalNative
nIsElegantTextHeight(long paintPtr)3189     private static native boolean nIsElegantTextHeight(long paintPtr);
3190     @CriticalNative
nSetElegantTextHeight(long paintPtr, boolean elegant)3191     private static native void nSetElegantTextHeight(long paintPtr, boolean elegant);
3192     @CriticalNative
nGetTextSize(long paintPtr)3193     private static native float nGetTextSize(long paintPtr);
3194     @CriticalNative
nGetTextScaleX(long paintPtr)3195     private static native float nGetTextScaleX(long paintPtr);
3196     @CriticalNative
nSetTextScaleX(long paintPtr, float scaleX)3197     private static native void nSetTextScaleX(long paintPtr, float scaleX);
3198     @CriticalNative
nGetTextSkewX(long paintPtr)3199     private static native float nGetTextSkewX(long paintPtr);
3200     @CriticalNative
nSetTextSkewX(long paintPtr, float skewX)3201     private static native void nSetTextSkewX(long paintPtr, float skewX);
3202     @CriticalNative
nAscent(long paintPtr)3203     private static native float nAscent(long paintPtr);
3204     @CriticalNative
nDescent(long paintPtr)3205     private static native float nDescent(long paintPtr);
3206     @CriticalNative
nGetUnderlinePosition(long paintPtr)3207     private static native float nGetUnderlinePosition(long paintPtr);
3208     @CriticalNative
nGetUnderlineThickness(long paintPtr)3209     private static native float nGetUnderlineThickness(long paintPtr);
3210     @CriticalNative
nGetStrikeThruPosition(long paintPtr)3211     private static native float nGetStrikeThruPosition(long paintPtr);
3212     @CriticalNative
nGetStrikeThruThickness(long paintPtr)3213     private static native float nGetStrikeThruThickness(long paintPtr);
3214     @CriticalNative
nSetTextSize(long paintPtr, float textSize)3215     private static native void nSetTextSize(long paintPtr, float textSize);
3216     @CriticalNative
nEqualsForTextMeasurement(long leftPaintPtr, long rightPaintPtr)3217     private static native boolean nEqualsForTextMeasurement(long leftPaintPtr, long rightPaintPtr);
3218 }
3219