• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 RECT_H
17 #define RECT_H
18 
19 #include <cmath>
20 #include <string>
21 #include "utils/drawing_macros.h"
22 #include "utils/scalar.h"
23 
24 namespace OHOS {
25 namespace Rosen {
26 namespace Drawing {
27 class RectF;
28 
29 typedef RectF Rect;
30 
31 #define DRAWING_MAX_S32_FITS_IN_FLOAT    2147483520
32 #define DRAWING_MIN_S32_FITS_IN_FLOAT    (-DRAWING_MAX_S32_FITS_IN_FLOAT)
33 
DrawingFloatSaturate2Int(float x)34 static inline int32_t DrawingFloatSaturate2Int(float x)
35 {
36     x = x < DRAWING_MAX_S32_FITS_IN_FLOAT ? x : DRAWING_MAX_S32_FITS_IN_FLOAT;
37     x = x > DRAWING_MIN_S32_FITS_IN_FLOAT ? x : DRAWING_MIN_S32_FITS_IN_FLOAT;
38     return (int32_t)x;
39 }
40 
41 class DRAWING_API RectI {
42 public:
43     inline RectI() noexcept;
44     inline RectI(const RectI& r) noexcept;
45     inline RectI(const int32_t l, const int32_t t, const int32_t r, const int32_t b) noexcept;
46 
~RectI()47     ~RectI() {}
48 
49     inline bool IsValid() const;
50     inline bool IsEmpty() const;
51 
52     inline int32_t GetLeft() const;
53     inline int32_t GetTop() const;
54     inline int32_t GetRight() const;
55     inline int32_t GetBottom() const;
56 
57     inline int32_t GetWidth() const;
58     inline int32_t GetHeight() const;
59 
60     inline void SetLeft(int32_t pos);
61     inline void SetTop(int32_t pos);
62     inline void SetRight(int32_t pos);
63     inline void SetBottom(int32_t pos);
64 
65     /**
66      * @brief Offsets RectI by adding dx to left, right; and by adding dy to top, bottom.
67      * If dx is negative, moves RectI returned to the left.
68      * If dx is positive, moves RectI returned to the right.
69      * If dy is negative, moves RectI returned upward.
70      * If dy is positive, moves RectI returned downward.
71      * @param dx  offset added to left and right
72      * @param dy  offset added to top and bottom
73      */
74     inline void Offset(int32_t dx, int32_t dy);
75 
76     /**
77      * @brief outset by (dx, dy).
78      * If dx is negative, RectI is narrower.
79      * If dx is positive, RectI is wider.
80      * If dy is negative, RectI is shorter.
81      * If dy is positive, RectI is taller.
82      * @param dx offset subtracted to left and added from right
83      * @param dy offset subtracted to top and added from bottom
84      */
85     inline void MakeOutset(int32_t dx, int32_t dy);
86 
87     /**
88      * @brief Returns true if RectI contains other.
89      * Returns false if RectI is empty or other is empty.
90      * RectI contains other when RectI area completely includes other area.
91      * @param other RectI contained
92      * @return true if all sides of RectI are outside other
93      */
94     inline bool Contains(const RectI& other) const;
95 
96     /**
97      * @brief If RectI intersects other, sets RectI to intersection.
98      * @param other limit of result.
99      * @return true if other and RectI have area in common.
100      */
101     inline bool Intersect(const RectI& other);
102 
103     /**
104      * @brief If other is valid, sets RectI to the union of itself and other.
105      * @param other expansion RectI.
106      * @return true if other is valid.
107      */
108     inline bool Join(const RectI& other);
109 
110     inline std::string ToString() const;
111 
112     friend inline bool operator==(const RectI& r1, const RectI& r2);
113     friend inline bool operator!=(const RectI& r1, const RectI& r2);
114 
115     inline void Dump(std::string& out) const;
116 
117     int32_t left_;
118     int32_t top_;
119     int32_t right_;
120     int32_t bottom_;
121 };
122 
RectI()123 inline RectI::RectI() noexcept : left_(0), top_(0), right_(0), bottom_(0) {}
124 
RectI(const RectI & r)125 inline RectI::RectI(const RectI& r) noexcept
126 {
127     // Tell the compiler there is no alias and to select wider load/store instructions.
128     int32_t left = r.GetLeft();
129     int32_t top = r.GetTop();
130     int32_t right = r.GetRight();
131     int32_t bottom = r.GetBottom();
132     left_ = left;
133     top_ = top;
134     right_ = right;
135     bottom_ = bottom;
136 }
137 
RectI(const int l,const int t,const int r,const int b)138 inline RectI::RectI(const int l, const int t, const int r, const int b) noexcept
139     : left_(l), top_(t), right_(r), bottom_(b)
140 {}
141 
IsValid()142 inline bool RectI::IsValid() const
143 {
144     return !IsEmpty();
145 }
146 
IsEmpty()147 inline bool RectI::IsEmpty() const
148 {
149     int64_t w = (int64_t)right_ - (int64_t)left_;
150     int64_t h = (int64_t)bottom_ - (int64_t)top_;
151     if (w <= 0 || h <= 0) {
152         return true;
153     }
154     // Return true if either exceeds int32_t
155     int32_t int32test = (w | h) & 0xFFFFFFFF;
156     return int32test < 0;
157 }
158 
GetLeft()159 inline int32_t RectI::GetLeft() const
160 {
161     return left_;
162 }
163 
GetTop()164 inline int32_t RectI::GetTop() const
165 {
166     return top_;
167 }
168 
GetRight()169 inline int32_t RectI::GetRight() const
170 {
171     return right_;
172 }
173 
GetBottom()174 inline int32_t RectI::GetBottom() const
175 {
176     return bottom_;
177 }
178 
GetWidth()179 inline int32_t RectI::GetWidth() const
180 {
181     return right_ - left_;
182 }
183 
GetHeight()184 inline int32_t RectI::GetHeight() const
185 {
186     return bottom_ - top_;
187 }
188 
SetLeft(int32_t pos)189 inline void RectI::SetLeft(int32_t pos)
190 {
191     left_ = pos;
192 }
193 
SetTop(int32_t pos)194 inline void RectI::SetTop(int32_t pos)
195 {
196     top_ = pos;
197 }
198 
SetRight(int32_t pos)199 inline void RectI::SetRight(int32_t pos)
200 {
201     right_ = pos;
202 }
203 
SetBottom(int32_t pos)204 inline void RectI::SetBottom(int32_t pos)
205 {
206     bottom_ = pos;
207 }
208 
Offset(int32_t dx,int32_t dy)209 inline void RectI::Offset(int32_t dx, int32_t dy)
210 {
211     left_ += dx;
212     right_ += dx;
213     top_ += dy;
214     bottom_ += dy;
215 }
216 
MakeOutset(int32_t dx,int32_t dy)217 inline void RectI::MakeOutset(int32_t dx, int32_t dy)
218 {
219     left_ -= dx;
220     right_ += dx;
221     top_ -= dy;
222     bottom_ += dy;
223 }
224 
Intersect(const RectI & other)225 inline bool RectI::Intersect(const RectI& other)
226 {
227     RectI rectI(left_ > other.left_ ? left_ : other.left_, top_ > other.top_ ? top_ : other.top_,
228         right_ < other.right_ ? right_ : other.right_, bottom_ < other.bottom_ ? bottom_ : other.bottom_);
229     if (!rectI.IsValid()) {
230         return false;
231     }
232     *this = rectI;
233     return true;
234 }
235 
Join(const RectI & other)236 inline bool RectI::Join(const RectI& other)
237 {
238     if (!other.IsValid()) {
239         return false;
240     }
241     if (!IsValid()) {
242         *this = other;
243     } else {
244         *this = RectI(left_ < other.left_ ? left_ : other.left_, top_ < other.top_ ? top_ : other.top_,
245             right_ > other.right_ ? right_ : other.right_, bottom_ > other.bottom_ ? bottom_ : other.bottom_);
246     }
247     return true;
248 }
249 
Contains(const RectI & other)250 inline bool RectI::Contains(const RectI& other) const
251 {
252     return !other.IsEmpty() && !this->IsEmpty() &&
253         left_ <= other.left_ && top_ <= other.top_ &&
254         right_ >= other.right_ && bottom_ >= other.bottom_;
255 }
256 
ToString()257 inline std::string RectI::ToString() const
258 {
259     return std::string("(") + std::to_string(left_) + ", " + std::to_string(top_) + ", " +
260         std::to_string(right_ - left_) + ", " + std::to_string(bottom_ - top_) + ")";
261 }
262 
Dump(std::string & out)263 inline void RectI::Dump(std::string& out) const
264 {
265     out += "[left:" + std::to_string(left_);
266     out += " top:" + std::to_string(top_);
267     out += " right:" + std::to_string(right_);
268     out += " bottom:" + std::to_string(bottom_);
269     out += "]";
270 }
271 
272 inline bool operator==(const RectI& r1, const RectI& r2)
273 {
274     return r1.left_ == r2.left_ && r1.right_ == r2.right_ && r1.top_ == r2.top_ && r1.bottom_ == r2.bottom_;
275 }
276 
277 inline bool operator!=(const RectI& r1, const RectI& r2)
278 {
279     return r1.left_ != r2.left_ || r1.right_ != r2.right_ || r1.top_ != r2.top_ || r1.bottom_ != r2.bottom_;
280 }
281 
282 class DRAWING_API RectF {
283 public:
284     inline RectF() noexcept;
285     inline RectF(const RectF& r) noexcept;
286     inline RectF(const RectI& r) noexcept;
287     inline RectF(const scalar l, const scalar t, const scalar r, const scalar b) noexcept;
288 
~RectF()289     ~RectF() {}
290 
291     inline bool IsValid() const;
292     inline bool IsEmpty() const;
293 
294     inline scalar GetLeft() const;
295     inline scalar GetTop() const;
296     inline scalar GetRight() const;
297     inline scalar GetBottom() const;
298 
299     inline scalar GetWidth() const;
300     inline scalar GetHeight() const;
301 
302     inline void SetLeft(scalar pos);
303     inline void SetTop(scalar pos);
304     inline void SetRight(scalar pos);
305     inline void SetBottom(scalar pos);
306 
307     inline void Offset(scalar dx, scalar dy);
308     inline void MakeOutset(scalar dx, scalar dy);
309     inline void Round();
310     inline RectI RoundOut();
311     inline std::string ToString() const;
312 
313     /*
314      * @brief        If RectF intersects other, sets RectF to intersection.
315      * @param other  other rectangle.
316      * @return       true if other and RectF have area in common.
317      */
318     inline bool Intersect(const RectF& other);
319 
320     /*
321      * @brief        Determine whether this and other intersect.
322      * @param other  other rectangle.
323      * @return       true if other and RectF have area in common.
324      */
325     inline bool IsIntersect(const RectF& other) const;
326 
327     /*
328      * @brief        If other is valid, sets RectF to the union of itself and other.
329      * @param other  expansion RectF.
330      * @return       true if other is valid.
331      */
332     inline bool Join(const RectF& other);
333 
334     /*
335      * @brief Determine if (x, y) is within this rectangle.
336      * @param x x-coordinate.
337      * @param y y-coordinate.
338      * @return true if rectangle contains (x, y), false otherwise.
339      */
340     inline bool Contains(scalar x, scalar y) const;
341 
342     /*
343      * @brief Determine if other rectangle is inside this rectangle.
344      * @param other other rectangle.
345      * @return true if rectangle contains other rectangle, false otherwise.
346      */
347     inline bool Contains(const RectF& other) const;
348 
349     /*
350      * @brief Swaps left and right if left is greater than right;
351      *        and swaps top and bottom if top is greater than bottom.
352      */
353     inline void Sort();
354 
355     friend inline bool operator==(const RectF& r1, const RectF& r2);
356     friend inline bool operator!=(const RectF& r1, const RectF& r2);
357 
358     inline void Dump(std::string& out) const;
359 
360     scalar left_;
361     scalar top_;
362     scalar right_;
363     scalar bottom_;
364 };
365 
RectF()366 inline RectF::RectF() noexcept : left_(0.0), top_(0.0), right_(0.0), bottom_(0.0) {}
367 
RectF(const RectF & r)368 inline RectF::RectF(const RectF& r) noexcept
369 {
370     // Tell the compiler there is no alias and to select wider load/store instructions.
371     scalar left = r.GetLeft();
372     scalar top = r.GetTop();
373     scalar right = r.GetRight();
374     scalar bottom = r.GetBottom();
375     left_ = left;
376     top_ = top;
377     right_ = right;
378     bottom_ = bottom;
379 }
380 
RectF(const RectI & r)381 inline RectF::RectF(const RectI& r) noexcept
382 {
383     // Tell the compiler there is no alias and to select wider load/store instructions.
384     scalar left = r.GetLeft();
385     scalar top = r.GetTop();
386     scalar right = r.GetRight();
387     scalar bottom = r.GetBottom();
388     left_ = left;
389     top_ = top;
390     right_ = right;
391     bottom_ = bottom;
392 }
393 
RectF(const scalar l,const scalar t,const scalar r,const scalar b)394 inline RectF::RectF(const scalar l, const scalar t, const scalar r, const scalar b) noexcept
395     : left_(l), top_(t), right_(r), bottom_(b)
396 {}
397 
IsValid()398 inline bool RectF::IsValid() const
399 {
400     return left_ < right_ && top_ < bottom_;
401 }
402 
IsEmpty()403 inline bool RectF::IsEmpty() const
404 {
405     return !(left_ < right_ && top_ < bottom_);
406 }
407 
GetLeft()408 inline scalar RectF::GetLeft() const
409 {
410     return left_;
411 }
412 
GetTop()413 inline scalar RectF::GetTop() const
414 {
415     return top_;
416 }
417 
GetRight()418 inline scalar RectF::GetRight() const
419 {
420     return right_;
421 }
422 
GetBottom()423 inline scalar RectF::GetBottom() const
424 {
425     return bottom_;
426 }
427 
GetWidth()428 inline scalar RectF::GetWidth() const
429 {
430     return right_ - left_;
431 }
432 
GetHeight()433 inline scalar RectF::GetHeight() const
434 {
435     return bottom_ - top_;
436 }
437 
SetLeft(scalar pos)438 inline void RectF::SetLeft(scalar pos)
439 {
440     left_ = pos;
441 }
442 
SetTop(scalar pos)443 inline void RectF::SetTop(scalar pos)
444 {
445     top_ = pos;
446 }
447 
SetRight(scalar pos)448 inline void RectF::SetRight(scalar pos)
449 {
450     right_ = pos;
451 }
452 
SetBottom(scalar pos)453 inline void RectF::SetBottom(scalar pos)
454 {
455     bottom_ = pos;
456 }
457 
Offset(scalar dx,scalar dy)458 inline void RectF::Offset(scalar dx, scalar dy)
459 {
460     left_ += dx;
461     right_ += dx;
462     top_ += dy;
463     bottom_ += dy;
464 }
465 
MakeOutset(scalar dx,scalar dy)466 inline void RectF::MakeOutset(scalar dx, scalar dy)
467 {
468     left_ -= dx;
469     right_ += dx;
470     top_ -= dy;
471     bottom_ += dy;
472 }
473 
Round()474 inline void RectF::Round()
475 {
476     left_ = DrawingFloatSaturate2Int(left_ + 0.5f);
477     right_ = DrawingFloatSaturate2Int(right_ + 0.5f);
478     top_ = DrawingFloatSaturate2Int(top_ + 0.5f);
479     bottom_ = DrawingFloatSaturate2Int(bottom_ + 0.5f);
480 }
481 
RoundOut()482 inline RectI RectF::RoundOut()
483 {
484     int32_t left = DrawingFloatSaturate2Int(floorf(left_));
485     int32_t right = DrawingFloatSaturate2Int(ceilf(right_));
486     int32_t top = DrawingFloatSaturate2Int(floorf(top_));
487     int32_t bottom = DrawingFloatSaturate2Int(ceilf(bottom_));
488     return RectI(left, top, right, bottom);
489 }
490 
Intersect(const RectF & other)491 inline bool RectF::Intersect(const RectF& other)
492 {
493     RectF rectF(left_ > other.left_ ? left_ : other.left_, top_ > other.top_ ? top_ : other.top_,
494                 right_ < other.right_ ? right_ : other.right_, bottom_ < other.bottom_ ? bottom_ : other.bottom_);
495     if (!rectF.IsValid()) {
496         return false;
497     }
498     *this = rectF;
499     return true;
500 }
501 
IsIntersect(const RectF & other)502 inline bool RectF::IsIntersect(const RectF& other) const
503 {
504     RectF rectF(left_ > other.left_ ? left_ : other.left_, top_ > other.top_ ? top_ : other.top_,
505                 right_ < other.right_ ? right_ : other.right_, bottom_ < other.bottom_ ? bottom_ : other.bottom_);
506     return rectF.IsValid();
507 }
508 
Join(const RectF & other)509 inline bool RectF::Join(const RectF& other)
510 {
511     if (!other.IsValid()) {
512         return false;
513     }
514     if (!IsValid()) {
515         *this = other;
516     } else {
517         *this = RectF(left_ < other.left_ ? left_ : other.left_, top_ < other.top_ ? top_ : other.top_,
518             right_ > other.right_ ? right_ : other.right_, bottom_ > other.bottom_ ? bottom_ : other.bottom_);
519     }
520     return true;
521 }
522 
Contains(scalar x,scalar y)523 inline bool RectF::Contains(scalar x, scalar y) const
524 {
525     return x >= left_ && x < right_ && y >= top_ && y < bottom_;
526 }
527 
Contains(const RectF & other)528 inline bool RectF::Contains(const RectF& other) const
529 {
530     return !other.IsEmpty() && !this->IsEmpty() &&
531         left_ <= other.left_ && top_ <= other.top_ &&
532         right_ >= other.right_ && bottom_ >= other.bottom_;
533 }
534 
Sort()535 inline void RectF::Sort()
536 {
537     if (left_ > right_) {
538         std::swap(left_, right_);
539     }
540 
541     if (top_ > bottom_) {
542         std::swap(top_, bottom_);
543     }
544 }
545 
ToString()546 inline std::string RectF::ToString() const
547 {
548     return std::string("(") + std::to_string(left_) + ", " + std::to_string(top_) + ", " +
549         std::to_string(right_ - left_) + ", " + std::to_string(bottom_ - top_) + ")";
550 }
551 
Dump(std::string & out)552 inline void RectF::Dump(std::string& out) const
553 {
554     out += "[left:" + std::to_string(left_);
555     out += " top:" + std::to_string(top_);
556     out += " right:" + std::to_string(right_);
557     out += " bottom:" + std::to_string(bottom_);
558     out += ']';
559 }
560 
561 inline bool operator==(const RectF& r1, const RectF& r2)
562 {
563     return IsScalarAlmostEqual(r1.left_, r2.left_) && IsScalarAlmostEqual(r1.right_, r2.right_) &&
564         IsScalarAlmostEqual(r1.top_, r2.top_) && IsScalarAlmostEqual(r1.bottom_, r2.bottom_);
565 }
566 
567 inline bool operator!=(const RectF& r1, const RectF& r2)
568 {
569     return !IsScalarAlmostEqual(r1.left_, r2.left_) || !IsScalarAlmostEqual(r1.right_, r2.right_) ||
570         !IsScalarAlmostEqual(r1.top_, r2.top_) || !IsScalarAlmostEqual(r1.bottom_, r2.bottom_);
571 }
572 } // namespace Drawing
573 } // namespace Rosen
574 } // namespace OHOS
575 #endif
576