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