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