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