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