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