BitmapDrawable.java revision fe7a18eeada1bf2553ca00afb71b372bd79666dd
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; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * BitmapDrawable from a file path, an input stream, through XML inflation, or from 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link android.graphics.Bitmap} object. 56dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code><bitmap></code> element. For more 57dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a 58dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p> 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 6012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * Also see the {@link android.graphics.Bitmap} class, which handles the management and 6112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * transformation of raw bitmap graphics, and should be used when drawing to a 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.graphics.Canvas}. 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_src 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_antialias 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_filter 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_dither 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_gravity 70b40c1fdaee6e6cabea8d1ed78f56d5b6bd133cfbScott Main * @attr ref android.R.styleable#BitmapDrawable_mipMap 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#BitmapDrawable_tileMode 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class BitmapDrawable extends Drawable { 74211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed private static final int DEFAULT_PAINT_FLAGS = 75211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG; 760cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 770cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette // Constants for {@link android.R.styleable#BitmapDrawable_tileMode}. 780cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_UNDEFINED = -2; 790cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_DISABLED = -1; 800cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_CLAMP = 0; 810cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_REPEAT = 1; 820cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private static final int TILE_MODE_MIRROR = 2; 830cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 84fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private final Rect mDstRect = new Rect(); // #updateDstRectAndInsetsIfDirty() sets this 850cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BitmapState mBitmapState; 8712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette private PorterDuffColorFilter mTintFilter; 88c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 890cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 91fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private boolean mDstRectAndInsetsDirty = true; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMutated; 9312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 94c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn // These are scaled to match the target density. 9511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private int mBitmapWidth; 9611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private int mBitmapHeight; 973f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 982356c5e69b0911e6334ebf6374217898371be5acAlan Viverette /** Optical insets due to gravity. */ 99fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private Insets mOpticalInsets = Insets.NONE; 1002356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 1013f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio // Mirroring matrix for using with Shaders 1023f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio private Matrix mMirrorMatrix; 1033f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 10411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 10511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create an empty drawable, not dealing with density. 1067ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)} 1077ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * instead to specify a bitmap to draw with and ensure the correct density is set. 10811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1094a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn @Deprecated 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable() { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = new BitmapState((Bitmap) null); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 11511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create an empty drawable, setting initial target density based on 11611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * the display metrics of the resources. 1170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * 1187ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)} 1197ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy * instead to specify a bitmap to draw with. 12011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1210cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette @SuppressWarnings("unused") 1227ac40e38696aa74d7b7938add8fdbc47180ae424Romain Guy @Deprecated 12311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public BitmapDrawable(Resources res) { 12411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mBitmapState = new BitmapState((Bitmap) null); 125c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 12611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 12711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 12811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 12911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create drawable from a bitmap, not dealing with density. 13011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure 13111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * that the drawable has correctly set its target density. 13211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 1334a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn @Deprecated 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(Bitmap bitmap) { 13552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette this(new BitmapState(bitmap), null, null); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn /** 13911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Create drawable from a bitmap, setting initial target density based on 14011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * the display metrics of the resources. 14111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn */ 14211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public BitmapDrawable(Resources res, Bitmap bitmap) { 14352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette this(new BitmapState(bitmap), res, null); 144c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 14511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 14611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn 147c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 148c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by opening a given file path and decoding the bitmap. 149c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, String)} to ensure 150c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * that the drawable has correctly set its target density. 151c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 15229e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn @Deprecated 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(String filepath) { 15452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette this(new BitmapState(BitmapFactory.decodeFile(filepath)), null, null); 1550cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 156c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); 157c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 158c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 159c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 160c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 161c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by opening a given file path and decoding the bitmap. 162c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 1630cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette @SuppressWarnings("unused") 164c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public BitmapDrawable(Resources res, String filepath) { 16552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette this(new BitmapState(BitmapFactory.decodeFile(filepath)), null, null); 166c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 1670cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 173c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by decoding a bitmap from the given input stream. 174c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * @deprecated Use {@link #BitmapDrawable(Resources, java.io.InputStream)} to ensure 175c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * that the drawable has correctly set its target density. 176c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 17729e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn @Deprecated 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public BitmapDrawable(java.io.InputStream is) { 17952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette this(new BitmapState(BitmapFactory.decodeStream(is)), null, null); 1800cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 181c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); 182c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 183c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 184c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn 185c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn /** 186c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn * Create a drawable by decoding a bitmap from the given input stream. 187c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn */ 1880cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette @SuppressWarnings("unused") 189c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public BitmapDrawable(Resources res, java.io.InputStream is) { 19052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette this(new BitmapState(BitmapFactory.decodeStream(is)), null, null); 191c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mBitmapState.mTargetDensity = mTargetDensity; 1920cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap == null) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 197ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 198ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Returns the paint used to render this drawable. 199ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Paint getPaint() { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mPaint; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 203ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy 204ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 205ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Returns the bitmap used by this drawable to render. May be null. 206ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Bitmap getBitmap() { 2080cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette return mBitmapState.mBitmap; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn private void computeBitmapSize() { 2120cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = mBitmapState.mBitmap; 2130cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (bitmap != null) { 2140cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapWidth = bitmap.getScaledWidth(mTargetDensity); 2150cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapHeight = bitmap.getScaledHeight(mTargetDensity); 2160cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } else { 2170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapWidth = mBitmapHeight = -1; 2180cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } 21911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 22012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setBitmap(Bitmap bitmap) { 2220cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap != bitmap) { 2230cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mBitmapState.mBitmap = bitmap; 2240cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette computeBitmapSize(); 2259891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the density scale at which this drawable will be rendered. This 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method assumes the drawable will be rendered at the same density as the 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified canvas. 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param canvas The Canvas from which the density scale must be obtained. 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 23611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 23711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(Canvas canvas) { 24011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn setTargetDensity(canvas.getDensity()); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the density scale at which this drawable will be rendered. 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param metrics The DisplayMetrics indicating the density scale for this drawable. 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 24811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 24911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 25111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(DisplayMetrics metrics) { 2529891e1fce5f29d0421d34aa481037417bd70853dChet Haase setTargetDensity(metrics.densityDpi); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 25611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * Set the density at which this drawable will be rendered. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param density The density scale for this drawable. 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 26011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#setDensity(int) 26111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * @see android.graphics.Bitmap#getDensity() 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn public void setTargetDensity(int density) { 2649891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mTargetDensity != density) { 2659891e1fce5f29d0421d34aa481037417bd70853dChet Haase mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density; 2660cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (mBitmapState.mBitmap != null) { 2679891e1fce5f29d0421d34aa481037417bd70853dChet Haase computeBitmapSize(); 2689891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 2699891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 27011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Get the gravity used to position/stretch the bitmap within its bounds. 27411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn * See android.view.Gravity 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the gravity applied to the bitmap 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getGravity() { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mGravity; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2805769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Set the gravity used to position/stretch the bitmap within its bounds. 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project See android.view.Gravity 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gravity the gravity 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGravity(int gravity) { 2869891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (mBitmapState.mGravity != gravity) { 2879891e1fce5f29d0421d34aa481037417bd70853dChet Haase mBitmapState.mGravity = gravity; 288fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = true; 2899891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2909891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 293ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 2945769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * Enables or disables the mipmap hint for this drawable's bitmap. 2955769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * See {@link Bitmap#setHasMipMap(boolean)} for more information. 2965769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 2975769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * If the bitmap is null calling this method has no effect. 2985769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 2995769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @param mipMap True if the bitmap should use mipmaps, false otherwise. 3005769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 30112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #hasMipMap() 3025769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy */ 3035769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy public void setMipMap(boolean mipMap) { 3045769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy if (mBitmapState.mBitmap != null) { 3055769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy mBitmapState.mBitmap.setHasMipMap(mipMap); 3065769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy invalidateSelf(); 3075769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3085769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3095769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3105769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy /** 3115769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * Indicates whether the mipmap hint is enabled on this drawable's bitmap. 3125769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3135769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @return True if the mipmap hint is set, false otherwise. If the bitmap 3145769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * is null, this method always returns false. 3155769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 31612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setMipMap(boolean) 317b40c1fdaee6e6cabea8d1ed78f56d5b6bd133cfbScott Main * @attr ref android.R.styleable#BitmapDrawable_mipMap 3185769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy */ 3195769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy public boolean hasMipMap() { 3205769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy return mBitmapState.mBitmap != null && mBitmapState.mBitmap.hasMipMap(); 3215769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3225769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3235769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy /** 324ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects 325ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * the edges of the bitmap only so it applies only when the drawable is rotated. 32612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 327ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param aa True if the bitmap should be anti-aliased, false otherwise. 3285769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 32912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #hasAntiAlias() 330ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAntiAlias(boolean aa) { 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setAntiAlias(aa); 3339891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3355769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3365769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy /** 3375769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * Indicates whether anti-aliasing is enabled for this drawable. 3385769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3395769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @return True if anti-aliasing is enabled, false otherwise. 3405769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * 3415769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy * @see #setAntiAlias(boolean) 3425769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy */ 3435769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy public boolean hasAntiAlias() { 3445769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy return mBitmapState.mPaint.isAntiAlias(); 3455769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy } 3465769fcd88a6b53aa9394d869a9428c80e61a1565Romain Guy 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilterBitmap(boolean filter) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setFilterBitmap(filter); 3509891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDither(boolean dither) { 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setDither(dither); 3569891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 360ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Indicates the repeat behavior of this drawable on the X axis. 36112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 3620cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * @return {@link android.graphics.Shader.TileMode#CLAMP} if the bitmap does not repeat, 3630cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#REPEAT} or 3640cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} otherwise. 365ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Shader.TileMode getTileModeX() { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mTileModeX; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 370ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 371ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Indicates the repeat behavior of this drawable on the Y axis. 37212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 3730cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * @return {@link android.graphics.Shader.TileMode#CLAMP} if the bitmap does not repeat, 3740cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#REPEAT} or 3750cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} otherwise. 37612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette */ 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Shader.TileMode getTileModeY() { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState.mTileModeY; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 381ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 382ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on the X axis. By default, the drawable 3830cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or 3840cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) 3850cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * if the bitmap is smaller than this drawable. 38612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 387ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param mode The repeat mode for this drawable. 38812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 38912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeY(android.graphics.Shader.TileMode) 39012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 3914f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @attr ref android.R.styleable#BitmapDrawable_tileModeX 392ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTileModeX(Shader.TileMode mode) { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(mode, mBitmapState.mTileModeY); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 397ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 398ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on the Y axis. By default, the drawable 3990cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or 4000cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) 4010cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * if the bitmap is smaller than this drawable. 40212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 403ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param mode The repeat mode for this drawable. 40412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 40512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeX(android.graphics.Shader.TileMode) 40612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 4074f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @attr ref android.R.styleable#BitmapDrawable_tileModeY 40812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette */ 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final void setTileModeY(Shader.TileMode mode) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTileModeXY(mBitmapState.mTileModeX, mode); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 413ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy /** 414ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * Sets the repeat behavior of this drawable on both axis. By default, the drawable 4150cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or 4160cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * {@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) 4170cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * if the bitmap is smaller than this drawable. 41812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 419ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param xmode The X repeat mode for this drawable. 420ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @param ymode The Y repeat mode for this drawable. 42112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * 422ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy * @see #setTileModeX(android.graphics.Shader.TileMode) 42312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette * @see #setTileModeY(android.graphics.Shader.TileMode) 424ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy */ 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final BitmapState state = mBitmapState; 427ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy if (state.mTileModeX != xmode || state.mTileModeY != ymode) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mTileModeX = xmode; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state.mTileModeY = ymode; 4302660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy state.mRebuildShader = true; 431fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = true; 4329891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4373f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio public void setAutoMirrored(boolean mirrored) { 4383f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (mBitmapState.mAutoMirrored != mirrored) { 4393f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mBitmapState.mAutoMirrored = mirrored; 4403f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio invalidateSelf(); 4413f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4423f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4433f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4443f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio @Override 4453f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio public final boolean isAutoMirrored() { 4463f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio return mBitmapState.mAutoMirrored; 4473f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4483f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4493f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio @Override 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations; 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4533f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4543f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio private boolean needMirroring() { 4553f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL; 4563f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4573f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4583f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio private void updateMirrorMatrix(float dx) { 4593f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (mMirrorMatrix == null) { 4603f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix = new Matrix(); 4613f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4623f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix.setTranslate(dx, 0); 4633f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix.preScale(-1.0f, 1.0f); 4643f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4653f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(Rect bounds) { 468fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = true; 4692356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 4702356c5e69b0911e6334ebf6374217898371be5acAlan Viverette final Shader shader = mBitmapState.mPaint.getShader(); 4713f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (shader != null) { 4723f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (needMirroring()) { 4733f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio updateMirrorMatrix(bounds.right - bounds.left); 4743f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio shader.setLocalMatrix(mMirrorMatrix); 475ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III mBitmapState.mPaint.setShader(shader); 4763f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } else { 4773f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio if (mMirrorMatrix != null) { 4783f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mMirrorMatrix = null; 4793f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); 480ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III mBitmapState.mPaint.setShader(shader); 4813f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4823f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4833f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 48716f1d81d47beb1e04504a76de66e2919dde08c33Alan Viverette public void draw(Canvas canvas) { 4880cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = mBitmapState.mBitmap; 48912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (bitmap == null) { 49012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette return; 49112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 49212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 49312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final BitmapState state = mBitmapState; 49412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Paint paint = state.mPaint; 49512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (state.mRebuildShader) { 49612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Shader.TileMode tmx = state.mTileModeX; 49712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Shader.TileMode tmy = state.mTileModeY; 49812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (tmx == null && tmy == null) { 49912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setShader(null); 50012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } else { 50112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setShader(new BitmapShader(bitmap, 50212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette tmx == null ? Shader.TileMode.CLAMP : tmx, 50312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette tmy == null ? Shader.TileMode.CLAMP : tmy)); 50412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 50512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 50612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette state.mRebuildShader = false; 50712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 50812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 509307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette final int restoreAlpha; 510307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette if (state.mBaseAlpha != 1.0f) { 511307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette final Paint p = getPaint(); 512307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette restoreAlpha = p.getAlpha(); 513307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f)); 514307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette } else { 515307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette restoreAlpha = -1; 516307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette } 517307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette 51812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final boolean clearColorFilter; 51912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (mTintFilter != null && paint.getColorFilter() == null) { 52012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setColorFilter(mTintFilter); 52112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette clearColorFilter = true; 52212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } else { 52312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette clearColorFilter = false; 52412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 52512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 526fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik updateDstRectAndInsetsIfDirty(); 52712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final Shader shader = paint.getShader(); 52812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final boolean needMirroring = needMirroring(); 52912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (shader == null) { 53012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (needMirroring) { 53112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.save(); 53212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette // Mirror the bitmap 53312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.translate(mDstRect.right - mDstRect.left, 0); 53412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.scale(-1.0f, 1.0f); 53512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 53612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 53712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.drawBitmap(bitmap, null, mDstRect, paint); 53812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 53912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (needMirroring) { 54012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.restore(); 54112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 54212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } else { 54312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (needMirroring) { 54412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette // Mirror the bitmap 54512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette updateMirrorMatrix(mDstRect.right - mDstRect.left); 54612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette shader.setLocalMatrix(mMirrorMatrix); 547ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III paint.setShader(shader); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 54912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (mMirrorMatrix != null) { 55012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette mMirrorMatrix = null; 55112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); 552ab87983a11e0bd2e08d752d86d5e945ea7d39a04Leon Scroggins III paint.setShader(shader); 5533f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 55512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 55612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette canvas.drawRect(mDstRect, paint); 55712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 55812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 55912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette if (clearColorFilter) { 56012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette paint.setColorFilter(null); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 562307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette 563307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette if (restoreAlpha >= 0) { 564307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette paint.setAlpha(restoreAlpha); 565307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 568fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik private void updateDstRectAndInsetsIfDirty() { 569fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik if (mDstRectAndInsetsDirty) { 570fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) { 571fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final Rect bounds = getBounds(); 572fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int layoutDirection = getLayoutDirection(); 573fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight, 574fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik bounds, mDstRect, layoutDirection); 575fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik 576fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int left = mDstRect.left - bounds.left; 577fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int top = mDstRect.top - bounds.top; 578fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int right = bounds.right - mDstRect.right; 579fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik final int bottom = bounds.bottom - mDstRect.bottom; 580fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mOpticalInsets = Insets.of(left, top, right, bottom); 581fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } else { 582fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik copyBounds(mDstRect); 583fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mOpticalInsets = Insets.NONE; 584fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } 585fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } 586fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik mDstRectAndInsetsDirty = false; 587fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik } 588fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik 589d30241541c3adcb126bb263ad8596e7902a6b5aeAlan Viverette /** 590d30241541c3adcb126bb263ad8596e7902a6b5aeAlan Viverette * @hide 591d30241541c3adcb126bb263ad8596e7902a6b5aeAlan Viverette */ 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5932356c5e69b0911e6334ebf6374217898371be5acAlan Viverette public Insets getOpticalInsets() { 594fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik updateDstRectAndInsetsIfDirty(); 595fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik return mOpticalInsets; 5962356c5e69b0911e6334ebf6374217898371be5acAlan Viverette } 5972356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 5982356c5e69b0911e6334ebf6374217898371be5acAlan Viverette @Override 599e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik public void getOutline(@NonNull Outline outline) { 600fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik updateDstRectAndInsetsIfDirty(); 601fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik outline.setRect(mDstRect); 602fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik 603fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik // Only opaque Bitmaps can report a non-0 alpha, 604fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik // since only they are guaranteed to fill their bounds 605fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik boolean opaqueOverShape = mBitmapState.mBitmap != null 606fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik && !mBitmapState.mBitmap.hasAlpha(); 607fe7a18eeada1bf2553ca00afb71b372bd79666ddChris Craik outline.setAlpha(opaqueOverShape ? getAlpha() / 255.0f : 0.0f); 608e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik } 609e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik 610e222e359a0aab985488a711f6edb76820fe8c6dfChris Craik @Override 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAlpha(int alpha) { 61212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final int oldAlpha = mBitmapState.mPaint.getAlpha(); 613ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase if (alpha != oldAlpha) { 614ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase mBitmapState.mPaint.setAlpha(alpha); 615ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase invalidateSelf(); 616ad4f70306b2089a273635b73a101fe48aa36cbe2Chet Haase } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 618b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase 619b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase @Override 620b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase public int getAlpha() { 621b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase return mBitmapState.mPaint.getAlpha(); 622b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase } 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setColorFilter(ColorFilter cf) { 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState.mPaint.setColorFilter(cf); 6279891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 630813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette @Override 631813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette public ColorFilter getColorFilter() { 632813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette return mBitmapState.mPaint.getColorFilter(); 633813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette } 634813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette 635e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viverette @Override 636a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintList(ColorStateList tint) { 637a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mBitmapState.mTint = tint; 638a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode); 639a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette invalidateSelf(); 640a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette } 641b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 642a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette @Override 643a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintMode(PorterDuff.Mode tintMode) { 644a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mBitmapState.mTintMode = tintMode; 645a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, tintMode); 646e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viverette invalidateSelf(); 64712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 64812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 64912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette /** 650e7772d313b88e9fd3366670a9c8d1b145edef344Alan Viverette * @hide only needed by a hack within ProgressBar 651813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette */ 652813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette public ColorStateList getTint() { 653813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette return mBitmapState.mTint; 654813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette } 655813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette 656813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette /** 6572f8ba8f7fad2b608102a9282219aaea2223e94f5Alan Viverette * @hide only needed by a hack within ProgressBar 658af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette */ 659af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette public Mode getTintMode() { 660af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette return mBitmapState.mTintMode; 661af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette } 662af7c240b99506d2c81a72be738eb270ecaa39699Alan Viverette 663813d85b82cb7cbaa5dbe05496d1038caa17a1698Alan Viverette /** 66431049d76c55b18a6d9993f0d9687598740b16014Adam Powell * @hide Candidate for future API inclusion 66531049d76c55b18a6d9993f0d9687598740b16014Adam Powell */ 66652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 66731049d76c55b18a6d9993f0d9687598740b16014Adam Powell public void setXfermode(Xfermode xfermode) { 66831049d76c55b18a6d9993f0d9687598740b16014Adam Powell mBitmapState.mPaint.setXfermode(xfermode); 66931049d76c55b18a6d9993f0d9687598740b16014Adam Powell invalidateSelf(); 67031049d76c55b18a6d9993f0d9687598740b16014Adam Powell } 67131049d76c55b18a6d9993f0d9687598740b16014Adam Powell 67231049d76c55b18a6d9993f0d9687598740b16014Adam Powell /** 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A mutable BitmapDrawable still shares its Bitmap with any other Drawable 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that comes from the same resource. 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This drawable. 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable mutate() { 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mMutated && super.mutate() == this) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmapState = new BitmapState(mBitmapState); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMutated = true; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 68812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette protected boolean onStateChange(int[] stateSet) { 689b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette final BitmapState state = mBitmapState; 690b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette if (state.mTint != null && state.mTintMode != null) { 691b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 692b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette return true; 69312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 69412b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette return false; 69512b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 69612b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 69712b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette @Override 69812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette public boolean isStateful() { 69912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final BitmapState s = mBitmapState; 70012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette return super.isStateful() || (s.mTint != null && s.mTint.isStateful()); 70112b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette } 70212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 70312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette @Override 70452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 70652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette super.inflate(r, parser, attrs, theme); 70752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7080cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.BitmapDrawable); 7090cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette updateStateFromTypedArray(a); 71006318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette verifyState(a); 71152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 71252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 71452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette /** 71506318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette * Ensures all required attributes are set. 71606318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette * 71706318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette * @throws XmlPullParserException if any required attributes are missing 71806318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette */ 71906318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette private void verifyState(TypedArray a) throws XmlPullParserException { 72006318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette final BitmapState state = mBitmapState; 72106318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette if (state.mBitmap == null) { 72206318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette throw new XmlPullParserException(a.getPositionDescription() + 72306318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette ": <bitmap> requires a valid src attribute"); 72406318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette } 72506318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette } 72606318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette 72706318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette /** 7280cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * Updates the constant state from the values in the typed array. 72952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette */ 7300cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { 73152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final Resources r = a.getResources(); 73212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette final BitmapState state = mBitmapState; 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 7358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mChangingConfigurations |= a.getChangingConfigurations(); 7368e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 73752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette // Extract the theme attributes, if any. 7388e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mThemeAttrs = a.extractThemeAttrs(); 73952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7400cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0); 7410cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (srcResId != 0) { 7420cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId); 74352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (bitmap == null) { 74452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette throw new XmlPullParserException(a.getPositionDescription() + 74552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette ": <bitmap> requires a valid src attribute"); 74652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 7470cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 74852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette state.mBitmap = bitmap; 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 75052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7510cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mTargetDensity = r.getDisplayMetrics().densityDpi; 75252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7530cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final boolean defMipMap = state.mBitmap != null ? state.mBitmap.hasMipMap() : false; 7540cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette setMipMap(a.getBoolean(R.styleable.BitmapDrawable_mipMap, defMipMap)); 75552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7560cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mAutoMirrored = a.getBoolean( 7570cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette R.styleable.BitmapDrawable_autoMirrored, state.mAutoMirrored); 7580cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, state.mBaseAlpha); 75952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7600cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final int tintMode = a.getInt(R.styleable.BitmapDrawable_tintMode, -1); 7610cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (tintMode != -1) { 7620cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); 76352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 76452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7650cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final ColorStateList tint = a.getColorStateList(R.styleable.BitmapDrawable_tint); 7660cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (tint != null) { 7670cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette state.mTint = tint; 76852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 76952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 77052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final Paint paint = mBitmapState.mPaint; 7710cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette paint.setAntiAlias(a.getBoolean( 7720cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette R.styleable.BitmapDrawable_antialias, paint.isAntiAlias())); 7730cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette paint.setFilterBitmap(a.getBoolean( 7740cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette R.styleable.BitmapDrawable_filter, paint.isFilterBitmap())); 7750cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette paint.setDither(a.getBoolean(R.styleable.BitmapDrawable_dither, paint.isDither())); 77652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7770cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette setGravity(a.getInt(R.styleable.BitmapDrawable_gravity, state.mGravity)); 77852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 7790cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final int tileMode = a.getInt(R.styleable.BitmapDrawable_tileMode, TILE_MODE_UNDEFINED); 7800cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (tileMode != TILE_MODE_UNDEFINED) { 78122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette final Shader.TileMode mode = parseTileMode(tileMode); 78222594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette setTileModeXY(mode, mode); 78322594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette } 78422594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette 78522594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette final int tileModeX = a.getInt(R.styleable.BitmapDrawable_tileModeX, TILE_MODE_UNDEFINED); 78622594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette if (tileModeX != TILE_MODE_UNDEFINED) { 78722594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette setTileModeX(parseTileMode(tileModeX)); 78822594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette } 78922594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette 79022594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette final int tileModeY = a.getInt(R.styleable.BitmapDrawable_tileModeY, TILE_MODE_UNDEFINED); 79122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette if (tileModeY != TILE_MODE_UNDEFINED) { 79222594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette setTileModeY(parseTileMode(tileModeY)); 79352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 7940cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 7950cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette // Update local properties. 7960cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette initializeWithState(state, r); 79752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 79852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 79952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 80052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void applyTheme(Theme t) { 80152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette super.applyTheme(t); 80252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 80352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final BitmapState state = mBitmapState; 8040cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette if (state == null || state.mThemeAttrs == null) { 8050cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette return; 80652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 80752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 8080cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable); 8090cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette try { 81052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette updateStateFromTypedArray(a); 8110cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } catch (XmlPullParserException e) { 8120cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette throw new RuntimeException(e); 8130cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette } finally { 81452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 81552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 81652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 81752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 81822594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette private static Shader.TileMode parseTileMode(int tileMode) { 81952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette switch (tileMode) { 8200cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette case TILE_MODE_CLAMP: 82122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return Shader.TileMode.CLAMP; 8220cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette case TILE_MODE_REPEAT: 82322594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return Shader.TileMode.REPEAT; 8240cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette case TILE_MODE_MIRROR: 82522594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return Shader.TileMode.MIRROR; 82622594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette default: 82722594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette return null; 82852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 82952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 83052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 83152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 83252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public boolean canApplyTheme() { 83352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return mBitmapState != null && mBitmapState.mThemeAttrs != null; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicWidth() { 83811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn return mBitmapWidth; 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicHeight() { 84311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn return mBitmapHeight; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBitmapState.mGravity != Gravity.FILL) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PixelFormat.TRANSLUCENT; 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8510cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8520cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Bitmap bitmap = mBitmapState.mBitmap; 8530cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette return (bitmap == null || bitmap.hasAlpha() || mBitmapState.mPaint.getAlpha() < 255) ? 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final ConstantState getConstantState() { 8596efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais mBitmapState.mChangingConfigurations = getChangingConfigurations(); 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmapState; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final static class BitmapState extends ConstantState { 8640cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette final Paint mPaint; 8650cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8660cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette // Values loaded during inflation. 8670cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette int[] mThemeAttrs = null; 8680cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette Bitmap mBitmap = null; 8690cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette ColorStateList mTint = null; 87009ceac298cc12471e4575fe49f97766c1ed7b2a1Alan Viverette Mode mTintMode = Mode.SRC_IN; 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mGravity = Gravity.FILL; 872307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette float mBaseAlpha = 1.0f; 873ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy Shader.TileMode mTileModeX = null; 874ee0c116ab2bd5acdfe50db36441cf4784d3a10b4Romain Guy Shader.TileMode mTileModeY = null; 87511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; 8760cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette boolean mAutoMirrored = false; 8770cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette 8780cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette int mChangingConfigurations; 8792660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy boolean mRebuildShader; 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BitmapState(Bitmap bitmap) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBitmap = bitmap; 8830cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette mPaint = new Paint(DEFAULT_PAINT_FLAGS); 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BitmapState(BitmapState bitmapState) { 887d9e788c4f0528e46db4a035cfac043736becb0d1Alan Viverette mBitmap = bitmapState.mBitmap; 88812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette mTint = bitmapState.mTint; 88912b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette mTintMode = bitmapState.mTintMode; 89052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mThemeAttrs = bitmapState.mThemeAttrs; 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangingConfigurations = bitmapState.mChangingConfigurations; 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGravity = bitmapState.mGravity; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTileModeX = bitmapState.mTileModeX; 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTileModeY = bitmapState.mTileModeY; 89511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn mTargetDensity = bitmapState.mTargetDensity; 896307ad09228ebf70f1b456f5f00540c0126277850Alan Viverette mBaseAlpha = bitmapState.mBaseAlpha; 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = new Paint(bitmapState.mPaint); 8982660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy mRebuildShader = bitmapState.mRebuildShader; 8993f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio mAutoMirrored = bitmapState.mAutoMirrored; 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 90352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public boolean canApplyTheme() { 90452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return mThemeAttrs != null; 90552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 90652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 90752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 9083b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy public Bitmap getBitmap() { 9093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return mBitmap; 9103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 9113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 9123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy @Override 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable newDrawable() { 91452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return new BitmapDrawable(this, null, null); 915c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 9162660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy 917c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn @Override 918c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public Drawable newDrawable(Resources res) { 91952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return new BitmapDrawable(this, res, null); 92052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 92152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 92252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 92352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public Drawable newDrawable(Resources res, Theme theme) { 92452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette return new BitmapDrawable(this, res, theme); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9262660a3ec8564918a243b1b02e3652c514bc93bfcRomain Guy 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChangingConfigurations; 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9330cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette /** 9340cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * The one constructor to rule them all. This is called by all public 9350cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette * constructors to set the state and initialize local properties. 9360cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette */ 93752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private BitmapDrawable(BitmapState state, Resources res, Theme theme) { 93852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (theme != null && state.canApplyTheme()) { 93906318a0869b9f214bc97cabf1d2b6854acb6431bAlan Viverette // If we need to apply a theme, implicitly mutate. 94052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mBitmapState = new BitmapState(state); 94152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette applyTheme(theme); 94252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } else { 94352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mBitmapState = state; 94452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 94552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 94652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette initializeWithState(state, res); 94752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 94812b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 94952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette /** 95022594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette * Initializes local dynamic properties from state. This should be called 95122594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette * after significant state changes, e.g. from the One True Constructor and 95222594f097242d9de0a538a9b8142f77da9df7ebdAlan Viverette * after inflating or applying a theme. 95352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette */ 95452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private void initializeWithState(BitmapState state, Resources res) { 955c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn if (res != null) { 956c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn mTargetDensity = res.getDisplayMetrics().densityDpi; 957c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } else { 958e42143aa575dcb8ab0616080b2e9b4614a1a4167Jozef BABJAK mTargetDensity = state.mTargetDensity; 959c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 96012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette 9615adf8ee451085ed6106b7dbadc6d8dcd9d90722bAlan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 9620cfb877f5a0a1bff82d9c3ee969195bf7812c0b5Alan Viverette computeBitmapSize(); 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 965