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