BitmapDrawable.java revision 3f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aa
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.BitmapFactory;
23b1216dd916e0f5fdec29684120c5bcc904800916Romain Guyimport android.graphics.BitmapShader;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter;
263f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglioimport android.graphics.Matrix;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Shader;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.DisplayMetrics;
333f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglioimport android.util.LayoutDirection;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * BitmapDrawable from a file path, an input stream, through XML inflation, or from
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link android.graphics.Bitmap} object.
44dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code>&lt;bitmap></code> element.  For more
45dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a
46dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Also see the {@link android.graphics.Bitmap} class, which handles the management and
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * transformation of raw bitmap graphics, and should be used when drawing to a
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.graphics.Canvas}.
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p>
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_src
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_antialias
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_filter
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_dither
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_gravity
58b40c1fdaee6e6cabea8d1ed78f56d5b6bd133cfbScott Main * @attr ref android.R.styleable#BitmapDrawable_mipMap
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_tileMode
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class BitmapDrawable extends Drawable {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
63211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed    private static final int DEFAULT_PAINT_FLAGS =
64211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed            Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private BitmapState mBitmapState;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bitmap mBitmap;
67c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private int mTargetDensity;
68c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Rect mDstRect = new Rect();   // Gravity.apply() sets this
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mApplyGravity;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mMutated;
7311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
74c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     // These are scaled to match the target density.
7511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private int mBitmapWidth;
7611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private int mBitmapHeight;
773f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
783f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    // Mirroring matrix for using with Shaders
793f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    private Matrix mMirrorMatrix;
803f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
8111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
8211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create an empty drawable, not dealing with density.
837ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy     * @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)}
847ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy     * instead to specify a bitmap to draw with and ensure the correct density is set.
8511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
864a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public BitmapDrawable() {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState = new BitmapState((Bitmap) null);
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
9211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create an empty drawable, setting initial target density based on
9311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * the display metrics of the resources.
947ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy     * @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)}
957ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy     * instead to specify a bitmap to draw with.
9611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
977ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy    @Deprecated
98ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    @SuppressWarnings({"UnusedParameters"})
9911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public BitmapDrawable(Resources res) {
10011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mBitmapState = new BitmapState((Bitmap) null);
101c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mBitmapState.mTargetDensity = mTargetDensity;
10211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
10311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
10411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
10511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create drawable from a bitmap, not dealing with density.
10611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure
10711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * that the drawable has correctly set its target density.
10811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
1094a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public BitmapDrawable(Bitmap bitmap) {
111c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new BitmapState(bitmap), null);
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
11511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create drawable from a bitmap, setting initial target density based on
11611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * the display metrics of the resources.
11711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
11811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public BitmapDrawable(Resources res, Bitmap bitmap) {
119c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new BitmapState(bitmap), res);
120c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mBitmapState.mTargetDensity = mTargetDensity;
12111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
12211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
123c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    /**
124c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * Create a drawable by opening a given file path and decoding the bitmap.
125c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * @deprecated Use {@link #BitmapDrawable(Resources, String)} to ensure
126c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * that the drawable has correctly set its target density.
127c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     */
12829e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn    @Deprecated
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public BitmapDrawable(String filepath) {
130c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
131c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        if (mBitmap == null) {
132c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
133c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
134c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    }
135c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
136c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    /**
137c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * Create a drawable by opening a given file path and decoding the bitmap.
138c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     */
139ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    @SuppressWarnings({"UnusedParameters"})
140c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    public BitmapDrawable(Resources res, String filepath) {
141c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
142c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mBitmapState.mTargetDensity = mTargetDensity;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBitmap == null) {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
148c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    /**
149c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * Create a drawable by decoding a bitmap from the given input stream.
150c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * @deprecated Use {@link #BitmapDrawable(Resources, java.io.InputStream)} to ensure
151c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * that the drawable has correctly set its target density.
152c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     */
15329e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn    @Deprecated
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public BitmapDrawable(java.io.InputStream is) {
155c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
156c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        if (mBitmap == null) {
157c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
158c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
159c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    }
160c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn
161c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    /**
162c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     * Create a drawable by decoding a bitmap from the given input stream.
163c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn     */
164ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    @SuppressWarnings({"UnusedParameters"})
165c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    public BitmapDrawable(Resources res, java.io.InputStream is) {
166c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
167c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mBitmapState.mTargetDensity = mTargetDensity;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBitmap == null) {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
173ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
174ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Returns the paint used to render this drawable.
175ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Paint getPaint() {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmapState.mPaint;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
179ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy
180ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
181ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Returns the bitmap used by this drawable to render. May be null.
182ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Bitmap getBitmap() {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmap;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private void computeBitmapSize() {
18811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
18911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
19011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
19111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setBitmap(Bitmap bitmap) {
1939891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (bitmap != mBitmap) {
1949891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mBitmap = bitmap;
1959891e1fce5f29d0421d34aa481037417bd70853dChet Haase            if (bitmap != null) {
1969891e1fce5f29d0421d34aa481037417bd70853dChet Haase                computeBitmapSize();
1979891e1fce5f29d0421d34aa481037417bd70853dChet Haase            } else {
1989891e1fce5f29d0421d34aa481037417bd70853dChet Haase                mBitmapWidth = mBitmapHeight = -1;
1999891e1fce5f29d0421d34aa481037417bd70853dChet Haase            }
2009891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the density scale at which this drawable will be rendered. This
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * method assumes the drawable will be rendered at the same density as the
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * specified canvas.
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param canvas The Canvas from which the density scale must be obtained.
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
21111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#setDensity(int)
21211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#getDensity()
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public void setTargetDensity(Canvas canvas) {
21511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        setTargetDensity(canvas.getDensity());
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the density scale at which this drawable will be rendered.
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param metrics The DisplayMetrics indicating the density scale for this drawable.
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
22311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#setDensity(int)
22411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#getDensity()
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public void setTargetDensity(DisplayMetrics metrics) {
2279891e1fce5f29d0421d34aa481037417bd70853dChet Haase        setTargetDensity(metrics.densityDpi);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
23111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Set the density at which this drawable will be rendered.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param density The density scale for this drawable.
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
23511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#setDensity(int)
23611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#getDensity()
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public void setTargetDensity(int density) {
2399891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (mTargetDensity != density) {
2409891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
2419891e1fce5f29d0421d34aa481037417bd70853dChet Haase            if (mBitmap != null) {
2429891e1fce5f29d0421d34aa481037417bd70853dChet Haase                computeBitmapSize();
2439891e1fce5f29d0421d34aa481037417bd70853dChet Haase            }
2449891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
24511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Get the gravity used to position/stretch the bitmap within its bounds.
24911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * See android.view.Gravity
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the gravity applied to the bitmap
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getGravity() {
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmapState.mGravity;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2555769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Set the gravity used to position/stretch the bitmap within its bounds.
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        See android.view.Gravity
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity the gravity
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGravity(int gravity) {
2619891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (mBitmapState.mGravity != gravity) {
2629891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mBitmapState.mGravity = gravity;
2639891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mApplyGravity = true;
2649891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
2659891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
268ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
2695769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * Enables or disables the mipmap hint for this drawable's bitmap.
2705769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * See {@link Bitmap#setHasMipMap(boolean)} for more information.
2715769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
2725769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * If the bitmap is null calling this method has no effect.
2735769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
2745769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @param mipMap True if the bitmap should use mipmaps, false otherwise.
2755769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
2765769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @see #hasMipMap()
2775769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     */
2785769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    public void setMipMap(boolean mipMap) {
2795769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy        if (mBitmapState.mBitmap != null) {
2805769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy            mBitmapState.mBitmap.setHasMipMap(mipMap);
2815769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy            invalidateSelf();
2825769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy        }
2835769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    }
2845769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy
2855769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    /**
2865769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * Indicates whether the mipmap hint is enabled on this drawable's bitmap.
2875769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
2885769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @return True if the mipmap hint is set, false otherwise. If the bitmap
2895769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *         is null, this method always returns false.
2905769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
2915769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @see #setMipMap(boolean)
292b40c1fdaee6e6cabea8d1ed78f56d5b6bd133cfbScott Main     * @attr ref android.R.styleable#BitmapDrawable_mipMap
2935769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     */
2945769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    public boolean hasMipMap() {
2955769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy        return mBitmapState.mBitmap != null && mBitmapState.mBitmap.hasMipMap();
2965769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    }
2975769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy
2985769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    /**
299ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects
300ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * the edges of the bitmap only so it applies only when the drawable is rotated.
301ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
302ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @param aa True if the bitmap should be anti-aliased, false otherwise.
3035769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
3045769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @see #hasAntiAlias()
305ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAntiAlias(boolean aa) {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState.mPaint.setAntiAlias(aa);
3089891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3105769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy
3115769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    /**
3125769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * Indicates whether anti-aliasing is enabled for this drawable.
3135769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
3145769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @return True if anti-aliasing is enabled, false otherwise.
3155769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     *
3165769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     * @see #setAntiAlias(boolean)
3175769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy     */
3185769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    public boolean hasAntiAlias() {
3195769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy        return mBitmapState.mPaint.isAntiAlias();
3205769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy    }
3215769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFilterBitmap(boolean filter) {
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState.mPaint.setFilterBitmap(filter);
3259891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState.mPaint.setDither(dither);
3319891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
334ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
335ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Indicates the repeat behavior of this drawable on the X axis.
336ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
337ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @return {@link Shader.TileMode#CLAMP} if the bitmap does not repeat,
338ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *         {@link Shader.TileMode#REPEAT} or {@link Shader.TileMode#MIRROR} otherwise.
339ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Shader.TileMode getTileModeX() {
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmapState.mTileModeX;
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
344ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
345ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Indicates the repeat behavior of this drawable on the Y axis.
346ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
347ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @return {@link Shader.TileMode#CLAMP} if the bitmap does not repeat,
348ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *         {@link Shader.TileMode#REPEAT} or {@link Shader.TileMode#MIRROR} otherwise.
349ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Shader.TileMode getTileModeY() {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmapState.mTileModeY;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
354ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
355ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Sets the repeat behavior of this drawable on the X axis. By default, the drawable
356ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or
357ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap
358ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * is smaller than this drawable.
359ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
360ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @param mode The repeat mode for this drawable.
361ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
362ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @see #setTileModeY(android.graphics.Shader.TileMode)
363ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode)
364ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTileModeX(Shader.TileMode mode) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setTileModeXY(mode, mBitmapState.mTileModeY);
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
370ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Sets the repeat behavior of this drawable on the Y axis. By default, the drawable
371ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or
372ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap
373ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * is smaller than this drawable.
374ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
375ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @param mode The repeat mode for this drawable.
376ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
377ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @see #setTileModeX(android.graphics.Shader.TileMode)
378ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode)
379ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final void setTileModeY(Shader.TileMode mode) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setTileModeXY(mBitmapState.mTileModeX, mode);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
384ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy    /**
385ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * Sets the repeat behavior of this drawable on both axis. By default, the drawable
386ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or
387ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap
388ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * is smaller than this drawable.
389ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
390ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @param xmode The X repeat mode for this drawable.
391ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @param ymode The Y repeat mode for this drawable.
392ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     *
393ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @see #setTileModeX(android.graphics.Shader.TileMode)
394ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     * @see #setTileModeY(android.graphics.Shader.TileMode)
395ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy     */
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final BitmapState state = mBitmapState;
398ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy        if (state.mTileModeX != xmode || state.mTileModeY != ymode) {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            state.mTileModeX = xmode;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            state.mTileModeY = ymode;
4012660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy            state.mRebuildShader = true;
4029891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4073f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public void setAutoMirrored(boolean mirrored) {
4083f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        if (mBitmapState.mAutoMirrored != mirrored) {
4093f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            mBitmapState.mAutoMirrored = mirrored;
4103f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            invalidateSelf();
4113f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
4123f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
4133f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
4143f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
4153f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public final boolean isAutoMirrored() {
4163f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        return mBitmapState.mAutoMirrored;
4173f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
4183f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
4193f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChangingConfigurations() {
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4233f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
4243f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    private boolean needMirroring() {
4253f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
4263f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
4273f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
4283f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    private void updateMirrorMatrix(float dx) {
4293f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        if (mMirrorMatrix == null) {
4303f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            mMirrorMatrix = new Matrix();
4313f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
4323f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        mMirrorMatrix.setTranslate(dx, 0);
4333f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        mMirrorMatrix.preScale(-1.0f, 1.0f);
4343f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
4353f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect bounds) {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onBoundsChange(bounds);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mApplyGravity = true;
4403f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        Shader shader = mBitmapState.mPaint.getShader();
4413f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        if (shader != null) {
4423f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            if (needMirroring()) {
4433f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                updateMirrorMatrix(bounds.right - bounds.left);
4443f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                shader.setLocalMatrix(mMirrorMatrix);
4453f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            } else {
4463f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                if (mMirrorMatrix != null) {
4473f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    mMirrorMatrix = null;
4483f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
4493f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                }
4503f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            }
4513f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bitmap = mBitmap;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bitmap != null) {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final BitmapState state = mBitmapState;
4592660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy            if (state.mRebuildShader) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Shader.TileMode tmx = state.mTileModeX;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Shader.TileMode tmy = state.mTileModeY;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (tmx == null && tmy == null) {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    state.mPaint.setShader(null);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
466ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy                    state.mPaint.setShader(new BitmapShader(bitmap,
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tmx == null ? Shader.TileMode.CLAMP : tmx,
468ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy                            tmy == null ? Shader.TileMode.CLAMP : tmy));
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4702660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy                state.mRebuildShader = false;
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                copyBounds(mDstRect);
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Shader shader = state.mPaint.getShader();
4753f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            final boolean needMirroring = needMirroring();
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (shader == null) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mApplyGravity) {
478b03b434089cf2106c467b2827a65e5c589c91d01Fabrice Di Meglio                    final int layoutDirection = getLayoutDirection();
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
480c0053223bedf33581b0830fb87be32c1f26e5372Fabrice Di Meglio                            getBounds(), mDstRect, layoutDirection);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mApplyGravity = false;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4833f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                if (needMirroring) {
4843f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    canvas.save();
4853f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    // Mirror the bitmap
4863f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    canvas.translate(mDstRect.right - mDstRect.left, 0);
4873f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    canvas.scale(-1.0f, 1.0f);
4883f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                }
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawBitmap(bitmap, null, mDstRect, state.mPaint);
4903f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                if (needMirroring) {
4913f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    canvas.restore();
4923f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mApplyGravity) {
495ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy                    copyBounds(mDstRect);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mApplyGravity = false;
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4983f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                if (needMirroring) {
4993f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    // Mirror the bitmap
5003f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    updateMirrorMatrix(mDstRect.right - mDstRect.left);
5013f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    shader.setLocalMatrix(mMirrorMatrix);
5023f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                } else {
5033f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    if (mMirrorMatrix != null) {
5043f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                        mMirrorMatrix = null;
5053f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                        shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
5063f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                    }
5073f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawRect(mDstRect, state.mPaint);
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
515ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase        int oldAlpha = mBitmapState.mPaint.getAlpha();
516ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase        if (alpha != oldAlpha) {
517ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase            mBitmapState.mPaint.setAlpha(alpha);
518ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase            invalidateSelf();
519ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase        }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
521b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
522b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
523b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
524b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return mBitmapState.mPaint.getAlpha();
525b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setColorFilter(ColorFilter cf) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState.mPaint.setColorFilter(cf);
5309891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A mutable BitmapDrawable still shares its Bitmap with any other Drawable
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that comes from the same resource.
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This drawable.
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBitmapState = new BitmapState(mBitmapState);
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.inflate(r, parser, attrs);
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.BitmapDrawable);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int id = a.getResourceId(com.android.internal.R.styleable.BitmapDrawable_src, 0);
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id == 0) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(parser.getPositionDescription() +
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ": <bitmap> requires a valid src attribute");
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Bitmap bitmap = BitmapFactory.decodeResource(r, id);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bitmap == null) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(parser.getPositionDescription() +
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ": <bitmap> requires a valid src attribute");
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState.mBitmap = bitmap;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setBitmap(bitmap);
56711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        setTargetDensity(r.getDisplayMetrics());
5685769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy        setMipMap(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_mipMap,
5695769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy                bitmap.hasMipMap()));
5703f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        setAutoMirrored(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_autoMirrored,
5713f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                false));
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Paint paint = mBitmapState.mPaint;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias,
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                paint.isAntiAlias()));
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        paint.setFilterBitmap(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_filter,
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                paint.isFilterBitmap()));
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        paint.setDither(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_dither,
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                paint.isDither()));
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setGravity(a.getInt(com.android.internal.R.styleable.BitmapDrawable_gravity, Gravity.FILL));
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int tileMode = a.getInt(com.android.internal.R.styleable.BitmapDrawable_tileMode, -1);
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tileMode != -1) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (tileMode) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case 0:
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case 1:
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case 2:
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setTileModeXY(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
60111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmapWidth;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
60611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmapHeight;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBitmapState.mGravity != Gravity.FILL) {
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return PixelFormat.TRANSLUCENT;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bm = mBitmap;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (bm == null || bm.hasAlpha() || mBitmapState.mPaint.getAlpha() < 255) ?
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final ConstantState getConstantState() {
6216efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais        mBitmapState.mChangingConfigurations = getChangingConfigurations();
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmapState;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final static class BitmapState extends ConstantState {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap mBitmap;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mChangingConfigurations;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mGravity = Gravity.FILL;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
630ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy        Shader.TileMode mTileModeX = null;
631ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy        Shader.TileMode mTileModeY = null;
63211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
6332660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy        boolean mRebuildShader;
6343f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        boolean mAutoMirrored;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BitmapState(Bitmap bitmap) {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBitmap = bitmap;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BitmapState(BitmapState bitmapState) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            this(bitmapState.mBitmap);
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChangingConfigurations = bitmapState.mChangingConfigurations;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGravity = bitmapState.mGravity;
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTileModeX = bitmapState.mTileModeX;
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTileModeY = bitmapState.mTileModeY;
64611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            mTargetDensity = bitmapState.mTargetDensity;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPaint = new Paint(bitmapState.mPaint);
6482660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy            mRebuildShader = bitmapState.mRebuildShader;
6493f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            mAutoMirrored = bitmapState.mAutoMirrored;
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
6533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        public Bitmap getBitmap() {
6543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            return mBitmap;
6553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        }
6563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
6573b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        @Override
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
659c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new BitmapDrawable(this, null);
660c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
6612660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy
662c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
663c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
664c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new BitmapDrawable(this, res);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6662660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getChangingConfigurations() {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mChangingConfigurations;
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
673c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private BitmapDrawable(BitmapState state, Resources res) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmapState = state;
675c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        if (res != null) {
676c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            mTargetDensity = res.getDisplayMetrics().densityDpi;
677c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        } else {
678e42143aa575dcb8ab0616080b2e9b4614a1a4167Jozef BABJAK            mTargetDensity = state.mTargetDensity;
679c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
680ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy        setBitmap(state != null ? state.mBitmap : null);
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
683