1 /*
2  * Copyright (C) 2023 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 android.tools.helpers
18 
19 import android.graphics.Insets
20 import android.graphics.Rect
21 import android.tools.Rotation
22 
23 /**
24  * A class containing utility methods related to rotation.
25  *
26  * @hide
27  */
28 object RotationUtils {
29     /** Rotates an Insets according to the given rotation. */
rotateInsetsnull30     fun rotateInsets(insets: Insets?, rotation: Rotation): Insets {
31         if (insets == null || insets === Insets.NONE) {
32             return Insets.NONE
33         }
34         val rotated =
35             when (rotation) {
36                 Rotation.ROTATION_0 -> insets
37                 Rotation.ROTATION_90 ->
38                     Insets.of(insets.top, insets.right, insets.bottom, insets.left)
39                 Rotation.ROTATION_180 ->
40                     Insets.of(insets.right, insets.bottom, insets.left, insets.top)
41                 Rotation.ROTATION_270 ->
42                     Insets.of(insets.bottom, insets.left, insets.top, insets.right)
43             }
44         return rotated
45     }
46 
47     /**
48      * Rotates bounds as if parentBounds and bounds are a group. The group is rotated from
49      * oldRotation to newRotation. This assumes that parentBounds is at 0,0 and remains at 0,0 after
50      * rotation. The bounds will be at the same physical position in parentBounds.
51      */
rotateBoundsnull52     fun rotateBounds(
53         inBounds: Rect,
54         parentBounds: Rect,
55         oldRotation: Rotation,
56         newRotation: Rotation
57     ): Rect = rotateBounds(inBounds, parentBounds, deltaRotation(oldRotation, newRotation))
58 
59     /**
60      * Rotates inOutBounds together with the parent for a given rotation delta. This assumes that
61      * the parent starts at 0,0 and remains at 0,0 after the rotation. The inOutBounds will remain
62      * at the same physical position within the parent.
63      */
64     fun rotateBounds(
65         inBounds: Rect,
66         parentWidth: Int,
67         parentHeight: Int,
68         rotation: Rotation
69     ): Rect {
70         val origLeft = inBounds.left
71         val origTop = inBounds.top
72         return when (rotation) {
73             Rotation.ROTATION_0 -> inBounds
74             Rotation.ROTATION_90 ->
75                 Rect(
76                     /* left */ inBounds.top,
77                     /* top */ parentWidth - inBounds.right,
78                     /* right */ inBounds.bottom,
79                     /* bottom */ parentWidth - origLeft
80                 )
81             Rotation.ROTATION_180 ->
82                 Rect(
83                     /* left */ parentWidth - inBounds.right,
84                     /* right */ parentWidth - origLeft,
85                     /* top */ parentHeight - inBounds.bottom,
86                     /* bottom */ parentHeight - origTop
87                 )
88             Rotation.ROTATION_270 ->
89                 Rect(
90                     /* left */ parentHeight - inBounds.bottom,
91                     /* bottom */ inBounds.right,
92                     /* right */ parentHeight - inBounds.top,
93                     /* top */ origLeft
94                 )
95         }
96     }
97 
98     /**
99      * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
100      * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and remains
101      * at 0,0 after rotation. The bounds will be at the same physical position in parentBounds.
102      */
rotateBoundsnull103     fun rotateBounds(inBounds: Rect, parentBounds: Rect, rotation: Rotation): Rect =
104         rotateBounds(inBounds, parentBounds.right, parentBounds.bottom, rotation)
105 
106     /** @return the rotation needed to rotate from oldRotation to newRotation. */
107     fun deltaRotation(oldRotation: Rotation, newRotation: Rotation): Rotation {
108         var delta = newRotation.value - oldRotation.value
109         if (delta < 0) delta += 4
110         return Rotation.getByValue(delta)
111     }
112 }
113