1 /*
2 * Copyright (c) 2021-2023 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 #ifndef RENDER_SERVICE_CLIENT_CORE_COMMON_RS_RECT_H
17 #define RENDER_SERVICE_CLIENT_CORE_COMMON_RS_RECT_H
18 #include <cmath>
19 #include <unordered_set>
20 #include <cinttypes>
21
22 #include "common/rs_common_def.h"
23 #include "common/rs_vector2.h"
24 #include "common/rs_vector4.h"
25 #include "transaction/rs_marshalling_helper.h"
26
27 namespace OHOS {
28 namespace Rosen {
29 template<typename T>
30 class RectT {
31 public:
32 union {
33 struct {
34 T left_;
35 T top_;
36 T width_;
37 T height_;
38 };
39 T data_[4]; // 4 is size of data or structure
40 };
41
RectT()42 RectT()
43 {
44 data_[0] = 0;
45 data_[1] = 0;
46 data_[2] = 0;
47 data_[3] = 0;
48 }
RectT(T left,T top,T width,T height)49 RectT(T left, T top, T width, T height)
50 {
51 data_[0] = left;
52 data_[1] = top;
53 data_[2] = width;
54 data_[3] = height;
55 }
RectT(Vector4<T> vector)56 RectT(Vector4<T> vector)
57 {
58 data_[0] = vector[0];
59 data_[1] = vector[1];
60 data_[2] = vector[2];
61 data_[3] = vector[3];
62 }
RectT(const T * v)63 explicit RectT(const T* v)
64 {
65 data_[0] = v[0];
66 data_[1] = v[1];
67 data_[2] = v[2];
68 data_[3] = v[3];
69 }
70 ~RectT() = default;
71
72 inline bool operator==(const RectT<T>& rect) const
73 {
74 return ROSEN_EQ<T>(left_, rect.left_) && ROSEN_EQ<T>(top_, rect.top_) &&
75 ROSEN_EQ<T>(width_, rect.width_) && ROSEN_EQ<T>(height_, rect.height_);
76 }
77
78 inline bool operator!=(const RectT<T>& rect) const
79 {
80 return !operator==(rect);
81 }
82
83 inline bool IsNearEqual(const RectT<T>& rect, T threshold = std::numeric_limits<T>::epsilon()) const
84 {
85 return ROSEN_EQ<T>(left_, rect.left_, threshold) && ROSEN_EQ<T>(top_, rect.top_, threshold) &&
86 ROSEN_EQ<T>(width_, rect.width_, threshold) && ROSEN_EQ<T>(height_, rect.height_, threshold);
87 }
88
89 inline RectT& operator=(const RectT& other)
90 {
91 const T* oData = other.data_;
92 data_[0] = oData[0];
93 data_[1] = oData[1];
94 data_[2] = oData[2];
95 data_[3] = oData[3];
96 return *this;
97 }
SetAll(T left,T top,T width,T height)98 void SetAll(T left, T top, T width, T height)
99 {
100 data_[0] = left;
101 data_[1] = top;
102 data_[2] = width;
103 data_[3] = height;
104 }
GetRight()105 T GetRight() const
106 {
107 return left_ + width_;
108 }
GetLeft()109 T GetLeft() const
110 {
111 return left_;
112 }
GetBottom()113 T GetBottom() const
114 {
115 return top_ + height_;
116 }
GetTop()117 T GetTop() const
118 {
119 return top_;
120 }
GetWidth()121 T GetWidth() const
122 {
123 return width_;
124 }
GetHeight()125 T GetHeight() const
126 {
127 return height_;
128 }
SetRight(T right)129 void SetRight(T right)
130 {
131 width_ = right - left_;
132 }
SetBottom(T bottom)133 void SetBottom(T bottom)
134 {
135 height_ = bottom - top_;
136 }
Move(T x,T y)137 void Move(T x, T y)
138 {
139 left_ += x;
140 top_ += y;
141 }
Clear()142 void Clear()
143 {
144 left_ = 0;
145 top_ = 0;
146 width_ = 0;
147 height_ = 0;
148 }
IsEmpty()149 bool IsEmpty() const
150 {
151 return width_ <= 0 || height_ <= 0;
152 }
Intersect(T x,T y)153 bool Intersect(T x, T y) const
154 {
155 return (x >= left_) && (x < GetRight()) && (y >= top_) && (y < GetBottom());
156 }
IsInsideOf(const RectT<T> & rect)157 bool IsInsideOf(const RectT<T>& rect) const
158 {
159 return (top_ >= rect.top_ && left_ >= rect.left_ &&
160 GetBottom() <= rect.GetBottom() && GetRight() <= rect.GetRight());
161 }
Intersect(const RectT<T> & other)162 bool Intersect(const RectT<T>& other) const
163 {
164 return !IsEmpty() && !other.IsEmpty() && (left_ <= other.left_ + other.width_) &&
165 (other.left_ <= left_ + width_) && (top_ <= other.top_ + other.height_) &&
166 (other.top_ <= top_ + height_);
167 }
IntersectRect(const RectT<T> & rect)168 RectT<T> IntersectRect(const RectT<T>& rect) const
169 {
170 T left = std::max(left_, rect.left_);
171 T top = std::max(top_, rect.top_);
172 T width = std::min(GetRight(), rect.GetRight()) - left;
173 T height = std::min(GetBottom(), rect.GetBottom()) - top;
174 return ((width <= 0) || (height <= 0)) ? RectT<T>() : RectT<T>(left, top, width, height);
175 }
JoinRect(const RectT<T> & rect)176 RectT<T> JoinRect(const RectT<T>& rect) const
177 {
178 if (rect.IsEmpty()) {
179 return RectT<T>(left_, top_, width_, height_);
180 }
181 if (IsEmpty()) {
182 return rect;
183 }
184 T left = std::min(left_, rect.left_);
185 T top = std::min(top_, rect.top_);
186 T width = std::max(GetRight(), rect.GetRight()) - left;
187 T height = std::max(GetBottom(), rect.GetBottom()) - top;
188 return ((width <= 0) || (height <= 0)) ? RectT<T>() : RectT<T>(left, top, width, height);
189 }
Offset(const T x,const T y)190 RectT<T> Offset(const T x, const T y) const
191 {
192 return RectT<T>(left_ + x, top_ + y, width_, height_);
193 }
194 template<typename P>
ConvertTo()195 RectT<P> ConvertTo() const
196 {
197 return RectT<P>(static_cast<P>(left_), static_cast<P>(top_), static_cast<P>(width_), static_cast<P>(height_));
198 }
ToString()199 std::string ToString() const
200 {
201 return std::string("[") + std::to_string(left_) + ", " + std::to_string(top_) + ", " +
202 std::to_string(width_) + ", " + std::to_string(height_) + "]";
203 }
204
205 // outset: left, top, right, bottom
MakeOutset(Vector4<T> outset)206 RectT<T> MakeOutset(Vector4<T> outset) const
207 {
208 return RectT(left_ - outset.x_,
209 top_ - outset.y_,
210 width_ + outset.x_ + outset.z_,
211 height_ + outset.y_ + outset.w_);
212 }
213
214 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel)215 bool Marshalling(Parcel& parcel) const
216 {
217 if (!(RSMarshallingHelper::Marshalling(parcel, left_) &&
218 RSMarshallingHelper::Marshalling(parcel, top_) &&
219 RSMarshallingHelper::Marshalling(parcel, width_) &&
220 RSMarshallingHelper::Marshalling(parcel, height_))) {
221 return false;
222 }
223 return true;
224 }
225
Unmarshalling(Parcel & parcel)226 [[nodiscard]] static RectT<T>* Unmarshalling(Parcel& parcel)
227 {
228 auto rect = std::make_unique<RectT<T>>();
229 if (!(RSMarshallingHelper::Unmarshalling(parcel, rect->left_) &&
230 RSMarshallingHelper::Unmarshalling(parcel, rect->top_) &&
231 RSMarshallingHelper::Unmarshalling(parcel, rect->width_) &&
232 RSMarshallingHelper::Unmarshalling(parcel, rect->height_))) {
233 return nullptr;
234 }
235 return rect.release();
236 }
237 #endif
238 };
239
240 typedef RectT<int> RectI;
241 typedef RectT<float> RectF;
242
243 /*
244 RectIComparator: Used for comparing rects
245 RectI_Hash_Func: provide hash value for rect comparing
246 */
247 struct RectIComparator {
operatorRectIComparator248 bool operator()(const std::pair<NodeId, RectI>& p1, const std::pair<NodeId, RectI>& p2) const
249 {
250 return p2.second.IsInsideOf(p1.second);
251 }
252 };
253
254 struct RectI_Hash_Func {
operatorRectI_Hash_Func255 size_t operator()(const std::pair<NodeId, RectI>& p) const
256 {
257 // this is set for all rects can be compared
258 int hash_value = 0;
259 return std::hash<int>()(hash_value);
260 }
261 };
262
263 typedef std::unordered_set<std::pair<NodeId, RectI>, RectI_Hash_Func, RectIComparator> OcclusionRectISet;
264
265 struct FilterRectIComparator {
operatorFilterRectIComparator266 bool operator()(const std::pair<NodeId, RectI>& p1, const std::pair<NodeId, RectI>& p2) const
267 {
268 return p1.second == p2.second;
269 }
270 };
271
272 struct Filter_RectI_Hash_Func {
operatorFilter_RectI_Hash_Func273 size_t operator()(const std::pair<NodeId, RectI>& p) const
274 {
275 return std::hash<NodeId>()(p.first);
276 }
277 };
278 typedef std::unordered_set<std::pair<NodeId, RectI>, Filter_RectI_Hash_Func, FilterRectIComparator> FilterRectISet;
279
280 template<typename T>
281 class RRectT {
282 public:
283 RectT<T> rect_ = RectT<T>();
284 Vector2f radius_[4] = { { 0, 0 } };
285
RRectT()286 RRectT() {}
287 ~RRectT() = default;
288
RRectT(RectT<T> rect,float rx,float ry)289 RRectT(RectT<T> rect, float rx, float ry)
290 {
291 rect_ = rect;
292 Vector2f vec = Vector2f(rx, ry);
293 radius_[0] = vec;
294 radius_[1] = vec;
295 radius_[2] = vec;
296 radius_[3] = vec;
297 }
RRectT(RectT<T> rect,const Vector2f * radius)298 RRectT(RectT<T> rect, const Vector2f* radius)
299 {
300 rect_ = rect;
301 radius_[0] = radius[0];
302 radius_[1] = radius[1];
303 radius_[2] = radius[2];
304 radius_[3] = radius[3];
305 }
RRectT(RectT<T> rect,const Vector4f & radius)306 RRectT(RectT<T> rect, const Vector4f& radius)
307 {
308 rect_ = rect;
309 radius_[0] = { radius[0], radius[0] };
310 radius_[1] = { radius[1], radius[1] };
311 radius_[2] = { radius[2], radius[2] };
312 radius_[3] = { radius[3], radius[3] };
313 }
314
SetValues(RectT<T> rect,const Vector2f * radius)315 void SetValues(RectT<T> rect, const Vector2f* radius)
316 {
317 rect_ = rect;
318 radius_[0] = radius[0];
319 radius_[1] = radius[1];
320 radius_[2] = radius[2];
321 radius_[3] = radius[3];
322 }
323
324 RRectT operator-(const RRectT<T>& other) const;
325 RRectT operator+(const RRectT<T>& other) const;
326 RRectT operator/(float scale) const;
327 RRectT operator*(float scale) const;
328 RRectT& operator-=(const RRectT<T>& other);
329 RRectT& operator+=(const RRectT<T>& other);
330 RRectT& operator*=(float scale);
331 RRectT& operator=(const RRectT<T>& other);
332 bool operator==(const RRectT& other) const;
333 bool operator!=(const RRectT& other) const;
334 bool IsNearEqual(const RRectT& other, T threshold = std::numeric_limits<T>::epsilon()) const;
335 };
336
337 typedef RRectT<float> RRect;
338
339 template<typename T>
340 RRectT<T> RRectT<T>::operator-(const RRectT<T>& other) const
341 {
342 RRectT<T> rrect;
343 rrect.rect_.SetAll(rect_.GetLeft() - other.rect_.GetLeft(), rect_.GetTop() - other.rect_.GetTop(),
344 rect_.GetWidth() - other.rect_.GetWidth(), rect_.GetHeight() - other.rect_.GetHeight());
345 for (int index = 0; index < 4; index++) {
346 rrect.radius_[index] = radius_[index] - other.radius_[index];
347 }
348 return rrect;
349 }
350
351 template<typename T>
352 RRectT<T> RRectT<T>::operator+(const RRectT<T>& other) const
353 {
354 RRectT<T> rrect;
355 rrect.rect_.SetAll(rect_.GetLeft() + other.rect_.GetLeft(), rect_.GetTop() + other.rect_.GetTop(),
356 rect_.GetWidth() + other.rect_.GetWidth(), rect_.GetHeight() + other.rect_.GetHeight());
357 for (int index = 0; index < 4; index++) {
358 rrect.radius_[index] = radius_[index] + other.radius_[index];
359 }
360 return rrect;
361 }
362
363 template<typename T>
364 RRectT<T> RRectT<T>::operator/(float scale) const
365 {
366 if (ROSEN_EQ<float>(scale, 0)) {
367 return *this;
368 }
369 RRectT<T> rrect;
370 rrect.rect_.SetAll(rect_.GetLeft() / scale, rect_.GetTop() / scale,
371 rect_.GetWidth() / scale, rect_.GetHeight() / scale);
372 for (int index = 0; index < 4; index++) {
373 rrect.radius_[index] = radius_[index] / scale;
374 }
375 return rrect;
376 }
377
378 template<typename T>
379 RRectT<T> RRectT<T>::operator*(float scale) const
380 {
381 RRectT<T> rrect;
382 rrect.rect_.SetAll(rect_.GetLeft() * scale, rect_.GetTop() * scale,
383 rect_.GetWidth() * scale, rect_.GetHeight() * scale);
384 for (int index = 0; index < 4; index++) {
385 rrect.radius_[index] = radius_[index] * scale;
386 }
387 return rrect;
388 }
389
390 template<typename T>
391 RRectT<T>& RRectT<T>::operator-=(const RRectT<T>& other)
392 {
393 rect_.SetAll(rect_.GetLeft() - other.rect_.GetLeft(), rect_.GetTop() - other.rect_.GetTop(),
394 rect_.GetWidth() - other.rect_.GetWidth(), rect_.GetHeight() - other.rect_.GetHeight());
395 for (int index = 0; index < 4; index++) {
396 radius_[index] = radius_[index] - other.radius_[index];
397 }
398 return *this;
399 }
400
401 template<typename T>
402 RRectT<T>& RRectT<T>::operator+=(const RRectT<T>& other)
403 {
404 rect_.SetAll(rect_.GetLeft() + other.rect_.GetLeft(), rect_.GetTop() + other.rect_.GetTop(),
405 rect_.GetWidth() + other.rect_.GetWidth(), rect_.GetHeight() + other.rect_.GetHeight());
406 for (int index = 0; index < 4; index++) {
407 radius_[index] = radius_[index] + other.radius_[index];
408 }
409 return *this;
410 }
411
412 template<typename T>
413 RRectT<T>& RRectT<T>::operator*=(float scale)
414 {
415 rect_.SetAll(rect_.GetLeft() * scale, rect_.GetTop() * scale,
416 rect_.GetWidth() * scale, rect_.GetHeight() * scale);
417 for (int index = 0; index < 4; index++) {
418 radius_[index] = radius_[index] * scale;
419 }
420 return *this;
421 }
422
423 template<typename T>
424 RRectT<T>& RRectT<T>::operator=(const RRectT<T>& other)
425 {
426 rect_ = other.rect_;
427 for (int index = 0; index < 4; index++) {
428 radius_[index] = other.radius_[index];
429 }
430 return *this;
431 }
432
433 template<typename T>
434 inline bool RRectT<T>::operator==(const RRectT& other) const
435 {
436 return (rect_ == other.rect_) && (radius_[0] == other.radius_[0]) &&
437 (radius_[1] == other.radius_[1]) && (radius_[2] == other.radius_[2]) &&
438 (radius_[3] == other.radius_[3]);
439 }
440
441 template<typename T>
442 inline bool RRectT<T>::operator!=(const RRectT& other) const
443 {
444 return !operator==(other);
445 }
446
447 template<typename T>
IsNearEqual(const RRectT & rrectT,T threshold)448 inline bool RRectT<T>::IsNearEqual(const RRectT& rrectT, T threshold) const
449 {
450 return (rect_.IsNearEqual(rrectT.rect_, threshold)) && (radius_[0].IsNearEqual(rrectT.radius_[0], threshold)) &&
451 (radius_[1].IsNearEqual(rrectT.radius_[1], threshold)) &&
452 (radius_[2].IsNearEqual(rrectT.radius_[2], threshold)) &&
453 (radius_[3].IsNearEqual(rrectT.radius_[3], threshold));
454 }
455 } // namespace Rosen
456 } // namespace OHOS
457 #endif
458