1 /*
2 * Copyright (c) 2020-2021 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 #include "gfx_utils/transform.h"
17
18 #include "gfx_utils/graphic_math.h"
19 namespace OHOS {
20 constexpr uint8_t VERTEX_NUM_MIN = 3;
21
TransformMap()22 TransformMap::TransformMap()
23 {
24 scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f, 1.0f, 1.0f), Vector3<float>(0, 0, 0));
25 rotate_ = Matrix4<float>::Rotate(0, Vector3<float>(0, 0, 0), Vector3<float>(0, 0, 0));
26 shear_ = Matrix4<float>::Shear(Vector2<float>(0, 0), Vector2<float>(0, 0), Vector2<float>(0, 0));
27 translate_ = Matrix4<float>::Translate(Vector3<float>(0, 0, 0));
28 trans_[ROTATE] = &rotate_;
29 trans_[SCALE] = &scale_;
30 trans_[SHEAR] = &shear_;
31 trans_[TRANSLATE] = &translate_;
32 opOrder_[ROTATE] = ROTATE;
33 opOrder_[SCALE] = SCALE;
34 opOrder_[SHEAR] = SHEAR;
35 opOrder_[TRANSLATE] = TRANSLATE;
36
37 UpdateMap();
38 }
39
TransformMap(const Rect & rect)40 TransformMap::TransformMap(const Rect& rect)
41 {
42 rect_ = rect;
43 polygon_ = rect;
44 scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f, 1.0f, 1.0f), Vector3<float>(0, 0, 0));
45 rotate_ = Matrix4<float>::Rotate(0, Vector3<float>(0, 0, 0), Vector3<float>(0, 0, 0));
46 shear_ = Matrix4<float>::Shear(Vector2<float>(0, 0), Vector2<float>(0, 0), Vector2<float>(0, 0));
47 translate_ = Matrix4<float>::Translate(Vector3<float>(0, 0, 0));
48 trans_[ROTATE] = &rotate_;
49 trans_[SCALE] = &scale_;
50 trans_[SHEAR] = &shear_;
51 trans_[TRANSLATE] = &translate_;
52 opOrder_[ROTATE] = ROTATE;
53 opOrder_[SCALE] = SCALE;
54 opOrder_[SHEAR] = SHEAR;
55 opOrder_[TRANSLATE] = TRANSLATE;
56
57 UpdateMap();
58 }
59
GetClockWise() const60 bool TransformMap::GetClockWise() const
61 {
62 int16_t count = 0;
63
64 uint8_t vertexNum = polygon_.GetVertexNum();
65 if (vertexNum < VERTEX_NUM_MIN) {
66 return false;
67 }
68
69 for (uint8_t i = 0; i < vertexNum; i++) {
70 uint8_t j = (i + 1) % vertexNum; // 1: the next vertex
71 uint8_t k = (i + 2) % vertexNum; // 2: the after next vertex
72 int32_t c = (static_cast<int32_t>(polygon_[j].x_ - polygon_[i].x_) * (polygon_[k].y_ - polygon_[j].y_)) -
73 (static_cast<int32_t>(polygon_[j].y_ - polygon_[i].y_) * (polygon_[k].x_ - polygon_[j].x_));
74 if (c < 0) {
75 count--;
76 } else if (c > 0) {
77 count++;
78 }
79 }
80 if (count > 0) {
81 return true;
82 }
83 return false;
84 }
85
SetTransMapRect(const Rect & rect)86 void TransformMap::SetTransMapRect(const Rect& rect)
87 {
88 rect_ = rect;
89 polygon_ = rect;
90 if (isInternalMatrix_) {
91 UpdateMap();
92 } else {
93 SetMatrix(matrixOrig_);
94 }
95 }
96
Scale(const Vector2<float> & scale,const Vector2<float> & pivot)97 void TransformMap::Scale(const Vector2<float>& scale, const Vector2<float>& pivot)
98 {
99 Scale(Vector3<float>(scale.x_, scale.y_, 1.0f), Vector3<float>(pivot.x_, pivot.y_, 0));
100 }
101
Scale(const Vector3<float> & scale,const Vector3<float> & pivot)102 void TransformMap::Scale(const Vector3<float>& scale, const Vector3<float>& pivot)
103 {
104 scaleCoeff_ = scale;
105 scalePivot_ = pivot;
106 AddOp(SCALE);
107 UpdateMap();
108 }
109
IsInvalid() const110 bool TransformMap::IsInvalid() const
111 {
112 if (isInvalid_ || isIdentity_) {
113 return true;
114 }
115
116 for (uint8_t i = 0; i < polygon_.GetVertexNum(); i++) {
117 if (polygon_[i].x_ != 0 || polygon_[i].y_ != 0) {
118 return false;
119 }
120 }
121 return true;
122 }
123
Rotate(int16_t angle,const Vector2<float> & pivot)124 void TransformMap::Rotate(int16_t angle, const Vector2<float>& pivot)
125 {
126 Rotate(angle, Vector3<float>(pivot.x_, pivot.y_, 0), Vector3<float>(pivot.x_, pivot.y_, 1.0f));
127 }
128
Rotate(int16_t angle,const Vector3<float> & rotatePivotStart,const Vector3<float> & rotatePivotEnd)129 void TransformMap::Rotate(int16_t angle, const Vector3<float>& rotatePivotStart, const Vector3<float>& rotatePivotEnd)
130 {
131 angle_ = angle;
132 rotatePivotStart_ = rotatePivotStart;
133 rotatePivotEnd_ = rotatePivotEnd;
134 AddOp(ROTATE);
135 UpdateMap();
136 }
137
Translate(const Vector2<int16_t> & trans)138 void TransformMap::Translate(const Vector2<int16_t>& trans)
139 {
140 Translate(Vector3<int16_t>(trans.x_, trans.y_, 0));
141 }
142
Translate(const Vector3<int16_t> & trans)143 void TransformMap::Translate(const Vector3<int16_t>& trans)
144 {
145 translate_ = Matrix4<float>::Translate(Vector3<float>(trans.x_, trans.y_, trans.z_));
146 AddOp(TRANSLATE);
147 UpdateMap();
148 }
149
Shear(const Vector2<float> & shearX,const Vector2<float> & shearY,const Vector2<float> & shearZ)150 void TransformMap::Shear(const Vector2<float>& shearX, const Vector2<float>& shearY, const Vector2<float>& shearZ)
151 {
152 shearX_ = shearX;
153 shearY_ = shearY;
154 shearZ_ = shearZ;
155 AddOp(SHEAR);
156 UpdateMap();
157 }
158
GetOrigPoint(const Point & point,const Rect & relativeRect)159 Point TransformMap::GetOrigPoint(const Point& point, const Rect& relativeRect)
160 {
161 Rect rect = Rect(point.x, point.y, point.x, point.y);
162 Rect rectTemp = rect_;
163 Polygon polygonTemp = polygon_;
164 short rectX = relativeRect.GetX();
165 short rectY = relativeRect.GetY();
166
167 rect_ = rect;
168 polygon_ = rect;
169 trans_[ROTATE] = &rotate_;
170 trans_[SCALE] = &scale_;
171 trans_[SHEAR] = &shear_;
172 trans_[TRANSLATE] = &translate_;
173 rotate_ = Matrix4<float>::Rotate(
174 angle_, Vector3<float>(rotatePivotStart_.x_ + rectX, rotatePivotStart_.y_ + rectY, rotatePivotStart_.z_),
175 Vector3<float>(rotatePivotEnd_.x_ + rectX, rotatePivotEnd_.y_ + rectY, rotatePivotEnd_.z_));
176 scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f / scaleCoeff_.x_, 1.0f / scaleCoeff_.y_, scaleCoeff_.z_),
177 Vector3<float>(scalePivot_.x_ + rectX, scalePivot_.y_ + rectY, scalePivot_.z_));
178
179 shear_ = Matrix4<float>::Shear(shearX_, shearY_, shearZ_);
180 shear_ = shear_ * Matrix4<float>::Translate(Vector3<float>(-rectX, -rectY, 0));
181 shear_ = Matrix4<float>::Translate(Vector3<float>(rectX, rectY, 0)) * shear_;
182 matrix_ = (*trans_[opOrder_[TRANSLATE]]) * (*trans_[opOrder_[SHEAR]]) * (*trans_[opOrder_[SCALE]]) *
183 (*trans_[opOrder_[ROTATE]]);
184
185 float x = rectX + cameraPosition_.x_;
186 float y = rectY + cameraPosition_.y_;
187 float z = 0;
188 Matrix4<float> translateFromCamera = Matrix4<float>::Translate(Vector3<float>(-x, -y, -z));
189 Matrix4<float> translateToCamera = Matrix4<float>::Translate(Vector3<float>(x, y, z));
190 Matrix4<float> perspectiveMatrix;
191 perspectiveMatrix[2][2] = 0; // 2 : index
192 if (!FloatEqual(cameraDistance_, 0)) {
193 perspectiveMatrix[2][3] = -1.0f / cameraDistance_; // 2 3 : index
194 }
195 perspectiveMatrix_ = translateToCamera * (perspectiveMatrix * translateFromCamera);
196 matrix_ = perspectiveMatrix_ * matrix_;
197 SetMatrix(matrix_, true);
198 Rect r = polygon_.MakeAABB();
199 rect_ = rectTemp;
200 polygon_ = polygonTemp;
201 scale_ = Matrix4<float>::Scale(scaleCoeff_,
202 Vector3<float>(scalePivot_.x_ + rectX, scalePivot_.y_ + rectY, scalePivot_.z_));
203 return {r.GetRight(), r.GetBottom()};
204 }
205
operator ==(const TransformMap & other) const206 bool TransformMap::operator==(const TransformMap& other) const
207 {
208 if (rotate_ == other.rotate_ && translate_ == other.translate_ && scale_ == other.scale_ &&
209 rect_ == other.rect_ && matrix_ == other.matrix_) {
210 return true;
211 }
212 return false;
213 }
214
SetCameraDistance(int16_t distance)215 void TransformMap::SetCameraDistance(int16_t distance)
216 {
217 cameraDistance_ = distance;
218 UpdateMap();
219 }
220
SetCameraPosition(const Vector2<float> & position)221 void TransformMap::SetCameraPosition(const Vector2<float>& position)
222 {
223 cameraPosition_ = position;
224 UpdateMap();
225 }
226
Is3DTransform() const227 bool TransformMap::Is3DTransform() const
228 {
229 return is3d_;
230 }
231
UpdateMap()232 void TransformMap::UpdateMap()
233 {
234 trans_[ROTATE] = &rotate_;
235 trans_[SCALE] = &scale_;
236 trans_[SHEAR] = &shear_;
237 trans_[TRANSLATE] = &translate_;
238 rotate_ =
239 Matrix4<float>::Rotate(angle_,
240 Vector3<float>(rotatePivotStart_.x_ + rect_.GetX(), rotatePivotStart_.y_ + rect_.GetY(),
241 rotatePivotStart_.z_),
242 Vector3<float>(rotatePivotEnd_.x_ + rect_.GetX(), rotatePivotEnd_.y_ + rect_.GetY(), rotatePivotEnd_.z_));
243
244 scale_ = Matrix4<float>::Scale(scaleCoeff_,
245 Vector3<float>(scalePivot_.x_ + rect_.GetX(), scalePivot_.y_ + rect_.GetY(), scalePivot_.z_));
246
247 shear_ = Matrix4<float>::Shear(shearX_, shearY_, shearZ_);
248 shear_ = shear_ * Matrix4<float>::Translate(Vector3<float>(-rect_.GetX(), -rect_.GetY(), 0));
249 shear_ = Matrix4<float>::Translate(Vector3<float>(rect_.GetX(), rect_.GetY(), 0)) * shear_;
250
251 matrix_ = (*trans_[opOrder_[TRANSLATE]]) * (*trans_[opOrder_[SHEAR]]) * (*trans_[opOrder_[SCALE]]) *
252 (*trans_[opOrder_[ROTATE]]);
253
254 float x = rect_.GetX() + cameraPosition_.x_;
255 float y = rect_.GetY() + cameraPosition_.y_;
256 float z = 0;
257 Matrix4<float> translateFromCamera = Matrix4<float>::Translate(Vector3<float>(-x, -y, -z));
258 Matrix4<float> translateToCamera = Matrix4<float>::Translate(Vector3<float>(x, y, z));
259 Matrix4<float> perspectiveMatrix;
260 perspectiveMatrix[2][2] = 0; // 2 : index
261 if (!FloatEqual(cameraDistance_, 0)) {
262 perspectiveMatrix[2][3] = -1.0f / cameraDistance_; // 2 3 : index
263 }
264 perspectiveMatrix_ = translateToCamera * (perspectiveMatrix * translateFromCamera);
265 matrix_ = perspectiveMatrix_ * matrix_;
266 SetMatrix(matrix_, true);
267 }
268
SetMatrix(const Matrix4<float> & matrix,bool isInternalMatrix)269 void TransformMap::SetMatrix(const Matrix4<float>& matrix, bool isInternalMatrix)
270 {
271 isInternalMatrix_ = isInternalMatrix;
272 polygon_ = rect_;
273 matrixOrig_ = matrix;
274 uint8_t vertexNum = polygon_.GetVertexNum();
275 Vector4<float> imgPoint4;
276 is3d_ = false;
277 for (uint8_t i = 0; i < vertexNum; i++) {
278 Vector4<float> point(polygon_[i].x_, polygon_[i].y_, 0, 1.0f);
279 imgPoint4 = matrix * point;
280 if (!FloatEqual(imgPoint4.w_, 1)) {
281 is3d_ = true;
282 }
283 if (!FloatEqual(imgPoint4.w_, 0)) {
284 imgPoint4.x_ /= imgPoint4.w_;
285 imgPoint4.y_ /= imgPoint4.w_;
286 }
287 if (imgPoint4.x_ < COORD_MIN) {
288 polygon_[i].x_ = COORD_MIN;
289 } else if (imgPoint4.x_ > COORD_MAX) {
290 polygon_[i].x_ = COORD_MAX;
291 } else {
292 polygon_[i].x_ = MATH_ROUND(imgPoint4.x_);
293 }
294
295 if (imgPoint4.y_ < COORD_MIN) {
296 polygon_[i].y_ = COORD_MIN;
297 } else if (imgPoint4.y_ > COORD_MAX) {
298 polygon_[i].y_ = COORD_MAX;
299 } else {
300 polygon_[i].y_ = MATH_ROUND(imgPoint4.y_);
301 }
302 }
303 isIdentity_ = IsIdentity(const_cast<Matrix4<float>&>(matrix));
304 Matrix4<float> translate = Matrix4<float>::Translate(Vector3<float>(rect_.GetX(), rect_.GetY(), 0));
305 matrix_ = matrix * translate;
306 /* 0 1 2 3 : index of matrix */
307 Matrix3<float> matrix3(matrix_[0][0], matrix_[0][1], matrix_[0][3],
308 matrix_[1][0], matrix_[1][1], matrix_[1][3],
309 matrix_[3][0], matrix_[3][1], matrix_[3][3]);
310 invMatrix_ = matrix3.Inverse();
311 }
312
AddOp(uint8_t op)313 void TransformMap::AddOp(uint8_t op)
314 {
315 uint8_t index = 0;
316 for (; index < TRANS_NUM; index++) {
317 if (opOrder_[index] == op) {
318 break;
319 }
320 }
321 for (; index < TRANSLATE; index++) {
322 opOrder_[index] = opOrder_[index + 1];
323 }
324 opOrder_[TRANSLATE] = op;
325 }
326
Rotate(const Vector2<int16_t> & point,int16_t angle,const Vector2<int16_t> & pivot,Vector2<int16_t> & out)327 void Rotate(const Vector2<int16_t>& point, int16_t angle, const Vector2<int16_t>& pivot, Vector2<int16_t>& out)
328 {
329 float sinma = Sin(angle);
330 float cosma = Sin(angle + 90); // 90: cos
331
332 int16_t xt = point.x_ - pivot.x_;
333 int16_t yt = point.y_ - pivot.y_;
334
335 /* 0.5: round up */
336 float temp = cosma * xt - sinma * yt;
337 out.x_ = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f)) + pivot.x_;
338 temp = sinma * xt + cosma * yt;
339 out.y_ = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f)) + pivot.y_;
340 }
341
Rotate(const Line & origLine,int16_t angle,const Vector2<int16_t> & pivot,Line & out)342 void Rotate(const Line& origLine, int16_t angle, const Vector2<int16_t>& pivot, Line& out)
343 {
344 Vector2<int16_t> pt1 = origLine[0];
345 Vector2<int16_t> pt2 = origLine[1];
346
347 Rotate(pt1, angle, pivot, out[1]); // 1: the first point of line
348 Rotate(pt2, angle, pivot, out[2]); // 2: the second point of line
349 }
350
Rotate(const Rect & origRect,int16_t angle,const Vector2<int16_t> & pivot,Polygon & out)351 void Rotate(const Rect& origRect, int16_t angle, const Vector2<int16_t>& pivot, Polygon& out)
352 {
353 Vector2<int16_t> pt1 = {origRect.GetLeft(), origRect.GetTop()};
354 Vector2<int16_t> pt2 = {origRect.GetRight(), origRect.GetTop()};
355 Vector2<int16_t> pt3 = {origRect.GetRight(), origRect.GetBottom()};
356 Vector2<int16_t> pt4 = {origRect.GetLeft(), origRect.GetBottom()};
357
358 Rotate(pt1, angle, pivot, out[1]); // 1: the first point
359 Rotate(pt2, angle, pivot, out[2]); // 2: the second point
360 Rotate(pt3, angle, pivot, out[3]); // 3: the third point
361 Rotate(pt4, angle, pivot, out[4]); // 4: the fourth point
362
363 out.SetVertexNum(4); // 4: number of vertex
364 }
365 } // namespace OHOS
366