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