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

Commit 14e8af72 authored by Nick Chameyev's avatar Nick Chameyev Committed by Automerger Merge Worker
Browse files

Merge "Extract PreviewPositionHelper to shared library" into tm-qpr-dev am:...

Merge "Extract PreviewPositionHelper to shared library" into tm-qpr-dev am: b55f5dae am: 43bb2573

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20024606



Change-Id: If01d85c9de625c2bd8cb6d0c510d603830e061db
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents db868e7f 43bb2573
Loading
Loading
Loading
Loading
+209 −0
Original line number Diff line number Diff line
package com.android.systemui.shared.recents.utilities;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;

import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.Surface;

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

/**
 * Utility class to position the thumbnail in the TaskView
 */
public class PreviewPositionHelper {

    public static final float MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT = 0.1f;

    // Contains the portion of the thumbnail that is unclipped when fullscreen progress = 1.
    private final RectF mClippedInsets = new RectF();
    private final Matrix mMatrix = new Matrix();
    private boolean mIsOrientationChanged;

    public Matrix getMatrix() {
        return mMatrix;
    }

    public void setOrientationChanged(boolean orientationChanged) {
        mIsOrientationChanged = orientationChanged;
    }

    public boolean isOrientationChanged() {
        return mIsOrientationChanged;
    }

    /**
     * Updates the matrix based on the provided parameters
     */
    public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
            int canvasWidth, int canvasHeight, int screenWidthPx, int taskbarSize, boolean isTablet,
            int currentRotation, boolean isRtl) {
        boolean isRotated = false;
        boolean isOrientationDifferent;

        int thumbnailRotation = thumbnailData.rotation;
        int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
        RectF thumbnailClipHint = new RectF();
        float canvasScreenRatio = canvasWidth / (float) screenWidthPx;
        float scaledTaskbarSize = taskbarSize * canvasScreenRatio;
        thumbnailClipHint.bottom = isTablet ? scaledTaskbarSize : 0;

        float scale = thumbnailData.scale;
        final float thumbnailScale;

        // Landscape vs portrait change.
        // Note: Disable rotation in grid layout.
        boolean windowingModeSupportsRotation =
                thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isTablet;
        isOrientationDifferent = isOrientationChange(deltaRotate)
                && windowingModeSupportsRotation;
        if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
            // If we haven't measured , skip the thumbnail drawing and only draw the background
            // color
            thumbnailScale = 0f;
        } else {
            // Rotate the screenshot if not in multi-window mode
            isRotated = deltaRotate > 0 && windowingModeSupportsRotation;

            float surfaceWidth = thumbnailBounds.width() / scale;
            float surfaceHeight = thumbnailBounds.height() / scale;
            float availableWidth = surfaceWidth
                    - (thumbnailClipHint.left + thumbnailClipHint.right);
            float availableHeight = surfaceHeight
                    - (thumbnailClipHint.top + thumbnailClipHint.bottom);

            float canvasAspect = canvasWidth / (float) canvasHeight;
            float availableAspect = isRotated
                    ? availableHeight / availableWidth
                    : availableWidth / availableHeight;
            boolean isAspectLargelyDifferent =
                    Utilities.isRelativePercentDifferenceGreaterThan(canvasAspect,
                            availableAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT);
            if (isRotated && isAspectLargelyDifferent) {
                // Do not rotate thumbnail if it would not improve fit
                isRotated = false;
                isOrientationDifferent = false;
            }

            if (isAspectLargelyDifferent) {
                // Crop letterbox insets if insets isn't already clipped
                thumbnailClipHint.left = thumbnailData.letterboxInsets.left;
                thumbnailClipHint.right = thumbnailData.letterboxInsets.right;
                thumbnailClipHint.top = thumbnailData.letterboxInsets.top;
                thumbnailClipHint.bottom = thumbnailData.letterboxInsets.bottom;
                availableWidth = surfaceWidth
                        - (thumbnailClipHint.left + thumbnailClipHint.right);
                availableHeight = surfaceHeight
                        - (thumbnailClipHint.top + thumbnailClipHint.bottom);
            }

            final float targetW, targetH;
            if (isOrientationDifferent) {
                targetW = canvasHeight;
                targetH = canvasWidth;
            } else {
                targetW = canvasWidth;
                targetH = canvasHeight;
            }
            float targetAspect = targetW / targetH;

            // Update the clipHint such that
            //   > the final clipped position has same aspect ratio as requested by canvas
            //   > first fit the width and crop the extra height
            //   > if that will leave empty space, fit the height and crop the width instead
            float croppedWidth = availableWidth;
            float croppedHeight = croppedWidth / targetAspect;
            if (croppedHeight > availableHeight) {
                croppedHeight = availableHeight;
                if (croppedHeight < targetH) {
                    croppedHeight = Math.min(targetH, surfaceHeight);
                }
                croppedWidth = croppedHeight * targetAspect;

                // One last check in case the task aspect radio messed up something
                if (croppedWidth > surfaceWidth) {
                    croppedWidth = surfaceWidth;
                    croppedHeight = croppedWidth / targetAspect;
                }
            }

            // Update the clip hints. Align to 0,0, crop the remaining.
            if (isRtl) {
                thumbnailClipHint.left += availableWidth - croppedWidth;
                if (thumbnailClipHint.right < 0) {
                    thumbnailClipHint.left += thumbnailClipHint.right;
                    thumbnailClipHint.right = 0;
                }
            } else {
                thumbnailClipHint.right += availableWidth - croppedWidth;
                if (thumbnailClipHint.left < 0) {
                    thumbnailClipHint.right += thumbnailClipHint.left;
                    thumbnailClipHint.left = 0;
                }
            }
            thumbnailClipHint.bottom += availableHeight - croppedHeight;
            if (thumbnailClipHint.top < 0) {
                thumbnailClipHint.bottom += thumbnailClipHint.top;
                thumbnailClipHint.top = 0;
            } else if (thumbnailClipHint.bottom < 0) {
                thumbnailClipHint.top += thumbnailClipHint.bottom;
                thumbnailClipHint.bottom = 0;
            }

            thumbnailScale = targetW / (croppedWidth * scale);
        }

        if (!isRotated) {
            mMatrix.setTranslate(
                    -thumbnailClipHint.left * scale,
                    -thumbnailClipHint.top * scale);
        } else {
            setThumbnailRotation(deltaRotate, thumbnailBounds);
        }

        mClippedInsets.set(0, 0, 0, scaledTaskbarSize);

        mMatrix.postScale(thumbnailScale, thumbnailScale);
        mIsOrientationChanged = isOrientationDifferent;
    }

    private int getRotationDelta(int oldRotation, int newRotation) {
        int delta = newRotation - oldRotation;
        if (delta < 0) delta += 4;
        return delta;
    }

    /**
     * @param deltaRotation the number of 90 degree turns from the current orientation
     * @return {@code true} if the change in rotation results in a shift from landscape to
     * portrait or vice versa, {@code false} otherwise
     */
    private boolean isOrientationChange(int deltaRotation) {
        return deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270;
    }

    private void setThumbnailRotation(int deltaRotate, Rect thumbnailPosition) {
        float translateX = 0;
        float translateY = 0;

        mMatrix.setRotate(90 * deltaRotate);
        switch (deltaRotate) { /* Counter-clockwise */
            case Surface.ROTATION_90:
                translateX = thumbnailPosition.height();
                break;
            case Surface.ROTATION_270:
                translateY = thumbnailPosition.width();
                break;
            case Surface.ROTATION_180:
                translateX = thumbnailPosition.width();
                translateY = thumbnailPosition.height();
                break;
        }
        mMatrix.postTranslate(translateX, translateY);
    }

    public RectF getClippedInsets() {
        return mClippedInsets;
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -62,6 +62,16 @@ public class Utilities {
        return false; // Default
    }

    /**
     * Compares the ratio of two quantities and returns whether that ratio is greater than the
     * provided bound. Order of quantities does not matter. Bound should be a decimal representation
     * of a percentage.
     */
    public static boolean isRelativePercentDifferenceGreaterThan(float first, float second,
            float bound) {
        return (Math.abs(first - second) / Math.abs((first + second) / 2.0f)) > bound;
    }

    /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
    public static float computeContrastBetweenColors(int bg, int fg) {
        float bgR = Color.red(bg) / 255f;