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