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 19e222e359a0aab985488a711f6edb76820fe8c6dfChris Craikimport android.annotation.NonNull; 2012b97f5d2b15194ed6673c9838b13c8312157709Alan Viveretteimport android.content.res.ColorStateList; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 2252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.BitmapFactory; 26b1216dd916e0f5fdec29684120c5bcc904800916Romain Guyimport android.graphics.BitmapShader; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter; 292356c5e69b0911e6334ebf6374217898371be5acAlan Viveretteimport android.graphics.Insets; 303f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglioimport android.graphics.Matrix; 31e222e359a0aab985488a711f6edb76820fe8c6dfChris Craikimport android.graphics.Outline; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat; 34e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viveretteimport android.graphics.PorterDuff; 35d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viveretteimport android.graphics.PorterDuff.Mode; 3612b97f5d2b15194ed6673c9838b13c8312157709Alan Viveretteimport android.graphics.PorterDuffColorFilter; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Shader; 3931049d76c55b18a6d9993f0d9687598740b16014Adam Powellimport android.graphics.Xfermode; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.DisplayMetrics; 423f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglioimport android.util.LayoutDirection; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 44d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette 4552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport com.android.internal.R; 4652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 51dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reckimport java.util.Collection; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * BitmapDrawable from a file path, an input stream, through XML inflation, or from 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link android.graphics.Bitmap} object. 57dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code><bitmap></code> element. For more 58dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a 59dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p> 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 6112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * Also see the {@link android.graphics.Bitmap} class, which handles the management and 6212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * transformation of raw bitmap graphics, and should be used when drawing to a 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.graphics.Canvas}. 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_src 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_antialias 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_filter 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_dither 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_gravity 71b40c1fdaee6e6cabea8d1ed78f56d5b6bd133cfbScott Main * @attr ref android.R.styleable#BitmapDrawable_mipMap 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_tileMode 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class BitmapDrawable extends Drawable { 75211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed private static final int DEFAULT_PAINT_FLAGS = 76211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG; 770cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 780cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette // Constants for {@link android.R.styleable#BitmapDrawable_tileMode}. 790cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_UNDEFINED = -2; 800cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_DISABLED = -1; 810cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_CLAMP = 0; 820cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_REPEAT = 1; 830cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_MIRROR = 2; 840cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 85fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private final Rect mDstRect = new Rect(); // #updateDstRectAndInsetsIfDirty() sets this 860cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BitmapState mBitmapState; 8812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette private PorterDuffColorFilter mTintFilter; 89c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 900cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 92fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private boolean mDstRectAndInsetsDirty = true; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMutated; 9412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 95c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn // These are scaled to match the target density. 9611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private int mBitmapWidth; 9711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private int mBitmapHeight; 983f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 992356c5e69b0911e6334ebf6374217898371be5acAlan Viverette /** Optical insets due to gravity. */ 100fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private Insets mOpticalInsets = Insets.NONE; 1012356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 1023f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio // Mirroring matrix for using with Shaders 1033f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio private Matrix mMirrorMatrix; 1043f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 10511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 10611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create an empty drawable, not dealing with density. 1077ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)} 1087ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * instead to specify a bitmap to draw with and ensure the correct density is set. 10911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1104a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn @Deprecated 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable() { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = new BitmapState((Bitmap) null); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 11611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create an empty drawable, setting initial target density based on 11711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * the display metrics of the resources. 1180cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * 1197ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)} 1207ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * instead to specify a bitmap to draw with. 12111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1220cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette @SuppressWarnings("unused") 1237ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy @Deprecated 12411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public BitmapDrawable(Resources res) { 12511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mBitmapState = new BitmapState((Bitmap) null); 126c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 12711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 12811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 12911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 13011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create drawable from a bitmap, not dealing with density. 13111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure 13211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * that the drawable has correctly set its target density. 13311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1344a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn @Deprecated 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(Bitmap bitmap) { 13617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(new BitmapState(bitmap), null); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 14011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create drawable from a bitmap, setting initial target density based on 14111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * the display metrics of the resources. 14211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 14311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public BitmapDrawable(Resources res, Bitmap bitmap) { 14417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(new BitmapState(bitmap), res); 145c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 14611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 14711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 148c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 149c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by opening a given file path and decoding the bitmap. 150c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, String)} 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(String filepath) { 15517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); 1560cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 157c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); 158c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 159c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 160c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 161c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 162c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by opening a given file path and decoding the bitmap. 163c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 1640cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette @SuppressWarnings("unused") 165c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public BitmapDrawable(Resources res, String filepath) { 16617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); 167c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 1680cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 173c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 174c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by decoding a bitmap from the given input stream. 175c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, java.io.InputStream)} to ensure 176c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * that the drawable has correctly set its target density. 177c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 17829e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn @Deprecated 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(java.io.InputStream is) { 18017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(new BitmapState(BitmapFactory.decodeStream(is)), null); 1810cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 182c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); 183c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 184c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 185c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 186c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 187c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by decoding a bitmap from the given input stream. 188c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 1890cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette @SuppressWarnings("unused") 190c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public BitmapDrawable(Resources res, java.io.InputStream is) { 19117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(new BitmapState(BitmapFactory.decodeStream(is)), null); 192c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 1930cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 198ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 199ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Returns the paint used to render this drawable. 200ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Paint getPaint() { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mPaint; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 204ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy 205ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 206ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Returns the bitmap used by this drawable to render. May be null. 207ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Bitmap getBitmap() { 2090cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette return mBitmapState.mBitmap; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private void computeBitmapSize() { 2130cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = mBitmapState.mBitmap; 2140cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (bitmap != null) { 2150cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapWidth = bitmap.getScaledWidth(mTargetDensity); 2160cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapHeight = bitmap.getScaledHeight(mTargetDensity); 2170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } else { 2180cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapWidth = mBitmapHeight = -1; 2190cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } 22011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 22112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setBitmap(Bitmap bitmap) { 2230cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap != bitmap) { 2240cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapState.mBitmap = bitmap; 2250cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette computeBitmapSize(); 2269891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the density scale at which this drawable will be rendered. This 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method assumes the drawable will be rendered at the same density as the 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified canvas. 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param canvas The Canvas from which the density scale must be obtained. 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 23711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 23811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 24011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(Canvas canvas) { 24111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn setTargetDensity(canvas.getDensity()); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the density scale at which this drawable will be rendered. 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param metrics The DisplayMetrics indicating the density scale for this drawable. 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 24911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 25011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 25211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(DisplayMetrics metrics) { 2539891e1fce5f29d0421d34aa481037417bd70853dChet Haase setTargetDensity(metrics.densityDpi); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 25711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Set the density at which this drawable will be rendered. 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param density The density scale for this drawable. 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 26111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 26211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(int density) { 2659891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mTargetDensity != density) { 2669891e1fce5f29d0421d34aa481037417bd70853dChet Haase mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density; 2670cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap != null) { 2689891e1fce5f29d0421d34aa481037417bd70853dChet Haase computeBitmapSize(); 2699891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 2709891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 27111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Get the gravity used to position/stretch the bitmap within its bounds. 27511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * See android.view.Gravity 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the gravity applied to the bitmap 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getGravity() { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mGravity; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2815769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Set the gravity used to position/stretch the bitmap within its bounds. 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project See android.view.Gravity 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gravity the gravity 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGravity(int gravity) { 2879891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mBitmapState.mGravity != gravity) { 2889891e1fce5f29d0421d34aa481037417bd70853dChet Haase mBitmapState.mGravity = gravity; 289fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = true; 2909891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2919891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 294ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 2955769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * Enables or disables the mipmap hint for this drawable's bitmap. 2965769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * See {@link Bitmap#setHasMipMap(boolean)} for more information. 2975769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 2985769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * If the bitmap is null calling this method has no effect. 2995769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3005769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @param mipMap True if the bitmap should use mipmaps, false otherwise. 3015769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 30212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #hasMipMap() 3035769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy */ 3045769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy public void setMipMap(boolean mipMap) { 3055769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy if (mBitmapState.mBitmap != null) { 3065769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy mBitmapState.mBitmap.setHasMipMap(mipMap); 3075769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy invalidateSelf(); 3085769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3095769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3105769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3115769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy /** 3125769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * Indicates whether the mipmap hint is enabled on this drawable's bitmap. 3135769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3145769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @return True if the mipmap hint is set, false otherwise. If the bitmap 3155769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * is null, this method always returns false. 3165769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 31712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setMipMap(boolean) 318b40c1fdaee6e6cabea8d1ed78f56d5b6bd133cfbScott Main * @attr ref android.R.styleable#BitmapDrawable_mipMap 3195769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy */ 3205769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy public boolean hasMipMap() { 3215769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy return mBitmapState.mBitmap != null && mBitmapState.mBitmap.hasMipMap(); 3225769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3235769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3245769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy /** 325ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects 326ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * the edges of the bitmap only so it applies only when the drawable is rotated. 32712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 328ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param aa True if the bitmap should be anti-aliased, false otherwise. 3295769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 33012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #hasAntiAlias() 331ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAntiAlias(boolean aa) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setAntiAlias(aa); 3349891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3365769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3375769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy /** 3385769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * Indicates whether anti-aliasing is enabled for this drawable. 3395769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3405769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @return True if anti-aliasing is enabled, false otherwise. 3415769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3425769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @see #setAntiAlias(boolean) 3435769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy */ 3445769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy public boolean hasAntiAlias() { 3455769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy return mBitmapState.mPaint.isAntiAlias(); 3465769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3475769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilterBitmap(boolean filter) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setFilterBitmap(filter); 3519891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDither(boolean dither) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setDither(dither); 3579891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 360ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 361ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Indicates the repeat behavior of this drawable on the X axis. 36212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 3630cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * @return {@link android.graphics.Shader.TileMode#CLAMP} if the bitmap does not repeat, 3640cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#REPEAT} or 3650cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} otherwise. 366ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Shader.TileMode getTileModeX() { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mTileModeX; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 371ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 372ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Indicates the repeat behavior of this drawable on the Y axis. 37312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 3740cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * @return {@link android.graphics.Shader.TileMode#CLAMP} if the bitmap does not repeat, 3750cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#REPEAT} or 3760cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} otherwise. 37712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette */ 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Shader.TileMode getTileModeY() { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mTileModeY; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 382ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 383ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on the X axis. By default, the drawable 3840cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or 3850cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) 3860cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * if the bitmap is smaller than this drawable. 38712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 388ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param mode The repeat mode for this drawable. 38912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 39012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeY(android.graphics.Shader.TileMode) 39112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 3924f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @attr ref android.R.styleable#BitmapDrawable_tileModeX 393ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTileModeX(Shader.TileMode mode) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(mode, mBitmapState.mTileModeY); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 398ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 399ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on the Y axis. By default, the drawable 4000cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or 4010cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) 4020cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * if the bitmap is smaller than this drawable. 40312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 404ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param mode The repeat mode for this drawable. 40512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 40612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeX(android.graphics.Shader.TileMode) 40712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 4084f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @attr ref android.R.styleable#BitmapDrawable_tileModeY 40912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette */ 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final void setTileModeY(Shader.TileMode mode) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(mBitmapState.mTileModeX, mode); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 414ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 415ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on both axis. By default, the drawable 4160cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or 4170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) 4180cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * if the bitmap is smaller than this drawable. 41912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 420ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param xmode The X repeat mode for this drawable. 421ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param ymode The Y repeat mode for this drawable. 42212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 423ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeX(android.graphics.Shader.TileMode) 42412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeY(android.graphics.Shader.TileMode) 425ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final BitmapState state = mBitmapState; 428ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy if (state.mTileModeX != xmode || state.mTileModeY != ymode) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mTileModeX = xmode; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mTileModeY = ymode; 4312660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy state.mRebuildShader = true; 432fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = true; 4339891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4383f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio public void setAutoMirrored(boolean mirrored) { 4393f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (mBitmapState.mAutoMirrored != mirrored) { 4403f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mBitmapState.mAutoMirrored = mirrored; 4413f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio invalidateSelf(); 4423f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4433f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4443f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4453f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio @Override 4463f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio public final boolean isAutoMirrored() { 4473f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio return mBitmapState.mAutoMirrored; 4483f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4493f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4503f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio @Override 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations; 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4543f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4553f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio private boolean needMirroring() { 4563f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL; 4573f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4583f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4593f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio private void updateMirrorMatrix(float dx) { 4603f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (mMirrorMatrix == null) { 4613f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix = new Matrix(); 4623f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4633f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix.setTranslate(dx, 0); 4643f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix.preScale(-1.0f, 1.0f); 4653f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4663f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(Rect bounds) { 469fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = true; 4702356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 4712356c5e69b0911e6334ebf6374217898371be5acAlan Viverette final Shader shader = mBitmapState.mPaint.getShader(); 4723f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (shader != null) { 4733f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (needMirroring()) { 4743f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio updateMirrorMatrix(bounds.right - bounds.left); 4753f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio shader.setLocalMatrix(mMirrorMatrix); 476ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III mBitmapState.mPaint.setShader(shader); 4773f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } else { 4783f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (mMirrorMatrix != null) { 4793f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix = null; 4803f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); 481ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III mBitmapState.mPaint.setShader(shader); 4823f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4833f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4843f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 48816f1d81d47beb1e04504a76de66e2919dde08c33Alan Viverette public void draw(Canvas canvas) { 4890cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = mBitmapState.mBitmap; 49012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (bitmap == null) { 49112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette return; 49212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 49312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 49412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final BitmapState state = mBitmapState; 49512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Paint paint = state.mPaint; 49612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (state.mRebuildShader) { 49712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Shader.TileMode tmx = state.mTileModeX; 49812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Shader.TileMode tmy = state.mTileModeY; 49912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (tmx == null && tmy == null) { 50012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setShader(null); 50112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } else { 50212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setShader(new BitmapShader(bitmap, 50312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette tmx == null ? Shader.TileMode.CLAMP : tmx, 50412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette tmy == null ? Shader.TileMode.CLAMP : tmy)); 50512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 50612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 50712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette state.mRebuildShader = false; 50812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 50912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 510307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette final int restoreAlpha; 511307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette if (state.mBaseAlpha != 1.0f) { 512307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette final Paint p = getPaint(); 513307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette restoreAlpha = p.getAlpha(); 514307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f)); 515307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette } else { 516307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette restoreAlpha = -1; 517307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette } 518307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette 51912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final boolean clearColorFilter; 52012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (mTintFilter != null && paint.getColorFilter() == null) { 52112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setColorFilter(mTintFilter); 52212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette clearColorFilter = true; 52312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } else { 52412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette clearColorFilter = false; 52512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 52612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 527fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik updateDstRectAndInsetsIfDirty(); 52812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Shader shader = paint.getShader(); 52912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final boolean needMirroring = needMirroring(); 53012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (shader == null) { 53112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (needMirroring) { 53212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.save(); 53312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette // Mirror the bitmap 53412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.translate(mDstRect.right - mDstRect.left, 0); 53512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.scale(-1.0f, 1.0f); 53612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 53712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 53812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.drawBitmap(bitmap, null, mDstRect, paint); 53912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 54012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (needMirroring) { 54112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.restore(); 54212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 54312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } else { 54412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (needMirroring) { 54512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette // Mirror the bitmap 54612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette updateMirrorMatrix(mDstRect.right - mDstRect.left); 54712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette shader.setLocalMatrix(mMirrorMatrix); 548ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III paint.setShader(shader); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 55012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (mMirrorMatrix != null) { 55112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette mMirrorMatrix = null; 55212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); 553ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III paint.setShader(shader); 5543f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 55612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 55712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.drawRect(mDstRect, paint); 55812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 55912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 56012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (clearColorFilter) { 56112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setColorFilter(null); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 563307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette 564307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette if (restoreAlpha >= 0) { 565307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette paint.setAlpha(restoreAlpha); 566307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private void updateDstRectAndInsetsIfDirty() { 570fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik if (mDstRectAndInsetsDirty) { 571fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) { 572fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final Rect bounds = getBounds(); 573fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int layoutDirection = getLayoutDirection(); 574fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight, 575fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik bounds, mDstRect, layoutDirection); 576fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik 577fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int left = mDstRect.left - bounds.left; 578fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int top = mDstRect.top - bounds.top; 579fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int right = bounds.right - mDstRect.right; 580fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int bottom = bounds.bottom - mDstRect.bottom; 581fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mOpticalInsets = Insets.of(left, top, right, bottom); 582fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } else { 583fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik copyBounds(mDstRect); 584fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mOpticalInsets = Insets.NONE; 585fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } 586fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } 587fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = false; 588fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } 589fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik 590d30241541c3adcb126bb263ad8596e7902a6b5aeAlan Viverette /** 591d30241541c3adcb126bb263ad8596e7902a6b5aeAlan Viverette * @hide 592d30241541c3adcb126bb263ad8596e7902a6b5aeAlan Viverette */ 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5942356c5e69b0911e6334ebf6374217898371be5acAlan Viverette public Insets getOpticalInsets() { 595fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik updateDstRectAndInsetsIfDirty(); 596fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik return mOpticalInsets; 5972356c5e69b0911e6334ebf6374217898371be5acAlan Viverette } 5982356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 5992356c5e69b0911e6334ebf6374217898371be5acAlan Viverette @Override 600e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik public void getOutline(@NonNull Outline outline) { 601fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik updateDstRectAndInsetsIfDirty(); 602fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik outline.setRect(mDstRect); 603fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik 604fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik // Only opaque Bitmaps can report a non-0 alpha, 605fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik // since only they are guaranteed to fill their bounds 606fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik boolean opaqueOverShape = mBitmapState.mBitmap != null 607fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik && !mBitmapState.mBitmap.hasAlpha(); 608fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik outline.setAlpha(opaqueOverShape ? getAlpha() / 255.0f : 0.0f); 609e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik } 610e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik 611e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik @Override 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAlpha(int alpha) { 61312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final int oldAlpha = mBitmapState.mPaint.getAlpha(); 614ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase if (alpha != oldAlpha) { 615ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase mBitmapState.mPaint.setAlpha(alpha); 616ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase invalidateSelf(); 617ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase } 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase 620b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase @Override 621b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase public int getAlpha() { 622b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase return mBitmapState.mPaint.getAlpha(); 623b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setColorFilter(ColorFilter cf) { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setColorFilter(cf); 6289891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 631813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette @Override 632813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette public ColorFilter getColorFilter() { 633813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette return mBitmapState.mPaint.getColorFilter(); 634813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette } 635813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette 636e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viverette @Override 637a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintList(ColorStateList tint) { 638a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mBitmapState.mTint = tint; 639a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode); 640a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette invalidateSelf(); 641a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette } 642b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 643a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette @Override 644a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintMode(PorterDuff.Mode tintMode) { 645a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mBitmapState.mTintMode = tintMode; 646a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, tintMode); 647e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viverette invalidateSelf(); 64812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 64912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 65012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette /** 651e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viverette * @hide only needed by a hack within ProgressBar 652813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette */ 653813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette public ColorStateList getTint() { 654813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette return mBitmapState.mTint; 655813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette } 656813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette 657813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette /** 6582f8ba8f7fad2b608102a9282219aaea2223e94f5Alan Viverette * @hide only needed by a hack within ProgressBar 659af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette */ 660af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette public Mode getTintMode() { 661af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette return mBitmapState.mTintMode; 662af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette } 663af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette 664813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette /** 66531049d76c55b18a6d9993f0d9687598740b16014Adam Powell * @hide Candidate for future API inclusion 66631049d76c55b18a6d9993f0d9687598740b16014Adam Powell */ 66752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 66831049d76c55b18a6d9993f0d9687598740b16014Adam Powell public void setXfermode(Xfermode xfermode) { 66931049d76c55b18a6d9993f0d9687598740b16014Adam Powell mBitmapState.mPaint.setXfermode(xfermode); 67031049d76c55b18a6d9993f0d9687598740b16014Adam Powell invalidateSelf(); 67131049d76c55b18a6d9993f0d9687598740b16014Adam Powell } 67231049d76c55b18a6d9993f0d9687598740b16014Adam Powell 67331049d76c55b18a6d9993f0d9687598740b16014Adam Powell /** 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A mutable BitmapDrawable still shares its Bitmap with any other Drawable 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that comes from the same resource. 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This drawable. 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable mutate() { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mMutated && super.mutate() == this) { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = new BitmapState(mBitmapState); 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMutated = true; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 688727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette /** 689727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette * @hide 690727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette */ 691727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette public void clearMutated() { 692727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette super.clearMutated(); 693727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette mMutated = false; 694727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette } 695727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 69712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette protected boolean onStateChange(int[] stateSet) { 698b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette final BitmapState state = mBitmapState; 699b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette if (state.mTint != null && state.mTintMode != null) { 700b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 701b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette return true; 70212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 70312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette return false; 70412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 70512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 70612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette @Override 70712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette public boolean isStateful() { 70812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final BitmapState s = mBitmapState; 70912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette return super.isStateful() || (s.mTint != null && s.mTint.isStateful()); 71012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 71112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 71212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette @Override 71352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 71552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette super.inflate(r, parser, attrs, theme); 71652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.BitmapDrawable); 7180cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette updateStateFromTypedArray(a); 71906318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette verifyState(a); 72052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 72152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 72352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette /** 72406318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette * Ensures all required attributes are set. 72506318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette * 72606318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette * @throws XmlPullParserException if any required attributes are missing 72706318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette */ 72806318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette private void verifyState(TypedArray a) throws XmlPullParserException { 72906318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette final BitmapState state = mBitmapState; 73006318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette if (state.mBitmap == null) { 73106318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette throw new XmlPullParserException(a.getPositionDescription() + 73206318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette ": <bitmap> requires a valid src attribute"); 73306318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette } 73406318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette } 73506318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette 73606318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette /** 7370cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * Updates the constant state from the values in the typed array. 73852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette */ 7390cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { 74052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final Resources r = a.getResources(); 74112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final BitmapState state = mBitmapState; 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7438e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 7448e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mChangingConfigurations |= a.getChangingConfigurations(); 7458e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 74652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette // Extract the theme attributes, if any. 7478e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mThemeAttrs = a.extractThemeAttrs(); 74852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7490cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0); 7500cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (srcResId != 0) { 7510cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId); 75252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (bitmap == null) { 75352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette throw new XmlPullParserException(a.getPositionDescription() + 75452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette ": <bitmap> requires a valid src attribute"); 75552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 7560cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 75752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette state.mBitmap = bitmap; 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 75952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7600cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mTargetDensity = r.getDisplayMetrics().densityDpi; 76152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7620cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final boolean defMipMap = state.mBitmap != null ? state.mBitmap.hasMipMap() : false; 7630cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette setMipMap(a.getBoolean(R.styleable.BitmapDrawable_mipMap, defMipMap)); 76452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7650cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mAutoMirrored = a.getBoolean( 7660cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette R.styleable.BitmapDrawable_autoMirrored, state.mAutoMirrored); 7670cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, state.mBaseAlpha); 76852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7690cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final int tintMode = a.getInt(R.styleable.BitmapDrawable_tintMode, -1); 7700cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (tintMode != -1) { 7710cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); 77252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 77352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7740cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final ColorStateList tint = a.getColorStateList(R.styleable.BitmapDrawable_tint); 7750cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (tint != null) { 7760cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mTint = tint; 77752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 77852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 77952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final Paint paint = mBitmapState.mPaint; 7800cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette paint.setAntiAlias(a.getBoolean( 7810cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette R.styleable.BitmapDrawable_antialias, paint.isAntiAlias())); 7820cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette paint.setFilterBitmap(a.getBoolean( 7830cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette R.styleable.BitmapDrawable_filter, paint.isFilterBitmap())); 7840cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette paint.setDither(a.getBoolean(R.styleable.BitmapDrawable_dither, paint.isDither())); 78552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7860cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette setGravity(a.getInt(R.styleable.BitmapDrawable_gravity, state.mGravity)); 78752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7880cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final int tileMode = a.getInt(R.styleable.BitmapDrawable_tileMode, TILE_MODE_UNDEFINED); 7890cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (tileMode != TILE_MODE_UNDEFINED) { 79022594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette final Shader.TileMode mode = parseTileMode(tileMode); 79122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette setTileModeXY(mode, mode); 79222594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette } 79322594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette 79422594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette final int tileModeX = a.getInt(R.styleable.BitmapDrawable_tileModeX, TILE_MODE_UNDEFINED); 79522594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette if (tileModeX != TILE_MODE_UNDEFINED) { 79622594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette setTileModeX(parseTileMode(tileModeX)); 79722594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette } 79822594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette 79922594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette final int tileModeY = a.getInt(R.styleable.BitmapDrawable_tileModeY, TILE_MODE_UNDEFINED); 80022594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette if (tileModeY != TILE_MODE_UNDEFINED) { 80122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette setTileModeY(parseTileMode(tileModeY)); 80252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 8030cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8040cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette // Update local properties. 8050cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette initializeWithState(state, r); 80652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 80752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 80852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 80952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void applyTheme(Theme t) { 81052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette super.applyTheme(t); 81152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 81252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final BitmapState state = mBitmapState; 8130cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (state == null || state.mThemeAttrs == null) { 8140cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette return; 81552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 81652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 8170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable); 8180cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette try { 81952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette updateStateFromTypedArray(a); 8200cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } catch (XmlPullParserException e) { 8210cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette throw new RuntimeException(e); 8220cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } finally { 82352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 82452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 82552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 82652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 82722594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette private static Shader.TileMode parseTileMode(int tileMode) { 82852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette switch (tileMode) { 8290cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette case TILE_MODE_CLAMP: 83022594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return Shader.TileMode.CLAMP; 8310cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette case TILE_MODE_REPEAT: 83222594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return Shader.TileMode.REPEAT; 8330cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette case TILE_MODE_MIRROR: 83422594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return Shader.TileMode.MIRROR; 83522594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette default: 83622594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return null; 83752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 83852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 83952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 84052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 84152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public boolean canApplyTheme() { 84252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return mBitmapState != null && mBitmapState.mThemeAttrs != null; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicWidth() { 84711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn return mBitmapWidth; 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicHeight() { 85211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn return mBitmapHeight; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBitmapState.mGravity != Gravity.FILL) { 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PixelFormat.TRANSLUCENT; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8600cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8610cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = mBitmapState.mBitmap; 8620cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette return (bitmap == null || bitmap.hasAlpha() || mBitmapState.mPaint.getAlpha() < 255) ? 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final ConstantState getConstantState() { 8686efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais mBitmapState.mChangingConfigurations = getChangingConfigurations(); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState; 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final static class BitmapState extends ConstantState { 8730cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Paint mPaint; 8740cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8750cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette // Values loaded during inflation. 8760cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette int[] mThemeAttrs = null; 8770cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette Bitmap mBitmap = null; 8780cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette ColorStateList mTint = null; 879607bd848269fb802550e63aa61945790616f97a7Alan Viverette Mode mTintMode = DEFAULT_TINT_MODE; 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mGravity = Gravity.FILL; 881307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette float mBaseAlpha = 1.0f; 882ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy Shader.TileMode mTileModeX = null; 883ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy Shader.TileMode mTileModeY = null; 88411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; 8850cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette boolean mAutoMirrored = false; 8860cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8870cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette int mChangingConfigurations; 8882660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy boolean mRebuildShader; 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BitmapState(Bitmap bitmap) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmap = bitmap; 8920cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mPaint = new Paint(DEFAULT_PAINT_FLAGS); 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BitmapState(BitmapState bitmapState) { 896d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette mBitmap = bitmapState.mBitmap; 89712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette mTint = bitmapState.mTint; 89812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette mTintMode = bitmapState.mTintMode; 89952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mThemeAttrs = bitmapState.mThemeAttrs; 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangingConfigurations = bitmapState.mChangingConfigurations; 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGravity = bitmapState.mGravity; 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTileModeX = bitmapState.mTileModeX; 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTileModeY = bitmapState.mTileModeY; 90411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mTargetDensity = bitmapState.mTargetDensity; 905307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette mBaseAlpha = bitmapState.mBaseAlpha; 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = new Paint(bitmapState.mPaint); 9072660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy mRebuildShader = bitmapState.mRebuildShader; 9083f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mAutoMirrored = bitmapState.mAutoMirrored; 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 91252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public boolean canApplyTheme() { 91352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return mThemeAttrs != null; 91452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 91552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 91652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 917dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck public int addAtlasableBitmaps(Collection<Bitmap> atlasList) { 918dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck if (isAtlasable(mBitmap) && atlasList.add(mBitmap)) { 919dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck return mBitmap.getWidth() * mBitmap.getHeight(); 920dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck } 921dad7d84c04c5954b63ea8bb58c52b2291f44b4dfJohn Reck return 0; 9223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 9233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 9243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy @Override 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable newDrawable() { 92617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette return new BitmapDrawable(this, null); 927c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 9282660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy 929c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn @Override 930c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public Drawable newDrawable(Resources res) { 93117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette return new BitmapDrawable(this, res); 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9332660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChangingConfigurations; 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9400cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette /** 9410cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * The one constructor to rule them all. This is called by all public 9420cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * constructors to set the state and initialize local properties. 9430cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette */ 94417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette private BitmapDrawable(BitmapState state, Resources res) { 94517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mBitmapState = state; 94652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 94717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette initializeWithState(mBitmapState, res); 94852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 94912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 95052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette /** 95122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette * Initializes local dynamic properties from state. This should be called 95222594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette * after significant state changes, e.g. from the One True Constructor and 95322594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette * after inflating or applying a theme. 95452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette */ 95552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private void initializeWithState(BitmapState state, Resources res) { 956c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn if (res != null) { 957c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mTargetDensity = res.getDisplayMetrics().densityDpi; 958c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } else { 959e42143aa575dcb8ab0616080b2e9b4614a1a4167Jozef BABJAK mTargetDensity = state.mTargetDensity; 960c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 96112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 9625adf8ee451085ed6106b7dbadc6d8dcd9d90722bAlan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 9630cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette computeBitmapSize(); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 966