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; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Shader; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.DisplayMetrics; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * BitmapDrawable from a file path, an input stream, through XML inflation, or from 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link android.graphics.Bitmap} object. 42dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code><bitmap></code> element. For more 43dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a 44dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p> 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Also see the {@link android.graphics.Bitmap} class, which handles the management and 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * transformation of raw bitmap graphics, and should be used when drawing to a 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.graphics.Canvas}. 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_src 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_antialias 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_filter 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_dither 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_gravity 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_tileMode 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class BitmapDrawable extends Drawable { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 60211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed private static final int DEFAULT_PAINT_FLAGS = 61211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BitmapState mBitmapState; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Bitmap mBitmap; 64c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn private int mTargetDensity; 65c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Rect mDstRect = new Rect(); // Gravity.apply() sets this 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mApplyGravity; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMutated; 7011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 71c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn // These are scaled to match the target density. 7211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private int mBitmapWidth; 7311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private int mBitmapHeight; 7411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 7511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 7611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create an empty drawable, not dealing with density. 7711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources)} to ensure 7811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * that the drawable has correctly set its target density. 7911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 804a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn @Deprecated 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable() { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = new BitmapState((Bitmap) null); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 8611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create an empty drawable, setting initial target density based on 8711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * the display metrics of the resources. 8811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 89ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy @SuppressWarnings({"UnusedParameters"}) 9011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public BitmapDrawable(Resources res) { 9111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mBitmapState = new BitmapState((Bitmap) null); 92c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 9311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 9411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 9511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 9611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create drawable from a bitmap, not dealing with density. 9711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure 9811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * that the drawable has correctly set its target density. 9911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1004a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn @Deprecated 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(Bitmap bitmap) { 102c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(new BitmapState(bitmap), null); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 10611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create drawable from a bitmap, setting initial target density based on 10711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * the display metrics of the resources. 10811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 10911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public BitmapDrawable(Resources res, Bitmap bitmap) { 110c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(new BitmapState(bitmap), res); 111c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 11211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 11311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 114c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 115c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by opening a given file path and decoding the bitmap. 116c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, String)} to ensure 117c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * that the drawable has correctly set its target density. 118c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 11929e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn @Deprecated 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(String filepath) { 121c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); 122c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn if (mBitmap == null) { 123c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); 124c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 125c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 126c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 127c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 128c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by opening a given file path and decoding the bitmap. 129c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 130ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy @SuppressWarnings({"UnusedParameters"}) 131c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public BitmapDrawable(Resources res, String filepath) { 132c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); 133c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBitmap == null) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 139c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 140c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by decoding a bitmap from the given input stream. 141c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, java.io.InputStream)} to ensure 142c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * that the drawable has correctly set its target density. 143c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 14429e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn @Deprecated 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(java.io.InputStream is) { 146c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(new BitmapState(BitmapFactory.decodeStream(is)), null); 147c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn if (mBitmap == null) { 148c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); 149c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 150c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 151c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 152c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 153c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by decoding a bitmap from the given input stream. 154c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 155ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy @SuppressWarnings({"UnusedParameters"}) 156c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public BitmapDrawable(Resources res, java.io.InputStream is) { 157c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn this(new BitmapState(BitmapFactory.decodeStream(is)), null); 158c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBitmap == null) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 164ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 165ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Returns the paint used to render this drawable. 166ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Paint getPaint() { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mPaint; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 170ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy 171ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 172ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Returns the bitmap used by this drawable to render. May be null. 173ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Bitmap getBitmap() { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmap; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private void computeBitmapSize() { 17911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity); 18011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity); 18111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 18211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setBitmap(Bitmap bitmap) { 1849891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (bitmap != mBitmap) { 1859891e1fce5f29d0421d34aa481037417bd70853dChet Haase mBitmap = bitmap; 1869891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (bitmap != null) { 1879891e1fce5f29d0421d34aa481037417bd70853dChet Haase computeBitmapSize(); 1889891e1fce5f29d0421d34aa481037417bd70853dChet Haase } else { 1899891e1fce5f29d0421d34aa481037417bd70853dChet Haase mBitmapWidth = mBitmapHeight = -1; 1909891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 1919891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the density scale at which this drawable will be rendered. This 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method assumes the drawable will be rendered at the same density as the 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified canvas. 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param canvas The Canvas from which the density scale must be obtained. 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 20211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 20311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(Canvas canvas) { 20611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn setTargetDensity(canvas.getDensity()); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the density scale at which this drawable will be rendered. 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param metrics The DisplayMetrics indicating the density scale for this drawable. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 21511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 21711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(DisplayMetrics metrics) { 2189891e1fce5f29d0421d34aa481037417bd70853dChet Haase setTargetDensity(metrics.densityDpi); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 22211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Set the density at which this drawable will be rendered. 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param density The density scale for this drawable. 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 22611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 22711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 22911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(int density) { 2309891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mTargetDensity != density) { 2319891e1fce5f29d0421d34aa481037417bd70853dChet Haase mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density; 2329891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mBitmap != null) { 2339891e1fce5f29d0421d34aa481037417bd70853dChet Haase computeBitmapSize(); 2349891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 2359891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 23611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Get the gravity used to position/stretch the bitmap within its bounds. 24011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * See android.view.Gravity 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the gravity applied to the bitmap 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getGravity() { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mGravity; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Set the gravity used to position/stretch the bitmap within its bounds. 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project See android.view.Gravity 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gravity the gravity 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGravity(int gravity) { 2529891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mBitmapState.mGravity != gravity) { 2539891e1fce5f29d0421d34aa481037417bd70853dChet Haase mBitmapState.mGravity = gravity; 2549891e1fce5f29d0421d34aa481037417bd70853dChet Haase mApplyGravity = true; 2559891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2569891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 260ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects 261ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * the edges of the bitmap only so it applies only when the drawable is rotated. 262ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 263ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param aa True if the bitmap should be anti-aliased, false otherwise. 264ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAntiAlias(boolean aa) { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setAntiAlias(aa); 2679891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilterBitmap(boolean filter) { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setFilterBitmap(filter); 2739891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDither(boolean dither) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setDither(dither); 2799891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 282ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 283ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Indicates the repeat behavior of this drawable on the X axis. 284ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 285ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @return {@link Shader.TileMode#CLAMP} if the bitmap does not repeat, 286ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * {@link Shader.TileMode#REPEAT} or {@link Shader.TileMode#MIRROR} otherwise. 287ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Shader.TileMode getTileModeX() { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mTileModeX; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 292ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 293ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Indicates the repeat behavior of this drawable on the Y axis. 294ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 295ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @return {@link Shader.TileMode#CLAMP} if the bitmap does not repeat, 296ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * {@link Shader.TileMode#REPEAT} or {@link Shader.TileMode#MIRROR} otherwise. 297ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Shader.TileMode getTileModeY() { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mTileModeY; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 302ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 303ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on the X axis. By default, the drawable 304ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or 305ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap 306ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * is smaller than this drawable. 307ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 308ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param mode The repeat mode for this drawable. 309ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 310ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeY(android.graphics.Shader.TileMode) 311ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 312ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTileModeX(Shader.TileMode mode) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(mode, mBitmapState.mTileModeY); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 317ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 318ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on the Y axis. By default, the drawable 319ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or 320ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap 321ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * is smaller than this drawable. 322ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 323ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param mode The repeat mode for this drawable. 324ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 325ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeX(android.graphics.Shader.TileMode) 326ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 327ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final void setTileModeY(Shader.TileMode mode) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(mBitmapState.mTileModeX, mode); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 332ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 333ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on both axis. By default, the drawable 334ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or 335ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap 336ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * is smaller than this drawable. 337ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 338ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param xmode The X repeat mode for this drawable. 339ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param ymode The Y repeat mode for this drawable. 340ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * 341ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeX(android.graphics.Shader.TileMode) 342ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeY(android.graphics.Shader.TileMode) 343ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final BitmapState state = mBitmapState; 346ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy if (state.mTileModeX != xmode || state.mTileModeY != ymode) { 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mTileModeX = xmode; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mTileModeY = ymode; 3492660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy state.mRebuildShader = true; 3509891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(Rect bounds) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onBoundsChange(bounds); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mApplyGravity = true; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(Canvas canvas) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bitmap bitmap = mBitmap; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bitmap != null) { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final BitmapState state = mBitmapState; 3702660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy if (state.mRebuildShader) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Shader.TileMode tmx = state.mTileModeX; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Shader.TileMode tmy = state.mTileModeY; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tmx == null && tmy == null) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mPaint.setShader(null); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 377ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy state.mPaint.setShader(new BitmapShader(bitmap, 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmx == null ? Shader.TileMode.CLAMP : tmx, 379ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy tmy == null ? Shader.TileMode.CLAMP : tmy)); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3812660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy state.mRebuildShader = false; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project copyBounds(mDstRect); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Shader shader = state.mPaint.getShader(); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (shader == null) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mApplyGravity) { 388b03b434089cf2106c467b2827a65e5c589c91d01Fabrice Di Meglio final int layoutDirection = getLayoutDirection(); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight, 390c0053223bedf33581b0830fb87be32c1f26e5372Fabrice Di Meglio getBounds(), mDstRect, layoutDirection); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mApplyGravity = false; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawBitmap(bitmap, null, mDstRect, state.mPaint); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mApplyGravity) { 396ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy copyBounds(mDstRect); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mApplyGravity = false; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawRect(mDstRect, state.mPaint); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAlpha(int alpha) { 406ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase int oldAlpha = mBitmapState.mPaint.getAlpha(); 407ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase if (alpha != oldAlpha) { 408ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase mBitmapState.mPaint.setAlpha(alpha); 409ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase invalidateSelf(); 410ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase } 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setColorFilter(ColorFilter cf) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setColorFilter(cf); 4169891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A mutable BitmapDrawable still shares its Bitmap with any other Drawable 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that comes from the same resource. 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This drawable. 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable mutate() { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mMutated && super.mutate() == this) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = new BitmapState(mBitmapState); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMutated = true; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.inflate(r, parser, attrs); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.BitmapDrawable); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = a.getResourceId(com.android.internal.R.styleable.BitmapDrawable_src, 0); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (id == 0) { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new XmlPullParserException(parser.getPositionDescription() + 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ": <bitmap> requires a valid src attribute"); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Bitmap bitmap = BitmapFactory.decodeResource(r, id); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bitmap == null) { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new XmlPullParserException(parser.getPositionDescription() + 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ": <bitmap> requires a valid src attribute"); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mBitmap = bitmap; 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setBitmap(bitmap); 45311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn setTargetDensity(r.getDisplayMetrics()); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Paint paint = mBitmapState.mPaint; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias, 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.isAntiAlias())); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.setFilterBitmap(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_filter, 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.isFilterBitmap())); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.setDither(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_dither, 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.isDither())); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setGravity(a.getInt(com.android.internal.R.styleable.BitmapDrawable_gravity, Gravity.FILL)); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tileMode = a.getInt(com.android.internal.R.styleable.BitmapDrawable_tileMode, -1); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tileMode != -1) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (tileMode) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 0: 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 1: 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 2: 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicWidth() { 48311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn return mBitmapWidth; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicHeight() { 48811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn return mBitmapHeight; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBitmapState.mGravity != Gravity.FILL) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PixelFormat.TRANSLUCENT; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bitmap bm = mBitmap; 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (bm == null || bm.hasAlpha() || mBitmapState.mPaint.getAlpha() < 255) ? 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final ConstantState getConstantState() { 5036efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais mBitmapState.mChangingConfigurations = getChangingConfigurations(); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final static class BitmapState extends ConstantState { 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bitmap mBitmap; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mChangingConfigurations; 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mGravity = Gravity.FILL; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS); 512ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy Shader.TileMode mTileModeX = null; 513ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy Shader.TileMode mTileModeY = null; 51411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; 5152660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy boolean mRebuildShader; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BitmapState(Bitmap bitmap) { 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmap = bitmap; 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BitmapState(BitmapState bitmapState) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(bitmapState.mBitmap); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangingConfigurations = bitmapState.mChangingConfigurations; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGravity = bitmapState.mGravity; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTileModeX = bitmapState.mTileModeX; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTileModeY = bitmapState.mTileModeY; 52711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mTargetDensity = bitmapState.mTargetDensity; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = new Paint(bitmapState.mPaint); 5292660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy mRebuildShader = bitmapState.mRebuildShader; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable newDrawable() { 534c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn return new BitmapDrawable(this, null); 535c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 5362660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy 537c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn @Override 538c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public Drawable newDrawable(Resources res) { 539c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn return new BitmapDrawable(this, res); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5412660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChangingConfigurations; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 548c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn private BitmapDrawable(BitmapState state, Resources res) { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = state; 550c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn if (res != null) { 551c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mTargetDensity = res.getDisplayMetrics().densityDpi; 552c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } else { 553e42143aa575dcb8ab0616080b2e9b4614a1a4167Jozef BABJAK mTargetDensity = state.mTargetDensity; 554c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 555ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy setBitmap(state != null ? state.mBitmap : null); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 558