xref: /aosp_15_r20/external/skia/include/core/SkRect.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkRect_DEFINED
9 #define SkRect_DEFINED
10 
11 #include "include/core/SkPoint.h"
12 #include "include/core/SkSize.h"
13 #include "include/core/SkTypes.h"
14 #include "include/private/base/SkFloatingPoint.h"
15 #include "include/private/base/SkSafe32.h"
16 #include "include/private/base/SkTFitsIn.h"
17 
18 #include <algorithm>
19 #include <cmath>
20 #include <cstdint>
21 #include <cstring>
22 
23 struct SkRect;
24 class SkString;
25 
26 /** \struct SkIRect
27     SkIRect holds four 32-bit integer coordinates describing the upper and
28     lower bounds of a rectangle. SkIRect may be created from outer bounds or
29     from position, width, and height. SkIRect describes an area; if its right
30     is less than or equal to its left, or if its bottom is less than or equal to
31     its top, it is considered empty.
32 */
33 struct SK_API SkIRect {
34     int32_t fLeft   = 0; //!< smaller x-axis bounds
35     int32_t fTop    = 0; //!< smaller y-axis bounds
36     int32_t fRight  = 0; //!< larger x-axis bounds
37     int32_t fBottom = 0; //!< larger y-axis bounds
38 
39     /** Returns constructed SkIRect set to (0, 0, 0, 0).
40         Many other rectangles are empty; if left is equal to or greater than right,
41         or if top is equal to or greater than bottom. Setting all members to zero
42         is a convenience, but does not designate a special empty rectangle.
43 
44         @return  bounds (0, 0, 0, 0)
45     */
MakeEmptySkIRect46     [[nodiscard]] static constexpr SkIRect MakeEmpty() {
47         return SkIRect{0, 0, 0, 0};
48     }
49 
50     /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
51         may be negative.
52 
53         @param w  width of constructed SkIRect
54         @param h  height of constructed SkIRect
55         @return   bounds (0, 0, w, h)
56     */
MakeWHSkIRect57     [[nodiscard]] static constexpr SkIRect MakeWH(int32_t w, int32_t h) {
58         return SkIRect{0, 0, w, h};
59     }
60 
61     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
62         Does not validate input; size.width() or size.height() may be negative.
63 
64         @param size  values for SkIRect width and height
65         @return      bounds (0, 0, size.width(), size.height())
66     */
MakeSizeSkIRect67     [[nodiscard]] static constexpr SkIRect MakeSize(const SkISize& size) {
68         return SkIRect{0, 0, size.fWidth, size.fHeight};
69     }
70 
71     /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
72         pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
73         negative.
74 
75         @param pt    values for SkIRect fLeft and fTop
76         @param size  values for SkIRect width and height
77         @return      bounds at pt with width and height of size
78     */
MakePtSizeSkIRect79     [[nodiscard]] static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size) {
80         return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
81     }
82 
83     /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
84         result in fLeft greater than fRight, or fTop greater than fBottom.
85 
86         @param l  integer stored in fLeft
87         @param t  integer stored in fTop
88         @param r  integer stored in fRight
89         @param b  integer stored in fBottom
90         @return   bounds (l, t, r, b)
91     */
MakeLTRBSkIRect92     [[nodiscard]] static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
93         return SkIRect{l, t, r, b};
94     }
95 
96     /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
97         Does not validate input; w or h may be negative.
98 
99         @param x  stored in fLeft
100         @param y  stored in fTop
101         @param w  added to x and stored in fRight
102         @param h  added to y and stored in fBottom
103         @return   bounds at (x, y) with width w and height h
104     */
MakeXYWHSkIRect105     [[nodiscard]] static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
106         return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
107     }
108 
109     /** Returns left edge of SkIRect, if sorted.
110         Call sort() to reverse fLeft and fRight if needed.
111 
112         @return  fLeft
113     */
leftSkIRect114     constexpr int32_t left() const { return fLeft; }
115 
116     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
117         and sort() to reverse fTop and fBottom if needed.
118 
119         @return  fTop
120     */
topSkIRect121     constexpr int32_t top() const { return fTop; }
122 
123     /** Returns right edge of SkIRect, if sorted.
124         Call sort() to reverse fLeft and fRight if needed.
125 
126         @return  fRight
127     */
rightSkIRect128     constexpr int32_t right() const { return fRight; }
129 
130     /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
131         and sort() to reverse fTop and fBottom if needed.
132 
133         @return  fBottom
134     */
bottomSkIRect135     constexpr int32_t bottom() const { return fBottom; }
136 
137     /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
138         and sort() to reverse fLeft and fRight if needed.
139 
140         @return  fLeft
141     */
xSkIRect142     constexpr int32_t x() const { return fLeft; }
143 
144     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
145         and sort() to reverse fTop and fBottom if needed.
146 
147         @return  fTop
148     */
ySkIRect149     constexpr int32_t y() const { return fTop; }
150 
151     // Experimental
topLeftSkIRect152     constexpr SkIPoint topLeft() const { return {fLeft, fTop}; }
153 
154     /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
155         result fits in 32-bit signed integer; result may be negative.
156 
157         @return  fRight minus fLeft
158     */
widthSkIRect159     constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
160 
161     /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
162         result fits in 32-bit signed integer; result may be negative.
163 
164         @return  fBottom minus fTop
165     */
heightSkIRect166     constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
167 
168     /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
169         or if result fits in 32-bit signed integer; result may be negative.
170 
171         @return  SkISize (width, height)
172     */
sizeSkIRect173     constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); }
174 
175     /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
176         result may be negative. This is safer than calling width() since width() might
177         overflow in its calculation.
178 
179         @return  fRight minus fLeft cast to int64_t
180     */
width64SkIRect181     constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
182 
183     /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
184         result may be negative. This is safer than calling height() since height() might
185         overflow in its calculation.
186 
187         @return  fBottom minus fTop cast to int64_t
188     */
height64SkIRect189     constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
190 
191     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
192         to or greater than fBottom. Call sort() to reverse rectangles with negative
193         width64() or height64().
194 
195         @return  true if width64() or height64() are zero or negative
196     */
isEmpty64SkIRect197     bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
198 
199     /** Returns true if width() or height() are zero or negative.
200 
201         @return  true if width() or height() are zero or negative
202     */
isEmptySkIRect203     bool isEmpty() const {
204         int64_t w = this->width64();
205         int64_t h = this->height64();
206         if (w <= 0 || h <= 0) {
207             return true;
208         }
209         // Return true if either exceeds int32_t
210         return !SkTFitsIn<int32_t>(w | h);
211     }
212 
213     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
214         identical to corresponding members in b.
215 
216         @param a  SkIRect to compare
217         @param b  SkIRect to compare
218         @return   true if members are equal
219     */
220     friend bool operator==(const SkIRect& a, const SkIRect& b) {
221         return a.fLeft == b.fLeft && a.fTop == b.fTop &&
222                a.fRight == b.fRight && a.fBottom == b.fBottom;
223     }
224 
225     /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
226         identical to the corresponding member in b.
227 
228         @param a  SkIRect to compare
229         @param b  SkIRect to compare
230         @return   true if members are not equal
231     */
232     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
233         return a.fLeft != b.fLeft || a.fTop != b.fTop ||
234                a.fRight != b.fRight || a.fBottom != b.fBottom;
235     }
236 
237     /** Sets SkIRect to (0, 0, 0, 0).
238 
239         Many other rectangles are empty; if left is equal to or greater than right,
240         or if top is equal to or greater than bottom. Setting all members to zero
241         is a convenience, but does not designate a special empty rectangle.
242     */
setEmptySkIRect243     void setEmpty() { memset(this, 0, sizeof(*this)); }
244 
245     /** Sets SkIRect to (left, top, right, bottom).
246         left and right are not sorted; left is not necessarily less than right.
247         top and bottom are not sorted; top is not necessarily less than bottom.
248 
249         @param left    stored in fLeft
250         @param top     stored in fTop
251         @param right   stored in fRight
252         @param bottom  stored in fBottom
253     */
setLTRBSkIRect254     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
255         fLeft   = left;
256         fTop    = top;
257         fRight  = right;
258         fBottom = bottom;
259     }
260 
261     /** Sets SkIRect to: (x, y, x + width, y + height).
262         Does not validate input; width or height may be negative.
263 
264         @param x       stored in fLeft
265         @param y       stored in fTop
266         @param width   added to x and stored in fRight
267         @param height  added to y and stored in fBottom
268     */
setXYWHSkIRect269     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
270         fLeft   = x;
271         fTop    = y;
272         fRight  = Sk32_sat_add(x, width);
273         fBottom = Sk32_sat_add(y, height);
274     }
275 
setWHSkIRect276     void setWH(int32_t width, int32_t height) {
277         fLeft   = 0;
278         fTop    = 0;
279         fRight  = width;
280         fBottom = height;
281     }
282 
setSizeSkIRect283     void setSize(SkISize size) {
284         fLeft = 0;
285         fTop = 0;
286         fRight = size.width();
287         fBottom = size.height();
288     }
289 
290     /** Returns SkIRect offset by (dx, dy).
291 
292         If dx is negative, SkIRect returned is moved to the left.
293         If dx is positive, SkIRect returned is moved to the right.
294         If dy is negative, SkIRect returned is moved upward.
295         If dy is positive, SkIRect returned is moved downward.
296 
297         @param dx  offset added to fLeft and fRight
298         @param dy  offset added to fTop and fBottom
299         @return    SkIRect offset by dx and dy, with original width and height
300     */
makeOffsetSkIRect301     constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
302         return {
303             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
304             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
305         };
306     }
307 
308     /** Returns SkIRect offset by (offset.x(), offset.y()).
309 
310         If offset.x() is negative, SkIRect returned is moved to the left.
311         If offset.x() is positive, SkIRect returned is moved to the right.
312         If offset.y() is negative, SkIRect returned is moved upward.
313         If offset.y() is positive, SkIRect returned is moved downward.
314 
315         @param offset  translation vector
316         @return    SkIRect translated by offset, with original width and height
317     */
makeOffsetSkIRect318     constexpr SkIRect makeOffset(SkIVector offset) const {
319         return this->makeOffset(offset.x(), offset.y());
320     }
321 
322     /** Returns SkIRect, inset by (dx, dy).
323 
324         If dx is negative, SkIRect returned is wider.
325         If dx is positive, SkIRect returned is narrower.
326         If dy is negative, SkIRect returned is taller.
327         If dy is positive, SkIRect returned is shorter.
328 
329         @param dx  offset added to fLeft and subtracted from fRight
330         @param dy  offset added to fTop and subtracted from fBottom
331         @return    SkIRect inset symmetrically left and right, top and bottom
332     */
makeInsetSkIRect333     SkIRect makeInset(int32_t dx, int32_t dy) const {
334         return {
335             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
336             Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
337         };
338     }
339 
340     /** Returns SkIRect, outset by (dx, dy).
341 
342         If dx is negative, SkIRect returned is narrower.
343         If dx is positive, SkIRect returned is wider.
344         If dy is negative, SkIRect returned is shorter.
345         If dy is positive, SkIRect returned is taller.
346 
347         @param dx  offset subtracted to fLeft and added from fRight
348         @param dy  offset subtracted to fTop and added from fBottom
349         @return    SkIRect outset symmetrically left and right, top and bottom
350     */
makeOutsetSkIRect351     SkIRect makeOutset(int32_t dx, int32_t dy) const {
352         return {
353             Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),
354             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
355         };
356     }
357 
358     /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
359 
360         If dx is negative, moves SkIRect returned to the left.
361         If dx is positive, moves SkIRect returned to the right.
362         If dy is negative, moves SkIRect returned upward.
363         If dy is positive, moves SkIRect returned downward.
364 
365         @param dx  offset added to fLeft and fRight
366         @param dy  offset added to fTop and fBottom
367     */
offsetSkIRect368     void offset(int32_t dx, int32_t dy) {
369         fLeft   = Sk32_sat_add(fLeft,   dx);
370         fTop    = Sk32_sat_add(fTop,    dy);
371         fRight  = Sk32_sat_add(fRight,  dx);
372         fBottom = Sk32_sat_add(fBottom, dy);
373     }
374 
375     /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
376         fTop, fBottom.
377 
378         If delta.fX is negative, moves SkIRect returned to the left.
379         If delta.fX is positive, moves SkIRect returned to the right.
380         If delta.fY is negative, moves SkIRect returned upward.
381         If delta.fY is positive, moves SkIRect returned downward.
382 
383         @param delta  offset added to SkIRect
384     */
offsetSkIRect385     void offset(const SkIPoint& delta) {
386         this->offset(delta.fX, delta.fY);
387     }
388 
389     /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
390         are unchanged.
391 
392         @param newX  stored in fLeft, preserving width()
393         @param newY  stored in fTop, preserving height()
394     */
offsetToSkIRect395     void offsetTo(int32_t newX, int32_t newY) {
396         fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
397         fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
398         fLeft   = newX;
399         fTop    = newY;
400     }
401 
402     /** Insets SkIRect by (dx,dy).
403 
404         If dx is positive, makes SkIRect narrower.
405         If dx is negative, makes SkIRect wider.
406         If dy is positive, makes SkIRect shorter.
407         If dy is negative, makes SkIRect taller.
408 
409         @param dx  offset added to fLeft and subtracted from fRight
410         @param dy  offset added to fTop and subtracted from fBottom
411     */
insetSkIRect412     void inset(int32_t dx, int32_t dy) {
413         fLeft   = Sk32_sat_add(fLeft,   dx);
414         fTop    = Sk32_sat_add(fTop,    dy);
415         fRight  = Sk32_sat_sub(fRight,  dx);
416         fBottom = Sk32_sat_sub(fBottom, dy);
417     }
418 
419     /** Outsets SkIRect by (dx, dy).
420 
421         If dx is positive, makes SkIRect wider.
422         If dx is negative, makes SkIRect narrower.
423         If dy is positive, makes SkIRect taller.
424         If dy is negative, makes SkIRect shorter.
425 
426         @param dx  subtracted to fLeft and added from fRight
427         @param dy  subtracted to fTop and added from fBottom
428     */
outsetSkIRect429     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
430 
431     /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
432 
433         If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
434         If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
435         If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
436         If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
437 
438         The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
439         greater than right, the SkIRect will be considered empty. Call sort() after this call
440         if that is not the desired behavior.
441 
442         @param dL  offset added to fLeft
443         @param dT  offset added to fTop
444         @param dR  offset added to fRight
445         @param dB  offset added to fBottom
446     */
adjustSkIRect447     void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
448         fLeft   = Sk32_sat_add(fLeft,   dL);
449         fTop    = Sk32_sat_add(fTop,    dT);
450         fRight  = Sk32_sat_add(fRight,  dR);
451         fBottom = Sk32_sat_add(fBottom, dB);
452     }
453 
454     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
455         Returns false if SkIRect is empty.
456 
457         Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
458         returns true if constructed area is completely enclosed by SkIRect area.
459 
460         @param x  test SkIPoint x-coordinate
461         @param y  test SkIPoint y-coordinate
462         @return   true if (x, y) is inside SkIRect
463     */
containsSkIRect464     bool contains(int32_t x, int32_t y) const {
465         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
466     }
467 
468     /** Returns true if SkIRect contains r.
469      Returns false if SkIRect is empty or r is empty.
470 
471      SkIRect contains r when SkIRect area completely includes r area.
472 
473      @param r  SkIRect contained
474      @return   true if all sides of SkIRect are outside r
475      */
containsSkIRect476     bool contains(const SkIRect& r) const {
477         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
478                 fLeft <= r.fLeft && fTop <= r.fTop &&
479                 fRight >= r.fRight && fBottom >= r.fBottom;
480     }
481 
482     /** Returns true if SkIRect contains r.
483         Returns false if SkIRect is empty or r is empty.
484 
485         SkIRect contains r when SkIRect area completely includes r area.
486 
487         @param r  SkRect contained
488         @return   true if all sides of SkIRect are outside r
489     */
490     inline bool contains(const SkRect& r) const;
491 
492     /** Returns true if SkIRect contains construction.
493         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
494 
495         Return is undefined if SkIRect is empty or construction is empty.
496 
497         @param r  SkIRect contained
498         @return   true if all sides of SkIRect are outside r
499     */
containsNoEmptyCheckSkIRect500     bool containsNoEmptyCheck(const SkIRect& r) const {
501         SkASSERT(fLeft < fRight && fTop < fBottom);
502         SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
503         return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
504     }
505 
506     /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
507         Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
508 
509         Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
510 
511         @param r  limit of result
512         @return   true if r and SkIRect have area in common
513     */
intersectSkIRect514     bool intersect(const SkIRect& r) {
515         return this->intersect(*this, r);
516     }
517 
518     /** Returns true if a intersects b, and sets SkIRect to intersection.
519         Returns false if a does not intersect b, and leaves SkIRect unchanged.
520 
521         Returns false if either a or b is empty, leaving SkIRect unchanged.
522 
523         @param a  SkIRect to intersect
524         @param b  SkIRect to intersect
525         @return   true if a and b have area in common
526     */
527     [[nodiscard]] bool intersect(const SkIRect& a, const SkIRect& b);
528 
529     /** Returns true if a intersects b.
530         Returns false if either a or b is empty, or do not intersect.
531 
532         @param a  SkIRect to intersect
533         @param b  SkIRect to intersect
534         @return   true if a and b have area in common
535     */
IntersectsSkIRect536     static bool Intersects(const SkIRect& a, const SkIRect& b) {
537         return SkIRect{}.intersect(a, b);
538     }
539 
540     /** Sets SkIRect to the union of itself and r.
541 
542      Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
543 
544      @param r  expansion SkIRect
545 
546         example: https://fiddle.skia.org/c/@IRect_join_2
547      */
548     void join(const SkIRect& r);
549 
550     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
551         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
552         and width() and height() will be zero or positive.
553     */
sortSkIRect554     void sort() {
555         using std::swap;
556         if (fLeft > fRight) {
557             swap(fLeft, fRight);
558         }
559         if (fTop > fBottom) {
560             swap(fTop, fBottom);
561         }
562     }
563 
564     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
565         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
566         and width() and height() will be zero or positive.
567 
568         @return  sorted SkIRect
569     */
makeSortedSkIRect570     SkIRect makeSorted() const {
571         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
572                         std::max(fLeft, fRight), std::max(fTop, fBottom));
573     }
574 };
575 
576 /** \struct SkRect
577     SkRect holds four float coordinates describing the upper and
578     lower bounds of a rectangle. SkRect may be created from outer bounds or
579     from position, width, and height. SkRect describes an area; if its right
580     is less than or equal to its left, or if its bottom is less than or equal to
581     its top, it is considered empty.
582 */
583 struct SK_API SkRect {
584     float fLeft   = 0; //!< smaller x-axis bounds
585     float fTop    = 0; //!< smaller y-axis bounds
586     float fRight  = 0; //!< larger x-axis bounds
587     float fBottom = 0; //!< larger y-axis bounds
588 
589     /** Returns constructed SkRect set to (0, 0, 0, 0).
590         Many other rectangles are empty; if left is equal to or greater than right,
591         or if top is equal to or greater than bottom. Setting all members to zero
592         is a convenience, but does not designate a special empty rectangle.
593 
594         @return  bounds (0, 0, 0, 0)
595     */
MakeEmptySkRect596     [[nodiscard]] static constexpr SkRect MakeEmpty() {
597         return SkRect{0, 0, 0, 0};
598     }
599 
600     /** Returns constructed SkRect set to float values (0, 0, w, h). Does not
601         validate input; w or h may be negative.
602 
603         Passing integer values may generate a compiler warning since SkRect cannot
604         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
605 
606         @param w  float width of constructed SkRect
607         @param h  float height of constructed SkRect
608         @return   bounds (0, 0, w, h)
609     */
MakeWHSkRect610     [[nodiscard]] static constexpr SkRect MakeWH(float w, float h) {
611         return SkRect{0, 0, w, h};
612     }
613 
614     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
615         input; w or h may be negative.
616 
617         Use to avoid a compiler warning that input may lose precision when stored.
618         Use SkIRect for an exact integer rectangle.
619 
620         @param w  integer width of constructed SkRect
621         @param h  integer height of constructed SkRect
622         @return   bounds (0, 0, w, h)
623     */
MakeIWHSkRect624     [[nodiscard]] static SkRect MakeIWH(int w, int h) {
625         return {0, 0, static_cast<float>(w), static_cast<float>(h)};
626     }
627 
628     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
629         validate input; size.width() or size.height() may be negative.
630 
631         @param size  float values for SkRect width and height
632         @return      bounds (0, 0, size.width(), size.height())
633     */
MakeSizeSkRect634     [[nodiscard]] static constexpr SkRect MakeSize(const SkSize& size) {
635         return SkRect{0, 0, size.fWidth, size.fHeight};
636     }
637 
638     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
639         result in fLeft greater than fRight, or fTop greater than fBottom.
640 
641         @param l  float stored in fLeft
642         @param t  float stored in fTop
643         @param r  float stored in fRight
644         @param b  float stored in fBottom
645         @return   bounds (l, t, r, b)
646     */
MakeLTRBSkRect647     [[nodiscard]] static constexpr SkRect MakeLTRB(float l, float t, float r, float b) {
648         return SkRect {l, t, r, b};
649     }
650 
651     /** Returns constructed SkRect set to (x, y, x + w, y + h).
652         Does not validate input; w or h may be negative.
653 
654         @param x  stored in fLeft
655         @param y  stored in fTop
656         @param w  added to x and stored in fRight
657         @param h  added to y and stored in fBottom
658         @return   bounds at (x, y) with width w and height h
659     */
MakeXYWHSkRect660     [[nodiscard]] static constexpr SkRect MakeXYWH(float x, float y, float w, float h) {
661         return SkRect {x, y, x + w, y + h};
662     }
663 
664     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
665         Does not validate input; size.width() or size.height() may be negative.
666 
667         @param size  integer values for SkRect width and height
668         @return      bounds (0, 0, size.width(), size.height())
669     */
MakeSkRect670     static SkRect Make(const SkISize& size) {
671         return MakeIWH(size.width(), size.height());
672     }
673 
674     /** Returns constructed SkIRect set to irect, promoting integers to float.
675         Does not validate input; fLeft may be greater than fRight, fTop may be greater
676         than fBottom.
677 
678         @param irect  integer unsorted bounds
679         @return       irect members converted to float
680     */
MakeSkRect681     [[nodiscard]] static SkRect Make(const SkIRect& irect) {
682         return {
683             static_cast<float>(irect.fLeft), static_cast<float>(irect.fTop),
684             static_cast<float>(irect.fRight), static_cast<float>(irect.fBottom)
685         };
686     }
687 
688     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
689         to or greater than fBottom. Call sort() to reverse rectangles with negative
690         width() or height().
691 
692         @return  true if width() or height() are zero or negative
693     */
isEmptySkRect694     bool isEmpty() const {
695         // We write it as the NOT of a non-empty rect, so we will return true if any values
696         // are NaN.
697         return !(fLeft < fRight && fTop < fBottom);
698     }
699 
700     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
701         to or less than fBottom. Call sort() to reverse rectangles with negative
702         width() or height().
703 
704         @return  true if width() or height() are zero or positive
705     */
isSortedSkRect706     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
707 
708     /** Returns true if all values in the rectangle are finite.
709 
710         @return  true if no member is infinite or NaN
711     */
isFiniteSkRect712     bool isFinite() const {
713         return SkIsFinite(fLeft, fTop, fRight, fBottom);
714     }
715 
716     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
717         Call sort() to reverse fLeft and fRight if needed.
718 
719         @return  fLeft
720     */
xSkRect721     constexpr float x() const { return fLeft; }
722 
723     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
724         and sort() to reverse fTop and fBottom if needed.
725 
726         @return  fTop
727     */
ySkRect728     constexpr float y() const { return fTop; }
729 
730     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
731         Call sort() to reverse fLeft and fRight if needed.
732 
733         @return  fLeft
734     */
leftSkRect735     constexpr float left() const { return fLeft; }
736 
737     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
738         and sort() to reverse fTop and fBottom if needed.
739 
740         @return  fTop
741     */
topSkRect742     constexpr float top() const { return fTop; }
743 
744     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
745         Call sort() to reverse fLeft and fRight if needed.
746 
747         @return  fRight
748     */
rightSkRect749     constexpr float right() const { return fRight; }
750 
751     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
752         and sort() to reverse fTop and fBottom if needed.
753 
754         @return  fBottom
755     */
bottomSkRect756     constexpr float bottom() const { return fBottom; }
757 
758     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
759         result fits in 32-bit float; result may be negative or infinity.
760 
761         @return  fRight minus fLeft
762     */
widthSkRect763     constexpr float width() const { return fRight - fLeft; }
764 
765     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
766         result fits in 32-bit float; result may be negative or infinity.
767 
768         @return  fBottom minus fTop
769     */
heightSkRect770     constexpr float height() const { return fBottom - fTop; }
771 
772     /** Returns average of left edge and right edge. Result does not change if SkRect
773         is sorted. Result may overflow to infinity if SkRect is far from the origin.
774 
775         @return  midpoint on x-axis
776     */
centerXSkRect777     constexpr float centerX() const {
778         return sk_float_midpoint(fLeft, fRight);
779     }
780 
781     /** Returns average of top edge and bottom edge. Result does not change if SkRect
782         is sorted.
783 
784         @return  midpoint on y-axis
785     */
centerYSkRect786     constexpr float centerY() const {
787         return sk_float_midpoint(fTop, fBottom);
788     }
789 
790     /** Returns the point this->centerX(), this->centerY().
791         @return  rectangle center
792      */
centerSkRect793     constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; }
794 
795     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
796         equal to the corresponding members in b.
797 
798         a and b are not equal if either contain NaN. a and b are equal if members
799         contain zeroes with different signs.
800 
801         @param a  SkRect to compare
802         @param b  SkRect to compare
803         @return   true if members are equal
804     */
805     friend bool operator==(const SkRect& a, const SkRect& b) {
806         return a.fLeft == b.fLeft &&
807                a.fTop == b.fTop &&
808                a.fRight == b.fRight &&
809                a.fBottom == b.fBottom;
810     }
811 
812     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
813         equal the corresponding members in b.
814 
815         a and b are not equal if either contain NaN. a and b are equal if members
816         contain zeroes with different signs.
817 
818         @param a  SkRect to compare
819         @param b  SkRect to compare
820         @return   true if members are not equal
821     */
822     friend bool operator!=(const SkRect& a, const SkRect& b) {
823         return !(a == b);
824     }
825 
826     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
827         bottom-right, bottom-left.
828 
829         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
830 
831         @param quad  storage for corners of SkRect
832 
833         example: https://fiddle.skia.org/c/@Rect_toQuad
834     */
835     void toQuad(SkPoint quad[4]) const;
836 
837     /** Sets SkRect to (0, 0, 0, 0).
838 
839         Many other rectangles are empty; if left is equal to or greater than right,
840         or if top is equal to or greater than bottom. Setting all members to zero
841         is a convenience, but does not designate a special empty rectangle.
842     */
setEmptySkRect843     void setEmpty() { *this = MakeEmpty(); }
844 
845     /** Sets SkRect to src, promoting src members from integer to float.
846         Very large values in src may lose precision.
847 
848         @param src  integer SkRect
849     */
setSkRect850     void set(const SkIRect& src) {
851         fLeft   = src.fLeft;
852         fTop    = src.fTop;
853         fRight  = src.fRight;
854         fBottom = src.fBottom;
855     }
856 
857     /** Sets SkRect to (left, top, right, bottom).
858         left and right are not sorted; left is not necessarily less than right.
859         top and bottom are not sorted; top is not necessarily less than bottom.
860 
861         @param left    stored in fLeft
862         @param top     stored in fTop
863         @param right   stored in fRight
864         @param bottom  stored in fBottom
865     */
setLTRBSkRect866     void setLTRB(float left, float top, float right, float bottom) {
867         fLeft   = left;
868         fTop    = top;
869         fRight  = right;
870         fBottom = bottom;
871     }
872 
873     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
874         or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
875 
876         Result is either empty or sorted: fLeft is less than or equal to fRight, and
877         fTop is less than or equal to fBottom.
878 
879         @param pts    SkPoint array
880         @param count  entries in array
881     */
setBoundsSkRect882     void setBounds(const SkPoint pts[], int count) {
883         (void)this->setBoundsCheck(pts, count);
884     }
885 
886     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
887         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
888         sets SkRect to (0, 0, 0, 0).
889 
890         Result is either empty or sorted: fLeft is less than or equal to fRight, and
891         fTop is less than or equal to fBottom.
892 
893         @param pts    SkPoint array
894         @param count  entries in array
895         @return       true if all SkPoint values are finite
896 
897         example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
898     */
899     bool setBoundsCheck(const SkPoint pts[], int count);
900 
901     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
902         contains infinity or NaN, all SkRect dimensions are set to NaN.
903 
904         @param pts    SkPoint array
905         @param count  entries in array
906 
907         example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
908     */
909     void setBoundsNoCheck(const SkPoint pts[], int count);
910 
911     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
912         sorted and may be empty. Does not check to see if values are finite.
913 
914         @param p0  corner to include
915         @param p1  corner to include
916     */
setSkRect917     void set(const SkPoint& p0, const SkPoint& p1) {
918         fLeft =   std::min(p0.fX, p1.fX);
919         fRight =  std::max(p0.fX, p1.fX);
920         fTop =    std::min(p0.fY, p1.fY);
921         fBottom = std::max(p0.fY, p1.fY);
922     }
923 
924     /** Sets SkRect to (x, y, x + width, y + height).
925         Does not validate input; width or height may be negative.
926 
927         @param x       stored in fLeft
928         @param y       stored in fTop
929         @param width   added to x and stored in fRight
930         @param height  added to y and stored in fBottom
931     */
setXYWHSkRect932     void setXYWH(float x, float y, float width, float height) {
933         fLeft = x;
934         fTop = y;
935         fRight = x + width;
936         fBottom = y + height;
937     }
938 
939     /** Sets SkRect to (0, 0, width, height). Does not validate input;
940         width or height may be negative.
941 
942         @param width   stored in fRight
943         @param height  stored in fBottom
944     */
setWHSkRect945     void setWH(float width, float height) {
946         fLeft = 0;
947         fTop = 0;
948         fRight = width;
949         fBottom = height;
950     }
setIWHSkRect951     void setIWH(int32_t width, int32_t height) {
952         this->setWH(width, height);
953     }
954 
955     /** Returns SkRect offset by (dx, dy).
956 
957         If dx is negative, SkRect returned is moved to the left.
958         If dx is positive, SkRect returned is moved to the right.
959         If dy is negative, SkRect returned is moved upward.
960         If dy is positive, SkRect returned is moved downward.
961 
962         @param dx  added to fLeft and fRight
963         @param dy  added to fTop and fBottom
964         @return    SkRect offset on axes, with original width and height
965     */
makeOffsetSkRect966     constexpr SkRect makeOffset(float dx, float dy) const {
967         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
968     }
969 
970     /** Returns SkRect offset by v.
971 
972         @param v  added to rect
973         @return    SkRect offset on axes, with original width and height
974     */
makeOffsetSkRect975     constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
976 
977     /** Returns SkRect, inset by (dx, dy).
978 
979         If dx is negative, SkRect returned is wider.
980         If dx is positive, SkRect returned is narrower.
981         If dy is negative, SkRect returned is taller.
982         If dy is positive, SkRect returned is shorter.
983 
984         @param dx  added to fLeft and subtracted from fRight
985         @param dy  added to fTop and subtracted from fBottom
986         @return    SkRect inset symmetrically left and right, top and bottom
987     */
makeInsetSkRect988     SkRect makeInset(float dx, float dy) const {
989         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
990     }
991 
992     /** Returns SkRect, outset by (dx, dy).
993 
994         If dx is negative, SkRect returned is narrower.
995         If dx is positive, SkRect returned is wider.
996         If dy is negative, SkRect returned is shorter.
997         If dy is positive, SkRect returned is taller.
998 
999         @param dx  subtracted to fLeft and added from fRight
1000         @param dy  subtracted to fTop and added from fBottom
1001         @return    SkRect outset symmetrically left and right, top and bottom
1002     */
makeOutsetSkRect1003     SkRect makeOutset(float dx, float dy) const {
1004         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1005     }
1006 
1007     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1008 
1009         If dx is negative, moves SkRect to the left.
1010         If dx is positive, moves SkRect to the right.
1011         If dy is negative, moves SkRect upward.
1012         If dy is positive, moves SkRect downward.
1013 
1014         @param dx  offset added to fLeft and fRight
1015         @param dy  offset added to fTop and fBottom
1016     */
offsetSkRect1017     void offset(float dx, float dy) {
1018         fLeft   += dx;
1019         fTop    += dy;
1020         fRight  += dx;
1021         fBottom += dy;
1022     }
1023 
1024     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1025         fTop, fBottom.
1026 
1027         If delta.fX is negative, moves SkRect to the left.
1028         If delta.fX is positive, moves SkRect to the right.
1029         If delta.fY is negative, moves SkRect upward.
1030         If delta.fY is positive, moves SkRect downward.
1031 
1032         @param delta  added to SkRect
1033     */
offsetSkRect1034     void offset(const SkPoint& delta) {
1035         this->offset(delta.fX, delta.fY);
1036     }
1037 
1038     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1039         are unchanged.
1040 
1041         @param newX  stored in fLeft, preserving width()
1042         @param newY  stored in fTop, preserving height()
1043     */
offsetToSkRect1044     void offsetTo(float newX, float newY) {
1045         fRight += newX - fLeft;
1046         fBottom += newY - fTop;
1047         fLeft = newX;
1048         fTop = newY;
1049     }
1050 
1051     /** Insets SkRect by (dx, dy).
1052 
1053         If dx is positive, makes SkRect narrower.
1054         If dx is negative, makes SkRect wider.
1055         If dy is positive, makes SkRect shorter.
1056         If dy is negative, makes SkRect taller.
1057 
1058         @param dx  added to fLeft and subtracted from fRight
1059         @param dy  added to fTop and subtracted from fBottom
1060     */
insetSkRect1061     void inset(float dx, float dy)  {
1062         fLeft   += dx;
1063         fTop    += dy;
1064         fRight  -= dx;
1065         fBottom -= dy;
1066     }
1067 
1068     /** Outsets SkRect by (dx, dy).
1069 
1070         If dx is positive, makes SkRect wider.
1071         If dx is negative, makes SkRect narrower.
1072         If dy is positive, makes SkRect taller.
1073         If dy is negative, makes SkRect shorter.
1074 
1075         @param dx  subtracted to fLeft and added from fRight
1076         @param dy  subtracted to fTop and added from fBottom
1077     */
outsetSkRect1078     void outset(float dx, float dy)  { this->inset(-dx, -dy); }
1079 
1080     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1081         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1082 
1083         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1084 
1085         @param r  limit of result
1086         @return   true if r and SkRect have area in common
1087 
1088         example: https://fiddle.skia.org/c/@Rect_intersect
1089     */
1090     bool intersect(const SkRect& r);
1091 
1092     /** Returns true if a intersects b, and sets SkRect to intersection.
1093         Returns false if a does not intersect b, and leaves SkRect unchanged.
1094 
1095         Returns false if either a or b is empty, leaving SkRect unchanged.
1096 
1097         @param a  SkRect to intersect
1098         @param b  SkRect to intersect
1099         @return   true if a and b have area in common
1100     */
1101     [[nodiscard]] bool intersect(const SkRect& a, const SkRect& b);
1102 
1103 
1104 private:
IntersectsSkRect1105     static bool Intersects(float al, float at, float ar, float ab,
1106                            float bl, float bt, float br, float bb) {
1107         float L = std::max(al, bl);
1108         float R = std::min(ar, br);
1109         float T = std::max(at, bt);
1110         float B = std::min(ab, bb);
1111         return L < R && T < B;
1112     }
1113 
1114 public:
1115 
1116     /** Returns true if SkRect intersects r.
1117      Returns false if either r or SkRect is empty, or do not intersect.
1118 
1119      @param r  SkRect to intersect
1120      @return   true if r and SkRect have area in common
1121      */
intersectsSkRect1122     bool intersects(const SkRect& r) const {
1123         return Intersects(fLeft, fTop, fRight, fBottom,
1124                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1125     }
1126 
1127     /** Returns true if a intersects b.
1128         Returns false if either a or b is empty, or do not intersect.
1129 
1130         @param a  SkRect to intersect
1131         @param b  SkRect to intersect
1132         @return   true if a and b have area in common
1133     */
IntersectsSkRect1134     static bool Intersects(const SkRect& a, const SkRect& b) {
1135         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1136                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1137     }
1138 
1139     /** Sets SkRect to the union of itself and r.
1140 
1141         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1142         SkRect to r.
1143 
1144         @param r  expansion SkRect
1145 
1146         example: https://fiddle.skia.org/c/@Rect_join_2
1147     */
1148     void join(const SkRect& r);
1149 
1150     /** Sets SkRect to the union of itself and r.
1151 
1152         Asserts if r is empty and SK_DEBUG is defined.
1153         If SkRect is empty, sets SkRect to r.
1154 
1155         May produce incorrect results if r is empty.
1156 
1157         @param r  expansion SkRect
1158     */
joinNonEmptyArgSkRect1159     void joinNonEmptyArg(const SkRect& r) {
1160         SkASSERT(!r.isEmpty());
1161         // if we are empty, just assign
1162         if (fLeft >= fRight || fTop >= fBottom) {
1163             *this = r;
1164         } else {
1165             this->joinPossiblyEmptyRect(r);
1166         }
1167     }
1168 
1169     /** Sets SkRect to the union of itself and the construction.
1170 
1171         May produce incorrect results if SkRect or r is empty.
1172 
1173         @param r  expansion SkRect
1174     */
joinPossiblyEmptyRectSkRect1175     void joinPossiblyEmptyRect(const SkRect& r) {
1176         fLeft   = std::min(fLeft, r.left());
1177         fTop    = std::min(fTop, r.top());
1178         fRight  = std::max(fRight, r.right());
1179         fBottom = std::max(fBottom, r.bottom());
1180     }
1181 
1182     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1183         Returns false if SkRect is empty.
1184 
1185         @param x  test SkPoint x-coordinate
1186         @param y  test SkPoint y-coordinate
1187         @return   true if (x, y) is inside SkRect
1188     */
containsSkRect1189     bool contains(float x, float y) const {
1190         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1191     }
1192 
1193     /** Returns true if SkRect contains r.
1194         Returns false if SkRect is empty or r is empty.
1195 
1196         SkRect contains r when SkRect area completely includes r area.
1197 
1198         @param r  SkRect contained
1199         @return   true if all sides of SkRect are outside r
1200     */
containsSkRect1201     bool contains(const SkRect& r) const {
1202         // todo: can we eliminate the this->isEmpty check?
1203         return  !r.isEmpty() && !this->isEmpty() &&
1204                 fLeft <= r.fLeft && fTop <= r.fTop &&
1205                 fRight >= r.fRight && fBottom >= r.fBottom;
1206     }
1207 
1208     /** Returns true if SkRect contains r.
1209         Returns false if SkRect is empty or r is empty.
1210 
1211         SkRect contains r when SkRect area completely includes r area.
1212 
1213         @param r  SkIRect contained
1214         @return   true if all sides of SkRect are outside r
1215     */
containsSkRect1216     bool contains(const SkIRect& r) const {
1217         // todo: can we eliminate the this->isEmpty check?
1218         return  !r.isEmpty() && !this->isEmpty() &&
1219                 fLeft <= r.fLeft && fTop <= r.fTop &&
1220                 fRight >= r.fRight && fBottom >= r.fBottom;
1221     }
1222 
1223     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1224         members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop),
1225                         sk_float_round2int(fRight), sk_float_round2int(fBottom)).
1226 
1227         @param dst  storage for SkIRect
1228     */
roundSkRect1229     void round(SkIRect* dst) const {
1230         SkASSERT(dst);
1231         dst->setLTRB(sk_float_round2int(fLeft),  sk_float_round2int(fTop),
1232                      sk_float_round2int(fRight), sk_float_round2int(fBottom));
1233     }
1234 
1235     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1236         up fRight and fBottom, using
1237         (sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1238          sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)).
1239 
1240         @param dst  storage for SkIRect
1241     */
roundOutSkRect1242     void roundOut(SkIRect* dst) const {
1243         SkASSERT(dst);
1244         dst->setLTRB(sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1245                      sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom));
1246     }
1247 
1248     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1249         up fRight and fBottom, using
1250         (std::floor(fLeft), std::floor(fTop),
1251          std::ceil(fRight), std::ceil(fBottom)).
1252 
1253         @param dst  storage for SkRect
1254     */
roundOutSkRect1255     void roundOut(SkRect* dst) const {
1256         dst->setLTRB(std::floor(fLeft), std::floor(fTop),
1257                      std::ceil(fRight), std::ceil(fBottom));
1258     }
1259 
1260     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1261         of fRight and fBottom, using
1262         (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1263          sk_float_floor2int(fRight), sk_float_floor2int(fBottom)).
1264 
1265         @param dst  storage for SkIRect
1266     */
roundInSkRect1267     void roundIn(SkIRect* dst) const {
1268         SkASSERT(dst);
1269         dst->setLTRB(sk_float_ceil2int(fLeft),   sk_float_ceil2int(fTop),
1270                      sk_float_floor2int(fRight), sk_float_floor2int(fBottom));
1271     }
1272 
1273     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1274         members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop),
1275                         sk_float_round2int(fRight), sk_float_round2int(fBottom)).
1276 
1277         @return  rounded SkIRect
1278     */
roundSkRect1279     SkIRect round() const {
1280         SkIRect ir;
1281         this->round(&ir);
1282         return ir;
1283     }
1284 
1285     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1286         up fRight and fBottom, using
1287         (sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1288          sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)).
1289 
1290         @return  rounded SkIRect
1291     */
roundOutSkRect1292     SkIRect roundOut() const {
1293         SkIRect ir;
1294         this->roundOut(&ir);
1295         return ir;
1296     }
1297     /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1298         of fRight and fBottom, using
1299         (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1300          sk_float_floor2int(fRight), sk_float_floor2int(fBottom)).
1301 
1302         @return  rounded SkIRect
1303     */
roundInSkRect1304     SkIRect roundIn() const {
1305         SkIRect ir;
1306         this->roundIn(&ir);
1307         return ir;
1308     }
1309 
1310     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1311         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1312         and width() and height() will be zero or positive.
1313     */
sortSkRect1314     void sort() {
1315         using std::swap;
1316         if (fLeft > fRight) {
1317             swap(fLeft, fRight);
1318         }
1319 
1320         if (fTop > fBottom) {
1321             swap(fTop, fBottom);
1322         }
1323     }
1324 
1325     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1326         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1327         and width() and height() will be zero or positive.
1328 
1329         @return  sorted SkRect
1330     */
makeSortedSkRect1331     SkRect makeSorted() const {
1332         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1333                         std::max(fLeft, fRight), std::max(fTop, fBottom));
1334     }
1335 
1336     /** Returns pointer to first float in SkRect, to treat it as an array with four
1337         entries.
1338 
1339         @return  pointer to fLeft
1340     */
asScalarsSkRect1341     const float* asScalars() const { return &fLeft; }
1342 
1343     /** Writes text representation of SkRect to standard output. Set asHex to true to
1344         generate exact binary representations of floating point numbers.
1345 
1346         @param asHex  true if SkScalar values are written as hexadecimal
1347 
1348         example: https://fiddle.skia.org/c/@Rect_dump
1349     */
1350     void dump(bool asHex) const;
1351     SkString dumpToString(bool asHex) const;
1352 
1353     /** Writes text representation of SkRect to standard output. The representation may be
1354         directly compiled as C++ code. Floating point values are written
1355         with limited precision; it may not be possible to reconstruct original SkRect
1356         from output.
1357     */
dumpSkRect1358     void dump() const { this->dump(false); }
1359 
1360     /** Writes text representation of SkRect to standard output. The representation may be
1361         directly compiled as C++ code. Floating point values are written
1362         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1363         original SkRect.
1364 
1365         Use instead of dump() when submitting
1366     */
dumpHexSkRect1367     void dumpHex() const { this->dump(true); }
1368 };
1369 
contains(const SkRect & r)1370 inline bool SkIRect::contains(const SkRect& r) const {
1371     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
1372             fLeft <= r.fLeft && fTop <= r.fTop &&
1373             fRight >= r.fRight && fBottom >= r.fBottom;
1374 }
1375 
1376 #endif
1377