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 
Translate(const Vector2<float> & trans)150 void TransformMap::Translate(const Vector2<float>& trans)
151 {
152     Translate(Vector3<float>(trans.x_, trans.y_, 0));
153 }
154 
Translate(const Vector3<float> & trans)155 void TransformMap::Translate(const Vector3<float>& trans)
156 {
157     translate_ = Matrix4<float>::Translate(trans);
158     AddOp(TRANSLATE);
159     UpdateMap();
160 }
161 
Shear(const Vector2<float> & shearX,const Vector2<float> & shearY,const Vector2<float> & shearZ)162 void TransformMap::Shear(const Vector2<float>& shearX, const Vector2<float>& shearY, const Vector2<float>& shearZ)
163 {
164     shearX_ = shearX;
165     shearY_ = shearY;
166     shearZ_ = shearZ;
167     AddOp(SHEAR);
168     UpdateMap();
169 }
170 
GetOrigPoint(const Point & point,const Rect & relativeRect)171 Point TransformMap::GetOrigPoint(const Point& point, const Rect& relativeRect)
172 {
173     Rect rect = Rect(point.x, point.y, point.x, point.y);
174     Rect rectTemp = rect_;
175     Polygon polygonTemp = polygon_;
176     short rectX = relativeRect.GetX();
177     short rectY = relativeRect.GetY();
178 
179     rect_ = rect;
180     polygon_ = rect;
181     trans_[ROTATE] = &rotate_;
182     trans_[SCALE] = &scale_;
183     trans_[SHEAR] = &shear_;
184     trans_[TRANSLATE] = &translate_;
185     rotate_ = Matrix4<float>::Rotate(
186         angle_, Vector3<float>(rotatePivotStart_.x_ + rectX, rotatePivotStart_.y_ + rectY, rotatePivotStart_.z_),
187         Vector3<float>(rotatePivotEnd_.x_ + rectX, rotatePivotEnd_.y_ + rectY, rotatePivotEnd_.z_));
188     scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f / scaleCoeff_.x_, 1.0f / scaleCoeff_.y_, scaleCoeff_.z_),
189                                    Vector3<float>(scalePivot_.x_ + rectX, scalePivot_.y_ + rectY, scalePivot_.z_));
190 
191     shear_ = Matrix4<float>::Shear(shearX_, shearY_, shearZ_);
192     shear_ = shear_ * Matrix4<float>::Translate(Vector3<float>(-rectX, -rectY, 0));
193     shear_ = Matrix4<float>::Translate(Vector3<float>(rectX, rectY, 0)) * shear_;
194     matrix_ = (*trans_[opOrder_[TRANSLATE]]) * (*trans_[opOrder_[SHEAR]]) * (*trans_[opOrder_[SCALE]]) *
195               (*trans_[opOrder_[ROTATE]]);
196 
197     float x = rectX + cameraPosition_.x_;
198     float y = rectY + cameraPosition_.y_;
199     float z = 0;
200     Matrix4<float> translateFromCamera = Matrix4<float>::Translate(Vector3<float>(-x, -y, -z));
201     Matrix4<float> translateToCamera = Matrix4<float>::Translate(Vector3<float>(x, y, z));
202     Matrix4<float> perspectiveMatrix;
203     perspectiveMatrix[2][2] = 0;                           // 2 : index
204     if (!FloatEqual(cameraDistance_, 0)) {
205         perspectiveMatrix[2][3] = -1.0f / cameraDistance_; // 2 3 : index
206     }
207     perspectiveMatrix_ = translateToCamera * (perspectiveMatrix * translateFromCamera);
208     matrix_ = perspectiveMatrix_ * matrix_;
209     SetMatrix(matrix_, true);
210     Rect r = polygon_.MakeAABB();
211     rect_ = rectTemp;
212     polygon_ = polygonTemp;
213     scale_ = Matrix4<float>::Scale(scaleCoeff_,
214                                    Vector3<float>(scalePivot_.x_ + rectX, scalePivot_.y_ + rectY, scalePivot_.z_));
215     return {r.GetRight(), r.GetBottom()};
216 }
217 
operator ==(const TransformMap & other) const218 bool TransformMap::operator==(const TransformMap& other) const
219 {
220     if (rotate_ == other.rotate_ && translate_ == other.translate_ && scale_ == other.scale_ &&
221         rect_ == other.rect_ && matrix_ == other.matrix_) {
222         return true;
223     }
224     return false;
225 }
226 
SetCameraDistance(int16_t distance)227 void TransformMap::SetCameraDistance(int16_t distance)
228 {
229     cameraDistance_ = distance;
230     UpdateMap();
231 }
232 
SetCameraPosition(const Vector2<float> & position)233 void TransformMap::SetCameraPosition(const Vector2<float>& position)
234 {
235     cameraPosition_ = position;
236     UpdateMap();
237 }
238 
Is3DTransform() const239 bool TransformMap::Is3DTransform() const
240 {
241     return is3d_;
242 }
243 
UpdateMap()244 void TransformMap::UpdateMap()
245 {
246     trans_[ROTATE] = &rotate_;
247     trans_[SCALE] = &scale_;
248     trans_[SHEAR] = &shear_;
249     trans_[TRANSLATE] = &translate_;
250     rotate_ =
251         Matrix4<float>::Rotate(angle_,
252             Vector3<float>(rotatePivotStart_.x_ + rect_.GetX(), rotatePivotStart_.y_ + rect_.GetY(),
253                            rotatePivotStart_.z_),
254             Vector3<float>(rotatePivotEnd_.x_ + rect_.GetX(), rotatePivotEnd_.y_ + rect_.GetY(), rotatePivotEnd_.z_));
255 
256     scale_ = Matrix4<float>::Scale(scaleCoeff_,
257         Vector3<float>(scalePivot_.x_ + rect_.GetX(), scalePivot_.y_ + rect_.GetY(), scalePivot_.z_));
258 
259     shear_ = Matrix4<float>::Shear(shearX_, shearY_, shearZ_);
260     shear_ = shear_ * Matrix4<float>::Translate(Vector3<float>(-rect_.GetX(), -rect_.GetY(), 0));
261     shear_ = Matrix4<float>::Translate(Vector3<float>(rect_.GetX(), rect_.GetY(), 0)) * shear_;
262 
263     matrix_ = (*trans_[opOrder_[TRANSLATE]]) * (*trans_[opOrder_[SHEAR]]) * (*trans_[opOrder_[SCALE]]) *
264               (*trans_[opOrder_[ROTATE]]);
265 
266     float x = rect_.GetX() + cameraPosition_.x_;
267     float y = rect_.GetY() + cameraPosition_.y_;
268     float z = 0;
269     Matrix4<float> translateFromCamera = Matrix4<float>::Translate(Vector3<float>(-x, -y, -z));
270     Matrix4<float> translateToCamera = Matrix4<float>::Translate(Vector3<float>(x, y, z));
271     Matrix4<float> perspectiveMatrix;
272     perspectiveMatrix[2][2] = 0; // 2 : index
273     if (!FloatEqual(cameraDistance_, 0)) {
274         perspectiveMatrix[2][3] = -1.0f / cameraDistance_; // 2 3 : index
275     }
276     perspectiveMatrix_ = translateToCamera * (perspectiveMatrix * translateFromCamera);
277     matrix_ = perspectiveMatrix_ * matrix_;
278     SetMatrix(matrix_, true);
279 }
280 
SetMatrix(const Matrix4<float> & matrix,bool isInternalMatrix)281 void TransformMap::SetMatrix(const Matrix4<float>& matrix, bool isInternalMatrix)
282 {
283     isInternalMatrix_ = isInternalMatrix;
284     polygon_ = rect_;
285     matrixOrig_ = matrix;
286     uint8_t vertexNum = polygon_.GetVertexNum();
287     Vector4<float> imgPoint4;
288     is3d_ = false;
289     for (uint8_t i = 0; i < vertexNum; i++) {
290         Vector4<float> point(polygon_[i].x_, polygon_[i].y_, 0, 1.0f);
291         imgPoint4 = matrix * point;
292         if (!FloatEqual(imgPoint4.w_, 1)) {
293             is3d_ = true;
294         }
295         if (!FloatEqual(imgPoint4.w_, 0)) {
296             imgPoint4.x_ /= imgPoint4.w_;
297             imgPoint4.y_ /= imgPoint4.w_;
298         }
299         if (imgPoint4.x_ < COORD_MIN) {
300             polygon_[i].x_ = COORD_MIN;
301         } else if (imgPoint4.x_ > COORD_MAX) {
302             polygon_[i].x_ = COORD_MAX;
303         } else {
304             polygon_[i].x_ = MATH_ROUND(imgPoint4.x_);
305         }
306 
307         if (imgPoint4.y_ < COORD_MIN) {
308             polygon_[i].y_ = COORD_MIN;
309         } else if (imgPoint4.y_ > COORD_MAX) {
310             polygon_[i].y_ = COORD_MAX;
311         } else {
312             polygon_[i].y_ = MATH_ROUND(imgPoint4.y_);
313         }
314     }
315     isIdentity_ = IsIdentity(const_cast<Matrix4<float>&>(matrix));
316     Matrix4<float> translate = Matrix4<float>::Translate(Vector3<float>(rect_.GetX(), rect_.GetY(), 0));
317     matrix_ = matrix * translate;
318     /* 0 1 2 3  : index of matrix */
319     Matrix3<float> matrix3(matrix_[0][0], matrix_[0][1], matrix_[0][3],
320                            matrix_[1][0], matrix_[1][1], matrix_[1][3],
321                            matrix_[3][0], matrix_[3][1], matrix_[3][3]);
322     invMatrix_ = matrix3.Inverse();
323 }
324 
AddOp(uint8_t op)325 void TransformMap::AddOp(uint8_t op)
326 {
327     uint8_t index = 0;
328     for (; index < TRANS_NUM; index++) {
329         if (opOrder_[index] == op) {
330             break;
331         }
332     }
333     for (; index < TRANSLATE; index++) {
334         opOrder_[index] = opOrder_[index + 1];
335     }
336     opOrder_[TRANSLATE] = op;
337 }
338 
Rotate(const Vector2<int16_t> & point,int16_t angle,const Vector2<int16_t> & pivot,Vector2<int16_t> & out)339 void Rotate(const Vector2<int16_t>& point, int16_t angle, const Vector2<int16_t>& pivot, Vector2<int16_t>& out)
340 {
341     float sinma = Sin(angle);
342     float cosma = Sin(angle + 90); // 90: cos
343 
344     int16_t xt = point.x_ - pivot.x_;
345     int16_t yt = point.y_ - pivot.y_;
346 
347     /* 0.5: round up */
348     float temp = cosma * xt - sinma * yt;
349     out.x_ = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f)) + pivot.x_;
350     temp = sinma * xt + cosma * yt;
351     out.y_ = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f)) + pivot.y_;
352 }
353 
Rotate(const Line & origLine,int16_t angle,const Vector2<int16_t> & pivot,Line & out)354 void Rotate(const Line& origLine, int16_t angle, const Vector2<int16_t>& pivot, Line& out)
355 {
356     Vector2<int16_t> pt1 = origLine[0];
357     Vector2<int16_t> pt2 = origLine[1];
358 
359     Rotate(pt1, angle, pivot, out[1]); // 1: the first point of line
360     Rotate(pt2, angle, pivot, out[2]); // 2: the second point of line
361 }
362 
Rotate(const Rect & origRect,int16_t angle,const Vector2<int16_t> & pivot,Polygon & out)363 void Rotate(const Rect& origRect, int16_t angle, const Vector2<int16_t>& pivot, Polygon& out)
364 {
365     Vector2<int16_t> pt1 = {origRect.GetLeft(), origRect.GetTop()};
366     Vector2<int16_t> pt2 = {origRect.GetRight(), origRect.GetTop()};
367     Vector2<int16_t> pt3 = {origRect.GetRight(), origRect.GetBottom()};
368     Vector2<int16_t> pt4 = {origRect.GetLeft(), origRect.GetBottom()};
369 
370     Rotate(pt1, angle, pivot, out[1]); // 1: the first point
371     Rotate(pt2, angle, pivot, out[2]); // 2: the second point
372     Rotate(pt3, angle, pivot, out[3]); // 3: the third point
373     Rotate(pt4, angle, pivot, out[4]); // 4: the fourth point
374 
375     out.SetVertexNum(4); // 4: number of vertex
376 }
377 } // namespace OHOS
378