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