Paint.java revision b2b7c6ebe474e75961368a3e144885f470777e11
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    /*package*/ 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        if (mShader != null && mShader.getNativeInstance() != mNativeShader) {
538            native_setShader(mNativePaint, mShader.getNativeInstance());
539        }
540        return mNativePaint;
541    }
542
543    /**
544     * Return the bidi flags on the paint.
545     *
546     * @return the bidi flags on the paint
547     * @hide
548     */
549    public int getBidiFlags() {
550        return mBidiFlags;
551    }
552
553    /**
554     * Set the bidi flags on the paint.
555     * @hide
556     */
557    public void setBidiFlags(int flags) {
558        // only flag value is the 3-bit BIDI control setting
559        flags &= BIDI_FLAG_MASK;
560        if (flags > BIDI_MAX_FLAG_VALUE) {
561            throw new IllegalArgumentException("unknown bidi flag: " + flags);
562        }
563        mBidiFlags = flags;
564    }
565
566    /**
567     * Return the paint's flags. Use the Flag enum to test flag values.
568     *
569     * @return the paint's flags (see enums ending in _Flag for bit masks)
570     */
571    public native int getFlags();
572
573    /**
574     * Set the paint's flags. Use the Flag enum to specific flag values.
575     *
576     * @param flags The new flag bits for the paint
577     */
578    public native void setFlags(int flags);
579
580    /**
581     * Return the paint's hinting mode.  Returns either
582     * {@link #HINTING_OFF} or {@link #HINTING_ON}.
583     */
584    public native int getHinting();
585
586    /**
587     * Set the paint's hinting mode.  May be either
588     * {@link #HINTING_OFF} or {@link #HINTING_ON}.
589     */
590    public native void setHinting(int mode);
591
592    /**
593     * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set
594     * AntiAliasing smooths out the edges of what is being drawn, but is has
595     * no impact on the interior of the shape. See setDither() and
596     * setFilterBitmap() to affect how colors are treated.
597     *
598     * @return true if the antialias bit is set in the paint's flags.
599     */
600    public final boolean isAntiAlias() {
601        return (getFlags() & ANTI_ALIAS_FLAG) != 0;
602    }
603
604    /**
605     * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit
606     * AntiAliasing smooths out the edges of what is being drawn, but is has
607     * no impact on the interior of the shape. See setDither() and
608     * setFilterBitmap() to affect how colors are treated.
609     *
610     * @param aa true to set the antialias bit in the flags, false to clear it
611     */
612    public native void setAntiAlias(boolean aa);
613
614    /**
615     * Helper for getFlags(), returning true if DITHER_FLAG bit is set
616     * Dithering affects how colors that are higher precision than the device
617     * are down-sampled. No dithering is generally faster, but higher precision
618     * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
619     * distribute the error inherent in this process, to reduce the visual
620     * artifacts.
621     *
622     * @return true if the dithering bit is set in the paint's flags.
623     */
624    public final boolean isDither() {
625        return (getFlags() & DITHER_FLAG) != 0;
626    }
627
628    /**
629     * Helper for setFlags(), setting or clearing the DITHER_FLAG bit
630     * Dithering affects how colors that are higher precision than the device
631     * are down-sampled. No dithering is generally faster, but higher precision
632     * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
633     * distribute the error inherent in this process, to reduce the visual
634     * artifacts.
635     *
636     * @param dither true to set the dithering bit in flags, false to clear it
637     */
638    public native void setDither(boolean dither);
639
640    /**
641     * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set
642     *
643     * @return true if the lineartext bit is set in the paint's flags
644     */
645    public final boolean isLinearText() {
646        return (getFlags() & LINEAR_TEXT_FLAG) != 0;
647    }
648
649    /**
650     * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit
651     *
652     * @param linearText true to set the linearText bit in the paint's flags,
653     *                   false to clear it.
654     */
655    public native void setLinearText(boolean linearText);
656
657    /**
658     * Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set
659     *
660     * @return true if the subpixel bit is set in the paint's flags
661     */
662    public final boolean isSubpixelText() {
663        return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0;
664    }
665
666    /**
667     * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit
668     *
669     * @param subpixelText true to set the subpixelText bit in the paint's
670     *                     flags, false to clear it.
671     */
672    public native void setSubpixelText(boolean subpixelText);
673
674    /**
675     * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
676     *
677     * @return true if the underlineText bit is set in the paint's flags.
678     */
679    public final boolean isUnderlineText() {
680        return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
681    }
682
683    /**
684     * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit
685     *
686     * @param underlineText true to set the underlineText bit in the paint's
687     *                      flags, false to clear it.
688     */
689    public native void setUnderlineText(boolean underlineText);
690
691    /**
692     * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
693     *
694     * @return true if the strikeThruText bit is set in the paint's flags.
695     */
696    public final boolean isStrikeThruText() {
697        return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
698    }
699
700    /**
701     * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
702     *
703     * @param strikeThruText true to set the strikeThruText bit in the paint's
704     *                       flags, false to clear it.
705     */
706    public native void setStrikeThruText(boolean strikeThruText);
707
708    /**
709     * Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set
710     *
711     * @return true if the fakeBoldText bit is set in the paint's flags.
712     */
713    public final boolean isFakeBoldText() {
714        return (getFlags() & FAKE_BOLD_TEXT_FLAG) != 0;
715    }
716
717    /**
718     * Helper for setFlags(), setting or clearing the FAKE_BOLD_TEXT_FLAG bit
719     *
720     * @param fakeBoldText true to set the fakeBoldText bit in the paint's
721     *                     flags, false to clear it.
722     */
723    public native void setFakeBoldText(boolean fakeBoldText);
724
725    /**
726     * Whether or not the bitmap filter is activated.
727     * Filtering affects the sampling of bitmaps when they are transformed.
728     * Filtering does not affect how the colors in the bitmap are converted into
729     * device pixels. That is dependent on dithering and xfermodes.
730     *
731     * @see #setFilterBitmap(boolean) setFilterBitmap()
732     */
733    public final boolean isFilterBitmap() {
734        return (getFlags() & FILTER_BITMAP_FLAG) != 0;
735    }
736
737    /**
738     * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit.
739     * Filtering affects the sampling of bitmaps when they are transformed.
740     * Filtering does not affect how the colors in the bitmap are converted into
741     * device pixels. That is dependent on dithering and xfermodes.
742     *
743     * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
744     *               flags, false to clear it.
745     */
746    public native void setFilterBitmap(boolean filter);
747
748    /**
749     * Return the paint's style, used for controlling how primitives'
750     * geometries are interpreted (except for drawBitmap, which always assumes
751     * FILL_STYLE).
752     *
753     * @return the paint's style setting (Fill, Stroke, StrokeAndFill)
754     */
755    public Style getStyle() {
756        return sStyleArray[native_getStyle(mNativePaint)];
757    }
758
759    /**
760     * Set the paint's style, used for controlling how primitives'
761     * geometries are interpreted (except for drawBitmap, which always assumes
762     * Fill).
763     *
764     * @param style The new style to set in the paint
765     */
766    public void setStyle(Style style) {
767        native_setStyle(mNativePaint, style.nativeInt);
768    }
769
770    /**
771     * Return the paint's color. Note that the color is a 32bit value
772     * containing alpha as well as r,g,b. This 32bit value is not premultiplied,
773     * meaning that its alpha can be any value, regardless of the values of
774     * r,g,b. See the Color class for more details.
775     *
776     * @return the paint's color (and alpha).
777     */
778    public native int getColor();
779
780    /**
781     * Set the paint's color. Note that the color is an int containing alpha
782     * as well as r,g,b. This 32bit value is not premultiplied, meaning that
783     * its alpha can be any value, regardless of the values of r,g,b.
784     * See the Color class for more details.
785     *
786     * @param color The new color (including alpha) to set in the paint.
787     */
788    public native void setColor(int color);
789
790    /**
791     * Helper to getColor() that just returns the color's alpha value. This is
792     * the same as calling getColor() >>> 24. It always returns a value between
793     * 0 (completely transparent) and 255 (completely opaque).
794     *
795     * @return the alpha component of the paint's color.
796     */
797    public native int getAlpha();
798
799    /**
800     * Helper to setColor(), that only assigns the color's alpha value,
801     * leaving its r,g,b values unchanged. Results are undefined if the alpha
802     * value is outside of the range [0..255]
803     *
804     * @param a set the alpha component [0..255] of the paint's color.
805     */
806    public native void setAlpha(int a);
807
808    /**
809     * Helper to setColor(), that takes a,r,g,b and constructs the color int
810     *
811     * @param a The new alpha component (0..255) of the paint's color.
812     * @param r The new red component (0..255) of the paint's color.
813     * @param g The new green component (0..255) of the paint's color.
814     * @param b The new blue component (0..255) of the paint's color.
815     */
816    public void setARGB(int a, int r, int g, int b) {
817        setColor((a << 24) | (r << 16) | (g << 8) | b);
818    }
819
820    /**
821     * Return the width for stroking.
822     * <p />
823     * A value of 0 strokes in hairline mode.
824     * Hairlines always draws a single pixel independent of the canva's matrix.
825     *
826     * @return the paint's stroke width, used whenever the paint's style is
827     *         Stroke or StrokeAndFill.
828     */
829    public native float getStrokeWidth();
830
831    /**
832     * Set the width for stroking.
833     * Pass 0 to stroke in hairline mode.
834     * Hairlines always draws a single pixel independent of the canva's matrix.
835     *
836     * @param width set the paint's stroke width, used whenever the paint's
837     *              style is Stroke or StrokeAndFill.
838     */
839    public native void setStrokeWidth(float width);
840
841    /**
842     * Return the paint's stroke miter value. Used to control the behavior
843     * of miter joins when the joins angle is sharp.
844     *
845     * @return the paint's miter limit, used whenever the paint's style is
846     *         Stroke or StrokeAndFill.
847     */
848    public native float getStrokeMiter();
849
850    /**
851     * Set the paint's stroke miter value. This is used to control the behavior
852     * of miter joins when the joins angle is sharp. This value must be >= 0.
853     *
854     * @param miter set the miter limit on the paint, used whenever the paint's
855     *              style is Stroke or StrokeAndFill.
856     */
857    public native void setStrokeMiter(float miter);
858
859    /**
860     * Return the paint's Cap, controlling how the start and end of stroked
861     * lines and paths are treated.
862     *
863     * @return the line cap style for the paint, used whenever the paint's
864     *         style is Stroke or StrokeAndFill.
865     */
866    public Cap getStrokeCap() {
867        return sCapArray[native_getStrokeCap(mNativePaint)];
868    }
869
870    /**
871     * Set the paint's Cap.
872     *
873     * @param cap set the paint's line cap style, used whenever the paint's
874     *            style is Stroke or StrokeAndFill.
875     */
876    public void setStrokeCap(Cap cap) {
877        native_setStrokeCap(mNativePaint, cap.nativeInt);
878    }
879
880    /**
881     * Return the paint's stroke join type.
882     *
883     * @return the paint's Join.
884     */
885    public Join getStrokeJoin() {
886        return sJoinArray[native_getStrokeJoin(mNativePaint)];
887    }
888
889    /**
890     * Set the paint's Join.
891     *
892     * @param join set the paint's Join, used whenever the paint's style is
893     *             Stroke or StrokeAndFill.
894     */
895    public void setStrokeJoin(Join join) {
896        native_setStrokeJoin(mNativePaint, join.nativeInt);
897    }
898
899    /**
900     * Applies any/all effects (patheffect, stroking) to src, returning the
901     * result in dst. The result is that drawing src with this paint will be
902     * the same as drawing dst with a default paint (at least from the
903     * geometric perspective).
904     *
905     * @param src input path
906     * @param dst output path (may be the same as src)
907     * @return    true if the path should be filled, or false if it should be
908     *                 drawn with a hairline (width == 0)
909     */
910    public boolean getFillPath(Path src, Path dst) {
911        return native_getFillPath(mNativePaint, src.ni(), dst.ni());
912    }
913
914    /**
915     * Get the paint's shader object.
916     *
917     * @return the paint's shader (or null)
918     */
919    public Shader getShader() {
920        return mShader;
921    }
922
923    /**
924     * Set or clear the shader object.
925     * <p />
926     * Pass null to clear any previous shader.
927     * As a convenience, the parameter passed is also returned.
928     *
929     * @param shader May be null. the new shader to be installed in the paint
930     * @return       shader
931     */
932    public Shader setShader(Shader shader) {
933        if (shader != null) {
934            mNativeShader = shader.getNativeInstance();
935        } else {
936            mNativeShader = 0;
937        }
938        native_setShader(mNativePaint, mNativeShader);
939        mShader = shader;
940        return shader;
941    }
942
943    /**
944     * Get the paint's colorfilter (maybe be null).
945     *
946     * @return the paint's colorfilter (maybe be null)
947     */
948    public ColorFilter getColorFilter() {
949        return mColorFilter;
950    }
951
952    /**
953     * Set or clear the paint's colorfilter, returning the parameter.
954     *
955     * @param filter May be null. The new filter to be installed in the paint
956     * @return       filter
957     */
958    public ColorFilter setColorFilter(ColorFilter filter) {
959        long filterNative = 0;
960        if (filter != null)
961            filterNative = filter.native_instance;
962        native_setColorFilter(mNativePaint, filterNative);
963        mColorFilter = filter;
964        return filter;
965    }
966
967    /**
968     * Get the paint's xfermode object.
969     *
970     * @return the paint's xfermode (or null)
971     */
972    public Xfermode getXfermode() {
973        return mXfermode;
974    }
975
976    /**
977     * Set or clear the xfermode object.
978     * <p />
979     * Pass null to clear any previous xfermode.
980     * As a convenience, the parameter passed is also returned.
981     *
982     * @param xfermode May be null. The xfermode to be installed in the paint
983     * @return         xfermode
984     */
985    public Xfermode setXfermode(Xfermode xfermode) {
986        long xfermodeNative = 0;
987        if (xfermode != null)
988            xfermodeNative = xfermode.native_instance;
989        native_setXfermode(mNativePaint, xfermodeNative);
990        mXfermode = xfermode;
991        return xfermode;
992    }
993
994    /**
995     * Get the paint's patheffect object.
996     *
997     * @return the paint's patheffect (or null)
998     */
999    public PathEffect getPathEffect() {
1000        return mPathEffect;
1001    }
1002
1003    /**
1004     * Set or clear the patheffect object.
1005     * <p />
1006     * Pass null to clear any previous patheffect.
1007     * As a convenience, the parameter passed is also returned.
1008     *
1009     * @param effect May be null. The patheffect to be installed in the paint
1010     * @return       effect
1011     */
1012    public PathEffect setPathEffect(PathEffect effect) {
1013        long effectNative = 0;
1014        if (effect != null) {
1015            effectNative = effect.native_instance;
1016        }
1017        native_setPathEffect(mNativePaint, effectNative);
1018        mPathEffect = effect;
1019        return effect;
1020    }
1021
1022    /**
1023     * Get the paint's maskfilter object.
1024     *
1025     * @return the paint's maskfilter (or null)
1026     */
1027    public MaskFilter getMaskFilter() {
1028        return mMaskFilter;
1029    }
1030
1031    /**
1032     * Set or clear the maskfilter object.
1033     * <p />
1034     * Pass null to clear any previous maskfilter.
1035     * As a convenience, the parameter passed is also returned.
1036     *
1037     * @param maskfilter May be null. The maskfilter to be installed in the
1038     *                   paint
1039     * @return           maskfilter
1040     */
1041    public MaskFilter setMaskFilter(MaskFilter maskfilter) {
1042        long maskfilterNative = 0;
1043        if (maskfilter != null) {
1044            maskfilterNative = maskfilter.native_instance;
1045        }
1046        native_setMaskFilter(mNativePaint, maskfilterNative);
1047        mMaskFilter = maskfilter;
1048        return maskfilter;
1049    }
1050
1051    /**
1052     * Get the paint's typeface object.
1053     * <p />
1054     * The typeface object identifies which font to use when drawing or
1055     * measuring text.
1056     *
1057     * @return the paint's typeface (or null)
1058     */
1059    public Typeface getTypeface() {
1060        return mTypeface;
1061    }
1062
1063    /**
1064     * Set or clear the typeface object.
1065     * <p />
1066     * Pass null to clear any previous typeface.
1067     * As a convenience, the parameter passed is also returned.
1068     *
1069     * @param typeface May be null. The typeface to be installed in the paint
1070     * @return         typeface
1071     */
1072    public Typeface setTypeface(Typeface typeface) {
1073        long typefaceNative = 0;
1074        if (typeface != null) {
1075            typefaceNative = typeface.native_instance;
1076        }
1077        native_setTypeface(mNativePaint, typefaceNative);
1078        mTypeface = typeface;
1079        mNativeTypeface = typefaceNative;
1080        return typeface;
1081    }
1082
1083    /**
1084     * Get the paint's rasterizer (or null).
1085     * <p />
1086     * The raster controls/modifies how paths/text are turned into alpha masks.
1087     *
1088     * @return         the paint's rasterizer (or null)
1089     *
1090     *  @deprecated Rasterizer is not supported by either the HW or PDF backends.
1091     */
1092    @Deprecated
1093    public Rasterizer getRasterizer() {
1094        return mRasterizer;
1095    }
1096
1097    /**
1098     * Set or clear the rasterizer object.
1099     * <p />
1100     * Pass null to clear any previous rasterizer.
1101     * As a convenience, the parameter passed is also returned.
1102     *
1103     * @param rasterizer May be null. The new rasterizer to be installed in
1104     *                   the paint.
1105     * @return           rasterizer
1106     *
1107     *  @deprecated Rasterizer is not supported by either the HW or PDF backends.
1108     */
1109    @Deprecated
1110    public Rasterizer setRasterizer(Rasterizer rasterizer) {
1111        long rasterizerNative = 0;
1112        if (rasterizer != null) {
1113            rasterizerNative = rasterizer.native_instance;
1114        }
1115        native_setRasterizer(mNativePaint, rasterizerNative);
1116        mRasterizer = rasterizer;
1117        return rasterizer;
1118    }
1119
1120    /**
1121     * This draws a shadow layer below the main layer, with the specified
1122     * offset and color, and blur radius. If radius is 0, then the shadow
1123     * layer is removed.
1124     * <p>
1125     * Can be used to create a blurred shadow underneath text. Support for use
1126     * with other drawing operations is constrained to the software rendering
1127     * pipeline.
1128     * <p>
1129     * The alpha of the shadow will be the paint's alpha if the shadow color is
1130     * opaque, or the alpha from the shadow color if not.
1131     */
1132    public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
1133      native_setShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
1134    }
1135
1136    /**
1137     * Clear the shadow layer.
1138     */
1139    public void clearShadowLayer() {
1140        setShadowLayer(0, 0, 0, 0);
1141    }
1142
1143    /**
1144     * Checks if the paint has a shadow layer attached
1145     *
1146     * @return true if the paint has a shadow layer attached and false otherwise
1147     * @hide
1148     */
1149    public boolean hasShadowLayer() {
1150      return native_hasShadowLayer(mNativePaint);
1151    }
1152
1153    /**
1154     * Return the paint's Align value for drawing text. This controls how the
1155     * text is positioned relative to its origin. LEFT align means that all of
1156     * the text will be drawn to the right of its origin (i.e. the origin
1157     * specifieds the LEFT edge of the text) and so on.
1158     *
1159     * @return the paint's Align value for drawing text.
1160     */
1161    public Align getTextAlign() {
1162        return sAlignArray[native_getTextAlign(mNativePaint)];
1163    }
1164
1165    /**
1166     * Set the paint's text alignment. This controls how the
1167     * text is positioned relative to its origin. LEFT align means that all of
1168     * the text will be drawn to the right of its origin (i.e. the origin
1169     * specifieds the LEFT edge of the text) and so on.
1170     *
1171     * @param align set the paint's Align value for drawing text.
1172     */
1173    public void setTextAlign(Align align) {
1174        native_setTextAlign(mNativePaint, align.nativeInt);
1175    }
1176
1177    /**
1178     * Get the text Locale.
1179     *
1180     * @return the paint's Locale used for drawing text, never null.
1181     */
1182    public Locale getTextLocale() {
1183        return mLocale;
1184    }
1185
1186    /**
1187     * Set the text locale.
1188     *
1189     * The text locale affects how the text is drawn for some languages.
1190     *
1191     * For example, if the locale is {@link Locale#CHINESE} or {@link Locale#CHINA},
1192     * then the text renderer will prefer to draw text using a Chinese font. Likewise,
1193     * if the locale is {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text
1194     * renderer will prefer to draw text using a Japanese font.
1195     *
1196     * This distinction is important because Chinese and Japanese text both use many
1197     * of the same Unicode code points but their appearance is subtly different for
1198     * each language.
1199     *
1200     * By default, the text locale is initialized to the system locale (as returned
1201     * by {@link Locale#getDefault}). This assumes that the text to be rendered will
1202     * most likely be in the user's preferred language.
1203     *
1204     * If the actual language of the text is known, then it can be provided to the
1205     * text renderer using this method. The text renderer may attempt to guess the
1206     * language script based on the contents of the text to be drawn independent of
1207     * the text locale here. Specifying the text locale just helps it do a better
1208     * job in certain ambiguous cases
1209     *
1210     * @param locale the paint's locale value for drawing text, must not be null.
1211     */
1212    public void setTextLocale(Locale locale) {
1213        if (locale == null) {
1214            throw new IllegalArgumentException("locale cannot be null");
1215        }
1216        if (locale.equals(mLocale)) return;
1217        mLocale = locale;
1218        native_setTextLocale(mNativePaint, locale.toString());
1219    }
1220
1221    /**
1222     * Get the elegant metrics flag.
1223     *
1224     * @return true if elegant metrics are enabled for text drawing.
1225     */
1226    public native boolean isElegantTextHeight();
1227
1228    /**
1229     * Set the paint's elegant height metrics flag. This setting selects font
1230     * variants that have not been compacted to fit Latin-based vertical
1231     * metrics, and also increases top and bottom bounds to provide more space.
1232     *
1233     * @param elegant set the paint's elegant metrics flag for drawing text.
1234     */
1235    public native void setElegantTextHeight(boolean elegant);
1236
1237    /**
1238     * Return the paint's text size.
1239     *
1240     * @return the paint's text size.
1241     */
1242    public native float getTextSize();
1243
1244    /**
1245     * Set the paint's text size. This value must be > 0
1246     *
1247     * @param textSize set the paint's text size.
1248     */
1249    public native void setTextSize(float textSize);
1250
1251    /**
1252     * Return the paint's horizontal scale factor for text. The default value
1253     * is 1.0.
1254     *
1255     * @return the paint's scale factor in X for drawing/measuring text
1256     */
1257    public native float getTextScaleX();
1258
1259    /**
1260     * Set the paint's horizontal scale factor for text. The default value
1261     * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
1262     * stretch the text narrower.
1263     *
1264     * @param scaleX set the paint's scale in X for drawing/measuring text.
1265     */
1266    public native void setTextScaleX(float scaleX);
1267
1268    /**
1269     * Return the paint's horizontal skew factor for text. The default value
1270     * is 0.
1271     *
1272     * @return         the paint's skew factor in X for drawing text.
1273     */
1274    public native float getTextSkewX();
1275
1276    /**
1277     * Set the paint's horizontal skew factor for text. The default value
1278     * is 0. For approximating oblique text, use values around -0.25.
1279     *
1280     * @param skewX set the paint's skew factor in X for drawing text.
1281     */
1282    public native void setTextSkewX(float skewX);
1283
1284    /**
1285     * Return the paint's letter-spacing for text. The default value
1286     * is 0.
1287     *
1288     * @return         the paint's letter-spacing for drawing text.
1289     */
1290    public float getLetterSpacing() {
1291        return native_getLetterSpacing(mNativePaint);
1292    }
1293
1294    /**
1295     * Set the paint's letter-spacing for text. The default value
1296     * is 0.  The value is in 'EM' units.  Typical values for slight
1297     * expansion will be around 0.05.  Negative values tighten text.
1298     *
1299     * @param letterSpacing set the paint's letter-spacing for drawing text.
1300     */
1301    public void setLetterSpacing(float letterSpacing) {
1302        native_setLetterSpacing(mNativePaint, letterSpacing);
1303    }
1304
1305    /**
1306     * Get font feature settings.  Default is null.
1307     *
1308     * @return the paint's currently set font feature settings.
1309     */
1310    public String getFontFeatureSettings() {
1311        return mFontFeatureSettings;
1312    }
1313
1314    /**
1315     * Set font feature settings.
1316     *
1317     * The format is the same as the CSS font-feature-settings attribute:
1318     * http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
1319     *
1320     * @param settings the font feature settings string to use, may be null.
1321     */
1322    public void setFontFeatureSettings(String settings) {
1323        if (settings != null && settings.equals("")) {
1324            settings = null;
1325        }
1326        if ((settings == null && mFontFeatureSettings == null)
1327                || (settings != null && settings.equals(mFontFeatureSettings))) {
1328            return;
1329        }
1330        mFontFeatureSettings = settings;
1331        native_setFontFeatureSettings(mNativePaint, settings);
1332    }
1333
1334    /**
1335     * Return the distance above (negative) the baseline (ascent) based on the
1336     * current typeface and text size.
1337     *
1338     * @return the distance above (negative) the baseline (ascent) based on the
1339     *         current typeface and text size.
1340     */
1341    public native float ascent();
1342
1343    /**
1344     * Return the distance below (positive) the baseline (descent) based on the
1345     * current typeface and text size.
1346     *
1347     * @return the distance below (positive) the baseline (descent) based on
1348     *         the current typeface and text size.
1349     */
1350    public native float descent();
1351
1352    /**
1353     * Class that describes the various metrics for a font at a given text size.
1354     * Remember, Y values increase going down, so those values will be positive,
1355     * and values that measure distances going up will be negative. This class
1356     * is returned by getFontMetrics().
1357     */
1358    public static class FontMetrics {
1359        /**
1360         * The maximum distance above the baseline for the tallest glyph in
1361         * the font at a given text size.
1362         */
1363        public float   top;
1364        /**
1365         * The recommended distance above the baseline for singled spaced text.
1366         */
1367        public float   ascent;
1368        /**
1369         * The recommended distance below the baseline for singled spaced text.
1370         */
1371        public float   descent;
1372        /**
1373         * The maximum distance below the baseline for the lowest glyph in
1374         * the font at a given text size.
1375         */
1376        public float   bottom;
1377        /**
1378         * The recommended additional space to add between lines of text.
1379         */
1380        public float   leading;
1381    }
1382
1383    /**
1384     * Return the font's recommended interline spacing, given the Paint's
1385     * settings for typeface, textSize, etc. If metrics is not null, return the
1386     * fontmetric values in it.
1387     *
1388     * @param metrics If this object is not null, its fields are filled with
1389     *                the appropriate values given the paint's text attributes.
1390     * @return the font's recommended interline spacing.
1391     */
1392    public native float getFontMetrics(FontMetrics metrics);
1393
1394    /**
1395     * Allocates a new FontMetrics object, and then calls getFontMetrics(fm)
1396     * with it, returning the object.
1397     */
1398    public FontMetrics getFontMetrics() {
1399        FontMetrics fm = new FontMetrics();
1400        getFontMetrics(fm);
1401        return fm;
1402    }
1403
1404    /**
1405     * Convenience method for callers that want to have FontMetrics values as
1406     * integers.
1407     */
1408    public static class FontMetricsInt {
1409        public int   top;
1410        public int   ascent;
1411        public int   descent;
1412        public int   bottom;
1413        public int   leading;
1414
1415        @Override public String toString() {
1416            return "FontMetricsInt: top=" + top + " ascent=" + ascent +
1417                    " descent=" + descent + " bottom=" + bottom +
1418                    " leading=" + leading;
1419        }
1420    }
1421
1422    /**
1423     * Return the font's interline spacing, given the Paint's settings for
1424     * typeface, textSize, etc. If metrics is not null, return the fontmetric
1425     * values in it. Note: all values have been converted to integers from
1426     * floats, in such a way has to make the answers useful for both spacing
1427     * and clipping. If you want more control over the rounding, call
1428     * getFontMetrics().
1429     *
1430     * @return the font's interline spacing.
1431     */
1432    public native int getFontMetricsInt(FontMetricsInt fmi);
1433
1434    public FontMetricsInt getFontMetricsInt() {
1435        FontMetricsInt fm = new FontMetricsInt();
1436        getFontMetricsInt(fm);
1437        return fm;
1438    }
1439
1440    /**
1441     * Return the recommend line spacing based on the current typeface and
1442     * text size.
1443     *
1444     * @return  recommend line spacing based on the current typeface and
1445     *          text size.
1446     */
1447    public float getFontSpacing() {
1448        return getFontMetrics(null);
1449    }
1450
1451    /**
1452     * Return the width of the text.
1453     *
1454     * @param text  The text to measure. Cannot be null.
1455     * @param index The index of the first character to start measuring
1456     * @param count THe number of characters to measure, beginning with start
1457     * @return      The width of the text
1458     */
1459    public float measureText(char[] text, int index, int count) {
1460        if (text == null) {
1461            throw new IllegalArgumentException("text cannot be null");
1462        }
1463        if ((index | count) < 0 || index + count > text.length) {
1464            throw new ArrayIndexOutOfBoundsException();
1465        }
1466
1467        if (text.length == 0 || count == 0) {
1468            return 0f;
1469        }
1470        if (!mHasCompatScaling) {
1471            return (float) Math.ceil(native_measureText(text, index, count, mBidiFlags));
1472        }
1473
1474        final float oldSize = getTextSize();
1475        setTextSize(oldSize*mCompatScaling);
1476        float w = native_measureText(text, index, count, mBidiFlags);
1477        setTextSize(oldSize);
1478        return (float) Math.ceil(w*mInvCompatScaling);
1479    }
1480
1481    private native float native_measureText(char[] text, int index, int count, int bidiFlags);
1482
1483    /**
1484     * Return the width of the text.
1485     *
1486     * @param text  The text to measure. Cannot be null.
1487     * @param start The index of the first character to start measuring
1488     * @param end   1 beyond the index of the last character to measure
1489     * @return      The width of the text
1490     */
1491    public float measureText(String text, int start, int end) {
1492        if (text == null) {
1493            throw new IllegalArgumentException("text cannot be null");
1494        }
1495        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1496            throw new IndexOutOfBoundsException();
1497        }
1498
1499        if (text.length() == 0 || start == end) {
1500            return 0f;
1501        }
1502        if (!mHasCompatScaling) {
1503            return (float) Math.ceil(native_measureText(text, start, end, mBidiFlags));
1504        }
1505
1506        final float oldSize = getTextSize();
1507        setTextSize(oldSize*mCompatScaling);
1508        float w = native_measureText(text, start, end, mBidiFlags);
1509        setTextSize(oldSize);
1510        return (float) Math.ceil(w*mInvCompatScaling);
1511    }
1512
1513    private native float native_measureText(String text, int start, int end, int bidiFlags);
1514
1515    /**
1516     * Return the width of the text.
1517     *
1518     * @param text  The text to measure. Cannot be null.
1519     * @return      The width of the text
1520     */
1521    public float measureText(String text) {
1522        if (text == null) {
1523            throw new IllegalArgumentException("text cannot be null");
1524        }
1525
1526        if (text.length() == 0) {
1527            return 0f;
1528        }
1529
1530        if (!mHasCompatScaling) {
1531            return (float) Math.ceil(native_measureText(text, mBidiFlags));
1532        }
1533        final float oldSize = getTextSize();
1534        setTextSize(oldSize*mCompatScaling);
1535        float w = native_measureText(text, mBidiFlags);
1536        setTextSize(oldSize);
1537        return (float) Math.ceil(w*mInvCompatScaling);
1538    }
1539
1540    private native float native_measureText(String text, int bidiFlags);
1541
1542    /**
1543     * Return the width of the text.
1544     *
1545     * @param text  The text to measure
1546     * @param start The index of the first character to start measuring
1547     * @param end   1 beyond the index of the last character to measure
1548     * @return      The width of the text
1549     */
1550    public float measureText(CharSequence text, int start, int end) {
1551        if (text == null) {
1552            throw new IllegalArgumentException("text cannot be null");
1553        }
1554        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1555            throw new IndexOutOfBoundsException();
1556        }
1557
1558        if (text.length() == 0 || start == end) {
1559            return 0f;
1560        }
1561        if (text instanceof String) {
1562            return measureText((String)text, start, end);
1563        }
1564        if (text instanceof SpannedString ||
1565            text instanceof SpannableString) {
1566            return measureText(text.toString(), start, end);
1567        }
1568        if (text instanceof GraphicsOperations) {
1569            return ((GraphicsOperations)text).measureText(start, end, this);
1570        }
1571
1572        char[] buf = TemporaryBuffer.obtain(end - start);
1573        TextUtils.getChars(text, start, end, buf, 0);
1574        float result = measureText(buf, 0, end - start);
1575        TemporaryBuffer.recycle(buf);
1576        return result;
1577    }
1578
1579    /**
1580     * Measure the text, stopping early if the measured width exceeds maxWidth.
1581     * Return the number of chars that were measured, and if measuredWidth is
1582     * not null, return in it the actual width measured.
1583     *
1584     * @param text  The text to measure. Cannot be null.
1585     * @param index The offset into text to begin measuring at
1586     * @param count The number of maximum number of entries to measure. If count
1587     *              is negative, then the characters are measured in reverse order.
1588     * @param maxWidth The maximum width to accumulate.
1589     * @param measuredWidth Optional. If not null, returns the actual width
1590     *                     measured.
1591     * @return The number of chars that were measured. Will always be <=
1592     *         abs(count).
1593     */
1594    public int breakText(char[] text, int index, int count,
1595                                float maxWidth, float[] measuredWidth) {
1596        if (text == null) {
1597            throw new IllegalArgumentException("text cannot be null");
1598        }
1599        if (index < 0 || text.length - index < Math.abs(count)) {
1600            throw new ArrayIndexOutOfBoundsException();
1601        }
1602
1603        if (text.length == 0 || count == 0) {
1604            return 0;
1605        }
1606        if (!mHasCompatScaling) {
1607            return native_breakText(mNativePaint, mNativeTypeface, text, index, count, maxWidth,
1608                    mBidiFlags, measuredWidth);
1609        }
1610
1611        final float oldSize = getTextSize();
1612        setTextSize(oldSize * mCompatScaling);
1613        int res = native_breakText(mNativePaint, mNativeTypeface, text, index, count,
1614                maxWidth * mCompatScaling, mBidiFlags, measuredWidth);
1615        setTextSize(oldSize);
1616        if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
1617        return res;
1618    }
1619
1620    private static native int native_breakText(long native_object, long native_typeface,
1621                                               char[] text, int index, int count,
1622                                               float maxWidth, int bidiFlags, float[] measuredWidth);
1623
1624    /**
1625     * Measure the text, stopping early if the measured width exceeds maxWidth.
1626     * Return the number of chars that were measured, and if measuredWidth is
1627     * not null, return in it the actual width measured.
1628     *
1629     * @param text  The text to measure. Cannot be null.
1630     * @param start The offset into text to begin measuring at
1631     * @param end   The end of the text slice to measure.
1632     * @param measureForwards If true, measure forwards, starting at start.
1633     *                        Otherwise, measure backwards, starting with end.
1634     * @param maxWidth The maximum width to accumulate.
1635     * @param measuredWidth Optional. If not null, returns the actual width
1636     *                     measured.
1637     * @return The number of chars that were measured. Will always be <=
1638     *         abs(end - start).
1639     */
1640    public int breakText(CharSequence text, int start, int end,
1641                         boolean measureForwards,
1642                         float maxWidth, float[] measuredWidth) {
1643        if (text == null) {
1644            throw new IllegalArgumentException("text cannot be null");
1645        }
1646        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1647            throw new IndexOutOfBoundsException();
1648        }
1649
1650        if (text.length() == 0 || start == end) {
1651            return 0;
1652        }
1653        if (start == 0 && text instanceof String && end == text.length()) {
1654            return breakText((String) text, measureForwards, maxWidth,
1655                             measuredWidth);
1656        }
1657
1658        char[] buf = TemporaryBuffer.obtain(end - start);
1659        int result;
1660
1661        TextUtils.getChars(text, start, end, buf, 0);
1662
1663        if (measureForwards) {
1664            result = breakText(buf, 0, end - start, maxWidth, measuredWidth);
1665        } else {
1666            result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth);
1667        }
1668
1669        TemporaryBuffer.recycle(buf);
1670        return result;
1671    }
1672
1673    /**
1674     * Measure the text, stopping early if the measured width exceeds maxWidth.
1675     * Return the number of chars that were measured, and if measuredWidth is
1676     * not null, return in it the actual width measured.
1677     *
1678     * @param text  The text to measure. Cannot be null.
1679     * @param measureForwards If true, measure forwards, starting with the
1680     *                        first character in the string. Otherwise,
1681     *                        measure backwards, starting with the
1682     *                        last character in the string.
1683     * @param maxWidth The maximum width to accumulate.
1684     * @param measuredWidth Optional. If not null, returns the actual width
1685     *                     measured.
1686     * @return The number of chars that were measured. Will always be <=
1687     *         abs(count).
1688     */
1689    public int breakText(String text, boolean measureForwards,
1690                                float maxWidth, float[] measuredWidth) {
1691        if (text == null) {
1692            throw new IllegalArgumentException("text cannot be null");
1693        }
1694
1695        if (text.length() == 0) {
1696            return 0;
1697        }
1698        if (!mHasCompatScaling) {
1699            return native_breakText(mNativePaint, mNativeTypeface, text, measureForwards,
1700                    maxWidth, mBidiFlags, measuredWidth);
1701        }
1702
1703        final float oldSize = getTextSize();
1704        setTextSize(oldSize*mCompatScaling);
1705        int res = native_breakText(mNativePaint, mNativeTypeface, text, measureForwards,
1706                maxWidth*mCompatScaling, mBidiFlags, measuredWidth);
1707        setTextSize(oldSize);
1708        if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
1709        return res;
1710    }
1711
1712    private static native int native_breakText(long native_object, long native_typeface,
1713                                        String text, boolean measureForwards,
1714                                        float maxWidth, int bidiFlags, float[] measuredWidth);
1715
1716    /**
1717     * Return the advance widths for the characters in the string.
1718     *
1719     * @param text     The text to measure. Cannot be null.
1720     * @param index    The index of the first char to to measure
1721     * @param count    The number of chars starting with index to measure
1722     * @param widths   array to receive the advance widths of the characters.
1723     *                 Must be at least a large as count.
1724     * @return         the actual number of widths returned.
1725     */
1726    public int getTextWidths(char[] text, int index, int count,
1727                             float[] widths) {
1728        if (text == null) {
1729            throw new IllegalArgumentException("text cannot be null");
1730        }
1731        if ((index | count) < 0 || index + count > text.length
1732                || count > widths.length) {
1733            throw new ArrayIndexOutOfBoundsException();
1734        }
1735
1736        if (text.length == 0 || count == 0) {
1737            return 0;
1738        }
1739        if (!mHasCompatScaling) {
1740            return native_getTextWidths(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags, widths);
1741        }
1742
1743        final float oldSize = getTextSize();
1744        setTextSize(oldSize*mCompatScaling);
1745        int res = native_getTextWidths(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags, widths);
1746        setTextSize(oldSize);
1747        for (int i=0; i<res; i++) {
1748            widths[i] *= mInvCompatScaling;
1749        }
1750        return res;
1751    }
1752
1753    /**
1754     * Return the advance widths for the characters in the string.
1755     *
1756     * @param text     The text to measure. Cannot be null.
1757     * @param start    The index of the first char to to measure
1758     * @param end      The end of the text slice to measure
1759     * @param widths   array to receive the advance widths of the characters.
1760     *                 Must be at least a large as (end - start).
1761     * @return         the actual number of widths returned.
1762     */
1763    public int getTextWidths(CharSequence text, int start, int end,
1764                             float[] widths) {
1765        if (text == null) {
1766            throw new IllegalArgumentException("text cannot be null");
1767        }
1768        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1769            throw new IndexOutOfBoundsException();
1770        }
1771        if (end - start > widths.length) {
1772            throw new ArrayIndexOutOfBoundsException();
1773        }
1774
1775        if (text.length() == 0 || start == end) {
1776            return 0;
1777        }
1778        if (text instanceof String) {
1779            return getTextWidths((String) text, start, end, widths);
1780        }
1781        if (text instanceof SpannedString ||
1782            text instanceof SpannableString) {
1783            return getTextWidths(text.toString(), start, end, widths);
1784        }
1785        if (text instanceof GraphicsOperations) {
1786            return ((GraphicsOperations) text).getTextWidths(start, end,
1787                                                                 widths, this);
1788        }
1789
1790        char[] buf = TemporaryBuffer.obtain(end - start);
1791        TextUtils.getChars(text, start, end, buf, 0);
1792        int result = getTextWidths(buf, 0, end - start, widths);
1793        TemporaryBuffer.recycle(buf);
1794        return result;
1795    }
1796
1797    /**
1798     * Return the advance widths for the characters in the string.
1799     *
1800     * @param text   The text to measure. Cannot be null.
1801     * @param start  The index of the first char to to measure
1802     * @param end    The end of the text slice to measure
1803     * @param widths array to receive the advance widths of the characters.
1804     *               Must be at least a large as the text.
1805     * @return       the number of unichars in the specified text.
1806     */
1807    public int getTextWidths(String text, int start, int end, float[] widths) {
1808        if (text == null) {
1809            throw new IllegalArgumentException("text cannot be null");
1810        }
1811        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1812            throw new IndexOutOfBoundsException();
1813        }
1814        if (end - start > widths.length) {
1815            throw new ArrayIndexOutOfBoundsException();
1816        }
1817
1818        if (text.length() == 0 || start == end) {
1819            return 0;
1820        }
1821        if (!mHasCompatScaling) {
1822            return native_getTextWidths(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, widths);
1823        }
1824
1825        final float oldSize = getTextSize();
1826        setTextSize(oldSize*mCompatScaling);
1827        int res = native_getTextWidths(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, widths);
1828        setTextSize(oldSize);
1829        for (int i=0; i<res; i++) {
1830            widths[i] *= mInvCompatScaling;
1831        }
1832        return res;
1833    }
1834
1835    /**
1836     * Return the advance widths for the characters in the string.
1837     *
1838     * @param text   The text to measure
1839     * @param widths array to receive the advance widths of the characters.
1840     *               Must be at least a large as the text.
1841     * @return       the number of unichars in the specified text.
1842     */
1843    public int getTextWidths(String text, float[] widths) {
1844        return getTextWidths(text, 0, text.length(), widths);
1845    }
1846
1847    /**
1848     * Convenience overload that takes a char array instead of a
1849     * String.
1850     *
1851     * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int)
1852     * @hide
1853     */
1854    public float getTextRunAdvances(char[] chars, int index, int count,
1855            int contextIndex, int contextCount, boolean isRtl, float[] advances,
1856            int advancesIndex) {
1857
1858        if (chars == null) {
1859            throw new IllegalArgumentException("text cannot be null");
1860        }
1861        if ((index | count | contextIndex | contextCount | advancesIndex
1862                | (index - contextIndex) | (contextCount - count)
1863                | ((contextIndex + contextCount) - (index + count))
1864                | (chars.length - (contextIndex + contextCount))
1865                | (advances == null ? 0 :
1866                    (advances.length - (advancesIndex + count)))) < 0) {
1867            throw new IndexOutOfBoundsException();
1868        }
1869
1870        if (chars.length == 0 || count == 0){
1871            return 0f;
1872        }
1873        if (!mHasCompatScaling) {
1874            return native_getTextRunAdvances(mNativePaint, mNativeTypeface, chars, index, count,
1875                    contextIndex, contextCount, isRtl, advances, advancesIndex);
1876        }
1877
1878        final float oldSize = getTextSize();
1879        setTextSize(oldSize * mCompatScaling);
1880        float res = native_getTextRunAdvances(mNativePaint, mNativeTypeface, chars, index, count,
1881                contextIndex, contextCount, isRtl, advances, advancesIndex);
1882        setTextSize(oldSize);
1883
1884        if (advances != null) {
1885            for (int i = advancesIndex, e = i + count; i < e; i++) {
1886                advances[i] *= mInvCompatScaling;
1887            }
1888        }
1889        return res * mInvCompatScaling; // assume errors are not significant
1890    }
1891
1892    /**
1893     * Convenience overload that takes a CharSequence instead of a
1894     * String.
1895     *
1896     * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int)
1897     * @hide
1898     */
1899    public float getTextRunAdvances(CharSequence text, int start, int end,
1900            int contextStart, int contextEnd, boolean isRtl, float[] advances,
1901            int advancesIndex) {
1902
1903        if (text == null) {
1904            throw new IllegalArgumentException("text cannot be null");
1905        }
1906        if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
1907                | (start - contextStart) | (contextEnd - end)
1908                | (text.length() - contextEnd)
1909                | (advances == null ? 0 :
1910                    (advances.length - advancesIndex - (end - start)))) < 0) {
1911            throw new IndexOutOfBoundsException();
1912        }
1913
1914        if (text instanceof String) {
1915            return getTextRunAdvances((String) text, start, end,
1916                    contextStart, contextEnd, isRtl, advances, advancesIndex);
1917        }
1918        if (text instanceof SpannedString ||
1919            text instanceof SpannableString) {
1920            return getTextRunAdvances(text.toString(), start, end,
1921                    contextStart, contextEnd, isRtl, advances, advancesIndex);
1922        }
1923        if (text instanceof GraphicsOperations) {
1924            return ((GraphicsOperations) text).getTextRunAdvances(start, end,
1925                    contextStart, contextEnd, isRtl, advances, advancesIndex, this);
1926        }
1927        if (text.length() == 0 || end == start) {
1928            return 0f;
1929        }
1930
1931        int contextLen = contextEnd - contextStart;
1932        int len = end - start;
1933        char[] buf = TemporaryBuffer.obtain(contextLen);
1934        TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
1935        float result = getTextRunAdvances(buf, start - contextStart, len,
1936                0, contextLen, isRtl, advances, advancesIndex);
1937        TemporaryBuffer.recycle(buf);
1938        return result;
1939    }
1940
1941    /**
1942     * Returns the total advance width for the characters in the run
1943     * between start and end, and if advances is not null, the advance
1944     * assigned to each of these characters (java chars).
1945     *
1946     * <p>The trailing surrogate in a valid surrogate pair is assigned
1947     * an advance of 0.  Thus the number of returned advances is
1948     * always equal to count, not to the number of unicode codepoints
1949     * represented by the run.
1950     *
1951     * <p>In the case of conjuncts or combining marks, the total
1952     * advance is assigned to the first logical character, and the
1953     * following characters are assigned an advance of 0.
1954     *
1955     * <p>This generates the sum of the advances of glyphs for
1956     * characters in a reordered cluster as the width of the first
1957     * logical character in the cluster, and 0 for the widths of all
1958     * other characters in the cluster.  In effect, such clusters are
1959     * treated like conjuncts.
1960     *
1961     * <p>The shaping bounds limit the amount of context available
1962     * outside start and end that can be used for shaping analysis.
1963     * These bounds typically reflect changes in bidi level or font
1964     * metrics across which shaping does not occur.
1965     *
1966     * @param text the text to measure. Cannot be null.
1967     * @param start the index of the first character to measure
1968     * @param end the index past the last character to measure
1969     * @param contextStart the index of the first character to use for shaping context,
1970     * must be <= start
1971     * @param contextEnd the index past the last character to use for shaping context,
1972     * must be >= end
1973     * @param isRtl whether the run is in RTL direction
1974     * @param advances array to receive the advances, must have room for all advances,
1975     * can be null if only total advance is needed
1976     * @param advancesIndex the position in advances at which to put the
1977     * advance corresponding to the character at start
1978     * @return the total advance
1979     *
1980     * @hide
1981     */
1982    public float getTextRunAdvances(String text, int start, int end, int contextStart,
1983            int contextEnd, boolean isRtl, float[] advances, int advancesIndex) {
1984
1985        if (text == null) {
1986            throw new IllegalArgumentException("text cannot be null");
1987        }
1988        if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
1989                | (start - contextStart) | (contextEnd - end)
1990                | (text.length() - contextEnd)
1991                | (advances == null ? 0 :
1992                    (advances.length - advancesIndex - (end - start)))) < 0) {
1993            throw new IndexOutOfBoundsException();
1994        }
1995
1996        if (text.length() == 0 || start == end) {
1997            return 0f;
1998        }
1999
2000        if (!mHasCompatScaling) {
2001            return native_getTextRunAdvances(mNativePaint, mNativeTypeface, text, start, end,
2002                    contextStart, contextEnd, isRtl, advances, advancesIndex);
2003        }
2004
2005        final float oldSize = getTextSize();
2006        setTextSize(oldSize * mCompatScaling);
2007        float totalAdvance = native_getTextRunAdvances(mNativePaint, mNativeTypeface, text, start, end,
2008                contextStart, contextEnd, isRtl, advances, advancesIndex);
2009        setTextSize(oldSize);
2010
2011        if (advances != null) {
2012            for (int i = advancesIndex, e = i + (end - start); i < e; i++) {
2013                advances[i] *= mInvCompatScaling;
2014            }
2015        }
2016        return totalAdvance * mInvCompatScaling; // assume errors are insignificant
2017    }
2018
2019    /**
2020     * Returns the next cursor position in the run.  This avoids placing the
2021     * cursor between surrogates, between characters that form conjuncts,
2022     * between base characters and combining marks, or within a reordering
2023     * cluster.
2024     *
2025     * <p>ContextStart and offset are relative to the start of text.
2026     * The context is the shaping context for cursor movement, generally
2027     * the bounds of the metric span enclosing the cursor in the direction of
2028     * movement.
2029     *
2030     * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
2031     * cursor position, this returns -1.  Otherwise this will never return a
2032     * value before contextStart or after contextStart + contextLength.
2033     *
2034     * @param text the text
2035     * @param contextStart the start of the context
2036     * @param contextLength the length of the context
2037     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
2038     * @param offset the cursor position to move from
2039     * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
2040     * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
2041     * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
2042     * @return the offset of the next position, or -1
2043     * @hide
2044     */
2045    public int getTextRunCursor(char[] text, int contextStart, int contextLength,
2046            int dir, int offset, int cursorOpt) {
2047        int contextEnd = contextStart + contextLength;
2048        if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
2049                | (offset - contextStart) | (contextEnd - offset)
2050                | (text.length - contextEnd) | cursorOpt) < 0)
2051                || cursorOpt > CURSOR_OPT_MAX_VALUE) {
2052            throw new IndexOutOfBoundsException();
2053        }
2054
2055        return native_getTextRunCursor(mNativePaint, text,
2056                contextStart, contextLength, dir, offset, cursorOpt);
2057    }
2058
2059    /**
2060     * Returns the next cursor position in the run.  This avoids placing the
2061     * cursor between surrogates, between characters that form conjuncts,
2062     * between base characters and combining marks, or within a reordering
2063     * cluster.
2064     *
2065     * <p>ContextStart, contextEnd, and offset are relative to the start of
2066     * text.  The context is the shaping context for cursor movement, generally
2067     * the bounds of the metric span enclosing the cursor in the direction of
2068     * movement.
2069     *
2070     * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
2071     * cursor position, this returns -1.  Otherwise this will never return a
2072     * value before contextStart or after contextEnd.
2073     *
2074     * @param text the text
2075     * @param contextStart the start of the context
2076     * @param contextEnd the end of the context
2077     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
2078     * @param offset the cursor position to move from
2079     * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
2080     * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
2081     * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
2082     * @return the offset of the next position, or -1
2083     * @hide
2084     */
2085    public int getTextRunCursor(CharSequence text, int contextStart,
2086           int contextEnd, int dir, int offset, int cursorOpt) {
2087
2088        if (text instanceof String || text instanceof SpannedString ||
2089                text instanceof SpannableString) {
2090            return getTextRunCursor(text.toString(), contextStart, contextEnd,
2091                    dir, offset, cursorOpt);
2092        }
2093        if (text instanceof GraphicsOperations) {
2094            return ((GraphicsOperations) text).getTextRunCursor(
2095                    contextStart, contextEnd, dir, offset, cursorOpt, this);
2096        }
2097
2098        int contextLen = contextEnd - contextStart;
2099        char[] buf = TemporaryBuffer.obtain(contextLen);
2100        TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
2101        int result = getTextRunCursor(buf, 0, contextLen, dir, offset - contextStart, cursorOpt);
2102        TemporaryBuffer.recycle(buf);
2103        return result;
2104    }
2105
2106    /**
2107     * Returns the next cursor position in the run.  This avoids placing the
2108     * cursor between surrogates, between characters that form conjuncts,
2109     * between base characters and combining marks, or within a reordering
2110     * cluster.
2111     *
2112     * <p>ContextStart, contextEnd, and offset are relative to the start of
2113     * text.  The context is the shaping context for cursor movement, generally
2114     * the bounds of the metric span enclosing the cursor in the direction of
2115     * movement.
2116     *
2117     * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
2118     * cursor position, this returns -1.  Otherwise this will never return a
2119     * value before contextStart or after contextEnd.
2120     *
2121     * @param text the text
2122     * @param contextStart the start of the context
2123     * @param contextEnd the end of the context
2124     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
2125     * @param offset the cursor position to move from
2126     * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
2127     * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
2128     * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
2129     * @return the offset of the next position, or -1
2130     * @hide
2131     */
2132    public int getTextRunCursor(String text, int contextStart, int contextEnd,
2133            int dir, int offset, int cursorOpt) {
2134        if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
2135                | (offset - contextStart) | (contextEnd - offset)
2136                | (text.length() - contextEnd) | cursorOpt) < 0)
2137                || cursorOpt > CURSOR_OPT_MAX_VALUE) {
2138            throw new IndexOutOfBoundsException();
2139        }
2140
2141        return native_getTextRunCursor(mNativePaint, text,
2142                contextStart, contextEnd, dir, offset, cursorOpt);
2143    }
2144
2145    /**
2146     * Return the path (outline) for the specified text.
2147     * Note: just like Canvas.drawText, this will respect the Align setting in
2148     * the paint.
2149     *
2150     * @param text     The text to retrieve the path from
2151     * @param index    The index of the first character in text
2152     * @param count    The number of characterss starting with index
2153     * @param x        The x coordinate of the text's origin
2154     * @param y        The y coordinate of the text's origin
2155     * @param path     The path to receive the data describing the text. Must
2156     *                 be allocated by the caller.
2157     */
2158    public void getTextPath(char[] text, int index, int count,
2159                            float x, float y, Path path) {
2160        if ((index | count) < 0 || index + count > text.length) {
2161            throw new ArrayIndexOutOfBoundsException();
2162        }
2163        native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, index, count, x, y,
2164                path.ni());
2165    }
2166
2167    /**
2168     * Return the path (outline) for the specified text.
2169     * Note: just like Canvas.drawText, this will respect the Align setting
2170     * in the paint.
2171     *
2172     * @param text  The text to retrieve the path from
2173     * @param start The first character in the text
2174     * @param end   1 past the last charcter in the text
2175     * @param x     The x coordinate of the text's origin
2176     * @param y     The y coordinate of the text's origin
2177     * @param path  The path to receive the data describing the text. Must
2178     *              be allocated by the caller.
2179     */
2180    public void getTextPath(String text, int start, int end,
2181                            float x, float y, Path path) {
2182        if ((start | end | (end - start) | (text.length() - end)) < 0) {
2183            throw new IndexOutOfBoundsException();
2184        }
2185        native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y,
2186                path.ni());
2187    }
2188
2189    /**
2190     * Return in bounds (allocated by the caller) the smallest rectangle that
2191     * encloses all of the characters, with an implied origin at (0,0).
2192     *
2193     * @param text  String to measure and return its bounds
2194     * @param start Index of the first char in the string to measure
2195     * @param end   1 past the last char in the string measure
2196     * @param bounds Returns the unioned bounds of all the text. Must be
2197     *               allocated by the caller.
2198     */
2199    public void getTextBounds(String text, int start, int end, Rect bounds) {
2200        if ((start | end | (end - start) | (text.length() - end)) < 0) {
2201            throw new IndexOutOfBoundsException();
2202        }
2203        if (bounds == null) {
2204            throw new NullPointerException("need bounds Rect");
2205        }
2206        nativeGetStringBounds(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, bounds);
2207    }
2208
2209    /**
2210     * Return in bounds (allocated by the caller) the smallest rectangle that
2211     * encloses all of the characters, with an implied origin at (0,0).
2212     *
2213     * @param text  Array of chars to measure and return their unioned bounds
2214     * @param index Index of the first char in the array to measure
2215     * @param count The number of chars, beginning at index, to measure
2216     * @param bounds Returns the unioned bounds of all the text. Must be
2217     *               allocated by the caller.
2218     */
2219    public void getTextBounds(char[] text, int index, int count, Rect bounds) {
2220        if ((index | count) < 0 || index + count > text.length) {
2221            throw new ArrayIndexOutOfBoundsException();
2222        }
2223        if (bounds == null) {
2224            throw new NullPointerException("need bounds Rect");
2225        }
2226        nativeGetCharArrayBounds(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags,
2227            bounds);
2228    }
2229
2230    @Override
2231    protected void finalize() throws Throwable {
2232        try {
2233            finalizer(mNativePaint);
2234        } finally {
2235            super.finalize();
2236        }
2237    }
2238
2239    private static native long native_init();
2240    private static native long native_initWithPaint(long paint);
2241    private static native void native_reset(long native_object);
2242    private static native void native_set(long native_dst, long native_src);
2243    private static native int native_getStyle(long native_object);
2244    private static native void native_setStyle(long native_object, int style);
2245    private static native int native_getStrokeCap(long native_object);
2246    private static native void native_setStrokeCap(long native_object, int cap);
2247    private static native int native_getStrokeJoin(long native_object);
2248    private static native void native_setStrokeJoin(long native_object,
2249                                                    int join);
2250    private static native boolean native_getFillPath(long native_object,
2251                                                     long src, long dst);
2252    private static native long native_setShader(long native_object, long shader);
2253    private static native long native_setColorFilter(long native_object,
2254                                                    long filter);
2255    private static native long native_setXfermode(long native_object,
2256                                                  long xfermode);
2257    private static native long native_setPathEffect(long native_object,
2258                                                    long effect);
2259    private static native long native_setMaskFilter(long native_object,
2260                                                    long maskfilter);
2261    private static native long native_setTypeface(long native_object,
2262                                                  long typeface);
2263    private static native long native_setRasterizer(long native_object,
2264                                                   long rasterizer);
2265
2266    private static native int native_getTextAlign(long native_object);
2267    private static native void native_setTextAlign(long native_object,
2268                                                   int align);
2269
2270    private static native void native_setTextLocale(long native_object,
2271                                                    String locale);
2272
2273    private static native int native_getTextWidths(long native_object, long native_typeface,
2274                            char[] text, int index, int count, int bidiFlags, float[] widths);
2275    private static native int native_getTextWidths(long native_object, long native_typeface,
2276                            String text, int start, int end, int bidiFlags, float[] widths);
2277
2278    private static native int native_getTextGlyphs(long native_object,
2279            String text, int start, int end, int contextStart, int contextEnd,
2280            int flags, char[] glyphs);
2281
2282    private static native float native_getTextRunAdvances(long native_object, long native_typeface,
2283            char[] text, int index, int count, int contextIndex, int contextCount,
2284            boolean isRtl, float[] advances, int advancesIndex);
2285    private static native float native_getTextRunAdvances(long native_object, long native_typeface,
2286            String text, int start, int end, int contextStart, int contextEnd,
2287            boolean isRtl, float[] advances, int advancesIndex);
2288
2289    private native int native_getTextRunCursor(long native_object, char[] text,
2290            int contextStart, int contextLength, int dir, int offset, int cursorOpt);
2291    private native int native_getTextRunCursor(long native_object, String text,
2292            int contextStart, int contextEnd, int dir, int offset, int cursorOpt);
2293
2294    private static native void native_getTextPath(long native_object, long native_typeface,
2295            int bidiFlags, char[] text, int index, int count, float x, float y, long path);
2296    private static native void native_getTextPath(long native_object, long native_typeface,
2297            int bidiFlags, String text, int start, int end, float x, float y, long path);
2298    private static native void nativeGetStringBounds(long nativePaint, long native_typeface,
2299                                String text, int start, int end, int bidiFlags, Rect bounds);
2300    private static native void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
2301                                char[] text, int index, int count, int bidiFlags, Rect bounds);
2302    private static native void finalizer(long nativePaint);
2303
2304    private static native void native_setShadowLayer(long native_object,
2305            float radius, float dx, float dy, int color);
2306    private static native boolean native_hasShadowLayer(long native_object);
2307
2308    private static native float native_getLetterSpacing(long native_object);
2309    private static native void native_setLetterSpacing(long native_object,
2310                                                       float letterSpacing);
2311    private static native void native_setFontFeatureSettings(long native_object,
2312                                                             String settings);
2313}
2314