BasicBitmapDrawable.java revision cea0c012d538f11b3ee97d4b7e78f4c1ea73d5be
15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/*
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Copyright (C) 2013 The Android Open Source Project
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Licensed under the Apache License, Version 2.0 (the "License");
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * you may not use this file except in compliance with the License.
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * You may obtain a copy of the License at
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *      http://www.apache.org/licenses/LICENSE-2.0
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Unless required by applicable law or agreed to in writing, software
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * distributed under the License is distributed on an "AS IS" BASIS,
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * See the License for the specific language governing permissions and
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * limitations under the License.
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liupackage com.android.bitmap.drawable;
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport android.content.res.Resources;
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport android.graphics.Canvas;
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport android.graphics.ColorFilter;
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport android.graphics.Paint;
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport android.graphics.PixelFormat;
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import android.graphics.Rect;
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import android.graphics.drawable.Drawable;
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import android.util.DisplayMetrics;
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import android.util.Log;
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport com.android.bitmap.BitmapCache;
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport com.android.bitmap.DecodeTask;
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.DecodeTask.DecodeOptions;
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.NamedThreadFactory;
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.RequestKey;
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.ReusableBitmap;
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.util.BitmapUtils;
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.util.RectUtils;
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import com.android.bitmap.util.Trace;
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import java.util.concurrent.Executor;
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import java.util.concurrent.LinkedBlockingQueue;
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import java.util.concurrent.ThreadPoolExecutor;
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)import java.util.concurrent.TimeUnit;
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)/**
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * This class encapsulates the basic functionality needed to display a single image bitmap,
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * including request creation/cancelling, and data unbinding and re-binding.
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * <p>
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * The actual bitmap decode work is handled by {@link DecodeTask}.
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) */
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)public class BasicBitmapDrawable extends Drawable implements DecodeTask.DecodeCallback,
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        Drawable.Callback {
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private RequestKey mCurrKey;
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private ReusableBitmap mBitmap;
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private final BitmapCache mCache;
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private final boolean mLimitDensity;
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private DecodeTask mTask;
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private int mDecodeWidth;
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private int mDecodeHeight;
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private static final String TAG = BasicBitmapDrawable.class.getSimpleName();
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // based on framework CL:I015d77
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private static final Executor SMALL_POOL_EXECUTOR = new ThreadPoolExecutor(
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, 1, TimeUnit.SECONDS,
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            new LinkedBlockingQueue<Runnable>(128), new NamedThreadFactory("decode"));
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private static final Executor EXECUTOR = SMALL_POOL_EXECUTOR;
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private static final int MAX_BITMAP_DENSITY = DisplayMetrics.DENSITY_HIGH;
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private static final float VERTICAL_CENTER = 1f / 2;
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private final float mDensity;
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private final Paint mPaint = new Paint();
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private final Rect mSrcRect = new Rect();
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private static final boolean DEBUG = DecodeTask.DEBUG;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public BasicBitmapDrawable(final Resources res, final BitmapCache cache,
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            final boolean limitDensity) {
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mDensity = res.getDisplayMetrics().density;
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mCache = cache;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mLimitDensity = limitDensity;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mPaint.setFilterBitmap(true);
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public RequestKey getKey() {
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return mCurrKey;
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    /**
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)     * Set the dimensions to decode into.
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)     */
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void setDecodeDimensions(int w, int h) {
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mDecodeWidth = w;
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mDecodeHeight = h;
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        decode();
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void unbind() {
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        setImage(null);
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void bind(RequestKey key) {
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        setImage(key);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    private void setImage(final RequestKey key) {
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (mCurrKey != null && mCurrKey.equals(key)) {
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return;
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        Trace.beginSection("set image");
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Trace.beginSection("release reference");
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (mBitmap != null) {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            mBitmap.releaseReference();
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            mBitmap = null;
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Trace.endSection();
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mCurrKey = key;
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (mTask != null) {
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            mTask.cancel();
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            mTask = null;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (key == null) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            invalidateSelf();
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            Trace.endSection();
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return;
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // find cached entry here and skip decode if found.
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        final ReusableBitmap cached = mCache.get(key, true /* incrementRefCount */);
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (cached != null) {
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            setBitmap(cached);
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            if (DEBUG) {
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                Log.d(TAG, String.format("CACHE HIT key=%s", mCurrKey));
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            }
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else {
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            decode();
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            if (DEBUG) {
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                Log.d(TAG, String.format(
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        "CACHE MISS key=%s\ncache=%s", mCurrKey, mCache.toDebugString()));
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            }
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Trace.endSection();
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    @Override
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void draw(final Canvas canvas) {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        final Rect bounds = getBounds();
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (bounds.isEmpty()) {
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return;
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (mBitmap != null && mBitmap.bmp != null) {
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            BitmapUtils.calculateCroppedSrcRect(
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight(),
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    bounds.width(), bounds.height(),
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    bounds.height(), Integer.MAX_VALUE,
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    VERTICAL_CENTER, false /* absoluteFraction */,
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    1, mSrcRect);
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            final int orientation = mBitmap.getOrientation();
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            // calculateCroppedSrcRect() gave us the source rectangle "as if" the orientation has
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            // been corrected. We need to decode the uncorrected source rectangle. Calculate true
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            // coordinates.
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            RectUtils.rotateRectForOrientation(orientation,
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    new Rect(0, 0, mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight()),
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    mSrcRect);
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            // We may need to rotate the canvas, so we also have to rotate the bounds.
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            final Rect rotatedBounds = new Rect(bounds);
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            RectUtils.rotateRect(orientation, bounds.centerX(), bounds.centerY(), rotatedBounds);
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            // Rotate the canvas.
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            canvas.save();
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            canvas.rotate(orientation, bounds.centerX(), bounds.centerY());
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            canvas.drawBitmap(mBitmap.bmp, mSrcRect, rotatedBounds, mPaint);
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            canvas.restore();
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    @Override
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void setAlpha(int alpha) {
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        final int old = mPaint.getAlpha();
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mPaint.setAlpha(alpha);
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (alpha != old) {
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            invalidateSelf();
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    @Override
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void setColorFilter(ColorFilter cf) {
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        mPaint.setColorFilter(cf);
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        invalidateSelf();
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    @Override
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    public int getOpacity() {
2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return (mBitmap != null && (mBitmap.bmp.hasAlpha() || mPaint.getAlpha() < 255)) ?
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    @Override
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    public void onDecodeBegin(final RequestKey key) { }
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    @Override
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    public void onDecodeComplete(final RequestKey key, final ReusableBitmap result) {
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (key.equals(mCurrKey)) {
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            setBitmap(result);
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        } else {
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            // if the requests don't match (i.e. this request is stale), decrement the
2190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)            // ref count to allow the bitmap to be pooled
2200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)            if (result != null) {
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                result.releaseReference();
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            }
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    @Override
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    public void onDecodeCancel(final RequestKey key) { }
2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    private void setBitmap(ReusableBitmap bmp) {
230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (mBitmap != null && mBitmap != bmp) {
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            mBitmap.releaseReference();
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        mBitmap = bmp;
234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        invalidateSelf();
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    private void decode() {
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        final int bufferW;
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        final int bufferH;
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (mCurrKey == null) {
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return;
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        Trace.beginSection("decode");
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (mLimitDensity) {
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            final float scale =
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                    Math.min(1f, (float) MAX_BITMAP_DENSITY / DisplayMetrics.DENSITY_DEFAULT
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            / mDensity);
2500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)            bufferW = (int) (mDecodeWidth * scale);
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            bufferH = (int) (mDecodeHeight * scale);
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        } else {
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            bufferW = mDecodeWidth;
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            bufferH = mDecodeHeight;
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (bufferW == 0 || bufferH == 0) {
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            Trace.endSection();
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            return;
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (mTask != null) {
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            mTask.cancel();
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        final DecodeOptions opts = new DecodeOptions(bufferW, bufferH, VERTICAL_CENTER,
2650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                DecodeOptions.STRATEGY_ROUND_NEAREST);
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        mTask = new DecodeTask(mCurrKey, opts, this, mCache);
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        mTask.executeOnExecutor(EXECUTOR);
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        Trace.endSection();
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    @Override
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    public void invalidateDrawable(Drawable who) {
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        invalidateSelf();
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    @Override
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    public void scheduleDrawable(Drawable who, Runnable what, long when) {
278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        scheduleSelf(what, when);
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    @Override
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    public void unscheduleDrawable(Drawable who, Runnable what) {
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        unscheduleSelf(what);
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)