• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "common/rs_obj_abs_geometry.h"
17 #include "utils/camera3d.h"
18 
19 namespace OHOS {
20 namespace Rosen {
21 constexpr unsigned RECT_POINT_NUM = 4;
22 constexpr unsigned LEFT_TOP_POINT = 0;
23 constexpr unsigned RIGHT_TOP_POINT = 1;
24 constexpr unsigned RIGHT_BOTTOM_POINT = 2;
25 constexpr unsigned LEFT_BOTTOM_POINT = 3;
26 constexpr float INCH_TO_PIXEL = 72;
27 constexpr float EPSILON = 1e-6f;
28 constexpr float DEGREE_TO_RADIAN = M_PI / 180;
29 
30 RSObjAbsGeometry::RSObjAbsGeometry() = default;
31 RSObjAbsGeometry::~RSObjAbsGeometry() = default;
32 
ConcatMatrix(const Drawing::Matrix & matrix)33 void RSObjAbsGeometry::ConcatMatrix(const Drawing::Matrix& matrix)
34 {
35     if (matrix.IsIdentity()) {
36         return;
37     }
38     matrix_.PreConcat(matrix);
39     if (absMatrix_.has_value()) {
40         absMatrix_->PreConcat(matrix);
41     }
42     SetAbsRect();
43 }
44 
45 /**
46  * @brief Updates the matrix of the view with respect to its parent view.
47  *
48  * @param parent The parent view of the current view.
49  * @param offset The offset of the current view with respect to its parent.
50  * @param clipRect The optional clipping rectangle of the current view.
51  */
UpdateMatrix(const Drawing::Matrix * parentMatrix,const std::optional<Drawing::Point> & offset)52 void RSObjAbsGeometry::UpdateMatrix(const Drawing::Matrix* parentMatrix, const std::optional<Drawing::Point>& offset)
53 {
54     // Initialize the absolute matrix with the absolute matrix of the parent view if the parent view exists
55     if (parentMatrix == nullptr) {
56         absMatrix_.reset();
57     } else {
58         absMatrix_ = *parentMatrix;
59         if (offset.has_value()) {
60             absMatrix_->PreTranslate(offset->GetX(), offset->GetY());
61         }
62     }
63     // Reset the matrix of the current view
64     matrix_.Reset();
65     // filter invalid width and height
66     if (IsEmpty()) {
67         return;
68     }
69     // If the view has no transformations or only 2D transformations, update the absolute matrix with 2D
70     // transformations
71     if (!trans_ || (ROSEN_EQ(trans_->translateZ_, 0.f) && ROSEN_EQ(trans_->rotationX_, 0.f) &&
72         ROSEN_EQ(trans_->rotationY_, 0.f) && trans_->quaternion_.IsIdentity() && ROSEN_EQ(trans_->scaleZ_, 1.f))) {
73         UpdateAbsMatrix2D();
74     } else {
75         // Otherwise, update the absolute matrix with 3D transformations
76         UpdateAbsMatrix3D();
77     }
78     // If the context matrix of the current view exists, update the current matrix with it
79     if (contextMatrix_.has_value()) {
80         matrix_.PostConcat(*contextMatrix_);
81     }
82     // If the absolute matrix of the current view exists, update it with the context matrix and the current matrix
83     if (absMatrix_.has_value()) {
84         absMatrix_->PreConcat(matrix_);
85     }
86     // Update the absolute rectangle of the current view
87     SetAbsRect();
88 }
89 
90 /**
91  * @brief Updates the matrix of the view without its parent view.
92  */
UpdateByMatrixFromSelf()93 void RSObjAbsGeometry::UpdateByMatrixFromSelf()
94 {
95     absMatrix_.reset();
96     matrix_.Reset();
97 
98     // If the view has no transformations or only 2D transformations, update the absolute matrix with 2D transformations
99     if (!trans_ || (ROSEN_EQ(trans_->translateZ_, 0.f) && ROSEN_EQ(trans_->rotationX_, 0.f) &&
100         ROSEN_EQ(trans_->rotationY_, 0.f) && trans_->quaternion_.IsIdentity() && ROSEN_EQ(trans_->scaleZ_, 1.f))) {
101         UpdateAbsMatrix2D();
102     } else {
103         // Otherwise, update the absolute matrix with 3D transformations
104         UpdateAbsMatrix3D();
105     }
106 
107     // If the context matrix of the view exists, update the current matrix with it
108     if (contextMatrix_.has_value()) {
109         matrix_.PostConcat(*contextMatrix_);
110     }
111 
112     // Update the absolute rectangle of the view
113     SetAbsRect();
114 }
115 
IsNeedClientCompose() const116 bool RSObjAbsGeometry::IsNeedClientCompose() const
117 {
118     if (!trans_) {
119         return false;
120     }
121     // return false if rotation degree is times of 90
122     return !ROSEN_EQ(std::remainder(trans_->rotation_, 90.f), 0.f, EPSILON);
123 }
124 
125 namespace {
ApplySkewToMatrix44(const RSTransform & trans,Drawing::Matrix44 & m44,bool preConcat)126     void ApplySkewToMatrix44(const RSTransform& trans, Drawing::Matrix44& m44, bool preConcat)
127     {
128         if (!ROSEN_EQ(trans.skewX_, 0.f, EPSILON) || !ROSEN_EQ(trans.skewY_, 0.f, EPSILON)) {
129             Drawing::Matrix44 skewM44 {};
130             skewM44.SetMatrix44RowMajor({1.f, trans.skewX_, 0.f, 0.f,
131                 trans.skewY_, 1.f, 0.f, 0.f,
132                 0.f, 0.f, 1.f, 0.f,
133                 0.f, 0.f, 0.f, 1.f});
134             if (preConcat) {
135                 m44 = m44 * skewM44;
136             } else {
137                 m44 = skewM44 * m44;
138             }
139         }
140     }
141 
ApplyPerspToMatrix(const RSTransform & trans,Drawing::Matrix & m,bool preConcat)142     void ApplyPerspToMatrix(const RSTransform& trans, Drawing::Matrix& m, bool preConcat)
143     {
144         if (!ROSEN_EQ(trans.perspX_, 0.f, EPSILON)
145             || !ROSEN_EQ(trans.perspY_, 0.f, EPSILON)
146             || !ROSEN_EQ(trans.perspW_, 1.f, EPSILON)) {
147             Drawing::Matrix perspM {};
148             perspM.SetMatrix(1.f, 0.f, 0.f,
149                 0.f, 1.f, 0.f,
150                 trans.perspX_, trans.perspY_, trans.perspW_);
151             if (preConcat) {
152                 m = m * perspM;
153             } else {
154                 m = perspM * m;
155             }
156         }
157     }
158 
ApplyPerspToMatrix44(const RSTransform & trans,Drawing::Matrix44 & m44,bool preConcat)159     void ApplyPerspToMatrix44(const RSTransform& trans, Drawing::Matrix44& m44, bool preConcat)
160     {
161         if (!ROSEN_EQ(trans.perspX_, 0.f, EPSILON)
162             || !ROSEN_EQ(trans.perspY_, 0.f, EPSILON)
163             || !ROSEN_EQ(trans.perspZ_, 0.f, EPSILON)
164             || !ROSEN_EQ(trans.perspW_, 1.f, EPSILON)) {
165             Drawing::Matrix44 perspM44 {};
166             perspM44.SetMatrix44RowMajor({1.f, 0.f, 0.f, 0.f,
167                 0.f, 1.f, 0.f, 0.f,
168                 0.f, 0.f, 1.f, 0.f,
169                 trans.perspX_, trans.perspY_, trans.perspZ_, trans.perspW_});
170             if (preConcat) {
171                 m44 = m44 * perspM44;
172             } else {
173                 m44 = perspM44 * m44;
174             }
175         }
176     }
177 }
178 
UpdateAbsMatrix2D()179 void RSObjAbsGeometry::UpdateAbsMatrix2D()
180 {
181     if (!trans_) {
182         matrix_.PreTranslate(x_, y_);
183     } else {
184         // Persp
185         if (!ROSEN_EQ(trans_->perspX_, 0.f, EPSILON)
186             || !ROSEN_EQ(trans_->perspY_, 0.f, EPSILON)
187             || !ROSEN_EQ(trans_->perspW_, 1.f, EPSILON)) {
188             matrix_.PreTranslate(trans_->pivotX_ * width_, trans_->pivotY_ * height_);
189             ApplyPerspToMatrix(trans_.value(), matrix_, true);
190             matrix_.PreTranslate(-trans_->pivotX_ * width_, -trans_->pivotY_ * height_);
191         }
192 
193         // Local Translate
194         if (!ROSEN_EQ(trans_->translateX_, 0.f, EPSILON) || !ROSEN_EQ(trans_->translateY_, 0.f, EPSILON)) {
195             matrix_.PreTranslate(trans_->translateX_, trans_->translateY_);
196         }
197 
198         // rotation
199         if (!ROSEN_EQ(trans_->rotation_, 0.f, EPSILON)) {
200             matrix_.PreRotate(trans_->rotation_, trans_->pivotX_ * width_, trans_->pivotY_ * height_);
201         }
202 
203         // Skew
204         if (!ROSEN_EQ(trans_->skewX_, 0.f, EPSILON) || !ROSEN_EQ(trans_->skewY_, 0.f, EPSILON)) {
205             matrix_.PreSkew(trans_->skewX_, trans_->skewY_, trans_->pivotX_ * width_, trans_->pivotY_ * height_);
206         }
207 
208         // Scale
209         if (!ROSEN_EQ(trans_->scaleX_, 1.f) || !ROSEN_EQ(trans_->scaleY_, 1.f)) {
210             matrix_.PreScale(trans_->scaleX_, trans_->scaleY_, trans_->pivotX_ * width_, trans_->pivotY_ * height_);
211         }
212 
213         // Global Translate
214         if (!ROSEN_EQ(x_, 0.f, EPSILON) || !ROSEN_EQ(y_, 0.f, EPSILON)) {
215             matrix_.PostTranslate(x_, y_);
216         }
217     }
218 }
219 
220 /**
221  * Update the absolute matrix in 3D space
222  */
UpdateAbsMatrix3D()223 void RSObjAbsGeometry::UpdateAbsMatrix3D()
224 {
225     // If the view has a non-identity quaternion, apply 3D transformations
226     if (!trans_->quaternion_.IsIdentity()) {
227         Drawing::Matrix44 matrix3D;
228         // Pivot
229         matrix3D.Translate(trans_->pivotX_ * width_, trans_->pivotY_ * height_, 0);
230 
231         // Persp
232         ApplyPerspToMatrix44(trans_.value(), matrix3D, true);
233 
234         // Translate
235         matrix3D.PreTranslate(trans_->translateX_, trans_->translateY_, trans_->translateZ_);
236 
237         // Rotate
238         float x = trans_->quaternion_[0];
239         float y = trans_->quaternion_[1];
240         float z = trans_->quaternion_[2];
241         float w = trans_->quaternion_[3];
242         float magnitudeRecp = 1.0f / sqrt((x * x) + (y * y) + (z * z) + (w * w));
243         x *= magnitudeRecp;
244         y *= magnitudeRecp;
245         z *= magnitudeRecp;
246         w *= magnitudeRecp;
247         Drawing::Matrix44::Buffer buffer = {
248             1.f - 2.f * (y * y + z * z), 2.f * (x * y + z * w), 2.f * (x * z - y * w), 0,   // m00 ~ m30
249             2.f * (x * y - z * w), 1.f - 2.f * (x * x + z * z), 2.f * (y * z + x * w), 0,   // m01 ~ m31
250             2.f * (x * z + y * w), 2.f * (y * z - x * w), 1.f - 2.f * (x * x + y * y), 0,   // m02 ~ m32
251             0, 0, 0, 1 };                                                                   // m03 ~ m33
252         Drawing::Matrix44 matrix4;
253         matrix4.SetMatrix44ColMajor(buffer);
254         matrix3D = matrix3D * matrix4;
255 
256         // Skew
257         ApplySkewToMatrix44(trans_.value(), matrix3D, true);
258 
259         // Scale
260         if (!ROSEN_EQ(trans_->scaleX_, 1.f) || !ROSEN_EQ(trans_->scaleY_, 1.f) || !ROSEN_EQ(trans_->scaleZ_, 1.f)) {
261             matrix3D.PreScale(trans_->scaleX_, trans_->scaleY_, trans_->scaleZ_);
262         }
263 
264         // Translate
265         matrix3D.PreTranslate(-trans_->pivotX_ * width_, -trans_->pivotY_ * height_, 0);
266 
267         matrix3D.PostTranslate(x_, y_);
268 
269         // Concatenate the 3D matrix with the 2D matrix
270         matrix_.PreConcat(matrix3D);
271     } else {
272         Drawing::Matrix matrix3D;
273         Drawing::Camera3D camera;
274         // Z Position
275         if (isZApplicableCamera3D_) {
276             camera.Translate(0, 0, z_ + trans_->translateZ_);
277         } else {
278             camera.Translate(0, 0, trans_->translateZ_);
279         }
280 
281         // Set camera distance
282         if (trans_->cameraDistance_ == 0) {
283             float zOffSet = sqrt(width_ * width_ + height_ * height_) / 2;
284             camera.SetCameraPos(0, 0, camera.GetCameraPosZ() - zOffSet / INCH_TO_PIXEL);
285         } else {
286             camera.SetCameraPos(0, 0, trans_->cameraDistance_);
287         }
288         // Rotate
289         if (!ROSEN_EQ(trans_->pivotZ_, 0.f, EPSILON)) {
290             camera.Translate(-sin(trans_->rotationY_ * DEGREE_TO_RADIAN) * trans_->pivotZ_,
291                 -sin(trans_->rotationX_ * DEGREE_TO_RADIAN) * trans_->pivotZ_,
292                 (1 - cos(trans_->rotationX_ * DEGREE_TO_RADIAN) * cos(trans_->rotationY_ * DEGREE_TO_RADIAN)) *
293                     trans_->pivotZ_);
294         }
295         camera.RotateXDegrees(-trans_->rotationX_);
296         camera.RotateYDegrees(-trans_->rotationY_);
297         camera.RotateZDegrees(-trans_->rotation_);
298         camera.ApplyToMatrix(matrix3D);
299         // Skew
300         if (!ROSEN_EQ(trans_->skewX_, 0.f, EPSILON) || !ROSEN_EQ(trans_->skewY_, 0.f, EPSILON)) {
301             matrix3D.PreSkew(trans_->skewX_, trans_->skewY_);
302         }
303         // Scale
304         if (!ROSEN_EQ(trans_->scaleX_, 1.f) || !ROSEN_EQ(trans_->scaleY_, 1.f)) {
305             matrix3D.PreScale(trans_->scaleX_, trans_->scaleY_);
306         }
307         // Pivot
308         matrix3D.PreTranslate(-trans_->pivotX_ * width_, -trans_->pivotY_ * height_);
309 
310         // Translate
311         matrix3D.PostTranslate(x_ + trans_->translateX_, y_ + trans_->translateY_);
312         // PostPersp
313         ApplyPerspToMatrix(trans_.value(), matrix3D, false);
314         // Pivot
315         matrix3D.PostTranslate(trans_->pivotX_ * width_, trans_->pivotY_ * height_);
316 
317         // Concatenate the 3D matrix with the 2D matrix
318         matrix_.PreConcat(matrix3D);
319     }
320 }
321 
SetAbsRect()322 void RSObjAbsGeometry::SetAbsRect()
323 {
324     absRect_ = MapAbsRect(RectF(0.f, 0.f, width_, height_));
325 }
326 
DeflateToRectI(const RectF & rect)327 RectI RSObjAbsGeometry::DeflateToRectI(const RectF& rect)
328 {
329     RectI dstRect;
330     dstRect.left_ = static_cast<int>(std::ceil(rect.GetLeft()));
331     dstRect.top_ = static_cast<int>(std::ceil(rect.GetTop()));
332     dstRect.width_ = static_cast<int>(std::floor(rect.GetRight() - dstRect.left_));
333     dstRect.height_ = static_cast<int>(std::floor(rect.GetBottom() - dstRect.top_));
334     return dstRect;
335 }
336 
InflateToRectI(const RectF & rect)337 RectI RSObjAbsGeometry::InflateToRectI(const RectF& rect)
338 {
339     RectI dstRect;
340     dstRect.left_ = static_cast<int>(std::floor(rect.GetLeft()));
341     dstRect.top_ = static_cast<int>(std::floor(rect.GetTop()));
342     dstRect.width_ = static_cast<int>(std::ceil(rect.GetRight() - dstRect.left_));
343     dstRect.height_ = static_cast<int>(std::ceil(rect.GetBottom() - dstRect.top_));
344     return dstRect;
345 }
346 
MapRectWithoutRounding(const RectF & rect,const Drawing::Matrix & matrix)347 RectF RSObjAbsGeometry::MapRectWithoutRounding(const RectF& rect, const Drawing::Matrix& matrix)
348 {
349     RectF absRect;
350     // Check if the matrix has skew or negative scaling
351     if (!ROSEN_EQ(matrix.Get(Drawing::Matrix::PERSP_0), 0.f, EPSILON) ||
352         !ROSEN_EQ(matrix.Get(Drawing::Matrix::PERSP_1), 0.f, EPSILON) ||
353         !ROSEN_EQ(matrix.Get(Drawing::Matrix::PERSP_2), 0.f, EPSILON)) {
354         Drawing::RectF src(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
355         Drawing::RectF dst;
356         matrix.MapRect(dst, src);
357         absRect.left_ = dst.GetLeft();
358         absRect.top_ = dst.GetTop();
359         absRect.width_ = dst.GetRight() - absRect.left_;
360         absRect.height_ = dst.GetBottom() - absRect.top_;
361     } else if (!ROSEN_EQ(matrix.Get(Drawing::Matrix::SKEW_X), 0.f) || (matrix.Get(Drawing::Matrix::SCALE_X) < 0) ||
362         !ROSEN_EQ(matrix.Get(Drawing::Matrix::SKEW_Y), 0.f) || (matrix.Get(Drawing::Matrix::SCALE_Y) < 0)) {
363         // Map the rectangle's points to the absolute matrix
364         std::vector<Drawing::Point> p(RECT_POINT_NUM);
365         p[LEFT_TOP_POINT] = {rect.left_, rect.top_};
366         p[RIGHT_TOP_POINT] = {rect.left_ + rect.width_, rect.top_};
367         p[RIGHT_BOTTOM_POINT] = {rect.left_ + rect.width_, rect.top_ + rect.height_};
368         p[LEFT_BOTTOM_POINT] = {rect.left_, rect.top_ + rect.height_};
369         matrix.MapPoints(p, p, RECT_POINT_NUM);
370 
371         Vector2f xRange = GetDataRange(p[LEFT_TOP_POINT].GetX(), p[RIGHT_TOP_POINT].GetX(),
372             p[RIGHT_BOTTOM_POINT].GetX(), p[LEFT_BOTTOM_POINT].GetX());
373         Vector2f yRange = GetDataRange(p[LEFT_TOP_POINT].GetY(), p[RIGHT_TOP_POINT].GetY(),
374             p[RIGHT_BOTTOM_POINT].GetY(), p[LEFT_BOTTOM_POINT].GetY());
375 
376         // Set the absolute rectangle's properties
377         absRect.left_ = xRange[0];
378         absRect.top_ = yRange[0];
379         absRect.width_ = xRange[1] - absRect.left_;
380         absRect.height_ = yRange[1] - absRect.top_;
381     } else {
382         // Calculate the absolute rectangle based on the matrix's translation and scaling
383         Drawing::scalar transX = matrix.Get(Drawing::Matrix::TRANS_X);
384         Drawing::scalar transY = matrix.Get(Drawing::Matrix::TRANS_Y);
385         Drawing::scalar scaleX = matrix.Get(Drawing::Matrix::SCALE_X);
386         Drawing::scalar scaleY = matrix.Get(Drawing::Matrix::SCALE_Y);
387         absRect.left_ = rect.left_ * scaleX + transX;
388         absRect.top_ = rect.top_ * scaleY + transY;
389         float right = (rect.left_ + rect.width_) * scaleX + transX;
390         float bottom = (rect.top_ + rect.height_) * scaleY + transY;
391         absRect.width_ = right - absRect.left_;
392         absRect.height_ = bottom - absRect.top_;
393     }
394     return absRect;
395 }
396 
397 /**
398  * Map the rectangle with specific matrix
399  * [planning] replaced by Drawing::MapRect
400  * @param rect the rectangle to map
401  * @param matrix the specific to map
402  * @return the mapped absolute rectangle
403  */
MapRect(const RectF & rect,const Drawing::Matrix & matrix)404 RectI RSObjAbsGeometry::MapRect(const RectF& rect, const Drawing::Matrix& matrix)
405 {
406     return InflateToRectI(MapRectWithoutRounding(rect, matrix));
407 }
408 
409 /**
410  * Map the absolute rectangle
411  * @param rect the rectangle to map
412  * @return the mapped absolute rectangle
413  */
MapAbsRect(const RectF & rect) const414 RectI RSObjAbsGeometry::MapAbsRect(const RectF& rect) const
415 {
416     return MapRect(rect, GetAbsMatrix());
417 }
418 
GetDataRange(float d0,float d1,float d2,float d3)419 Vector2f RSObjAbsGeometry::GetDataRange(float d0, float d1, float d2, float d3)
420 {
421     float min = d0;
422     float max = d0;
423     if (d0 > d1) {
424         min = d1;
425     } else {
426         max = d1;
427     }
428     if (d2 > d3) {
429         if (min > d3) {
430             min = d3;
431         }
432         if (max < d2) {
433             max = d2;
434         }
435     } else {
436         if (min > d2) {
437             min = d2;
438         }
439         if (max < d3) {
440             max = d3;
441         }
442     }
443     return {min, max};
444 }
445 
SetContextMatrix(const std::optional<Drawing::Matrix> & matrix)446 void RSObjAbsGeometry::SetContextMatrix(const std::optional<Drawing::Matrix>& matrix)
447 {
448     contextMatrix_ = matrix;
449 }
450 
GetMatrix() const451 const Drawing::Matrix& RSObjAbsGeometry::GetMatrix() const
452 {
453     return matrix_;
454 }
455 
GetAbsMatrix() const456 const Drawing::Matrix& RSObjAbsGeometry::GetAbsMatrix() const
457 {
458     // if absMatrix_ is empty, return matrix_ instead
459     return absMatrix_ ? *absMatrix_ : matrix_;
460 }
461 } // namespace Rosen
462 } // namespace OHOS
463