BasicBitmapDrawable.java revision 7be91f8fe3c6d9af037b36918ea5bd86a10bbb44
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 61e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei protected static Rect sRect; 6293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 63528300fdc3caeb96a24873acf2b1cc0914b97593Mark Wei protected RequestKey mCurrKey; 642e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected RequestKey mPrevKey; 6541af50eb1ac488572b066629c3954b23c21dfa76Mark Wei protected int mDecodeWidth; 6641af50eb1ac488572b066629c3954b23c21dfa76Mark Wei protected int mDecodeHeight; 67e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei 682e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected final Paint mPaint = new Paint(); 6993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final BitmapCache mCache; 702e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 71cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei private final boolean mLimitDensity; 72e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei private final float mDensity; 73a23358fbfd62c7aa1c84bfa8395b4dc427a71ce6Mark Wei private ReusableBitmap mBitmap; 7493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private DecodeTask mTask; 759c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei private Cancelable mCreateFileDescriptorFactoryTask; 7693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 7793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // based on framework CL:I015d77 7893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); 7993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int CORE_POOL_SIZE = CPU_COUNT + 1; 8093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; 81cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei 8293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final Executor SMALL_POOL_EXECUTOR = new ThreadPoolExecutor( 8393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, 1, TimeUnit.SECONDS, 84cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei new LinkedBlockingQueue<Runnable>(128), new NamedThreadFactory("decode")); 8593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final Executor EXECUTOR = SMALL_POOL_EXECUTOR; 8693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final int MAX_BITMAP_DENSITY = DisplayMetrics.DENSITY_HIGH; 88cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei private static final float VERTICAL_CENTER = 1f / 2; 892e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei private static final float NO_MULTIPLIER = 1f; 9093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 91e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei private static final String TAG = BasicBitmapDrawable.class.getSimpleName(); 92cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei private static final boolean DEBUG = DecodeTask.DEBUG; 9393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 94cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei public BasicBitmapDrawable(final Resources res, final BitmapCache cache, 95cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei final boolean limitDensity) { 9693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDensity = res.getDisplayMetrics().density; 9793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache = cache; 98cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei mLimitDensity = limitDensity; 9993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setFilterBitmap(true); 100e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei mPaint.setAntiAlias(true); 101e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei mPaint.setDither(true); 102e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei 103e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei if (sRect == null) { 104e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei sRect = new Rect(); 105e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei } 10693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10810dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei public final RequestKey getKey() { 10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return mCurrKey; 11093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 11193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 11241af50eb1ac488572b066629c3954b23c21dfa76Mark Wei protected ReusableBitmap getBitmap() { 1132e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return mBitmap; 1142e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 1152e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 11693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 11710dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Set the dimensions to decode into. These dimensions should never change while the drawable is 11810dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * attached to the same cache, because caches can only contain bitmaps of one size for re-use. 11910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * 12010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * All UI operations should be called from the UI thread. 12193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 12210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei public final void setDecodeDimensions(int w, int h) { 12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDecodeWidth = w; 12493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDecodeHeight = h; 1259c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei loadFileDescriptorFactory(); 12693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 12793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12810dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 12910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Binds to the given key and start the decode process. This will first look in the cache, then 13010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * decode from the request key if not found. 13110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * 13210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * All UI operations should be called from the UI thread. 13310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 13441af50eb1ac488572b066629c3954b23c21dfa76Mark Wei public void bind(RequestKey key) { 13510dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei setImage(key); 13693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 13793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 13810dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 13910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Unbinds the current key and bitmap from the drawable. This will cause the bitmap to decrement 14010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * its ref count. 14110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * 14210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * All UI operations should be called from the UI thread. 14310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 14441af50eb1ac488572b066629c3954b23c21dfa76Mark Wei public void unbind() { 14510dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei setImage(null); 14693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 14793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 14810dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 14910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 15010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 1512e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void setImage(final RequestKey key) { 15293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mCurrKey != null && mCurrKey.equals(key)) { 15393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 15493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 15593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 15693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("set image"); 15793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("release reference"); 15893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mBitmap != null) { 15993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mBitmap.releaseReference(); 16093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mBitmap = null; 16193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 16293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 1632e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 1642e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mPrevKey = mCurrKey; 16593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCurrKey = key; 16693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 16793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mTask != null) { 16893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mTask.cancel(); 16993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mTask = null; 17093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 1719c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei if (mCreateFileDescriptorFactoryTask != null) { 1729c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei mCreateFileDescriptorFactoryTask.cancel(); 1739c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei mCreateFileDescriptorFactoryTask = null; 1749c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei } 17593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 17693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (key == null) { 17793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 17893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 17993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 18093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 18293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // find cached entry here and skip decode if found. 18393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final ReusableBitmap cached = mCache.get(key, true /* incrementRefCount */); 18493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (cached != null) { 18593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setBitmap(cached); 18693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 18793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.d(TAG, String.format("CACHE HIT key=%s", mCurrKey)); 18893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 1909c6ac19d4a3d39b7c2992060957920118ff56a65Mark Wei loadFileDescriptorFactory(); 19193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 19293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.d(TAG, String.format( 19393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein "CACHE MISS key=%s\ncache=%s", mCurrKey, mCache.toDebugString())); 19493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 19593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 19693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 19793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 19893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 19910dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 20010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 20110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 2022e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void setBitmap(ReusableBitmap bmp) { 2032e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mBitmap != null && mBitmap != bmp) { 2042e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mBitmap.releaseReference(); 2052e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2062e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mBitmap = bmp; 2072e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei invalidateSelf(); 2082e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2092e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 21010dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 21110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 21210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 2132e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void loadFileDescriptorFactory() { 2142e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mCurrKey == null || mDecodeWidth == 0 || mDecodeHeight == 0) { 2152e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return; 2162e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2172e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2182e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei // Create file descriptor if request supports it. 2192e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mCreateFileDescriptorFactoryTask = mCurrKey 2202e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei .createFileDescriptorFactoryAsync(mCurrKey, this); 2212e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mCreateFileDescriptorFactoryTask == null) { 2222e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei // Use input stream if request does not. 2232e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei decode(null); 2242e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2252e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2262e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2272e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei @Override 2282e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei public void fileDescriptorFactoryCreated(final RequestKey key, 2292e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final FileDescriptorFactory factory) { 2302e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mCreateFileDescriptorFactoryTask == null) { 2312e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei // Cancelled. 2322e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return; 2332e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2342e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mCreateFileDescriptorFactoryTask = null; 2352e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2362e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (key.equals(mCurrKey)) { 2372e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei decode(factory); 2382e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2392e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2402e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 24110dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei /** 24210dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei * Should only be overriden, not called. 24310dddd8a24a80d1d539997d8eaa9763c62bd02adMark Wei */ 2442e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected void decode(final FileDescriptorFactory factory) { 2452e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei Trace.beginSection("decode"); 2462e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final int bufferW; 2472e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final int bufferH; 2482e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mLimitDensity) { 2492e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final float scale = 2502e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei Math.min(1f, (float) MAX_BITMAP_DENSITY / DisplayMetrics.DENSITY_DEFAULT 2512e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei / mDensity); 2522e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferW = (int) (mDecodeWidth * scale); 2532e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferH = (int) (mDecodeHeight * scale); 2542e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } else { 2552e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferW = mDecodeWidth; 2562e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei bufferH = mDecodeHeight; 2572e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2582e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2592e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei if (mTask != null) { 2602e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mTask.cancel(); 2612e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2622e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei final DecodeOptions opts = new DecodeOptions(bufferW, bufferH, getDecodeVerticalCenter(), 2632e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei DecodeOptions.STRATEGY_ROUND_NEAREST); 2642e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei mTask = new DecodeTask(mCurrKey, opts, factory, this, mCache); 265aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei mTask.executeOnExecutor(getExecutor()); 2662e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei Trace.endSection(); 2672e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2682e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 269aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei protected Executor getExecutor() { 270aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei return EXECUTOR; 271aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei } 272aab539ecd75ae365912200eb7f3318a53e9834f4Mark Wei 2732e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected float getDrawVerticalCenter() { 2742e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return VERTICAL_CENTER; 2752e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2762e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2772e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected float getDrawVerticalOffsetMultiplier() { 2782e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return NO_MULTIPLIER; 2792e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2802e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 2812e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei protected float getDecodeVerticalCenter() { 2822e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei return VERTICAL_CENTER; 2832e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei } 2842e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei 28593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 28693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void draw(final Canvas canvas) { 28793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Rect bounds = getBounds(); 28893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (bounds.isEmpty()) { 28993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 29093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 29193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 29293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mBitmap != null && mBitmap.bmp != null) { 29393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein BitmapUtils.calculateCroppedSrcRect( 29493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight(), 29593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein bounds.width(), bounds.height(), 29693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein bounds.height(), Integer.MAX_VALUE, 2972e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei getDrawVerticalCenter(), false /* absoluteFraction */, 2982e4d0863dba53435372ec96538f2ef3e1c3675bfMark Wei getDrawVerticalOffsetMultiplier(), sRect); 29993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 30093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int orientation = mBitmap.getOrientation(); 30193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // calculateCroppedSrcRect() gave us the source rectangle "as if" the orientation has 30293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // been corrected. We need to decode the uncorrected source rectangle. Calculate true 30393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // coordinates. 30493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein RectUtils.rotateRectForOrientation(orientation, 30593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein new Rect(0, 0, mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight()), 306e03daa1db89106c11d8885b94d7ac97c10bea3b3Mark Wei sRect); 30793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 30893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // We may need to rotate the canvas, so we also have to rotate the bounds. 30993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Rect rotatedBounds = new Rect(bounds); 31093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein RectUtils.rotateRect(orientation, bounds.centerX(), bounds.centerY(), rotatedBounds); 31193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 31293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // Rotate the canvas. 31393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein canvas.save(); 31493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein canvas.rotate(orientation, bounds.centerX(), bounds.centerY()); 3157be91f8fe3c6d9af037b36918ea5bd86a10bbb44Mark Wei onDrawBitmap(canvas, sRect, rotatedBounds); 31693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein canvas.restore(); 31793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 31893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 31993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 3200c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei /** 3210c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei * Override this method to customize how to draw the bitmap to the canvas for the given bounds. 3220c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei * The bitmap to be drawn can be found at {@link #getBitmap()}. 3230c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei */ 3247be91f8fe3c6d9af037b36918ea5bd86a10bbb44Mark Wei protected void onDrawBitmap(final Canvas canvas, final Rect src, final Rect dst) { 3257be91f8fe3c6d9af037b36918ea5bd86a10bbb44Mark Wei canvas.drawBitmap(mBitmap.bmp, src, dst, mPaint); 3260c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei } 3270c9aacac20202f4a41e98d8a34a6ee2c152ae2deMark Wei 32893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 32993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setAlpha(int alpha) { 33093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int old = mPaint.getAlpha(); 33193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setAlpha(alpha); 33293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (alpha != old) { 33393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 33493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 33593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 33693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 33793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 33893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setColorFilter(ColorFilter cf) { 33993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setColorFilter(cf); 34093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 34193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 34293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 34393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 34493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public int getOpacity() { 34593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return (mBitmap != null && (mBitmap.bmp.hasAlpha() || mPaint.getAlpha() < 255)) ? 34693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 34793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 34893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 34993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 35040662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public void onDecodeBegin(final RequestKey key) { } 35193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 35293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 35340662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public void onDecodeComplete(final RequestKey key, final ReusableBitmap result) { 35493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (key.equals(mCurrKey)) { 35593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setBitmap(result); 35693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 35793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // if the requests don't match (i.e. this request is stale), decrement the 35893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // ref count to allow the bitmap to be pooled 35993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (result != null) { 36093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.releaseReference(); 36193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 36293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 36393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 36493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 36593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 36640662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public void onDecodeCancel(final RequestKey key) { } 36793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 36893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 36993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void invalidateDrawable(Drawable who) { 37093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 37193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 37293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 37393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 37493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void scheduleDrawable(Drawable who, Runnable what, long when) { 37593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein scheduleSelf(what, when); 37693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 37793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 37893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 37993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void unscheduleDrawable(Drawable who, Runnable what) { 38093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein unscheduleSelf(what); 38193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 38293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein} 383