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