1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef MMI_TRANSFORM_H
17 #define MMI_TRANSFORM_H
18
19 #include "window_info.h"
20
21 namespace OHOS {
22 namespace MMI {
23
24 template <typename T> struct Vector2D {
25 T x;
26 T y;
27 };
28
29 template <typename T> class SimpleTransform {
30 public:
31 enum class Type {
32 Translate,
33 Rotate,
34 };
35 const Type type;
36 const T a00;
37 const T a01;
38 const T x0;
39 const T a10;
40 const T a11;
41 const T y0;
42 static SimpleTransform<T> Translate(const Vector2D<T> &v);
43 static SimpleTransform<T> RotateDirection(Direction direction);
44 Vector2D<T> Apply(const Vector2D<T> &v) const;
45 Vector2D<T> Reset(const Vector2D<T> &v) const;
46 };
47
Translate(const Vector2D<T> & v)48 template <typename T> SimpleTransform<T> SimpleTransform<T>::Translate(const Vector2D<T> &v)
49 {
50 return SimpleTransform<T>{
51 .type = Type::Translate,
52 .a00 = 1,
53 .a01 = 0,
54 .x0 = v.x,
55 .a10 = 0,
56 .a11 = 1,
57 .y0 = v.y,
58 };
59 }
60
RotateDirection(Direction direction)61 template <typename T> SimpleTransform<T> SimpleTransform<T>::RotateDirection(Direction direction)
62 {
63 // direction 0 1 2 3
64 // cos 1 0 -1 0
65 // sin 0 1 0 -1
66 T cosine = 1;
67 T sine = 0;
68 switch (direction) {
69 case DIRECTION90:
70 cosine = 0;
71 sine = 1;
72 break;
73 case DIRECTION180:
74 cosine = -1;
75 sine = 0;
76 break;
77 case DIRECTION270:
78 cosine = 0;
79 sine = -1;
80 break;
81 case DIRECTION0:
82 default:
83 break;
84 }
85 return SimpleTransform<T>{
86 .type = Type::Rotate,
87 .a00 = cosine,
88 .a01 = -sine,
89 .x0 = 0,
90 .a10 = sine,
91 .a11 = cosine,
92 .y0 = 0,
93 };
94 }
95
Apply(const Vector2D<T> & v)96 template <typename T> Vector2D<T> SimpleTransform<T>::Apply(const Vector2D<T> &v) const
97 {
98 return {
99 .x = a00 * v.x + a01 * v.y + x0,
100 .y = a10 * v.x + a11 * v.y + y0,
101 };
102 }
103
Reset(const Vector2D<T> & v)104 template <typename T> Vector2D<T> SimpleTransform<T>::Reset(const Vector2D<T> &v) const
105 {
106 // Since only translate and rotation are supported,
107 // we can assert the inverse of transform matrix is in the following form:
108 return {
109 .x = a00 * v.x + a10 * v.y - x0,
110 .y = a01 * v.x + a11 * v.y - y0,
111 };
112 }
113
114 template <typename T>
ApplyTransformSteps(const std::vector<SimpleTransform<T>> & steps,const Vector2D<T> & v)115 inline Vector2D<T> ApplyTransformSteps(const std::vector<SimpleTransform<T>> &steps, const Vector2D<T> &v)
116 {
117 Vector2D<T> result = v;
118 for (const auto &step : steps) {
119 result = step.Apply(result);
120 }
121 return result;
122 }
123
124 template <typename T>
ResetTransformSteps(const std::vector<SimpleTransform<T>> & steps,const Vector2D<T> & v)125 inline Vector2D<T> ResetTransformSteps(const std::vector<SimpleTransform<T>> &steps, const Vector2D<T> &v)
126 {
127 Vector2D<T> result = v;
128 for (auto iter = steps.rbegin(); iter != steps.rend(); ++iter) {
129 result = iter->Reset(result);
130 }
131 return result;
132 }
133
RotateAndFitScreen(Direction direction,const Vector2D<T> & size)134 template <typename T> std::vector<SimpleTransform<T>> RotateAndFitScreen(Direction direction, const Vector2D<T> &size)
135 {
136 std::vector<SimpleTransform<T>> result;
137 if (direction == DIRECTION0) {
138 return result;
139 }
140 result.emplace_back(SimpleTransform<T>::RotateDirection(direction));
141 switch (direction) {
142 case DIRECTION90:
143 result.emplace_back(SimpleTransform<T>::Translate({ size.y, 0 }));
144 break;
145 case DIRECTION180:
146 result.emplace_back(SimpleTransform<T>::Translate(size));
147 break;
148 case DIRECTION270:
149 result.emplace_back(SimpleTransform<T>::Translate({ 0, size.x }));
150 break;
151 case DIRECTION0:
152 default:
153 break;
154 }
155
156 return result;
157 }
158
RotateRect(Direction direction,const Vector2D<T> & size)159 template <typename T> inline Vector2D<T> RotateRect(Direction direction, const Vector2D<T> &size)
160 {
161 switch (direction) {
162 case DIRECTION90:
163 case DIRECTION270:
164 return { size.y, size.x };
165 case DIRECTION0:
166 case DIRECTION180:
167 default:
168 return size;
169 }
170 }
171
172 } // namespace MMI
173 } // namespace OHOS
174
175 #endif /* MMI_TRANSFORM_H */
176