193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/* 293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Copyright (C) 2013 The Android Open Source Project 393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Licensed under the Apache License, Version 2.0 (the "License"); 593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * you may not use this file except in compliance with the License. 693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * You may obtain a copy of the License at 793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * http://www.apache.org/licenses/LICENSE-2.0 993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 1093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Unless required by applicable law or agreed to in writing, software 1193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * distributed under the License is distributed on an "AS IS" BASIS, 1293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * See the License for the specific language governing permissions and 1493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * limitations under the License. 1593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 1693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpackage com.android.bitmap.drawable; 1793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.content.res.Resources; 1993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Canvas; 2093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.ColorFilter; 2193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Paint; 2293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.PixelFormat; 2393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Rect; 2493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.drawable.Drawable; 2593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.util.DisplayMetrics; 2693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.util.Log; 2793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 2893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.BitmapCache; 2993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.DecodeTask; 309c6ac19d4a3d39b7c2992060957920118ff56a65Mark Weiimport com.android.bitmap.DecodeTask.DecodeCallback; 31cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Weiimport com.android.bitmap.DecodeTask.DecodeOptions; 32cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Weiimport com.android.bitmap.NamedThreadFactory; 3340662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzsteinimport com.android.bitmap.RequestKey; 349c6ac19d4a3d39b7c2992060957920118ff56a65Mark Weiimport com.android.bitmap.RequestKey.Cancelable; 359c6ac19d4a3d39b7c2992060957920118ff56a65Mark Weiimport com.android.bitmap.RequestKey.FileDescriptorFactory; 3693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.ReusableBitmap; 3793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.BitmapUtils; 3893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.RectUtils; 3993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.Trace; 4093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 4193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.concurrent.Executor; 4293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.concurrent.LinkedBlockingQueue; 4393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.concurrent.ThreadPoolExecutor; 4493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.concurrent.TimeUnit; 4593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 4693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/** 4793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * This class encapsulates the basic functionality needed to display a single image bitmap, 4893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * including request creation/cancelling, and data unbinding and re-binding. 4993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <p> 5093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * The actual bitmap decode work is handled by {@link DecodeTask}. 51a23358fbfd62c7aa1c84bfa8395b4dc427a71ce6Mark Wei * <p> 52a23358fbfd62c7aa1c84bfa8395b4dc427a71ce6Mark Wei * If being used with a long-lived cache (static cache, attached to the Application instead of the 53a23358fbfd62c7aa1c84bfa8395b4dc427a71ce6Mark Wei * Activity, etc) then make sure to call {@link BasicBitmapDrawable#unbind()} at the appropriate 549c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei * times so the cache has accurate unref counts. The 559c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei * {@link com.android.bitmap.view.BitmapDrawableImageView} class has been created to do the 569c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei * appropriate unbind operation when the view is detached from the window. 5793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 589c6ac19d4a3d39b7c2992060957920118ff56a65Mark Weipublic class BasicBitmapDrawable extends Drawable implements DecodeCallback, 599c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei Drawable.Callback, RequestKey.Callback { 602e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 61528300fdc3caeb96a24873acf2b1cc0914b97593Mark Wei protected RequestKey mCurrKey; 622e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected RequestKey mPrevKey; 6341af50eb1ac488572b066629c3954b23c21dfa76Mark Wei protected int mDecodeWidth; 6441af50eb1ac488572b066629c3954b23c21dfa76Mark Wei protected int mDecodeHeight; 65e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei 662e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected final Paint mPaint = new Paint(); 6793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final BitmapCache mCache; 68a8b1e1f5cad36086e89c052007473609c379ccbdOleksandr Kyreiev private final Rect mRect = new Rect(); 692e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 70cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei private final boolean mLimitDensity; 71e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei private final float mDensity; 72a23358fbfd62c7aa1c84bfa8395b4dc427a71ce6Mark Wei private ReusableBitmap mBitmap; 7393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private DecodeTask mTask; 749c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei private Cancelable mCreateFileDescriptorFactoryTask; 7593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 76856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei private int mLayoutDirection; 77856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei 7893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // based on framework CL:I015d77 7993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); 8093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int CORE_POOL_SIZE = CPU_COUNT + 1; 8193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; 82cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei 8393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final Executor SMALL_POOL_EXECUTOR = new ThreadPoolExecutor( 8493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, 1, TimeUnit.SECONDS, 85cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei new LinkedBlockingQueue<Runnable>(128), new NamedThreadFactory("decode")); 8693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final Executor EXECUTOR = SMALL_POOL_EXECUTOR; 8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 8893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int MAX_BITMAP_DENSITY = DisplayMetrics.DENSITY_HIGH; 89cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei private static final float VERTICAL_CENTER = 1f / 2; 903a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung private static final float HORIZONTAL_CENTER = 1f / 2; 912e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei private static final float NO_MULTIPLIER = 1f; 9293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 93e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei private static final String TAG = BasicBitmapDrawable.class.getSimpleName(); 94cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei private static final boolean DEBUG = DecodeTask.DEBUG; 9593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 96cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei public BasicBitmapDrawable(final Resources res, final BitmapCache cache, 97cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei final boolean limitDensity) { 9893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDensity = res.getDisplayMetrics().density; 9993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache = cache; 100cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei mLimitDensity = limitDensity; 10193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setFilterBitmap(true); 102e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei mPaint.setAntiAlias(true); 103e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei mPaint.setDither(true); 10493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10610dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei public final RequestKey getKey() { 10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return mCurrKey; 10893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 110ad97cd0e0753930ec68f189e6be1023dc0f62f75Mark Wei public final RequestKey getPreviousKey() { 111ad97cd0e0753930ec68f189e6be1023dc0f62f75Mark Wei return mPrevKey; 112ad97cd0e0753930ec68f189e6be1023dc0f62f75Mark Wei } 113ad97cd0e0753930ec68f189e6be1023dc0f62f75Mark Wei 11441af50eb1ac488572b066629c3954b23c21dfa76Mark Wei protected ReusableBitmap getBitmap() { 1152e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return mBitmap; 1162e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 1172e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 11893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 11910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Set the dimensions to decode into. These dimensions should never change while the drawable is 12010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * attached to the same cache, because caches can only contain bitmaps of one size for re-use. 12110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * 12210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * All UI operations should be called from the UI thread. 12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 12489e59f00d67791754e44e65413baa95f94056df4Mark Wei public void setDecodeDimensions(int width, int height) { 12589e59f00d67791754e44e65413baa95f94056df4Mark Wei if (mDecodeWidth == 0 || mDecodeHeight == 0) { 12689e59f00d67791754e44e65413baa95f94056df4Mark Wei mDecodeWidth = width; 12789e59f00d67791754e44e65413baa95f94056df4Mark Wei mDecodeHeight = height; 12889e59f00d67791754e44e65413baa95f94056df4Mark Wei setImage(mCurrKey); 12989e59f00d67791754e44e65413baa95f94056df4Mark Wei } 13093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 13193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 13210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 133856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * Set layout direction. 134856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * It ends with Local so as not conflict with hidden Drawable.setLayoutDirection. 135856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * @param layoutDirection the resolved layout direction for the drawable, 136856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * either {@link android.view.View#LAYOUT_DIRECTION_LTR} 137856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * or {@link android.view.View#LAYOUT_DIRECTION_RTL} 138856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei */ 139856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei public void setLayoutDirectionLocal(int layoutDirection) { 140856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei if (mLayoutDirection != layoutDirection) { 141856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei mLayoutDirection = layoutDirection; 142856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei onLayoutDirectionChangeLocal(layoutDirection); 143856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei } 144856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei } 145856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei 146856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei /** 147856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * Called when the drawable's resolved layout direction changes. 148856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * It ends with Local so as not conflict with hidden Drawable.onLayoutDirectionChange. 149856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * 150856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * @param layoutDirection the new resolved layout direction 151856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei */ 152856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei public void onLayoutDirectionChangeLocal(int layoutDirection) {} 153856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei 154856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei /** 155856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * Returns the resolved layout direction for this Drawable. 156856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * It ends with Local so as not conflict with hidden Drawable.getLayoutDirection. 157856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * 158856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR}, 159856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * {@link android.view.View#LAYOUT_DIRECTION_RTL} 160856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei * @see #setLayoutDirectionLocal(int) 161856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei */ 162856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei public int getLayoutDirectionLocal() { 163856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei return mLayoutDirection; 164856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei } 165856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei 166856e2a9d72fe3a79cd7bfa5cf443d13a60495c4bMark Wei /** 16710dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Binds to the given key and start the decode process. This will first look in the cache, then 16810dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * decode from the request key if not found. 16910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * 1705b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * The key being replaced will be kept in {@link #mPrevKey}. 1715b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * 17210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * All UI operations should be called from the UI thread. 17310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 17441af50eb1ac488572b066629c3954b23c21dfa76Mark Wei public void bind(RequestKey key) { 175c4ba226c78b8478de6ac8e293d7f9bc64cba36ecMark Wei Trace.beginSection("bind"); 17689e59f00d67791754e44e65413baa95f94056df4Mark Wei if (mCurrKey != null && mCurrKey.equals(key)) { 1772d10993c4276db5b28ef7cb909362fbbc26c460cRuben Trace.endSection(); 17889e59f00d67791754e44e65413baa95f94056df4Mark Wei return; 17989e59f00d67791754e44e65413baa95f94056df4Mark Wei } 18010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei setImage(key); 181c4ba226c78b8478de6ac8e293d7f9bc64cba36ecMark Wei Trace.endSection(); 18293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 18410dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 18510dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Unbinds the current key and bitmap from the drawable. This will cause the bitmap to decrement 18610dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * its ref count. 18710dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * 1885b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * This will assume that you do not want to keep the unbound key in {@link #mPrevKey}. 1895b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * 19010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * All UI operations should be called from the UI thread. 19110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 19241af50eb1ac488572b066629c3954b23c21dfa76Mark Wei public void unbind() { 1935b46c679794d2f4362e8064b0291c578835d75e0Mark Wei unbind(false); 1945b46c679794d2f4362e8064b0291c578835d75e0Mark Wei } 1955b46c679794d2f4362e8064b0291c578835d75e0Mark Wei 1965b46c679794d2f4362e8064b0291c578835d75e0Mark Wei /** 1975b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * Unbinds the current key and bitmap from the drawable. This will cause the bitmap to decrement 1985b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * its ref count. 1995b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * 2005b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * If the temporary parameter is true, we will keep the unbound key in {@link #mPrevKey}. 2015b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * 2025b46c679794d2f4362e8064b0291c578835d75e0Mark Wei * All UI operations should be called from the UI thread. 2035b46c679794d2f4362e8064b0291c578835d75e0Mark Wei */ 2045b46c679794d2f4362e8064b0291c578835d75e0Mark Wei public void unbind(boolean temporary) { 205c4ba226c78b8478de6ac8e293d7f9bc64cba36ecMark Wei Trace.beginSection("unbind"); 20610dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei setImage(null); 2075b46c679794d2f4362e8064b0291c578835d75e0Mark Wei if (!temporary) { 2085b46c679794d2f4362e8064b0291c578835d75e0Mark Wei mPrevKey = null; 2095b46c679794d2f4362e8064b0291c578835d75e0Mark Wei } 210c4ba226c78b8478de6ac8e293d7f9bc64cba36ecMark Wei Trace.endSection(); 21193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 21293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 21310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 21410dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 21510dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 2162e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void setImage(final RequestKey key) { 21793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("set image"); 21893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("release reference"); 21993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mBitmap != null) { 22093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mBitmap.releaseReference(); 22193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mBitmap = null; 22293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 22393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 2242e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2252e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mPrevKey = mCurrKey; 22693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCurrKey = key; 22793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 22893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mTask != null) { 22993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mTask.cancel(); 23093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mTask = null; 23193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 2329c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei if (mCreateFileDescriptorFactoryTask != null) { 2339c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei mCreateFileDescriptorFactoryTask.cancel(); 2349c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei mCreateFileDescriptorFactoryTask = null; 2359c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei } 23693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 23793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (key == null) { 238c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei onDecodeFailed(); 23993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 24093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 24193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 24293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 24393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // find cached entry here and skip decode if found. 24493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final ReusableBitmap cached = mCache.get(key, true /* incrementRefCount */); 24593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (cached != null) { 24693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setBitmap(cached); 24793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 24893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.d(TAG, String.format("CACHE HIT key=%s", mCurrKey)); 24993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 25093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 2519c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei loadFileDescriptorFactory(); 25293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 25393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.d(TAG, String.format( 25493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein "CACHE MISS key=%s\ncache=%s", mCurrKey, mCache.toDebugString())); 25593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 25693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 25793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 25893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 25993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 26010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 26110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 26210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 2632e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void setBitmap(ReusableBitmap bmp) { 2648aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei if (hasBitmap()) { 2652e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mBitmap.releaseReference(); 2662e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2672e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mBitmap = bmp; 2682e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei invalidateSelf(); 2692e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2702e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 27110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 27210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 27310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 2742e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void loadFileDescriptorFactory() { 2752e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mCurrKey == null || mDecodeWidth == 0 || mDecodeHeight == 0) { 276c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei onDecodeFailed(); 2772e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return; 2782e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2792e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2802e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei // Create file descriptor if request supports it. 2812e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mCreateFileDescriptorFactoryTask = mCurrKey 2822e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei .createFileDescriptorFactoryAsync(mCurrKey, this); 2832e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mCreateFileDescriptorFactoryTask == null) { 2842e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei // Use input stream if request does not. 2852e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei decode(null); 2862e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2872e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2882e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2892e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei @Override 2902e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei public void fileDescriptorFactoryCreated(final RequestKey key, 2912e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final FileDescriptorFactory factory) { 2922e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mCreateFileDescriptorFactoryTask == null) { 2932e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei // Cancelled. 294c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei onDecodeFailed(); 2952e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return; 2962e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2972e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mCreateFileDescriptorFactoryTask = null; 2982e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2992e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (key.equals(mCurrKey)) { 3002e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei decode(factory); 3012e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3022e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3032e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 30410dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 305c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei * Called when the decode process is cancelled at any time. 306c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei */ 307c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei protected void onDecodeFailed() { 308c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei invalidateSelf(); 309c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei } 310c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei 311c5644927c0e7e121049b063046296ee8a59a4b37Mark Wei /** 31210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 31310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 3142e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void decode(final FileDescriptorFactory factory) { 3152e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei Trace.beginSection("decode"); 3162e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final int bufferW; 3172e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final int bufferH; 3182e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mLimitDensity) { 3192e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final float scale = 3202e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei Math.min(1f, (float) MAX_BITMAP_DENSITY / DisplayMetrics.DENSITY_DEFAULT 3212e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei / mDensity); 3222e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferW = (int) (mDecodeWidth * scale); 3232e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferH = (int) (mDecodeHeight * scale); 3242e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } else { 3252e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferW = mDecodeWidth; 3262e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferH = mDecodeHeight; 3272e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3282e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 3292e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mTask != null) { 3302e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mTask.cancel(); 3312e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3323a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung final DecodeOptions opts = new DecodeOptions(bufferW, bufferH, getDecodeHorizontalCenter(), 3333a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung getDecodeVerticalCenter(), getDecodeStrategy()); 3342e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mTask = new DecodeTask(mCurrKey, opts, factory, this, mCache); 335aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei mTask.executeOnExecutor(getExecutor()); 3362e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei Trace.endSection(); 3372e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3382e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 339d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein /** 340d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein * Return one of the STRATEGY constants in {@link DecodeOptions}. 341d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein */ 342d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein protected int getDecodeStrategy() { 343d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein return DecodeOptions.STRATEGY_ROUND_NEAREST; 344d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein } 345d05e64cf9f9b1542ccdac8675c63b8b185c97a48Sam Blitzstein 346aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei protected Executor getExecutor() { 347aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei return EXECUTOR; 348aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei } 349aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei 3502e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected float getDrawVerticalCenter() { 3512e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return VERTICAL_CENTER; 3522e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3532e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 3542e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected float getDrawVerticalOffsetMultiplier() { 3552e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return NO_MULTIPLIER; 3562e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3572e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 35889e59f00d67791754e44e65413baa95f94056df4Mark Wei /** 35989e59f00d67791754e44e65413baa95f94056df4Mark Wei * Clients can override this to specify which section of the source image to decode from. 36089e59f00d67791754e44e65413baa95f94056df4Mark Wei * Possible applications include using face detection to always decode around facial features. 36189e59f00d67791754e44e65413baa95f94056df4Mark Wei */ 3623a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung protected float getDecodeHorizontalCenter() { 3633a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung return HORIZONTAL_CENTER; 3643a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung } 3653a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung 3663a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung /** 3673a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung * Clients can override this to specify which section of the source image to decode from. 3683a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung * Possible applications include using face detection to always decode around facial features. 3693a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung */ 3702e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected float getDecodeVerticalCenter() { 3712e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return VERTICAL_CENTER; 3722e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 3732e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 37493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 37593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void draw(final Canvas canvas) { 37693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Rect bounds = getBounds(); 37793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (bounds.isEmpty()) { 37893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 37993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 38093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 3818aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei if (hasBitmap()) { 38293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein BitmapUtils.calculateCroppedSrcRect( 38393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight(), 38493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein bounds.width(), bounds.height(), 3853a79e2002f9f6114b549c4bc2cc08bb10e75a4d2James Kung bounds.height(), Integer.MAX_VALUE, getDecodeHorizontalCenter(), 3862e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei getDrawVerticalCenter(), false /* absoluteFraction */, 387a8b1e1f5cad36086e89c052007473609c379ccbdOleksandr Kyreiev getDrawVerticalOffsetMultiplier(), mRect); 38893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 38993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int orientation = mBitmap.getOrientation(); 39093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // calculateCroppedSrcRect() gave us the source rectangle "as if" the orientation has 39193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // been corrected. We need to decode the uncorrected source rectangle. Calculate true 39293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // coordinates. 39393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein RectUtils.rotateRectForOrientation(orientation, 39493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein new Rect(0, 0, mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight()), 395a8b1e1f5cad36086e89c052007473609c379ccbdOleksandr Kyreiev mRect); 39693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 39793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // We may need to rotate the canvas, so we also have to rotate the bounds. 39893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Rect rotatedBounds = new Rect(bounds); 39993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein RectUtils.rotateRect(orientation, bounds.centerX(), bounds.centerY(), rotatedBounds); 40093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 40193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // Rotate the canvas. 40293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein canvas.save(); 40393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein canvas.rotate(orientation, bounds.centerX(), bounds.centerY()); 404a8b1e1f5cad36086e89c052007473609c379ccbdOleksandr Kyreiev onDrawBitmap(canvas, mRect, rotatedBounds); 40593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein canvas.restore(); 40693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 40793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 40893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 4098aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei protected boolean hasBitmap() { 4108aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei return mBitmap != null && mBitmap.bmp != null; 4118aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei } 4128aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei 4130c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei /** 4140c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei * Override this method to customize how to draw the bitmap to the canvas for the given bounds. 4150c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei * The bitmap to be drawn can be found at {@link #getBitmap()}. 4160c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei */ 4177be91f8fe3c6d9af037b36918ea5bd86a10bbb44Mark Wei protected void onDrawBitmap(final Canvas canvas, final Rect src, final Rect dst) { 4188aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei if (hasBitmap()) { 4198aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei canvas.drawBitmap(mBitmap.bmp, src, dst, mPaint); 4208aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei } 4210c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei } 4220c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei 42393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 42493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setAlpha(int alpha) { 42593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int old = mPaint.getAlpha(); 42693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setAlpha(alpha); 42793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (alpha != old) { 42893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 42993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 43093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 43193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 43293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 43393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setColorFilter(ColorFilter cf) { 43493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setColorFilter(cf); 43593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 43693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 43793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 43893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 43993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public int getOpacity() { 4408aa2d8601f6a97af4a329cfc3bfd5fb5fb5bcbf8Mark Wei return (hasBitmap() && (mBitmap.bmp.hasAlpha() || mPaint.getAlpha() < 255)) ? 44193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 44293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 44393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 44493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 44540662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public void onDecodeBegin(final RequestKey key) { } 44693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 44793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 44840662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public void onDecodeComplete(final RequestKey key, final ReusableBitmap result) { 44993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (key.equals(mCurrKey)) { 45093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setBitmap(result); 45193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 45293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // if the requests don't match (i.e. this request is stale), decrement the 45393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // ref count to allow the bitmap to be pooled 45493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (result != null) { 45593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.releaseReference(); 45693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 45793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 45893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 45993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 46093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 46140662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public void onDecodeCancel(final RequestKey key) { } 46293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 46393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 46493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void invalidateDrawable(Drawable who) { 46593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 46693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 46793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 46893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 46993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void scheduleDrawable(Drawable who, Runnable what, long when) { 47093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein scheduleSelf(what, when); 47193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 47293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 47393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 47493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void unscheduleDrawable(Drawable who, Runnable what) { 47593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein unscheduleSelf(what); 47693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 47793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein} 478