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 android.graphics.Insets;
20import android.graphics.Xfermode;
21import android.os.Trace;
22import org.xmlpull.v1.XmlPullParser;
23import org.xmlpull.v1.XmlPullParserException;
24
25import android.content.res.Resources;
26import android.content.res.TypedArray;
27import android.graphics.Bitmap;
28import android.graphics.BitmapFactory;
29import android.graphics.Canvas;
30import android.graphics.ColorFilter;
31import android.graphics.NinePatch;
32import android.graphics.PixelFormat;
33import android.graphics.PorterDuff;
34import android.graphics.PorterDuffColorFilter;
35import android.graphics.Rect;
36import android.graphics.Region;
37import android.util.AttributeSet;
38import android.util.DisplayMetrics;
39import android.util.StateSet;
40import android.util.TypedValue;
41import android.util.Xml;
42
43import java.io.IOException;
44import java.io.InputStream;
45import java.lang.ref.WeakReference;
46import java.util.Arrays;
47
48/**
49 * A Drawable is a general abstraction for "something that can be drawn."  Most
50 * often you will deal with Drawable as the type of resource retrieved for
51 * drawing things to the screen; the Drawable class provides a generic API for
52 * dealing with an underlying visual resource that may take a variety of forms.
53 * Unlike a {@link android.view.View}, a Drawable does not have any facility to
54 * receive events or otherwise interact with the user.
55 *
56 * <p>In addition to simple drawing, Drawable provides a number of generic
57 * mechanisms for its client to interact with what is being drawn:
58 *
59 * <ul>
60 *     <li> The {@link #setBounds} method <var>must</var> be called to tell the
61 *     Drawable where it is drawn and how large it should be.  All Drawables
62 *     should respect the requested size, often simply by scaling their
63 *     imagery.  A client can find the preferred size for some Drawables with
64 *     the {@link #getIntrinsicHeight} and {@link #getIntrinsicWidth} methods.
65 *
66 *     <li> The {@link #getPadding} method can return from some Drawables
67 *     information about how to frame content that is placed inside of them.
68 *     For example, a Drawable that is intended to be the frame for a button
69 *     widget would need to return padding that correctly places the label
70 *     inside of itself.
71 *
72 *     <li> The {@link #setState} method allows the client to tell the Drawable
73 *     in which state it is to be drawn, such as "focused", "selected", etc.
74 *     Some drawables may modify their imagery based on the selected state.
75 *
76 *     <li> The {@link #setLevel} method allows the client to supply a single
77 *     continuous controller that can modify the Drawable is displayed, such as
78 *     a battery level or progress level.  Some drawables may modify their
79 *     imagery based on the current level.
80 *
81 *     <li> A Drawable can perform animations by calling back to its client
82 *     through the {@link Callback} interface.  All clients should support this
83 *     interface (via {@link #setCallback}) so that animations will work.  A
84 *     simple way to do this is through the system facilities such as
85 *     {@link android.view.View#setBackgroundDrawable(Drawable)} and
86 *     {@link android.widget.ImageView}.
87 * </ul>
88 *
89 * Though usually not visible to the application, Drawables may take a variety
90 * of forms:
91 *
92 * <ul>
93 *     <li> <b>Bitmap</b>: the simplest Drawable, a PNG or JPEG image.
94 *     <li> <b>Nine Patch</b>: an extension to the PNG format allows it to
95 *     specify information about how to stretch it and place things inside of
96 *     it.
97 *     <li> <b>Shape</b>: contains simple drawing commands instead of a raw
98 *     bitmap, allowing it to resize better in some cases.
99 *     <li> <b>Layers</b>: a compound drawable, which draws multiple underlying
100 *     drawables on top of each other.
101 *     <li> <b>States</b>: a compound drawable that selects one of a set of
102 *     drawables based on its state.
103 *     <li> <b>Levels</b>: a compound drawable that selects one of a set of
104 *     drawables based on its level.
105 *     <li> <b>Scale</b>: a compound drawable with a single child drawable,
106 *     whose overall size is modified based on the current level.
107 * </ul>
108 *
109 * <div class="special reference">
110 * <h3>Developer Guides</h3>
111 * <p>For more information about how to use drawables, read the
112 * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html">Canvas and Drawables</a> developer
113 * guide. For information and examples of creating drawable resources (XML or bitmap files that
114 * can be loaded in code), read the
115 * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>
116 * document.</p></div>
117 */
118public abstract class Drawable {
119    private static final Rect ZERO_BOUNDS_RECT = new Rect();
120
121    private int[] mStateSet = StateSet.WILD_CARD;
122    private int mLevel = 0;
123    private int mChangingConfigurations = 0;
124    private Rect mBounds = ZERO_BOUNDS_RECT;  // lazily becomes a new Rect()
125    private WeakReference<Callback> mCallback = null;
126    private boolean mVisible = true;
127
128    private int mLayoutDirection;
129
130    /**
131     * Draw in its bounds (set via setBounds) respecting optional effects such
132     * as alpha (set via setAlpha) and color filter (set via setColorFilter).
133     *
134     * @param canvas The canvas to draw into
135     */
136    public abstract void draw(Canvas canvas);
137
138    /**
139     * Specify a bounding rectangle for the Drawable. This is where the drawable
140     * will draw when its draw() method is called.
141     */
142    public void setBounds(int left, int top, int right, int bottom) {
143        Rect oldBounds = mBounds;
144
145        if (oldBounds == ZERO_BOUNDS_RECT) {
146            oldBounds = mBounds = new Rect();
147        }
148
149        if (oldBounds.left != left || oldBounds.top != top ||
150                oldBounds.right != right || oldBounds.bottom != bottom) {
151            if (!oldBounds.isEmpty()) {
152                // first invalidate the previous bounds
153                invalidateSelf();
154            }
155            mBounds.set(left, top, right, bottom);
156            onBoundsChange(mBounds);
157        }
158    }
159
160    /**
161     * Specify a bounding rectangle for the Drawable. This is where the drawable
162     * will draw when its draw() method is called.
163     */
164    public void setBounds(Rect bounds) {
165        setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
166    }
167
168    /**
169     * Return a copy of the drawable's bounds in the specified Rect (allocated
170     * by the caller). The bounds specify where this will draw when its draw()
171     * method is called.
172     *
173     * @param bounds Rect to receive the drawable's bounds (allocated by the
174     *               caller).
175     */
176    public final void copyBounds(Rect bounds) {
177        bounds.set(mBounds);
178    }
179
180    /**
181     * Return a copy of the drawable's bounds in a new Rect. This returns the
182     * same values as getBounds(), but the returned object is guaranteed to not
183     * be changed later by the drawable (i.e. it retains no reference to this
184     * rect). If the caller already has a Rect allocated, call copyBounds(rect).
185     *
186     * @return A copy of the drawable's bounds
187     */
188    public final Rect copyBounds() {
189        return new Rect(mBounds);
190    }
191
192    /**
193     * Return the drawable's bounds Rect. Note: for efficiency, the returned
194     * object may be the same object stored in the drawable (though this is not
195     * guaranteed), so if a persistent copy of the bounds is needed, call
196     * copyBounds(rect) instead.
197     * You should also not change the object returned by this method as it may
198     * be the same object stored in the drawable.
199     *
200     * @return The bounds of the drawable (which may change later, so caller
201     *         beware). DO NOT ALTER the returned object as it may change the
202     *         stored bounds of this drawable.
203     *
204     * @see #copyBounds()
205     * @see #copyBounds(android.graphics.Rect)
206     */
207    public final Rect getBounds() {
208        if (mBounds == ZERO_BOUNDS_RECT) {
209            mBounds = new Rect();
210        }
211
212        return mBounds;
213    }
214
215    /**
216     * Set a mask of the configuration parameters for which this drawable
217     * may change, requiring that it be re-created.
218     *
219     * @param configs A mask of the changing configuration parameters, as
220     * defined by {@link android.content.res.Configuration}.
221     *
222     * @see android.content.res.Configuration
223     */
224    public void setChangingConfigurations(int configs) {
225        mChangingConfigurations = configs;
226    }
227
228    /**
229     * Return a mask of the configuration parameters for which this drawable
230     * may change, requiring that it be re-created.  The default implementation
231     * returns whatever was provided through
232     * {@link #setChangingConfigurations(int)} or 0 by default.  Subclasses
233     * may extend this to or in the changing configurations of any other
234     * drawables they hold.
235     *
236     * @return Returns a mask of the changing configuration parameters, as
237     * defined by {@link android.content.res.Configuration}.
238     *
239     * @see android.content.res.Configuration
240     */
241    public int getChangingConfigurations() {
242        return mChangingConfigurations;
243    }
244
245    /**
246     * Set to true to have the drawable dither its colors when drawn to a device
247     * with fewer than 8-bits per color component. This can improve the look on
248     * those devices, but can also slow down the drawing a little.
249     */
250    public void setDither(boolean dither) {}
251
252    /**
253     * Set to true to have the drawable filter its bitmap when scaled or rotated
254     * (for drawables that use bitmaps). If the drawable does not use bitmaps,
255     * this call is ignored. This can improve the look when scaled or rotated,
256     * but also slows down the drawing.
257     */
258    public void setFilterBitmap(boolean filter) {}
259
260    /**
261     * Implement this interface if you want to create an animated drawable that
262     * extends {@link android.graphics.drawable.Drawable Drawable}.
263     * Upon retrieving a drawable, use
264     * {@link Drawable#setCallback(android.graphics.drawable.Drawable.Callback)}
265     * to supply your implementation of the interface to the drawable; it uses
266     * this interface to schedule and execute animation changes.
267     */
268    public static interface Callback {
269        /**
270         * Called when the drawable needs to be redrawn.  A view at this point
271         * should invalidate itself (or at least the part of itself where the
272         * drawable appears).
273         *
274         * @param who The drawable that is requesting the update.
275         */
276        public void invalidateDrawable(Drawable who);
277
278        /**
279         * A Drawable can call this to schedule the next frame of its
280         * animation.  An implementation can generally simply call
281         * {@link android.os.Handler#postAtTime(Runnable, Object, long)} with
282         * the parameters <var>(what, who, when)</var> to perform the
283         * scheduling.
284         *
285         * @param who The drawable being scheduled.
286         * @param what The action to execute.
287         * @param when The time (in milliseconds) to run.  The timebase is
288         *             {@link android.os.SystemClock#uptimeMillis}
289         */
290        public void scheduleDrawable(Drawable who, Runnable what, long when);
291
292        /**
293         * A Drawable can call this to unschedule an action previously
294         * scheduled with {@link #scheduleDrawable}.  An implementation can
295         * generally simply call
296         * {@link android.os.Handler#removeCallbacks(Runnable, Object)} with
297         * the parameters <var>(what, who)</var> to unschedule the drawable.
298         *
299         * @param who The drawable being unscheduled.
300         * @param what The action being unscheduled.
301         */
302        public void unscheduleDrawable(Drawable who, Runnable what);
303    }
304
305    /**
306     * Bind a {@link Callback} object to this Drawable.  Required for clients
307     * that want to support animated drawables.
308     *
309     * @param cb The client's Callback implementation.
310     *
311     * @see #getCallback()
312     */
313    public final void setCallback(Callback cb) {
314        mCallback = new WeakReference<Callback>(cb);
315    }
316
317    /**
318     * Return the current {@link Callback} implementation attached to this
319     * Drawable.
320     *
321     * @return A {@link Callback} instance or null if no callback was set.
322     *
323     * @see #setCallback(android.graphics.drawable.Drawable.Callback)
324     */
325    public Callback getCallback() {
326        if (mCallback != null) {
327            return mCallback.get();
328        }
329        return null;
330    }
331
332    /**
333     * Use the current {@link Callback} implementation to have this Drawable
334     * redrawn.  Does nothing if there is no Callback attached to the
335     * Drawable.
336     *
337     * @see Callback#invalidateDrawable
338     * @see #getCallback()
339     * @see #setCallback(android.graphics.drawable.Drawable.Callback)
340     */
341    public void invalidateSelf() {
342        final Callback callback = getCallback();
343        if (callback != null) {
344            callback.invalidateDrawable(this);
345        }
346    }
347
348    /**
349     * Use the current {@link Callback} implementation to have this Drawable
350     * scheduled.  Does nothing if there is no Callback attached to the
351     * Drawable.
352     *
353     * @param what The action being scheduled.
354     * @param when The time (in milliseconds) to run.
355     *
356     * @see Callback#scheduleDrawable
357     */
358    public void scheduleSelf(Runnable what, long when) {
359        final Callback callback = getCallback();
360        if (callback != null) {
361            callback.scheduleDrawable(this, what, when);
362        }
363    }
364
365    /**
366     * Use the current {@link Callback} implementation to have this Drawable
367     * unscheduled.  Does nothing if there is no Callback attached to the
368     * Drawable.
369     *
370     * @param what The runnable that you no longer want called.
371     *
372     * @see Callback#unscheduleDrawable
373     */
374    public void unscheduleSelf(Runnable what) {
375        final Callback callback = getCallback();
376        if (callback != null) {
377            callback.unscheduleDrawable(this, what);
378        }
379    }
380
381    /**
382     * Returns the resolved layout direction for this Drawable.
383     *
384     * @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
385     *   {@link android.view.View#LAYOUT_DIRECTION_RTL}
386     *
387     * @hide
388     */
389    public int getLayoutDirection() {
390        return mLayoutDirection;
391    }
392
393    /**
394     * Set the layout direction for this drawable. Should be a resolved direction as the
395     * Drawable as no capacity to do the resolution on his own.
396     *
397     * @param layoutDirection One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
398     *   {@link android.view.View#LAYOUT_DIRECTION_RTL}
399     *
400     * @hide
401     */
402    public void setLayoutDirection(int layoutDirection) {
403        if (getLayoutDirection() != layoutDirection) {
404            mLayoutDirection = layoutDirection;
405        }
406    }
407
408    /**
409     * Specify an alpha value for the drawable. 0 means fully transparent, and
410     * 255 means fully opaque.
411     */
412    public abstract void setAlpha(int alpha);
413
414    /**
415     * Gets the current alpha value for the drawable. 0 means fully transparent,
416     * 255 means fully opaque. This method is implemented by
417     * Drawable subclasses and the value returned is specific to how that class treats alpha.
418     * The default return value is 255 if the class does not override this method to return a value
419     * specific to its use of alpha.
420     */
421    public int getAlpha() {
422        return 0xFF;
423    }
424
425    /**
426     * Specify an optional colorFilter for the drawable. Pass null to remove
427     * any filters.
428    */
429    public abstract void setColorFilter(ColorFilter cf);
430
431    /**
432     * @hide Consider for future API inclusion
433     */
434    public void setXfermode(Xfermode mode) {
435        // Base implementation drops it on the floor for compatibility. Whee!
436        // TODO: For this to be included in the API proper, all framework drawables need impls.
437        // For right now only BitmapDrawable has it.
438    }
439
440    /**
441     * Specify a color and porterduff mode to be the colorfilter for this
442     * drawable.
443     */
444    public void setColorFilter(int color, PorterDuff.Mode mode) {
445        setColorFilter(new PorterDuffColorFilter(color, mode));
446    }
447
448    public void clearColorFilter() {
449        setColorFilter(null);
450    }
451
452    /**
453     * Indicates whether this view will change its appearance based on state.
454     * Clients can use this to determine whether it is necessary to calculate
455     * their state and call setState.
456     *
457     * @return True if this view changes its appearance based on state, false
458     *         otherwise.
459     *
460     * @see #setState(int[])
461     */
462    public boolean isStateful() {
463        return false;
464    }
465
466    /**
467     * Specify a set of states for the drawable. These are use-case specific,
468     * so see the relevant documentation. As an example, the background for
469     * widgets like Button understand the following states:
470     * [{@link android.R.attr#state_focused},
471     *  {@link android.R.attr#state_pressed}].
472     *
473     * <p>If the new state you are supplying causes the appearance of the
474     * Drawable to change, then it is responsible for calling
475     * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
476     * true will be returned from this function.
477     *
478     * <p>Note: The Drawable holds a reference on to <var>stateSet</var>
479     * until a new state array is given to it, so you must not modify this
480     * array during that time.</p>
481     *
482     * @param stateSet The new set of states to be displayed.
483     *
484     * @return Returns true if this change in state has caused the appearance
485     * of the Drawable to change (hence requiring an invalidate), otherwise
486     * returns false.
487     */
488    public boolean setState(final int[] stateSet) {
489        if (!Arrays.equals(mStateSet, stateSet)) {
490            mStateSet = stateSet;
491            return onStateChange(stateSet);
492        }
493        return false;
494    }
495
496    /**
497     * Describes the current state, as a union of primitve states, such as
498     * {@link android.R.attr#state_focused},
499     * {@link android.R.attr#state_selected}, etc.
500     * Some drawables may modify their imagery based on the selected state.
501     * @return An array of resource Ids describing the current state.
502     */
503    public int[] getState() {
504        return mStateSet;
505    }
506
507    /**
508     * If this Drawable does transition animations between states, ask that
509     * it immediately jump to the current state and skip any active animations.
510     */
511    public void jumpToCurrentState() {
512    }
513
514    /**
515     * @return The current drawable that will be used by this drawable. For simple drawables, this
516     *         is just the drawable itself. For drawables that change state like
517     *         {@link StateListDrawable} and {@link LevelListDrawable} this will be the child drawable
518     *         currently in use.
519     */
520    public Drawable getCurrent() {
521        return this;
522    }
523
524    /**
525     * Specify the level for the drawable.  This allows a drawable to vary its
526     * imagery based on a continuous controller, for example to show progress
527     * or volume level.
528     *
529     * <p>If the new level you are supplying causes the appearance of the
530     * Drawable to change, then it is responsible for calling
531     * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
532     * true will be returned from this function.
533     *
534     * @param level The new level, from 0 (minimum) to 10000 (maximum).
535     *
536     * @return Returns true if this change in level has caused the appearance
537     * of the Drawable to change (hence requiring an invalidate), otherwise
538     * returns false.
539     */
540    public final boolean setLevel(int level) {
541        if (mLevel != level) {
542            mLevel = level;
543            return onLevelChange(level);
544        }
545        return false;
546    }
547
548    /**
549     * Retrieve the current level.
550     *
551     * @return int Current level, from 0 (minimum) to 10000 (maximum).
552     */
553    public final int getLevel() {
554        return mLevel;
555    }
556
557    /**
558     * Set whether this Drawable is visible.  This generally does not impact
559     * the Drawable's behavior, but is a hint that can be used by some
560     * Drawables, for example, to decide whether run animations.
561     *
562     * @param visible Set to true if visible, false if not.
563     * @param restart You can supply true here to force the drawable to behave
564     *                as if it has just become visible, even if it had last
565     *                been set visible.  Used for example to force animations
566     *                to restart.
567     *
568     * @return boolean Returns true if the new visibility is different than
569     *         its previous state.
570     */
571    public boolean setVisible(boolean visible, boolean restart) {
572        boolean changed = mVisible != visible;
573        if (changed) {
574            mVisible = visible;
575            invalidateSelf();
576        }
577        return changed;
578    }
579
580    public final boolean isVisible() {
581        return mVisible;
582    }
583
584    /**
585     * Set whether this Drawable is automatically mirrored when its layout direction is RTL
586     * (right-to left). See {@link android.util.LayoutDirection}.
587     *
588     * @param mirrored Set to true if the Drawable should be mirrored, false if not.
589     */
590    public void setAutoMirrored(boolean mirrored) {
591    }
592
593    /**
594     * Tells if this Drawable will be automatically mirrored  when its layout direction is RTL
595     * right-to-left. See {@link android.util.LayoutDirection}.
596     *
597     * @return boolean Returns true if this Drawable will be automatically mirrored.
598     */
599    public boolean isAutoMirrored() {
600        return false;
601    }
602
603    /**
604     * Return the opacity/transparency of this Drawable.  The returned value is
605     * one of the abstract format constants in
606     * {@link android.graphics.PixelFormat}:
607     * {@link android.graphics.PixelFormat#UNKNOWN},
608     * {@link android.graphics.PixelFormat#TRANSLUCENT},
609     * {@link android.graphics.PixelFormat#TRANSPARENT}, or
610     * {@link android.graphics.PixelFormat#OPAQUE}.
611     *
612     * <p>Generally a Drawable should be as conservative as possible with the
613     * value it returns.  For example, if it contains multiple child drawables
614     * and only shows one of them at a time, if only one of the children is
615     * TRANSLUCENT and the others are OPAQUE then TRANSLUCENT should be
616     * returned.  You can use the method {@link #resolveOpacity} to perform a
617     * standard reduction of two opacities to the appropriate single output.
618     *
619     * <p>Note that the returned value does <em>not</em> take into account a
620     * custom alpha or color filter that has been applied by the client through
621     * the {@link #setAlpha} or {@link #setColorFilter} methods.
622     *
623     * @return int The opacity class of the Drawable.
624     *
625     * @see android.graphics.PixelFormat
626     */
627    public abstract int getOpacity();
628
629    /**
630     * Return the appropriate opacity value for two source opacities.  If
631     * either is UNKNOWN, that is returned; else, if either is TRANSLUCENT,
632     * that is returned; else, if either is TRANSPARENT, that is returned;
633     * else, OPAQUE is returned.
634     *
635     * <p>This is to help in implementing {@link #getOpacity}.
636     *
637     * @param op1 One opacity value.
638     * @param op2 Another opacity value.
639     *
640     * @return int The combined opacity value.
641     *
642     * @see #getOpacity
643     */
644    public static int resolveOpacity(int op1, int op2) {
645        if (op1 == op2) {
646            return op1;
647        }
648        if (op1 == PixelFormat.UNKNOWN || op2 == PixelFormat.UNKNOWN) {
649            return PixelFormat.UNKNOWN;
650        }
651        if (op1 == PixelFormat.TRANSLUCENT || op2 == PixelFormat.TRANSLUCENT) {
652            return PixelFormat.TRANSLUCENT;
653        }
654        if (op1 == PixelFormat.TRANSPARENT || op2 == PixelFormat.TRANSPARENT) {
655            return PixelFormat.TRANSPARENT;
656        }
657        return PixelFormat.OPAQUE;
658    }
659
660    /**
661     * Returns a Region representing the part of the Drawable that is completely
662     * transparent.  This can be used to perform drawing operations, identifying
663     * which parts of the target will not change when rendering the Drawable.
664     * The default implementation returns null, indicating no transparent
665     * region; subclasses can optionally override this to return an actual
666     * Region if they want to supply this optimization information, but it is
667     * not required that they do so.
668     *
669     * @return Returns null if the Drawables has no transparent region to
670     * report, else a Region holding the parts of the Drawable's bounds that
671     * are transparent.
672     */
673    public Region getTransparentRegion() {
674        return null;
675    }
676
677    /**
678     * Override this in your subclass to change appearance if you recognize the
679     * specified state.
680     *
681     * @return Returns true if the state change has caused the appearance of
682     * the Drawable to change (that is, it needs to be drawn), else false
683     * if it looks the same and there is no need to redraw it since its
684     * last state.
685     */
686    protected boolean onStateChange(int[] state) { return false; }
687    /** Override this in your subclass to change appearance if you vary based
688     *  on level.
689     * @return Returns true if the level change has caused the appearance of
690     * the Drawable to change (that is, it needs to be drawn), else false
691     * if it looks the same and there is no need to redraw it since its
692     * last level.
693     */
694    protected boolean onLevelChange(int level) { return false; }
695    /**
696     * Override this in your subclass to change appearance if you recognize the
697     * specified state.
698     */
699    protected void onBoundsChange(Rect bounds) {}
700
701    /**
702     * Return the intrinsic width of the underlying drawable object.  Returns
703     * -1 if it has no intrinsic width, such as with a solid color.
704     */
705    public int getIntrinsicWidth() {
706        return -1;
707    }
708
709    /**
710     * Return the intrinsic height of the underlying drawable object. Returns
711     * -1 if it has no intrinsic height, such as with a solid color.
712     */
713    public int getIntrinsicHeight() {
714        return -1;
715    }
716
717    /**
718     * Returns the minimum width suggested by this Drawable. If a View uses this
719     * Drawable as a background, it is suggested that the View use at least this
720     * value for its width. (There will be some scenarios where this will not be
721     * possible.) This value should INCLUDE any padding.
722     *
723     * @return The minimum width suggested by this Drawable. If this Drawable
724     *         doesn't have a suggested minimum width, 0 is returned.
725     */
726    public int getMinimumWidth() {
727        final int intrinsicWidth = getIntrinsicWidth();
728        return intrinsicWidth > 0 ? intrinsicWidth : 0;
729    }
730
731    /**
732     * Returns the minimum height suggested by this Drawable. If a View uses this
733     * Drawable as a background, it is suggested that the View use at least this
734     * value for its height. (There will be some scenarios where this will not be
735     * possible.) This value should INCLUDE any padding.
736     *
737     * @return The minimum height suggested by this Drawable. If this Drawable
738     *         doesn't have a suggested minimum height, 0 is returned.
739     */
740    public int getMinimumHeight() {
741        final int intrinsicHeight = getIntrinsicHeight();
742        return intrinsicHeight > 0 ? intrinsicHeight : 0;
743    }
744
745    /**
746     * Return in padding the insets suggested by this Drawable for placing
747     * content inside the drawable's bounds. Positive values move toward the
748     * center of the Drawable (set Rect.inset). Returns true if this drawable
749     * actually has a padding, else false. When false is returned, the padding
750     * is always set to 0.
751     */
752    public boolean getPadding(Rect padding) {
753        padding.set(0, 0, 0, 0);
754        return false;
755    }
756
757    /**
758     * Return in insets the layout insets suggested by this Drawable for use with alignment
759     * operations during layout.
760     *
761     * @hide
762     */
763    public Insets getOpticalInsets() {
764        return Insets.NONE;
765    }
766
767    /**
768     * Make this drawable mutable. This operation cannot be reversed. A mutable
769     * drawable is guaranteed to not share its state with any other drawable.
770     * This is especially useful when you need to modify properties of drawables
771     * loaded from resources. By default, all drawables instances loaded from
772     * the same resource share a common state; if you modify the state of one
773     * instance, all the other instances will receive the same modification.
774     *
775     * Calling this method on a mutable Drawable will have no effect.
776     *
777     * @return This drawable.
778     * @see ConstantState
779     * @see #getConstantState()
780     */
781    public Drawable mutate() {
782        return this;
783    }
784
785    /**
786     * Create a drawable from an inputstream
787     */
788    public static Drawable createFromStream(InputStream is, String srcName) {
789        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
790        try {
791            return createFromResourceStream(null, null, is, srcName, null);
792        } finally {
793            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
794        }
795    }
796
797    /**
798     * Create a drawable from an inputstream, using the given resources and
799     * value to determine density information.
800     */
801    public static Drawable createFromResourceStream(Resources res, TypedValue value,
802            InputStream is, String srcName) {
803        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
804        try {
805            return createFromResourceStream(res, value, is, srcName, null);
806        } finally {
807            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
808        }
809    }
810
811    /**
812     * Create a drawable from an inputstream, using the given resources and
813     * value to determine density information.
814     */
815    public static Drawable createFromResourceStream(Resources res, TypedValue value,
816            InputStream is, String srcName, BitmapFactory.Options opts) {
817
818        if (is == null) {
819            return null;
820        }
821
822        /*  ugh. The decodeStream contract is that we have already allocated
823            the pad rect, but if the bitmap does not had a ninepatch chunk,
824            then the pad will be ignored. If we could change this to lazily
825            alloc/assign the rect, we could avoid the GC churn of making new
826            Rects only to drop them on the floor.
827        */
828        Rect pad = new Rect();
829
830        // Special stuff for compatibility mode: if the target density is not
831        // the same as the display density, but the resource -is- the same as
832        // the display density, then don't scale it down to the target density.
833        // This allows us to load the system's density-correct resources into
834        // an application in compatibility mode, without scaling those down
835        // to the compatibility density only to have them scaled back up when
836        // drawn to the screen.
837        if (opts == null) opts = new BitmapFactory.Options();
838        opts.inScreenDensity = res != null
839                ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
840        Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
841        if (bm != null) {
842            byte[] np = bm.getNinePatchChunk();
843            if (np == null || !NinePatch.isNinePatchChunk(np)) {
844                np = null;
845                pad = null;
846            }
847            int[] layoutBounds = bm.getLayoutBounds();
848            Rect layoutBoundsRect = null;
849            if (layoutBounds != null) {
850                layoutBoundsRect = new Rect(layoutBounds[0], layoutBounds[1],
851                                             layoutBounds[2], layoutBounds[3]);
852            }
853            return drawableFromBitmap(res, bm, np, pad, layoutBoundsRect, srcName);
854        }
855        return null;
856    }
857
858    /**
859     * Create a drawable from an XML document. For more information on how to
860     * create resources in XML, see
861     * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
862     */
863    public static Drawable createFromXml(Resources r, XmlPullParser parser)
864            throws XmlPullParserException, IOException {
865        AttributeSet attrs = Xml.asAttributeSet(parser);
866
867        int type;
868        while ((type=parser.next()) != XmlPullParser.START_TAG &&
869                type != XmlPullParser.END_DOCUMENT) {
870            // Empty loop
871        }
872
873        if (type != XmlPullParser.START_TAG) {
874            throw new XmlPullParserException("No start tag found");
875        }
876
877        Drawable drawable = createFromXmlInner(r, parser, attrs);
878
879        if (drawable == null) {
880            throw new RuntimeException("Unknown initial tag: " + parser.getName());
881        }
882
883        return drawable;
884    }
885
886    /**
887     * Create from inside an XML document.  Called on a parser positioned at
888     * a tag in an XML document, tries to create a Drawable from that tag.
889     * Returns null if the tag is not a valid drawable.
890     */
891    public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
892    throws XmlPullParserException, IOException {
893        Drawable drawable;
894
895        final String name = parser.getName();
896
897        if (name.equals("selector")) {
898            drawable = new StateListDrawable();
899        } else if (name.equals("level-list")) {
900            drawable = new LevelListDrawable();
901        } else if (name.equals("layer-list")) {
902            drawable = new LayerDrawable();
903        } else if (name.equals("transition")) {
904            drawable = new TransitionDrawable();
905        } else if (name.equals("color")) {
906            drawable = new ColorDrawable();
907        } else if (name.equals("shape")) {
908            drawable = new GradientDrawable();
909        } else if (name.equals("scale")) {
910            drawable = new ScaleDrawable();
911        } else if (name.equals("clip")) {
912            drawable = new ClipDrawable();
913        } else if (name.equals("rotate")) {
914            drawable = new RotateDrawable();
915        } else if (name.equals("animated-rotate")) {
916            drawable = new AnimatedRotateDrawable();
917        } else if (name.equals("animation-list")) {
918            drawable = new AnimationDrawable();
919        } else if (name.equals("inset")) {
920            drawable = new InsetDrawable();
921        } else if (name.equals("bitmap")) {
922            //noinspection deprecation
923            drawable = new BitmapDrawable(r);
924            if (r != null) {
925               ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
926            }
927        } else if (name.equals("nine-patch")) {
928            drawable = new NinePatchDrawable();
929            if (r != null) {
930                ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
931             }
932        } else {
933            throw new XmlPullParserException(parser.getPositionDescription() +
934                    ": invalid drawable tag " + name);
935        }
936
937        drawable.inflate(r, parser, attrs);
938        return drawable;
939    }
940
941
942    /**
943     * Create a drawable from file path name.
944     */
945    public static Drawable createFromPath(String pathName) {
946        if (pathName == null) {
947            return null;
948        }
949
950        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
951        try {
952            Bitmap bm = BitmapFactory.decodeFile(pathName);
953            if (bm != null) {
954                return drawableFromBitmap(null, bm, null, null, null, pathName);
955            }
956        } finally {
957            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
958        }
959
960        return null;
961    }
962
963    /**
964     * Inflate this Drawable from an XML resource.
965     */
966    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
967            throws XmlPullParserException, IOException {
968
969        TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.Drawable);
970        inflateWithAttributes(r, parser, a, com.android.internal.R.styleable.Drawable_visible);
971        a.recycle();
972    }
973
974    /**
975     * Inflate a Drawable from an XML resource.
976     *
977     * @throws XmlPullParserException
978     * @throws IOException
979     */
980    void inflateWithAttributes(Resources r, XmlPullParser parser,
981            TypedArray attrs, int visibleAttr)
982            throws XmlPullParserException, IOException {
983
984        mVisible = attrs.getBoolean(visibleAttr, mVisible);
985    }
986
987    /**
988     * This abstract class is used by {@link Drawable}s to store shared constant state and data
989     * between Drawables. {@link BitmapDrawable}s created from the same resource will for instance
990     * share a unique bitmap stored in their ConstantState.
991     *
992     * <p>
993     * {@link #newDrawable(Resources)} can be used as a factory to create new Drawable instances
994     * from this ConstantState.
995     * </p>
996     *
997     * Use {@link Drawable#getConstantState()} to retrieve the ConstantState of a Drawable. Calling
998     * {@link Drawable#mutate()} on a Drawable should typically create a new ConstantState for that
999     * Drawable.
1000     */
1001    public static abstract class ConstantState {
1002        /**
1003         * Create a new drawable without supplying resources the caller
1004         * is running in.  Note that using this means the density-dependent
1005         * drawables (like bitmaps) will not be able to update their target
1006         * density correctly. One should use {@link #newDrawable(Resources)}
1007         * instead to provide a resource.
1008         */
1009        public abstract Drawable newDrawable();
1010        /**
1011         * Create a new Drawable instance from its constant state.  This
1012         * must be implemented for drawables that change based on the target
1013         * density of their caller (that is depending on whether it is
1014         * in compatibility mode).
1015         */
1016        public Drawable newDrawable(Resources res) {
1017            return newDrawable();
1018        }
1019        /**
1020         * Return a bit mask of configuration changes that will impact
1021         * this drawable (and thus require completely reloading it).
1022         */
1023        public abstract int getChangingConfigurations();
1024
1025        /**
1026         * @hide
1027         */
1028        public Bitmap getBitmap() {
1029            return null;
1030        }
1031    }
1032
1033    /**
1034     * Return a {@link ConstantState} instance that holds the shared state of this Drawable.
1035     *q
1036     * @return The ConstantState associated to that Drawable.
1037     * @see ConstantState
1038     * @see Drawable#mutate()
1039     */
1040    public ConstantState getConstantState() {
1041        return null;
1042    }
1043
1044    private static Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np,
1045            Rect pad, Rect layoutBounds, String srcName) {
1046
1047        if (np != null) {
1048            return new NinePatchDrawable(res, bm, np, pad, layoutBounds, srcName);
1049        }
1050
1051        return new BitmapDrawable(res, bm);
1052    }
1053}
1054
1055