Home | History | Annotate | Download | only in drawable
      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.drawable;
     18 
     19 import android.annotation.ColorInt;
     20 import android.annotation.NonNull;
     21 import android.annotation.Nullable;
     22 import android.content.res.ColorStateList;
     23 import android.content.res.Resources;
     24 import android.content.res.Resources.Theme;
     25 import android.content.res.TypedArray;
     26 import android.graphics.Bitmap;
     27 import android.graphics.BitmapFactory;
     28 import android.graphics.Canvas;
     29 import android.graphics.Color;
     30 import android.graphics.ColorFilter;
     31 import android.graphics.Insets;
     32 import android.graphics.NinePatch;
     33 import android.graphics.Outline;
     34 import android.graphics.PixelFormat;
     35 import android.graphics.PorterDuff;
     36 import android.graphics.PorterDuff.Mode;
     37 import android.graphics.PorterDuffColorFilter;
     38 import android.graphics.Rect;
     39 import android.graphics.Region;
     40 import android.graphics.Xfermode;
     41 import android.os.Trace;
     42 import android.util.AttributeSet;
     43 import android.util.DisplayMetrics;
     44 import android.util.StateSet;
     45 import android.util.TypedValue;
     46 import android.util.Xml;
     47 import android.view.View;
     48 
     49 import org.xmlpull.v1.XmlPullParser;
     50 import org.xmlpull.v1.XmlPullParserException;
     51 
     52 import java.io.IOException;
     53 import java.io.InputStream;
     54 import java.lang.ref.WeakReference;
     55 import java.util.Arrays;
     56 import java.util.Collection;
     57 
     58 /**
     59  * A Drawable is a general abstraction for "something that can be drawn."  Most
     60  * often you will deal with Drawable as the type of resource retrieved for
     61  * drawing things to the screen; the Drawable class provides a generic API for
     62  * dealing with an underlying visual resource that may take a variety of forms.
     63  * Unlike a {@link android.view.View}, a Drawable does not have any facility to
     64  * receive events or otherwise interact with the user.
     65  *
     66  * <p>In addition to simple drawing, Drawable provides a number of generic
     67  * mechanisms for its client to interact with what is being drawn:
     68  *
     69  * <ul>
     70  *     <li> The {@link #setBounds} method <var>must</var> be called to tell the
     71  *     Drawable where it is drawn and how large it should be.  All Drawables
     72  *     should respect the requested size, often simply by scaling their
     73  *     imagery.  A client can find the preferred size for some Drawables with
     74  *     the {@link #getIntrinsicHeight} and {@link #getIntrinsicWidth} methods.
     75  *
     76  *     <li> The {@link #getPadding} method can return from some Drawables
     77  *     information about how to frame content that is placed inside of them.
     78  *     For example, a Drawable that is intended to be the frame for a button
     79  *     widget would need to return padding that correctly places the label
     80  *     inside of itself.
     81  *
     82  *     <li> The {@link #setState} method allows the client to tell the Drawable
     83  *     in which state it is to be drawn, such as "focused", "selected", etc.
     84  *     Some drawables may modify their imagery based on the selected state.
     85  *
     86  *     <li> The {@link #setLevel} method allows the client to supply a single
     87  *     continuous controller that can modify the Drawable is displayed, such as
     88  *     a battery level or progress level.  Some drawables may modify their
     89  *     imagery based on the current level.
     90  *
     91  *     <li> A Drawable can perform animations by calling back to its client
     92  *     through the {@link Callback} interface.  All clients should support this
     93  *     interface (via {@link #setCallback}) so that animations will work.  A
     94  *     simple way to do this is through the system facilities such as
     95  *     {@link android.view.View#setBackground(Drawable)} and
     96  *     {@link android.widget.ImageView}.
     97  * </ul>
     98  *
     99  * Though usually not visible to the application, Drawables may take a variety
    100  * of forms:
    101  *
    102  * <ul>
    103  *     <li> <b>Bitmap</b>: the simplest Drawable, a PNG or JPEG image.
    104  *     <li> <b>Nine Patch</b>: an extension to the PNG format allows it to
    105  *     specify information about how to stretch it and place things inside of
    106  *     it.
    107  *     <li> <b>Shape</b>: contains simple drawing commands instead of a raw
    108  *     bitmap, allowing it to resize better in some cases.
    109  *     <li> <b>Layers</b>: a compound drawable, which draws multiple underlying
    110  *     drawables on top of each other.
    111  *     <li> <b>States</b>: a compound drawable that selects one of a set of
    112  *     drawables based on its state.
    113  *     <li> <b>Levels</b>: a compound drawable that selects one of a set of
    114  *     drawables based on its level.
    115  *     <li> <b>Scale</b>: a compound drawable with a single child drawable,
    116  *     whose overall size is modified based on the current level.
    117  * </ul>
    118  *
    119  * <div class="special reference">
    120  * <h3>Developer Guides</h3>
    121  * <p>For more information about how to use drawables, read the
    122  * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html">Canvas and Drawables</a> developer
    123  * guide. For information and examples of creating drawable resources (XML or bitmap files that
    124  * can be loaded in code), read the
    125  * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>
    126  * document.</p></div>
    127  */
    128 public abstract class Drawable {
    129     private static final Rect ZERO_BOUNDS_RECT = new Rect();
    130 
    131     static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
    132 
    133     private int[] mStateSet = StateSet.WILD_CARD;
    134     private int mLevel = 0;
    135     private int mChangingConfigurations = 0;
    136     private Rect mBounds = ZERO_BOUNDS_RECT;  // lazily becomes a new Rect()
    137     private WeakReference<Callback> mCallback = null;
    138     private boolean mVisible = true;
    139 
    140     private int mLayoutDirection;
    141 
    142     /**
    143      * Draw in its bounds (set via setBounds) respecting optional effects such
    144      * as alpha (set via setAlpha) and color filter (set via setColorFilter).
    145      *
    146      * @param canvas The canvas to draw into
    147      */
    148     public abstract void draw(Canvas canvas);
    149 
    150     /**
    151      * Specify a bounding rectangle for the Drawable. This is where the drawable
    152      * will draw when its draw() method is called.
    153      */
    154     public void setBounds(int left, int top, int right, int bottom) {
    155         Rect oldBounds = mBounds;
    156 
    157         if (oldBounds == ZERO_BOUNDS_RECT) {
    158             oldBounds = mBounds = new Rect();
    159         }
    160 
    161         if (oldBounds.left != left || oldBounds.top != top ||
    162                 oldBounds.right != right || oldBounds.bottom != bottom) {
    163             if (!oldBounds.isEmpty()) {
    164                 // first invalidate the previous bounds
    165                 invalidateSelf();
    166             }
    167             mBounds.set(left, top, right, bottom);
    168             onBoundsChange(mBounds);
    169         }
    170     }
    171 
    172     /**
    173      * Specify a bounding rectangle for the Drawable. This is where the drawable
    174      * will draw when its draw() method is called.
    175      */
    176     public void setBounds(Rect bounds) {
    177         setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
    178     }
    179 
    180     /**
    181      * Return a copy of the drawable's bounds in the specified Rect (allocated
    182      * by the caller). The bounds specify where this will draw when its draw()
    183      * method is called.
    184      *
    185      * @param bounds Rect to receive the drawable's bounds (allocated by the
    186      *               caller).
    187      */
    188     public final void copyBounds(Rect bounds) {
    189         bounds.set(mBounds);
    190     }
    191 
    192     /**
    193      * Return a copy of the drawable's bounds in a new Rect. This returns the
    194      * same values as getBounds(), but the returned object is guaranteed to not
    195      * be changed later by the drawable (i.e. it retains no reference to this
    196      * rect). If the caller already has a Rect allocated, call copyBounds(rect).
    197      *
    198      * @return A copy of the drawable's bounds
    199      */
    200     public final Rect copyBounds() {
    201         return new Rect(mBounds);
    202     }
    203 
    204     /**
    205      * Return the drawable's bounds Rect. Note: for efficiency, the returned
    206      * object may be the same object stored in the drawable (though this is not
    207      * guaranteed), so if a persistent copy of the bounds is needed, call
    208      * copyBounds(rect) instead.
    209      * You should also not change the object returned by this method as it may
    210      * be the same object stored in the drawable.
    211      *
    212      * @return The bounds of the drawable (which may change later, so caller
    213      *         beware). DO NOT ALTER the returned object as it may change the
    214      *         stored bounds of this drawable.
    215      *
    216      * @see #copyBounds()
    217      * @see #copyBounds(android.graphics.Rect)
    218      */
    219     public final Rect getBounds() {
    220         if (mBounds == ZERO_BOUNDS_RECT) {
    221             mBounds = new Rect();
    222         }
    223 
    224         return mBounds;
    225     }
    226 
    227     /**
    228      * Return the drawable's dirty bounds Rect. Note: for efficiency, the
    229      * returned object may be the same object stored in the drawable (though
    230      * this is not guaranteed).
    231      * <p>
    232      * By default, this returns the full drawable bounds. Custom drawables may
    233      * override this method to perform more precise invalidation.
    234      *
    235      * @return The dirty bounds of this drawable
    236      */
    237     public Rect getDirtyBounds() {
    238         return getBounds();
    239     }
    240 
    241     /**
    242      * Set a mask of the configuration parameters for which this drawable
    243      * may change, requiring that it be re-created.
    244      *
    245      * @param configs A mask of the changing configuration parameters, as
    246      * defined by {@link android.content.pm.ActivityInfo}.
    247      *
    248      * @see android.content.pm.ActivityInfo
    249      */
    250     public void setChangingConfigurations(int configs) {
    251         mChangingConfigurations = configs;
    252     }
    253 
    254     /**
    255      * Return a mask of the configuration parameters for which this drawable
    256      * may change, requiring that it be re-created.  The default implementation
    257      * returns whatever was provided through
    258      * {@link #setChangingConfigurations(int)} or 0 by default.  Subclasses
    259      * may extend this to or in the changing configurations of any other
    260      * drawables they hold.
    261      *
    262      * @return Returns a mask of the changing configuration parameters, as
    263      * defined by {@link android.content.pm.ActivityInfo}.
    264      *
    265      * @see android.content.pm.ActivityInfo
    266      */
    267     public int getChangingConfigurations() {
    268         return mChangingConfigurations;
    269     }
    270 
    271     /**
    272      * Set to true to have the drawable dither its colors when drawn to a
    273      * device with fewer than 8-bits per color component.
    274      *
    275      * @see android.graphics.Paint#setDither(boolean);
    276      * @deprecated This property is ignored.
    277      */
    278     @Deprecated
    279     public void setDither(boolean dither) {}
    280 
    281     /**
    282      * Set to true to have the drawable filter its bitmaps with bilinear
    283      * sampling when they are scaled or rotated.
    284      *
    285      * <p>This can improve appearance when bitmaps are rotated. If the drawable
    286      * does not use bitmaps, this call is ignored.</p>
    287      *
    288      * @see #isFilterBitmap()
    289      * @see android.graphics.Paint#setFilterBitmap(boolean);
    290      */
    291     public void setFilterBitmap(boolean filter) {}
    292 
    293     /**
    294      * @return whether this drawable filters its bitmaps
    295      * @see #setFilterBitmap(boolean)
    296      */
    297     public boolean isFilterBitmap() {
    298         return false;
    299     }
    300 
    301     /**
    302      * Implement this interface if you want to create an animated drawable that
    303      * extends {@link android.graphics.drawable.Drawable Drawable}.
    304      * Upon retrieving a drawable, use
    305      * {@link Drawable#setCallback(android.graphics.drawable.Drawable.Callback)}
    306      * to supply your implementation of the interface to the drawable; it uses
    307      * this interface to schedule and execute animation changes.
    308      */
    309     public static interface Callback {
    310         /**
    311          * Called when the drawable needs to be redrawn.  A view at this point
    312          * should invalidate itself (or at least the part of itself where the
    313          * drawable appears).
    314          *
    315          * @param who The drawable that is requesting the update.
    316          */
    317         public void invalidateDrawable(Drawable who);
    318 
    319         /**
    320          * A Drawable can call this to schedule the next frame of its
    321          * animation.  An implementation can generally simply call
    322          * {@link android.os.Handler#postAtTime(Runnable, Object, long)} with
    323          * the parameters <var>(what, who, when)</var> to perform the
    324          * scheduling.
    325          *
    326          * @param who The drawable being scheduled.
    327          * @param what The action to execute.
    328          * @param when The time (in milliseconds) to run.  The timebase is
    329          *             {@link android.os.SystemClock#uptimeMillis}
    330          */
    331         public void scheduleDrawable(Drawable who, Runnable what, long when);
    332 
    333         /**
    334          * A Drawable can call this to unschedule an action previously
    335          * scheduled with {@link #scheduleDrawable}.  An implementation can
    336          * generally simply call
    337          * {@link android.os.Handler#removeCallbacks(Runnable, Object)} with
    338          * the parameters <var>(what, who)</var> to unschedule the drawable.
    339          *
    340          * @param who The drawable being unscheduled.
    341          * @param what The action being unscheduled.
    342          */
    343         public void unscheduleDrawable(Drawable who, Runnable what);
    344     }
    345 
    346     /**
    347      * Bind a {@link Callback} object to this Drawable.  Required for clients
    348      * that want to support animated drawables.
    349      *
    350      * @param cb The client's Callback implementation.
    351      *
    352      * @see #getCallback()
    353      */
    354     public final void setCallback(Callback cb) {
    355         mCallback = new WeakReference<Callback>(cb);
    356     }
    357 
    358     /**
    359      * Return the current {@link Callback} implementation attached to this
    360      * Drawable.
    361      *
    362      * @return A {@link Callback} instance or null if no callback was set.
    363      *
    364      * @see #setCallback(android.graphics.drawable.Drawable.Callback)
    365      */
    366     public Callback getCallback() {
    367         if (mCallback != null) {
    368             return mCallback.get();
    369         }
    370         return null;
    371     }
    372 
    373     /**
    374      * Use the current {@link Callback} implementation to have this Drawable
    375      * redrawn.  Does nothing if there is no Callback attached to the
    376      * Drawable.
    377      *
    378      * @see Callback#invalidateDrawable
    379      * @see #getCallback()
    380      * @see #setCallback(android.graphics.drawable.Drawable.Callback)
    381      */
    382     public void invalidateSelf() {
    383         final Callback callback = getCallback();
    384         if (callback != null) {
    385             callback.invalidateDrawable(this);
    386         }
    387     }
    388 
    389     /**
    390      * Use the current {@link Callback} implementation to have this Drawable
    391      * scheduled.  Does nothing if there is no Callback attached to the
    392      * Drawable.
    393      *
    394      * @param what The action being scheduled.
    395      * @param when The time (in milliseconds) to run.
    396      *
    397      * @see Callback#scheduleDrawable
    398      */
    399     public void scheduleSelf(Runnable what, long when) {
    400         final Callback callback = getCallback();
    401         if (callback != null) {
    402             callback.scheduleDrawable(this, what, when);
    403         }
    404     }
    405 
    406     /**
    407      * Use the current {@link Callback} implementation to have this Drawable
    408      * unscheduled.  Does nothing if there is no Callback attached to the
    409      * Drawable.
    410      *
    411      * @param what The runnable that you no longer want called.
    412      *
    413      * @see Callback#unscheduleDrawable
    414      */
    415     public void unscheduleSelf(Runnable what) {
    416         final Callback callback = getCallback();
    417         if (callback != null) {
    418             callback.unscheduleDrawable(this, what);
    419         }
    420     }
    421 
    422     /**
    423      * Returns the resolved layout direction for this Drawable.
    424      *
    425      * @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
    426      *         {@link android.view.View#LAYOUT_DIRECTION_RTL}
    427      * @see #setLayoutDirection(int)
    428      */
    429     public int getLayoutDirection() {
    430         return mLayoutDirection;
    431     }
    432 
    433     /**
    434      * Set the layout direction for this drawable. Should be a resolved
    435      * layout direction, as the Drawable has no capacity to do the resolution on
    436      * its own.
    437      *
    438      * @param layoutDirection the resolved layout direction for the drawable,
    439      *                        either {@link android.view.View#LAYOUT_DIRECTION_LTR}
    440      *                        or {@link android.view.View#LAYOUT_DIRECTION_RTL}
    441      * @see #getLayoutDirection()
    442      */
    443     public final boolean setLayoutDirection(@View.ResolvedLayoutDir int layoutDirection) {
    444         if (mLayoutDirection != layoutDirection) {
    445             mLayoutDirection = layoutDirection;
    446             return onLayoutDirectionChanged(layoutDirection);
    447         }
    448         return false;
    449     }
    450 
    451     /**
    452      * Called when the drawable's resolved layout direction changes.
    453      *
    454      * @param layoutDirection the new resolved layout direction
    455      * @return true if the layout direction change has caused the appearance of
    456      *         the drawable to change and it needs to be re-drawn
    457      * @see #setLayoutDirection(int)
    458      */
    459     public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
    460         return false;
    461     }
    462 
    463     /**
    464      * Specify an alpha value for the drawable. 0 means fully transparent, and
    465      * 255 means fully opaque.
    466      */
    467     public abstract void setAlpha(int alpha);
    468 
    469     /**
    470      * Gets the current alpha value for the drawable. 0 means fully transparent,
    471      * 255 means fully opaque. This method is implemented by
    472      * Drawable subclasses and the value returned is specific to how that class treats alpha.
    473      * The default return value is 255 if the class does not override this method to return a value
    474      * specific to its use of alpha.
    475      */
    476     public int getAlpha() {
    477         return 0xFF;
    478     }
    479 
    480     /**
    481      * @hide
    482      *
    483      * Internal-only method for setting xfermode on certain supported drawables.
    484      *
    485      * Should not be made public since the layers and drawing area with which
    486      * Drawables draw is private implementation detail, and not something apps
    487      * should rely upon.
    488      */
    489     public void setXfermode(Xfermode mode) {
    490         // Base implementation drops it on the floor for compatibility. Whee!
    491     }
    492 
    493     /**
    494      * Specify an optional color filter for the drawable.
    495      * <p>
    496      * If a Drawable has a ColorFilter, each output pixel of the Drawable's
    497      * drawing contents will be modified by the color filter before it is
    498      * blended onto the render target of a Canvas.
    499      * </p>
    500      * <p>
    501      * Pass {@code null} to remove any existing color filter.
    502      * </p>
    503      * <p class="note"><strong>Note:</strong> Setting a non-{@code null} color
    504      * filter disables {@link #setTintList(ColorStateList) tint}.
    505      * </p>
    506      *
    507      * @param colorFilter The color filter to apply, or {@code null} to remove the
    508      *            existing color filter
    509      */
    510     public abstract void setColorFilter(@Nullable ColorFilter colorFilter);
    511 
    512     /**
    513      * Specify a color and Porter-Duff mode to be the color filter for this
    514      * drawable.
    515      * <p>
    516      * Convenience for {@link #setColorFilter(ColorFilter)} which constructs a
    517      * {@link PorterDuffColorFilter}.
    518      * </p>
    519      * <p class="note"><strong>Note:</strong> Setting a color filter disables
    520      * {@link #setTintList(ColorStateList) tint}.
    521      * </p>
    522      */
    523     public void setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
    524         setColorFilter(new PorterDuffColorFilter(color, mode));
    525     }
    526 
    527     /**
    528      * Specifies tint color for this drawable.
    529      * <p>
    530      * A Drawable's drawing content will be blended together with its tint
    531      * before it is drawn to the screen. This functions similarly to
    532      * {@link #setColorFilter(int, PorterDuff.Mode)}.
    533      * </p>
    534      * <p>
    535      * To clear the tint, pass {@code null} to
    536      * {@link #setTintList(ColorStateList)}.
    537      * </p>
    538      * <p class="note"><strong>Note:</strong> Setting a color filter via
    539      * {@link #setColorFilter(ColorFilter)} or
    540      * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint.
    541      * </p>
    542      *
    543      * @param tintColor Color to use for tinting this drawable
    544      * @see #setTintList(ColorStateList)
    545      * @see #setTintMode(PorterDuff.Mode)
    546      */
    547     public void setTint(@ColorInt int tintColor) {
    548         setTintList(ColorStateList.valueOf(tintColor));
    549     }
    550 
    551     /**
    552      * Specifies tint color for this drawable as a color state list.
    553      * <p>
    554      * A Drawable's drawing content will be blended together with its tint
    555      * before it is drawn to the screen. This functions similarly to
    556      * {@link #setColorFilter(int, PorterDuff.Mode)}.
    557      * </p>
    558      * <p class="note"><strong>Note:</strong> Setting a color filter via
    559      * {@link #setColorFilter(ColorFilter)} or
    560      * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint.
    561      * </p>
    562      *
    563      * @param tint Color state list to use for tinting this drawable, or
    564      *            {@code null} to clear the tint
    565      * @see #setTint(int)
    566      * @see #setTintMode(PorterDuff.Mode)
    567      */
    568     public void setTintList(@Nullable ColorStateList tint) {}
    569 
    570     /**
    571      * Specifies a tint blending mode for this drawable.
    572      * <p>
    573      * Defines how this drawable's tint color should be blended into the drawable
    574      * before it is drawn to screen. Default tint mode is {@link PorterDuff.Mode#SRC_IN}.
    575      * </p>
    576      * <p class="note"><strong>Note:</strong> Setting a color filter via
    577      * {@link #setColorFilter(ColorFilter)} or
    578      * {@link #setColorFilter(int, PorterDuff.Mode)} overrides tint.
    579      * </p>
    580      *
    581      * @param tintMode A Porter-Duff blending mode
    582      * @see #setTint(int)
    583      * @see #setTintList(ColorStateList)
    584      */
    585     public void setTintMode(@NonNull PorterDuff.Mode tintMode) {}
    586 
    587     /**
    588      * Returns the current color filter, or {@code null} if none set.
    589      *
    590      * @return the current color filter, or {@code null} if none set
    591      */
    592     public ColorFilter getColorFilter() {
    593         return null;
    594     }
    595 
    596     /**
    597      * Removes the color filter for this drawable.
    598      */
    599     public void clearColorFilter() {
    600         setColorFilter(null);
    601     }
    602 
    603     /**
    604      * Specifies the hotspot's location within the drawable.
    605      *
    606      * @param x The X coordinate of the center of the hotspot
    607      * @param y The Y coordinate of the center of the hotspot
    608      */
    609     public void setHotspot(float x, float y) {}
    610 
    611     /**
    612      * Sets the bounds to which the hotspot is constrained, if they should be
    613      * different from the drawable bounds.
    614      *
    615      * @param left position in pixels of the left bound
    616      * @param top position in pixels of the top bound
    617      * @param right position in pixels of the right bound
    618      * @param bottom position in pixels of the bottom bound
    619      * @see #getHotspotBounds(android.graphics.Rect)
    620      */
    621     public void setHotspotBounds(int left, int top, int right, int bottom) {}
    622 
    623     /**
    624      * Populates {@code outRect} with the hotspot bounds.
    625      *
    626      * @param outRect the rect to populate with the hotspot bounds
    627      * @see #setHotspotBounds(int, int, int, int)
    628      */
    629     public void getHotspotBounds(Rect outRect) {
    630         outRect.set(getBounds());
    631     }
    632 
    633     /**
    634      * Whether this drawable requests projection.
    635      *
    636      * @hide magic!
    637      */
    638     public boolean isProjected() {
    639         return false;
    640     }
    641 
    642     /**
    643      * Indicates whether this drawable will change its appearance based on
    644      * state. Clients can use this to determine whether it is necessary to
    645      * calculate their state and call setState.
    646      *
    647      * @return True if this drawable changes its appearance based on state,
    648      *         false otherwise.
    649      * @see #setState(int[])
    650      */
    651     public boolean isStateful() {
    652         return false;
    653     }
    654 
    655     /**
    656      * Specify a set of states for the drawable. These are use-case specific,
    657      * so see the relevant documentation. As an example, the background for
    658      * widgets like Button understand the following states:
    659      * [{@link android.R.attr#state_focused},
    660      *  {@link android.R.attr#state_pressed}].
    661      *
    662      * <p>If the new state you are supplying causes the appearance of the
    663      * Drawable to change, then it is responsible for calling
    664      * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
    665      * true will be returned from this function.
    666      *
    667      * <p>Note: The Drawable holds a reference on to <var>stateSet</var>
    668      * until a new state array is given to it, so you must not modify this
    669      * array during that time.</p>
    670      *
    671      * @param stateSet The new set of states to be displayed.
    672      *
    673      * @return Returns true if this change in state has caused the appearance
    674      * of the Drawable to change (hence requiring an invalidate), otherwise
    675      * returns false.
    676      */
    677     public boolean setState(final int[] stateSet) {
    678         if (!Arrays.equals(mStateSet, stateSet)) {
    679             mStateSet = stateSet;
    680             return onStateChange(stateSet);
    681         }
    682         return false;
    683     }
    684 
    685     /**
    686      * Describes the current state, as a union of primitve states, such as
    687      * {@link android.R.attr#state_focused},
    688      * {@link android.R.attr#state_selected}, etc.
    689      * Some drawables may modify their imagery based on the selected state.
    690      * @return An array of resource Ids describing the current state.
    691      */
    692     public int[] getState() {
    693         return mStateSet;
    694     }
    695 
    696     /**
    697      * If this Drawable does transition animations between states, ask that
    698      * it immediately jump to the current state and skip any active animations.
    699      */
    700     public void jumpToCurrentState() {
    701     }
    702 
    703     /**
    704      * @return The current drawable that will be used by this drawable. For simple drawables, this
    705      *         is just the drawable itself. For drawables that change state like
    706      *         {@link StateListDrawable} and {@link LevelListDrawable} this will be the child drawable
    707      *         currently in use.
    708      */
    709     public Drawable getCurrent() {
    710         return this;
    711     }
    712 
    713     /**
    714      * Specify the level for the drawable.  This allows a drawable to vary its
    715      * imagery based on a continuous controller, for example to show progress
    716      * or volume level.
    717      *
    718      * <p>If the new level you are supplying causes the appearance of the
    719      * Drawable to change, then it is responsible for calling
    720      * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
    721      * true will be returned from this function.
    722      *
    723      * @param level The new level, from 0 (minimum) to 10000 (maximum).
    724      *
    725      * @return Returns true if this change in level has caused the appearance
    726      * of the Drawable to change (hence requiring an invalidate), otherwise
    727      * returns false.
    728      */
    729     public final boolean setLevel(int level) {
    730         if (mLevel != level) {
    731             mLevel = level;
    732             return onLevelChange(level);
    733         }
    734         return false;
    735     }
    736 
    737     /**
    738      * Retrieve the current level.
    739      *
    740      * @return int Current level, from 0 (minimum) to 10000 (maximum).
    741      */
    742     public final int getLevel() {
    743         return mLevel;
    744     }
    745 
    746     /**
    747      * Set whether this Drawable is visible.  This generally does not impact
    748      * the Drawable's behavior, but is a hint that can be used by some
    749      * Drawables, for example, to decide whether run animations.
    750      *
    751      * @param visible Set to true if visible, false if not.
    752      * @param restart You can supply true here to force the drawable to behave
    753      *                as if it has just become visible, even if it had last
    754      *                been set visible.  Used for example to force animations
    755      *                to restart.
    756      *
    757      * @return boolean Returns true if the new visibility is different than
    758      *         its previous state.
    759      */
    760     public boolean setVisible(boolean visible, boolean restart) {
    761         boolean changed = mVisible != visible;
    762         if (changed) {
    763             mVisible = visible;
    764             invalidateSelf();
    765         }
    766         return changed;
    767     }
    768 
    769     public final boolean isVisible() {
    770         return mVisible;
    771     }
    772 
    773     /**
    774      * Set whether this Drawable is automatically mirrored when its layout direction is RTL
    775      * (right-to left). See {@link android.util.LayoutDirection}.
    776      *
    777      * @param mirrored Set to true if the Drawable should be mirrored, false if not.
    778      */
    779     public void setAutoMirrored(boolean mirrored) {
    780     }
    781 
    782     /**
    783      * Tells if this Drawable will be automatically mirrored  when its layout direction is RTL
    784      * right-to-left. See {@link android.util.LayoutDirection}.
    785      *
    786      * @return boolean Returns true if this Drawable will be automatically mirrored.
    787      */
    788     public boolean isAutoMirrored() {
    789         return false;
    790     }
    791 
    792     /**
    793      * Applies the specified theme to this Drawable and its children.
    794      */
    795     public void applyTheme(@SuppressWarnings("unused") Theme t) {
    796     }
    797 
    798     public boolean canApplyTheme() {
    799         return false;
    800     }
    801 
    802     /**
    803      * Return the opacity/transparency of this Drawable.  The returned value is
    804      * one of the abstract format constants in
    805      * {@link android.graphics.PixelFormat}:
    806      * {@link android.graphics.PixelFormat#UNKNOWN},
    807      * {@link android.graphics.PixelFormat#TRANSLUCENT},
    808      * {@link android.graphics.PixelFormat#TRANSPARENT}, or
    809      * {@link android.graphics.PixelFormat#OPAQUE}.
    810      *
    811      * <p>An OPAQUE drawable is one that draws all all content within its bounds, completely
    812      * covering anything behind the drawable. A TRANSPARENT drawable is one that draws nothing
    813      * within its bounds, allowing everything behind it to show through. A TRANSLUCENT drawable
    814      * is a drawable in any other state, where the drawable will draw some, but not all,
    815      * of the content within its bounds and at least some content behind the drawable will
    816      * be visible. If the visibility of the drawable's contents cannot be determined, the
    817      * safest/best return value is TRANSLUCENT.
    818      *
    819      * <p>Generally a Drawable should be as conservative as possible with the
    820      * value it returns.  For example, if it contains multiple child drawables
    821      * and only shows one of them at a time, if only one of the children is
    822      * TRANSLUCENT and the others are OPAQUE then TRANSLUCENT should be
    823      * returned.  You can use the method {@link #resolveOpacity} to perform a
    824      * standard reduction of two opacities to the appropriate single output.
    825      *
    826      * <p>Note that the returned value does not necessarily take into account a
    827      * custom alpha or color filter that has been applied by the client through
    828      * the {@link #setAlpha} or {@link #setColorFilter} methods. Some subclasses,
    829      * such as {@link BitmapDrawable}, {@link ColorDrawable}, and {@link GradientDrawable},
    830      * do account for the value of {@link #setAlpha}, but the general behavior is dependent
    831      * upon the implementation of the subclass.
    832      *
    833      * @return int The opacity class of the Drawable.
    834      *
    835      * @see android.graphics.PixelFormat
    836      */
    837     public abstract int getOpacity();
    838 
    839     /**
    840      * Return the appropriate opacity value for two source opacities.  If
    841      * either is UNKNOWN, that is returned; else, if either is TRANSLUCENT,
    842      * that is returned; else, if either is TRANSPARENT, that is returned;
    843      * else, OPAQUE is returned.
    844      *
    845      * <p>This is to help in implementing {@link #getOpacity}.
    846      *
    847      * @param op1 One opacity value.
    848      * @param op2 Another opacity value.
    849      *
    850      * @return int The combined opacity value.
    851      *
    852      * @see #getOpacity
    853      */
    854     public static int resolveOpacity(int op1, int op2) {
    855         if (op1 == op2) {
    856             return op1;
    857         }
    858         if (op1 == PixelFormat.UNKNOWN || op2 == PixelFormat.UNKNOWN) {
    859             return PixelFormat.UNKNOWN;
    860         }
    861         if (op1 == PixelFormat.TRANSLUCENT || op2 == PixelFormat.TRANSLUCENT) {
    862             return PixelFormat.TRANSLUCENT;
    863         }
    864         if (op1 == PixelFormat.TRANSPARENT || op2 == PixelFormat.TRANSPARENT) {
    865             return PixelFormat.TRANSPARENT;
    866         }
    867         return PixelFormat.OPAQUE;
    868     }
    869 
    870     /**
    871      * Returns a Region representing the part of the Drawable that is completely
    872      * transparent.  This can be used to perform drawing operations, identifying
    873      * which parts of the target will not change when rendering the Drawable.
    874      * The default implementation returns null, indicating no transparent
    875      * region; subclasses can optionally override this to return an actual
    876      * Region if they want to supply this optimization information, but it is
    877      * not required that they do so.
    878      *
    879      * @return Returns null if the Drawables has no transparent region to
    880      * report, else a Region holding the parts of the Drawable's bounds that
    881      * are transparent.
    882      */
    883     public Region getTransparentRegion() {
    884         return null;
    885     }
    886 
    887     /**
    888      * Override this in your subclass to change appearance if you recognize the
    889      * specified state.
    890      *
    891      * @return Returns true if the state change has caused the appearance of
    892      * the Drawable to change (that is, it needs to be drawn), else false
    893      * if it looks the same and there is no need to redraw it since its
    894      * last state.
    895      */
    896     protected boolean onStateChange(int[] state) { return false; }
    897     /** Override this in your subclass to change appearance if you vary based
    898      *  on level.
    899      * @return Returns true if the level change has caused the appearance of
    900      * the Drawable to change (that is, it needs to be drawn), else false
    901      * if it looks the same and there is no need to redraw it since its
    902      * last level.
    903      */
    904     protected boolean onLevelChange(int level) { return false; }
    905     /**
    906      * Override this in your subclass to change appearance if you vary based on
    907      * the bounds.
    908      */
    909     protected void onBoundsChange(Rect bounds) {}
    910 
    911     /**
    912      * Return the intrinsic width of the underlying drawable object.  Returns
    913      * -1 if it has no intrinsic width, such as with a solid color.
    914      */
    915     public int getIntrinsicWidth() {
    916         return -1;
    917     }
    918 
    919     /**
    920      * Return the intrinsic height of the underlying drawable object. Returns
    921      * -1 if it has no intrinsic height, such as with a solid color.
    922      */
    923     public int getIntrinsicHeight() {
    924         return -1;
    925     }
    926 
    927     /**
    928      * Returns the minimum width suggested by this Drawable. If a View uses this
    929      * Drawable as a background, it is suggested that the View use at least this
    930      * value for its width. (There will be some scenarios where this will not be
    931      * possible.) This value should INCLUDE any padding.
    932      *
    933      * @return The minimum width suggested by this Drawable. If this Drawable
    934      *         doesn't have a suggested minimum width, 0 is returned.
    935      */
    936     public int getMinimumWidth() {
    937         final int intrinsicWidth = getIntrinsicWidth();
    938         return intrinsicWidth > 0 ? intrinsicWidth : 0;
    939     }
    940 
    941     /**
    942      * Returns the minimum height suggested by this Drawable. If a View uses this
    943      * Drawable as a background, it is suggested that the View use at least this
    944      * value for its height. (There will be some scenarios where this will not be
    945      * possible.) This value should INCLUDE any padding.
    946      *
    947      * @return The minimum height suggested by this Drawable. If this Drawable
    948      *         doesn't have a suggested minimum height, 0 is returned.
    949      */
    950     public int getMinimumHeight() {
    951         final int intrinsicHeight = getIntrinsicHeight();
    952         return intrinsicHeight > 0 ? intrinsicHeight : 0;
    953     }
    954 
    955     /**
    956      * Return in padding the insets suggested by this Drawable for placing
    957      * content inside the drawable's bounds. Positive values move toward the
    958      * center of the Drawable (set Rect.inset).
    959      *
    960      * @return true if this drawable actually has a padding, else false. When false is returned,
    961      * the padding is always set to 0.
    962      */
    963     public boolean getPadding(@NonNull Rect padding) {
    964         padding.set(0, 0, 0, 0);
    965         return false;
    966     }
    967 
    968     /**
    969      * Return in insets the layout insets suggested by this Drawable for use with alignment
    970      * operations during layout.
    971      *
    972      * @hide
    973      */
    974     public Insets getOpticalInsets() {
    975         return Insets.NONE;
    976     }
    977 
    978     /**
    979      * Called to get the drawable to populate the Outline that defines its drawing area.
    980      * <p>
    981      * This method is called by the default {@link android.view.ViewOutlineProvider} to define
    982      * the outline of the View.
    983      * <p>
    984      * The default behavior defines the outline to be the bounding rectangle of 0 alpha.
    985      * Subclasses that wish to convey a different shape or alpha value must override this method.
    986      *
    987      * @see android.view.View#setOutlineProvider(android.view.ViewOutlineProvider)
    988      */
    989     public void getOutline(@NonNull Outline outline) {
    990         outline.setRect(getBounds());
    991         outline.setAlpha(0);
    992     }
    993 
    994     /**
    995      * Make this drawable mutable. This operation cannot be reversed. A mutable
    996      * drawable is guaranteed to not share its state with any other drawable.
    997      * This is especially useful when you need to modify properties of drawables
    998      * loaded from resources. By default, all drawables instances loaded from
    999      * the same resource share a common state; if you modify the state of one
   1000      * instance, all the other instances will receive the same modification.
   1001      *
   1002      * Calling this method on a mutable Drawable will have no effect.
   1003      *
   1004      * @return This drawable.
   1005      * @see ConstantState
   1006      * @see #getConstantState()
   1007      */
   1008     public Drawable mutate() {
   1009         return this;
   1010     }
   1011 
   1012     /**
   1013      * Clears the mutated state, allowing this drawable to be cached and
   1014      * mutated again.
   1015      * <p>
   1016      * This is hidden because only framework drawables can be cached, so
   1017      * custom drawables don't need to support constant state, mutate(), or
   1018      * clearMutated().
   1019      *
   1020      * @hide
   1021      */
   1022     public void clearMutated() {
   1023         // Default implementation is no-op.
   1024     }
   1025 
   1026     /**
   1027      * Create a drawable from an inputstream
   1028      */
   1029     public static Drawable createFromStream(InputStream is, String srcName) {
   1030         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
   1031         try {
   1032             return createFromResourceStream(null, null, is, srcName);
   1033         } finally {
   1034             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
   1035         }
   1036     }
   1037 
   1038     /**
   1039      * Create a drawable from an inputstream, using the given resources and
   1040      * value to determine density information.
   1041      */
   1042     public static Drawable createFromResourceStream(Resources res, TypedValue value,
   1043             InputStream is, String srcName) {
   1044         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
   1045         try {
   1046             return createFromResourceStream(res, value, is, srcName, null);
   1047         } finally {
   1048             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
   1049         }
   1050     }
   1051 
   1052     /**
   1053      * Create a drawable from an inputstream, using the given resources and
   1054      * value to determine density information.
   1055      */
   1056     public static Drawable createFromResourceStream(Resources res, TypedValue value,
   1057             InputStream is, String srcName, BitmapFactory.Options opts) {
   1058         if (is == null) {
   1059             return null;
   1060         }
   1061 
   1062         /*  ugh. The decodeStream contract is that we have already allocated
   1063             the pad rect, but if the bitmap does not had a ninepatch chunk,
   1064             then the pad will be ignored. If we could change this to lazily
   1065             alloc/assign the rect, we could avoid the GC churn of making new
   1066             Rects only to drop them on the floor.
   1067         */
   1068         Rect pad = new Rect();
   1069 
   1070         // Special stuff for compatibility mode: if the target density is not
   1071         // the same as the display density, but the resource -is- the same as
   1072         // the display density, then don't scale it down to the target density.
   1073         // This allows us to load the system's density-correct resources into
   1074         // an application in compatibility mode, without scaling those down
   1075         // to the compatibility density only to have them scaled back up when
   1076         // drawn to the screen.
   1077         if (opts == null) opts = new BitmapFactory.Options();
   1078         opts.inScreenDensity = res != null
   1079                 ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
   1080         Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
   1081         if (bm != null) {
   1082             byte[] np = bm.getNinePatchChunk();
   1083             if (np == null || !NinePatch.isNinePatchChunk(np)) {
   1084                 np = null;
   1085                 pad = null;
   1086             }
   1087 
   1088             final Rect opticalInsets = new Rect();
   1089             bm.getOpticalInsets(opticalInsets);
   1090             return drawableFromBitmap(res, bm, np, pad, opticalInsets, srcName);
   1091         }
   1092         return null;
   1093     }
   1094 
   1095     /**
   1096      * Create a drawable from an XML document. For more information on how to
   1097      * create resources in XML, see
   1098      * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
   1099      */
   1100     public static Drawable createFromXml(Resources r, XmlPullParser parser)
   1101             throws XmlPullParserException, IOException {
   1102         return createFromXml(r, parser, null);
   1103     }
   1104 
   1105     /**
   1106      * Create a drawable from an XML document using an optional {@link Theme}.
   1107      * For more information on how to create resources in XML, see
   1108      * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
   1109      */
   1110     public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)
   1111             throws XmlPullParserException, IOException {
   1112         AttributeSet attrs = Xml.asAttributeSet(parser);
   1113 
   1114         int type;
   1115         while ((type=parser.next()) != XmlPullParser.START_TAG &&
   1116                 type != XmlPullParser.END_DOCUMENT) {
   1117             // Empty loop
   1118         }
   1119 
   1120         if (type != XmlPullParser.START_TAG) {
   1121             throw new XmlPullParserException("No start tag found");
   1122         }
   1123 
   1124         Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
   1125 
   1126         if (drawable == null) {
   1127             throw new RuntimeException("Unknown initial tag: " + parser.getName());
   1128         }
   1129 
   1130         return drawable;
   1131     }
   1132 
   1133     /**
   1134      * Create from inside an XML document.  Called on a parser positioned at
   1135      * a tag in an XML document, tries to create a Drawable from that tag.
   1136      * Returns null if the tag is not a valid drawable.
   1137      */
   1138     public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
   1139             throws XmlPullParserException, IOException {
   1140         return createFromXmlInner(r, parser, attrs, null);
   1141     }
   1142 
   1143     /**
   1144      * Create a drawable from inside an XML document using an optional
   1145      * {@link Theme}. Called on a parser positioned at a tag in an XML
   1146      * document, tries to create a Drawable from that tag. Returns {@code null}
   1147      * if the tag is not a valid drawable.
   1148      */
   1149     @SuppressWarnings("deprecation")
   1150     public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
   1151             Theme theme) throws XmlPullParserException, IOException {
   1152         final Drawable drawable;
   1153 
   1154         final String name = parser.getName();
   1155         switch (name) {
   1156             case "selector":
   1157                 drawable = new StateListDrawable();
   1158                 break;
   1159             case "animated-selector":
   1160                 drawable = new AnimatedStateListDrawable();
   1161                 break;
   1162             case "level-list":
   1163                 drawable = new LevelListDrawable();
   1164                 break;
   1165             case "layer-list":
   1166                 drawable = new LayerDrawable();
   1167                 break;
   1168             case "transition":
   1169                 drawable = new TransitionDrawable();
   1170                 break;
   1171             case "ripple":
   1172                 drawable = new RippleDrawable();
   1173                 break;
   1174             case "color":
   1175                 drawable = new ColorDrawable();
   1176                 break;
   1177             case "shape":
   1178                 drawable = new GradientDrawable();
   1179                 break;
   1180             case "vector":
   1181                 drawable = new VectorDrawable();
   1182                 break;
   1183             case "animated-vector":
   1184                 drawable = new AnimatedVectorDrawable();
   1185                 break;
   1186             case "scale":
   1187                 drawable = new ScaleDrawable();
   1188                 break;
   1189             case "clip":
   1190                 drawable = new ClipDrawable();
   1191                 break;
   1192             case "rotate":
   1193                 drawable = new RotateDrawable();
   1194                 break;
   1195             case "animated-rotate":
   1196                 drawable = new AnimatedRotateDrawable();
   1197                 break;
   1198             case "animation-list":
   1199                 drawable = new AnimationDrawable();
   1200                 break;
   1201             case "inset":
   1202                 drawable = new InsetDrawable();
   1203                 break;
   1204             case "bitmap":
   1205                 drawable = new BitmapDrawable();
   1206                 break;
   1207             case "nine-patch":
   1208                 drawable = new NinePatchDrawable();
   1209                 break;
   1210             default:
   1211                 throw new XmlPullParserException(parser.getPositionDescription() +
   1212                         ": invalid drawable tag " + name);
   1213 
   1214         }
   1215         drawable.inflate(r, parser, attrs, theme);
   1216         return drawable;
   1217     }
   1218 
   1219 
   1220     /**
   1221      * Create a drawable from file path name.
   1222      */
   1223     public static Drawable createFromPath(String pathName) {
   1224         if (pathName == null) {
   1225             return null;
   1226         }
   1227 
   1228         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
   1229         try {
   1230             Bitmap bm = BitmapFactory.decodeFile(pathName);
   1231             if (bm != null) {
   1232                 return drawableFromBitmap(null, bm, null, null, null, pathName);
   1233             }
   1234         } finally {
   1235             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
   1236         }
   1237 
   1238         return null;
   1239     }
   1240 
   1241     /**
   1242      * Inflate this Drawable from an XML resource. Does not apply a theme.
   1243      *
   1244      * @see #inflate(Resources, XmlPullParser, AttributeSet, Theme)
   1245      */
   1246     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
   1247             throws XmlPullParserException, IOException {
   1248         inflate(r, parser, attrs, null);
   1249     }
   1250 
   1251     /**
   1252      * Inflate this Drawable from an XML resource optionally styled by a theme.
   1253      *
   1254      * @param r Resources used to resolve attribute values
   1255      * @param parser XML parser from which to inflate this Drawable
   1256      * @param attrs Base set of attribute values
   1257      * @param theme Theme to apply, may be null
   1258      * @throws XmlPullParserException
   1259      * @throws IOException
   1260      */
   1261     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
   1262             throws XmlPullParserException, IOException {
   1263         final TypedArray a;
   1264         if (theme != null) {
   1265             a = theme.obtainStyledAttributes(
   1266                     attrs, com.android.internal.R.styleable.Drawable, 0, 0);
   1267         } else {
   1268             a = r.obtainAttributes(attrs, com.android.internal.R.styleable.Drawable);
   1269         }
   1270 
   1271         inflateWithAttributes(r, parser, a, com.android.internal.R.styleable.Drawable_visible);
   1272         a.recycle();
   1273     }
   1274 
   1275     /**
   1276      * Inflate a Drawable from an XML resource.
   1277      *
   1278      * @throws XmlPullParserException
   1279      * @throws IOException
   1280      */
   1281     void inflateWithAttributes(Resources r, XmlPullParser parser, TypedArray attrs, int visibleAttr)
   1282             throws XmlPullParserException, IOException {
   1283         mVisible = attrs.getBoolean(visibleAttr, mVisible);
   1284     }
   1285 
   1286     /**
   1287      * This abstract class is used by {@link Drawable}s to store shared constant state and data
   1288      * between Drawables. {@link BitmapDrawable}s created from the same resource will for instance
   1289      * share a unique bitmap stored in their ConstantState.
   1290      *
   1291      * <p>
   1292      * {@link #newDrawable(Resources)} can be used as a factory to create new Drawable instances
   1293      * from this ConstantState.
   1294      * </p>
   1295      *
   1296      * Use {@link Drawable#getConstantState()} to retrieve the ConstantState of a Drawable. Calling
   1297      * {@link Drawable#mutate()} on a Drawable should typically create a new ConstantState for that
   1298      * Drawable.
   1299      */
   1300     public static abstract class ConstantState {
   1301         /**
   1302          * Create a new drawable without supplying resources the caller
   1303          * is running in.  Note that using this means the density-dependent
   1304          * drawables (like bitmaps) will not be able to update their target
   1305          * density correctly. One should use {@link #newDrawable(Resources)}
   1306          * instead to provide a resource.
   1307          */
   1308         public abstract Drawable newDrawable();
   1309 
   1310         /**
   1311          * Create a new Drawable instance from its constant state.  This
   1312          * must be implemented for drawables that change based on the target
   1313          * density of their caller (that is depending on whether it is
   1314          * in compatibility mode).
   1315          */
   1316         public Drawable newDrawable(Resources res) {
   1317             return newDrawable();
   1318         }
   1319 
   1320         /**
   1321          * Create a new Drawable instance from its constant state. This must be
   1322          * implemented for drawables that can have a theme applied.
   1323          */
   1324         public Drawable newDrawable(Resources res, Theme theme) {
   1325             return newDrawable(null);
   1326         }
   1327 
   1328         /**
   1329          * Return a bit mask of configuration changes that will impact
   1330          * this drawable (and thus require completely reloading it).
   1331          */
   1332         public abstract int getChangingConfigurations();
   1333 
   1334         /**
   1335          * @return Total pixel count
   1336          * @hide
   1337          */
   1338         public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
   1339             return 0;
   1340         }
   1341 
   1342         /** @hide */
   1343         protected final boolean isAtlasable(Bitmap bitmap) {
   1344             return bitmap != null && bitmap.getConfig() == Bitmap.Config.ARGB_8888;
   1345         }
   1346 
   1347         /**
   1348          * Return whether this constant state can have a theme applied.
   1349          */
   1350         public boolean canApplyTheme() {
   1351             return false;
   1352         }
   1353     }
   1354 
   1355     /**
   1356      * Return a {@link ConstantState} instance that holds the shared state of this Drawable.
   1357      *
   1358      * @return The ConstantState associated to that Drawable.
   1359      * @see ConstantState
   1360      * @see Drawable#mutate()
   1361      */
   1362     public ConstantState getConstantState() {
   1363         return null;
   1364     }
   1365 
   1366     private static Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np,
   1367             Rect pad, Rect layoutBounds, String srcName) {
   1368 
   1369         if (np != null) {
   1370             return new NinePatchDrawable(res, bm, np, pad, layoutBounds, srcName);
   1371         }
   1372 
   1373         return new BitmapDrawable(res, bm);
   1374     }
   1375 
   1376     /**
   1377      * Ensures the tint filter is consistent with the current tint color and
   1378      * mode.
   1379      */
   1380     PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
   1381             PorterDuff.Mode tintMode) {
   1382         if (tint == null || tintMode == null) {
   1383             return null;
   1384         }
   1385 
   1386         final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
   1387         if (tintFilter == null) {
   1388             return new PorterDuffColorFilter(color, tintMode);
   1389         }
   1390 
   1391         tintFilter.setColor(color);
   1392         tintFilter.setMode(tintMode);
   1393         return tintFilter;
   1394     }
   1395 
   1396     /**
   1397      * Obtains styled attributes from the theme, if available, or unstyled
   1398      * resources if the theme is null.
   1399      */
   1400     static TypedArray obtainAttributes(
   1401             Resources res, Theme theme, AttributeSet set, int[] attrs) {
   1402         if (theme == null) {
   1403             return res.obtainAttributes(set, attrs);
   1404         }
   1405         return theme.obtainStyledAttributes(set, attrs, 0, 0);
   1406     }
   1407 
   1408     /**
   1409      * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
   1410      * attribute's enum value.
   1411      *
   1412      * @hide
   1413      */
   1414     public static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) {
   1415         switch (value) {
   1416             case 3: return Mode.SRC_OVER;
   1417             case 5: return Mode.SRC_IN;
   1418             case 9: return Mode.SRC_ATOP;
   1419             case 14: return Mode.MULTIPLY;
   1420             case 15: return Mode.SCREEN;
   1421             case 16: return Mode.ADD;
   1422             default: return defaultMode;
   1423         }
   1424     }
   1425 }
   1426 
   1427