Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 518ff108 authored by Kevin's avatar Kevin
Browse files

Use custom drawable for Recents Go thumbnails (1/2)

In order to support rotated thumbnails based off the device orientation,
we should create a custom drawable that supports drawing a rotated
bitmap based off some requested orientation. This CL adds this class,
and we'll use it in a later CL.

By baking this directly into the drawable, we prevent unnecessary
allocations of rotated bitmaps.

Bug: 114136250
Bug: 131095241
Test: Builds
Change-Id: Ib4e83e3619028c583e10f1b8d743a365ec310346
parent 1942fabf
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.quickstep;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

import androidx.annotation.NonNull;

import com.android.systemui.shared.recents.model.ThumbnailData;

/**
 * Bitmap backed drawable that supports rotating the thumbnail bitmap depending on if the
 * orientation the thumbnail was taken in matches the desired orientation. In addition, the
 * thumbnail always fills into the containing bounds.
 */
public final class ThumbnailDrawable extends Drawable {

    private final Paint mPaint = new Paint();
    private final Matrix mMatrix = new Matrix();
    private final ThumbnailData mThumbnailData;
    private int mRequestedOrientation;

    public ThumbnailDrawable(@NonNull ThumbnailData thumbnailData, int requestedOrientation) {
        mThumbnailData = thumbnailData;
        mRequestedOrientation = requestedOrientation;
        updateMatrix();
    }

    /**
     * Set the requested orientation.
     *
     * @param orientation the orientation we want the thumbnail to be in
     */
    public void setRequestedOrientation(int orientation) {
        if (mRequestedOrientation != orientation) {
            mRequestedOrientation = orientation;
            updateMatrix();
        }
    }

    @Override
    public void draw(Canvas canvas) {
        if (mThumbnailData.thumbnail == null) {
            return;
        }
        canvas.drawBitmap(mThumbnailData.thumbnail, mMatrix, mPaint);
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        updateMatrix();
    }

    @Override
    public void setAlpha(int alpha) {
        final int oldAlpha = mPaint.getAlpha();
        if (alpha != oldAlpha) {
            mPaint.setAlpha(alpha);
            invalidateSelf();
        }
    }

    @Override
    public int getAlpha() {
        return mPaint.getAlpha();
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        invalidateSelf();
    }

    @Override
    public ColorFilter getColorFilter() {
        return mPaint.getColorFilter();
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    private void updateMatrix() {
        if (mThumbnailData.thumbnail == null) {
            return;
        }
        mMatrix.reset();
        float scaleX;
        float scaleY;
        Rect bounds = getBounds();
        Bitmap thumbnail = mThumbnailData.thumbnail;
        if (mRequestedOrientation != mThumbnailData.orientation) {
            // Rotate and translate so that top left is the same.
            mMatrix.postRotate(90, 0, 0);
            mMatrix.postTranslate(thumbnail.getHeight(), 0);

            scaleX = (float) bounds.width() / thumbnail.getHeight();
            scaleY = (float) bounds.height() / thumbnail.getWidth();
        } else {
            scaleX = (float) bounds.width() / thumbnail.getWidth();
            scaleY = (float) bounds.height() / thumbnail.getHeight();
        }
        // Scale to fill.
        mMatrix.postScale(scaleX, scaleY);
    }
}