1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm.utils;
18 
19 import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
20 import static android.view.Surface.ROTATION_0;
21 import static android.view.Surface.ROTATION_180;
22 import static android.view.Surface.ROTATION_270;
23 import static android.view.Surface.ROTATION_90;
24 
25 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
26 
27 import android.graphics.Matrix;
28 import android.graphics.Rect;
29 import android.graphics.RectF;
30 
31 import com.android.internal.annotations.VisibleForTesting;
32 
33 /**
34  * Utility to compute bounds after rotating the screen.
35  */
36 public class DisplayRotationUtil {
37     private final Matrix mTmpMatrix = new Matrix();
38 
getRotationToBoundsOffset(int rotation)39     private static int getRotationToBoundsOffset(int rotation) {
40         switch (rotation) {
41             case ROTATION_0:
42                 return 0;
43             case ROTATION_90:
44                 return -1;
45             case ROTATION_180:
46                 return 2;
47             case ROTATION_270:
48                 return 1;
49             default:
50                 // should not happen
51                 return 0;
52         }
53     }
54 
55     @VisibleForTesting
getBoundIndexFromRotation(int i, int rotation)56     static int getBoundIndexFromRotation(int i, int rotation) {
57         return Math.floorMod(i + getRotationToBoundsOffset(rotation),
58                 BOUNDS_POSITION_LENGTH);
59     }
60 
61     /**
62      * Compute bounds after rotating teh screen.
63      *
64      * @param bounds Bounds before the rotation. The array must contain exactly 4 non-null elements.
65      * @param rotation rotation constant defined in android.view.Surface.
66      * @param initialDisplayWidth width of the display before the rotation.
67      * @param initialDisplayHeight height of the display before the rotation.
68      * @return Bounds after the rotation.
69      *
70      * @hide
71      */
getRotatedBounds( Rect[] bounds, int rotation, int initialDisplayWidth, int initialDisplayHeight)72     public Rect[] getRotatedBounds(
73             Rect[] bounds, int rotation, int initialDisplayWidth, int initialDisplayHeight) {
74         if (bounds.length != BOUNDS_POSITION_LENGTH) {
75             throw new IllegalArgumentException(
76                     "bounds must have exactly 4 elements: bounds=" + bounds);
77         }
78         if (rotation == ROTATION_0) {
79             return bounds;
80         }
81         transformPhysicalToLogicalCoordinates(rotation, initialDisplayWidth, initialDisplayHeight,
82                 mTmpMatrix);
83         Rect[] newBounds = new Rect[BOUNDS_POSITION_LENGTH];
84         for (int i = 0; i < bounds.length; i++) {
85 
86             final Rect rect = bounds[i];
87             if (!rect.isEmpty()) {
88                 final RectF rectF = new RectF(rect);
89                 mTmpMatrix.mapRect(rectF);
90                 rectF.round(rect);
91             }
92             newBounds[getBoundIndexFromRotation(i, rotation)] = rect;
93         }
94         return newBounds;
95     }
96 }
97