BasicBitmapDrawable.java revision 93a35b93dc582e38ff8ee5979754a16b4bf4da0c
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/*
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright (C) 2013 The Android Open Source Project
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * you may not use this file except in compliance with the License.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch * See the License for the specific language governing permissions and
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License.
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochpackage com.android.bitmap.drawable;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.res.Resources;
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.graphics.Canvas;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.graphics.ColorFilter;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.graphics.Paint;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.graphics.PixelFormat;
23bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochimport android.graphics.Rect;
24bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochimport android.graphics.drawable.Drawable;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.util.DisplayMetrics;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.util.Log;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.BitmapCache;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.DecodeTask;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.DecodeTask.Request;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.ReusableBitmap;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.util.BitmapUtils;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.util.RectUtils;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.bitmap.util.Trace;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.concurrent.Executor;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.concurrent.LinkedBlockingQueue;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.concurrent.ThreadPoolExecutor;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.concurrent.TimeUnit;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class encapsulates the basic functionality needed to display a single image bitmap,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * including request creation/cancelling, and data unbinding and re-binding.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * <p>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The actual bitmap decode work is handled by {@link DecodeTask}.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class BasicBitmapDrawable extends Drawable implements DecodeTask.DecodeCallback,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Drawable.Callback {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private BitmapRequestKey mCurrKey;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private ReusableBitmap mBitmap;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private final BitmapCache mCache;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private DecodeTask mTask;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private int mDecodeWidth;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private int mDecodeHeight;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // based on framework CL:I015d77
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final Executor SMALL_POOL_EXECUTOR = new ThreadPoolExecutor(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, 1, TimeUnit.SECONDS,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new LinkedBlockingQueue<Runnable>(128));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final Executor EXECUTOR = SMALL_POOL_EXECUTOR;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final boolean LIMIT_BITMAP_DENSITY = true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int MAX_BITMAP_DENSITY = DisplayMetrics.DENSITY_HIGH;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private final float mDensity;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private final Paint mPaint = new Paint();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private final Rect mSrcRect = new Rect();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final String TAG = BasicBitmapDrawable.class.getSimpleName();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final boolean DEBUG = false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public BasicBitmapDrawable(final Resources res, final BitmapCache cache) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mDensity = res.getDisplayMetrics().density;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mCache = cache;
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mPaint.setFilterBitmap(true);
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public DecodeTask.Request getKey() {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return mCurrKey;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Set the dimensions to decode into.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void setDecodeDimensions(int w, int h) {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        mDecodeWidth = w;
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        mDecodeHeight = h;
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        decode();
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void unbind() {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        setImage(null);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void bind(BitmapRequestKey key) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        setImage(key);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void setImage(final BitmapRequestKey key) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mCurrKey != null && mCurrKey.equals(key)) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Trace.beginSection("set image");
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Trace.beginSection("release reference");
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mBitmap != null) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mBitmap.releaseReference();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mBitmap = null;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Trace.endSection();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mCurrKey = key;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mTask != null) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mTask.cancel();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mTask = null;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (key == null) {
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            invalidateSelf();
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            Trace.endSection();
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return;
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // find cached entry here and skip decode if found.
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        final ReusableBitmap cached = mCache.get(key, true /* incrementRefCount */);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (cached != null) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            setBitmap(cached);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (DEBUG) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                Log.d(TAG, String.format("CACHE HIT key=%s", mCurrKey));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
138bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            decode();
139bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            if (DEBUG) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                Log.d(TAG, String.format(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "CACHE MISS key=%s\ncache=%s", mCurrKey, mCache.toDebugString()));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
143bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        }
144bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        Trace.endSection();
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public void draw(final Canvas canvas) {
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        final Rect bounds = getBounds();
150bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        if (bounds.isEmpty()) {
151bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            return;
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mBitmap != null && mBitmap.bmp != null) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BitmapUtils.calculateCroppedSrcRect(
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight(),
157bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                    bounds.width(), bounds.height(),
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    bounds.height(), Integer.MAX_VALUE,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    0.5f, false /* absoluteFraction */,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    1, mSrcRect);
161bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            final int orientation = mBitmap.getOrientation();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // calculateCroppedSrcRect() gave us the source rectangle "as if" the orientation has
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // been corrected. We need to decode the uncorrected source rectangle. Calculate true
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            // coordinates.
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            RectUtils.rotateRectForOrientation(orientation,
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    new Rect(0, 0, mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight()),
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    mSrcRect);
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // We may need to rotate the canvas, so we also have to rotate the bounds.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            final Rect rotatedBounds = new Rect(bounds);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RectUtils.rotateRect(orientation, bounds.centerX(), bounds.centerY(), rotatedBounds);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // Rotate the canvas.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            canvas.save();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            canvas.rotate(orientation, bounds.centerX(), bounds.centerY());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            canvas.drawBitmap(mBitmap.bmp, mSrcRect, rotatedBounds, mPaint);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            canvas.restore();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void setAlpha(int alpha) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        final int old = mPaint.getAlpha();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mPaint.setAlpha(alpha);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (alpha != old) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            invalidateSelf();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void setColorFilter(ColorFilter cf) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mPaint.setColorFilter(cf);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalidateSelf();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public int getOpacity() {
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return (mBitmap != null && (mBitmap.bmp.hasAlpha() || mPaint.getAlpha() < 255)) ?
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @Override
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public void onDecodeBegin(final Request key) { }
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onDecodeComplete(final Request key, final ReusableBitmap result) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (key.equals(mCurrKey)) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            setBitmap(result);
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else {
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            // if the requests don't match (i.e. this request is stale), decrement the
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            // ref count to allow the bitmap to be pooled
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            if (result != null) {
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                result.releaseReference();
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            }
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onDecodeCancel(final Request key) { }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void setBitmap(ReusableBitmap bmp) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mBitmap != null && mBitmap != bmp) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mBitmap.releaseReference();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mBitmap = bmp;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalidateSelf();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private void decode() {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        final int bufferW;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int bufferH;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mCurrKey == null) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Trace.beginSection("decode");
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (LIMIT_BITMAP_DENSITY) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            final float scale =
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    Math.min(1f, (float) MAX_BITMAP_DENSITY / DisplayMetrics.DENSITY_DEFAULT
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            / mDensity);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bufferW = (int) (mDecodeWidth * scale);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            bufferH = (int) (mDecodeHeight * scale);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bufferW = mDecodeWidth;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bufferH = mDecodeHeight;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (bufferW == 0 || bufferH == 0) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Trace.endSection();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mTask != null) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mTask.cancel();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mTask = new DecodeTask(mCurrKey, bufferW, bufferH, this, mCache);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mTask.executeOnExecutor(EXECUTOR);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Trace.endSection();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void invalidateDrawable(Drawable who) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalidateSelf();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void scheduleDrawable(Drawable who, Runnable what, long when) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scheduleSelf(what, when);
270bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
271bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
272bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    @Override
273bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    public void unscheduleDrawable(Drawable who, Runnable what) {
274bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        unscheduleSelf(what);
275bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
276bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
277bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch