• 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 
18 #include "include/utils/SkCamera.h"
19 #include "include/core/SkMatrix44.h"
20 namespace OHOS {
21 namespace Rosen {
22 constexpr unsigned RECT_POINT_NUM = 4;
23 constexpr unsigned LEFT_TOP_POINT = 0;
24 constexpr unsigned RIGHT_TOP_POINT = 1;
25 constexpr unsigned RIGHT_BOTTOM_POINT = 2;
26 constexpr unsigned LEFT_BOTTOM_POINT = 3;
27 constexpr float INCH_TO_PIXEL = 72;
RSObjAbsGeometry()28 RSObjAbsGeometry::RSObjAbsGeometry() : RSObjGeometry()
29 {
30     vertices_[LEFT_TOP_POINT].set(0, 0);
31     vertices_[RIGHT_TOP_POINT].set(0, 0);
32     vertices_[RIGHT_BOTTOM_POINT].set(0, 0);
33     vertices_[LEFT_BOTTOM_POINT].set(0, 0);
34 }
35 
~RSObjAbsGeometry()36 RSObjAbsGeometry::~RSObjAbsGeometry() {}
37 
ConcatMatrix(const SkMatrix & matrix)38 void RSObjAbsGeometry::ConcatMatrix(const SkMatrix& matrix)
39 {
40     matrix_.preConcat(matrix);
41     absMatrix_.preConcat(matrix);
42     SetAbsRect();
43 }
44 
UpdateMatrix(const std::shared_ptr<RSObjAbsGeometry> & parent,float offsetX,float offsetY)45 void RSObjAbsGeometry::UpdateMatrix(const std::shared_ptr<RSObjAbsGeometry>& parent, float offsetX, float offsetY)
46 {
47     if (parent == nullptr) {
48         absMatrix_.reset();
49     } else {
50         absMatrix_ = parent->absMatrix_;
51         absMatrix_.preTranslate(offsetX, offsetY);
52     }
53     matrix_.reset();
54     // filter invalid width and height
55     if (IsEmpty()) {
56         return;
57     }
58     if (!trans_ || (ROSEN_EQ(trans_->translateZ_, 0.f) && ROSEN_EQ(trans_->rotationX_, 0.f) &&
59         ROSEN_EQ(trans_->rotationY_, 0.f) && trans_->quaternion_.IsIdentity())) {
60         UpdateAbsMatrix2D();
61     } else {
62         UpdateAbsMatrix3D();
63     }
64     absMatrix_.preConcat(matrix_);
65     SetAbsRect();
66 }
67 
UpdateByMatrixFromSelf()68 void RSObjAbsGeometry::UpdateByMatrixFromSelf()
69 {
70     absMatrix_.reset();
71     matrix_.reset();
72     if (!trans_ || (ROSEN_EQ(trans_->translateZ_, 0.f) && ROSEN_EQ(trans_->rotationX_, 0.f) &&
73         ROSEN_EQ(trans_->rotationY_, 0.f) && trans_->quaternion_.IsIdentity())) {
74         UpdateAbsMatrix2D();
75     } else {
76         UpdateAbsMatrix3D();
77     }
78     absMatrix_.preConcat(matrix_);
79     SetAbsRect();
80 }
81 
IsNeedClientCompose() const82 bool RSObjAbsGeometry::IsNeedClientCompose() const
83 {
84     if (!trans_) {
85         return false;
86     }
87     // return false if rotation degree is times of 90
88     return !ROSEN_EQ(std::remainder(trans_->rotation_, 90.f), 0.f);
89 }
90 
UpdateAbsMatrix2D()91 void RSObjAbsGeometry::UpdateAbsMatrix2D()
92 {
93     if (!trans_) {
94         matrix_.preTranslate(x_, y_);
95     } else {
96         // Translate
97         if ((x_ + trans_->translateX_ != 0) || (y_ + trans_->translateY_ != 0)) {
98             matrix_.preTranslate(x_ + trans_->translateX_, y_ + trans_->translateY_);
99         }
100         // rotation
101         if (!ROSEN_EQ(trans_->rotation_, 0.f)) {
102             matrix_.preRotate(trans_->rotation_, trans_->pivotX_ * width_, trans_->pivotY_ * height_);
103         }
104         // Scale
105         if (!ROSEN_EQ(trans_->scaleX_, 1.f) || !ROSEN_EQ(trans_->scaleY_, 1.f)) {
106             matrix_.preScale(trans_->scaleX_, trans_->scaleY_, trans_->pivotX_ * width_, trans_->pivotY_ * height_);
107         }
108     }
109 }
110 
UpdateAbsMatrix3D()111 void RSObjAbsGeometry::UpdateAbsMatrix3D()
112 {
113     if (!trans_->quaternion_.IsIdentity()) {
114         SkMatrix44 matrix3D;
115         // Translate
116         matrix3D.setTranslate(trans_->pivotX_ * width_ + x_ + trans_->translateX_,
117             trans_->pivotY_ * height_ + y_ + trans_->translateY_, z_ + trans_->translateZ_);
118         // Rotate
119         SkMatrix44 matrix4;
120         float x = trans_->quaternion_[0];
121         float y = trans_->quaternion_[1];
122         float z = trans_->quaternion_[2];
123         float w = trans_->quaternion_[3];
124         matrix4.set3x3(1.f - 2.f * (y * y + z * z), 2.f * (x * y + z * w), 2.f * (x * z - y * w), 2.f * (x * y - z * w),
125             1.f - 2.f * (x * x + z * z), 2.f * (y * z + x * w), 2.f * (x * z + y * w), 2.f * (y * z - x * w),
126             1.f - 2.f * (x * x + y * y));
127         matrix3D = matrix3D * matrix4;
128 
129         // Scale
130         if (!ROSEN_EQ(trans_->scaleX_, 1.f) || !ROSEN_EQ(trans_->scaleY_, 1.f)) {
131             matrix3D.preScale(trans_->scaleX_, trans_->scaleY_, 1.f);
132         }
133         // Translate
134         matrix3D.preTranslate(-trans_->pivotX_ * width_, -trans_->pivotY_ * height_, 0);
135         matrix_.preConcat(SkMatrix(matrix3D));
136     } else {
137         SkMatrix matrix3D;
138         Sk3DView camera;
139         // Z Position
140         camera.translate(0, 0, z_ + trans_->translateZ_);
141         float zOffSet = sqrt(width_ * width_ + height_ * height_) / 2;
142         camera.setCameraLocation(0, 0, camera.getCameraLocationZ() - zOffSet / INCH_TO_PIXEL);
143         // Rotate
144         camera.rotateX(-trans_->rotationX_);
145         camera.rotateY(-trans_->rotationY_);
146         camera.rotateZ(-trans_->rotation_);
147         camera.getMatrix(&matrix3D);
148         // Scale
149         if (!ROSEN_EQ(trans_->scaleX_, 1.f) || !ROSEN_EQ(trans_->scaleY_, 1.f)) {
150             matrix3D.preScale(trans_->scaleX_, trans_->scaleY_);
151         }
152         // Translate
153         matrix3D.preTranslate(-trans_->pivotX_ * width_, -trans_->pivotY_ * height_);
154         matrix3D.postTranslate(
155             trans_->pivotX_ * width_ + x_ + trans_->translateX_, trans_->pivotY_ * height_ + y_ + trans_->translateY_);
156         matrix_.preConcat(matrix3D);
157     }
158 }
159 
SetAbsRect()160 void RSObjAbsGeometry::SetAbsRect()
161 {
162     absRect_ = MapAbsRect(RectF(0.f, 0.f, width_, height_));
163 }
164 
MapAbsRect(const RectF & rect) const165 RectI RSObjAbsGeometry::MapAbsRect(const RectF& rect) const
166 {
167     RectI absRect;
168     if (!ROSEN_EQ(absMatrix_.getSkewX(), 0.f) || (absMatrix_.getScaleX() < 0) ||
169         !ROSEN_EQ(absMatrix_.getSkewY(), 0.f) || (absMatrix_.getScaleY() < 0)) {
170         SkPoint p[RECT_POINT_NUM];
171         p[LEFT_TOP_POINT].set(rect.left_, rect.top_);
172         p[RIGHT_TOP_POINT].set(rect.left_ + rect.width_, rect.top_);
173         p[RIGHT_BOTTOM_POINT].set(rect.left_ + rect.width_, rect.top_ + rect.height_);
174         p[LEFT_BOTTOM_POINT].set(rect.left_, rect.top_ + rect.height_);
175         absMatrix_.mapPoints(p, RECT_POINT_NUM);
176 
177         Vector2f xRange = GetDataRange(p[LEFT_TOP_POINT].x(), p[RIGHT_TOP_POINT].x(),
178             p[RIGHT_BOTTOM_POINT].x(), p[LEFT_BOTTOM_POINT].x());
179         Vector2f yRange = GetDataRange(p[LEFT_TOP_POINT].y(), p[RIGHT_TOP_POINT].y(),
180             p[RIGHT_BOTTOM_POINT].y(), p[LEFT_BOTTOM_POINT].y());
181         absRect.left_ = static_cast<int>(xRange[0]);
182         absRect.top_ = static_cast<int>(yRange[0]);
183         absRect.width_ = static_cast<int>(std::ceil(xRange[1] - absRect.left_));
184         absRect.height_ = static_cast<int>(std::ceil(yRange[1] - absRect.top_));
185     } else {
186         absRect.left_ = static_cast<int>(rect.left_ + absMatrix_.getTranslateX());
187         absRect.top_ = static_cast<int>(rect.top_ + absMatrix_.getTranslateY());
188         float right = rect.left_ + absMatrix_.getTranslateX() + rect.width_ * absMatrix_.getScaleX();
189         float bottom = rect.top_ + absMatrix_.getTranslateY() + rect.height_ * absMatrix_.getScaleY();
190         absRect.width_ = static_cast<int>(std::ceil(right - absRect.left_));
191         absRect.height_ = static_cast<int>(std::ceil(bottom - absRect.top_));
192     }
193     return absRect;
194 }
GetDataRange(float d0,float d1,float d2,float d3) const195 Vector2f RSObjAbsGeometry::GetDataRange(float d0, float d1, float d2, float d3) const
196 {
197     float min = d0;
198     float max = d0;
199     if (d0 > d1) {
200         min = d1;
201     } else {
202         max = d1;
203     }
204     if (d2 > d3) {
205         if (min > d3) {
206             min = d3;
207         }
208         if (max < d2) {
209             max = d2;
210         }
211     } else {
212         if (min > d2) {
213             min = d2;
214         }
215         if (max < d3) {
216             max = d3;
217         }
218     }
219     return Vector2f(min, max);
220 }
221 
222 /**
223  * calculate | p1 p2 | X | p1 p |
224  * @param p1 a point on a line
225  * @param p2 a point on a line
226  * @param p a point on a line
227  * @return the result of two cross multiplications
228  */
GetCross(const SkPoint & p1,const SkPoint & p2,const SkPoint & p) const229 float RSObjAbsGeometry::GetCross(const SkPoint& p1, const SkPoint& p2, const SkPoint& p) const
230 {
231     return (p2.x() - p1.x()) * (p.y() - p1.y()) - (p.x() - p1.x()) * (p2.y() - p1.y());
232 }
233 
234 /**
235  * Determine whether a point is within a rectangle.
236  *
237  * Determine whether a point is between two line segments by the directivity of cross multiplication.For example
238  * (AB X AE ) * (CDX CE)  >= 0 This indicates that E is between AD and BC.
239  * Two judgments can prove whether the point is in the rectangle.
240  *
241  * @param p Point to be judged
242  * @return If true indicates that the point is in the rectangle, if false indicates that the point is not in.
243  */
IsPointInHotZone(const float x,const float y) const244 bool RSObjAbsGeometry::IsPointInHotZone(const float x, const float y) const
245 {
246     SkPoint p = SkPoint::Make(x, y);
247     float crossResult1 = GetCross(vertices_[LEFT_TOP_POINT], vertices_[RIGHT_TOP_POINT], p);
248     float crossResult2 = GetCross(vertices_[RIGHT_BOTTOM_POINT], vertices_[LEFT_BOTTOM_POINT], p);
249     float crossResult3 = GetCross(vertices_[RIGHT_TOP_POINT], vertices_[RIGHT_BOTTOM_POINT], p);
250     float crossResult4 = GetCross(vertices_[LEFT_BOTTOM_POINT], vertices_[LEFT_TOP_POINT], p);
251     return IsPointInLine(vertices_[LEFT_TOP_POINT], vertices_[RIGHT_TOP_POINT], p, crossResult1) ||
252            IsPointInLine(vertices_[RIGHT_BOTTOM_POINT], vertices_[LEFT_BOTTOM_POINT], p, crossResult2) ||
253            IsPointInLine(vertices_[RIGHT_TOP_POINT], vertices_[RIGHT_BOTTOM_POINT], p, crossResult3) ||
254            IsPointInLine(vertices_[LEFT_BOTTOM_POINT], vertices_[LEFT_TOP_POINT], p, crossResult4) ||
255            (crossResult1 * crossResult2 > 0 && crossResult3 * crossResult4 > 0);
256 }
257 
IsPointInLine(const SkPoint & p1,const SkPoint & p2,const SkPoint & p,const float crossRes) const258 bool RSObjAbsGeometry::IsPointInLine(const SkPoint& p1, const SkPoint& p2, const SkPoint& p, const float crossRes) const
259 {
260     return ROSEN_EQ(crossRes, 0.0f) && std::min(p1.x(), p2.x()) <= p.x() && p.x() <= std::max(p1.x(), p2.x()) &&
261            std::min(p1.y(), p2.y()) <= p.y() && p.y() <= std::max(p1.y(), p2.y());
262 }
263 } // namespace Rosen
264 } // namespace OHOS
265