165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.util;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Color;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Rect;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.RectF;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.BitmapDrawable;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.Drawable;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Parcelable;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils;
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View;
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.ImageView;
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
336e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.widget.BitmapWorkerOptions;
346e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.widget.DrawableDownloader;
356e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList;
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.List;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Initiator calls {@link #createFromImageView(ImageView)} and
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * {@link #writeMultipleToIntent(List, Intent)}.
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p>
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Receiver calls {@link #readMultipleFromIntent(Context, Intent)} to read source and
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * {@link #createFromImageView(ImageView)} for target image view;  then start animation
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * using {@link TransitionImageView} between these two.<p>
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * The matching of Uri is up to receiver, typically using {@link TransitionImageMatcher}
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p>
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * The transition image has three bounds, all relative to window<p>
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * - {@link #setRect(Rect)}  bounds of the image view, including background color<p>
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * - {@link #setUnclippedRect(RectF)} bounds of original bitmap without clipping,  the rect
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *   might be bigger than the image view<p>
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * - {@link #setClippedRect(RectF)} bounds of clipping<p>
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class TransitionImage {
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Uri mUri;
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private BitmapDrawable mBitmap;
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Rect mRect = new Rect();
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mBackground = Color.TRANSPARENT;
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private float mAlpha = 1f;
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private float mSaturation = 1f;
626e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler    private final RectF mUnclippedRect = new RectF();
636e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler    private final RectF mClippedRect = new RectF();
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private boolean mUseClippedRectOnTransparent = true;
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP =
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bitmap";
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_RECT =
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_rect";
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_URI =
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_uri";
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_ALPHA =
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_alpha";
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_SATURATION =
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_saturation";
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_BACKGROUND =
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_background";
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT =
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_unclipped_rect";
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_BITMAP_CLIPPED_RECT =
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_bmp_clipped_rect";
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_TRANSITION_MULTIPLE_BITMAP =
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            "com.android.tv.settings.transition_multiple_bitmap";
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public TransitionImage() {
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public Uri getUri() {
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mUri;
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setUri(Uri uri) {
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mUri = uri;
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public BitmapDrawable getBitmap() {
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mBitmap;
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setBitmap(BitmapDrawable bitmap) {
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mBitmap = bitmap;
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public Rect getRect() {
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mRect;
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setRect(Rect rect) {
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mRect.set(rect);
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int getBackground() {
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mBackground;
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setBackground(int color) {
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mBackground = color;
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public float getAlpha() {
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mAlpha;
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setAlpha(float alpha) {
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mAlpha = alpha;
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public float getSaturation() {
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mSaturation;
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setSaturation(float saturation) {
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mSaturation = saturation;
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public RectF getUnclippedRect() {
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mUnclippedRect;
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setUnclippedRect(RectF rect) {
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mUnclippedRect.set(rect);
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public RectF getClippedRect() {
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mClippedRect;
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setClippedRect(RectF rect) {
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mClippedRect.set(rect);
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static List<TransitionImage> readMultipleFromIntent(Context context, Intent intent) {
1536e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler        ArrayList<TransitionImage> transitions = new ArrayList<>();
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Bundle extras = intent.getExtras();
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (extras == null) {
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return transitions;
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        TransitionImage image = new TransitionImage();
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (image.readFromBundle(context, intent.getSourceBounds(), extras)) {
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            transitions.add(image);
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Parcelable[] multiple =
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                intent.getParcelableArrayExtra(EXTRA_TRANSITION_MULTIPLE_BITMAP);
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (multiple != null) {
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            for (int i = 0, size = multiple.length; i < size; i++) {
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (!(multiple[i] instanceof Bundle)) {
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    break;
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                image = new TransitionImage();
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (image.readFromBundle(context, null, (Bundle) multiple[i])) {
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    transitions.add(image);
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return transitions;
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static void writeMultipleToIntent(List<TransitionImage> transitions, Intent intent) {
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (transitions == null || transitions.size() == 0) {
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return;
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int size = transitions.size();
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (size == 1) {
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            TransitionImage image = transitions.get(0);
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            image.writeToIntent(intent);
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return;
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Parcelable[] multipleBundle = new Parcelable[size];
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (int i = 0; i < size; i++) {
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Bundle b = new Bundle();
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            transitions.get(i).writeToBundle(b);
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            multipleBundle[i] = b;
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_MULTIPLE_BITMAP, multipleBundle);
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean readFromBundle(Context context, Rect intentSourceBounds, Bundle bundle) {
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setBitmap(null);
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (bundle == null) {
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mUri = bundle.getParcelable(EXTRA_TRANSITION_BITMAP_URI);
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        BitmapDrawable bitmap = null;
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mUri != null) {
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            DrawableDownloader downloader = DrawableDownloader.getInstance(context);
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            BitmapWorkerOptions key = new BitmapWorkerOptions.Builder(context)
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .resource(mUri).build();
2086e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler            bitmap = downloader.getLargestBitmapFromMemCache(key);
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (bitmap == null) {
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (bundle.containsKey(EXTRA_TRANSITION_BITMAP)) {
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                bitmap = new BitmapDrawable(context.getResources(),
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        ActivityTransitionBitmapHelper.getBitmapFromBinderBundle(
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        bundle.getBundle(EXTRA_TRANSITION_BITMAP)));
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (bitmap == null) {
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return false;
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Rect rect = null;
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String bitmapRectStr = bundle.getString(EXTRA_TRANSITION_BITMAP_RECT);
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (!TextUtils.isEmpty(bitmapRectStr)) {
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            rect = Rect.unflattenFromString(bitmapRectStr);
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (rect == null) {
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            rect = intentSourceBounds;
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (rect == null) {
22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setBitmap(bitmap);
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setRect(rect);
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (!readRectF(bundle.getFloatArray(EXTRA_TRANSITION_BITMAP_CLIPPED_RECT),
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mClippedRect)) {
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mClippedRect.set(rect);
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (!readRectF(bundle.getFloatArray(EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT),
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mUnclippedRect)) {
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mUnclippedRect.set(rect);
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setAlpha(bundle.getFloat(EXTRA_TRANSITION_BITMAP_ALPHA, 1f));
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setSaturation(bundle.getFloat(EXTRA_TRANSITION_BITMAP_SATURATION, 1f));
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        setBackground(bundle.getInt(EXTRA_TRANSITION_BITMAP_BACKGROUND, 0));
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return true;
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void writeToBundle(Bundle bundle) {
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putParcelable(EXTRA_TRANSITION_BITMAP_URI, mUri);
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putString(EXTRA_TRANSITION_BITMAP_RECT, mRect.flattenToString());
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mBitmap != null) {
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            bundle.putBundle(EXTRA_TRANSITION_BITMAP,
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    ActivityTransitionBitmapHelper.bitmapAsBinderBundle(mBitmap.getBitmap()));
25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putFloatArray(EXTRA_TRANSITION_BITMAP_CLIPPED_RECT,
25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                writeRectF(mClippedRect, new float[4]));
25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putFloatArray(EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT,
25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                writeRectF(mUnclippedRect, new float[4]));
25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putFloat(EXTRA_TRANSITION_BITMAP_ALPHA, mAlpha);
25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putFloat(EXTRA_TRANSITION_BITMAP_SATURATION, mSaturation);
26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        bundle.putInt(EXTRA_TRANSITION_BITMAP_BACKGROUND, mBackground);
26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void writeToIntent(Intent intent) {
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.setSourceBounds(mRect);
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_URI, mUri);
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_RECT, mRect.flattenToString());
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mBitmap != null) {
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            intent.putExtra(EXTRA_TRANSITION_BITMAP,
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    ActivityTransitionBitmapHelper.bitmapAsBinderBundle(mBitmap.getBitmap()));
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_CLIPPED_RECT,
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                writeRectF(mClippedRect, new float[4]));
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT,
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                writeRectF(mUnclippedRect, new float[4]));
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_ALPHA, mAlpha);
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_SATURATION, mSaturation);
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.putExtra(EXTRA_TRANSITION_BITMAP_BACKGROUND, mBackground);
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static boolean readRectF(float[] values, RectF f) {
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (values == null || values.length != 4) {
28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        f.set(values[0], values[1], values[2], values[3]);
28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return true;
28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static float[] writeRectF(RectF f, float[] values) {
28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        values[0] = f.left;
29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        values[1] = f.top;
29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        values[2] = f.right;
29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        values[3] = f.bottom;
29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return values;
29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * set bounds and bitmap
29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void createFromImageView(ImageView imageView) {
30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        createFromImageView(imageView, imageView);
30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * set bounds and bitmap
30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param backgroundView background view can be larger than the image view that will
30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * be drawn with background color
30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void createFromImageView(ImageView view, View backgroundView) {
31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Drawable drawable = view.getDrawable();
31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (drawable instanceof BitmapDrawable) {
31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            setBitmap((BitmapDrawable) drawable);
31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // use background View as the outside bounds and we can fill
31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // background color in it
31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mClippedRect.set(0, 0, backgroundView.getWidth(), backgroundView.getHeight());
31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        WindowLocationUtil.getLocationsInWindow(backgroundView, mClippedRect);
31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mClippedRect.round(mRect);
31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // get image view rects
32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        WindowLocationUtil.getImageLocationsInWindow(view, mClippedRect, mUnclippedRect);
32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * set if background is transparent, set if we want to use {@link #setClippedRect(RectF)}
32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * instead of {@link #setRect(Rect)}.  Default value is true,  and the value is not
32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * serialized.  User should call it before using TransitionImageAnimation.
32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setUseClippedRectOnTransparent(boolean ignoreBackground) {
32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mUseClippedRectOnTransparent = ignoreBackground;
33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * get if background is not transparent, set if we want to use {@link #setClippedRect(RectF)}
33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * instead of {@link #setRect(Rect)}
33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean getUseClippedRectOnTransparent() {
33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mUseClippedRectOnTransparent;
33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Get optimized rect depending on the background color
34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void getOptimizedRect(Rect rect) {
34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mUseClippedRectOnTransparent && mBackground == Color.TRANSPARENT) {
34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mClippedRect.round(rect);
34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            rect.set(mRect);
34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String toString() {
35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return "{TransitionImage Uri=" + mUri + " rect=" + mRect
35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                + " unclipRect=" + mUnclippedRect + " clipRect=" + mClippedRect
35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                + " bitmap=" + mBitmap + " alpha=" + mAlpha + " saturation=" + mSaturation
35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                + " background=" + mBackground;
35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
359