• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 /** \struct SkIRect
26     SkIRect holds four 32-bit integer coordinates describing the upper and
27     lower bounds of a rectangle. SkIRect may be created from outer bounds or
28     from position, width, and height. SkIRect describes an area; if its right
29     is less than or equal to its left, or if its bottom is less than or equal to
30     its top, it is considered empty.
31 */
32 struct SK_API SkIRect {
33     int32_t fLeft   = 0; //!< smaller x-axis bounds
34     int32_t fTop    = 0; //!< smaller y-axis bounds
35     int32_t fRight  = 0; //!< larger x-axis bounds
36     int32_t fBottom = 0; //!< larger y-axis bounds
37 
38     /** Returns constructed SkIRect set to (0, 0, 0, 0).
39         Many other rectangles are empty; if left is equal to or greater than right,
40         or if top is equal to or greater than bottom. Setting all members to zero
41         is a convenience, but does not designate a special empty rectangle.
42 
43         @return  bounds (0, 0, 0, 0)
44     */
MakeEmptySkIRect45     [[nodiscard]] static constexpr SkIRect MakeEmpty() {
46         return SkIRect{0, 0, 0, 0};
47     }
48 
49     /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
50         may be negative.
51 
52         @param w  width of constructed SkIRect
53         @param h  height of constructed SkIRect
54         @return   bounds (0, 0, w, h)
55     */
MakeWHSkIRect56     [[nodiscard]] static constexpr SkIRect MakeWH(int32_t w, int32_t h) {
57         return SkIRect{0, 0, w, h};
58     }
59 
60     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
61         Does not validate input; size.width() or size.height() may be negative.
62 
63         @param size  values for SkIRect width and height
64         @return      bounds (0, 0, size.width(), size.height())
65     */
MakeSizeSkIRect66     [[nodiscard]] static constexpr SkIRect MakeSize(const SkISize& size) {
67         return SkIRect{0, 0, size.fWidth, size.fHeight};
68     }
69 
70     /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
71         pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
72         negative.
73 
74         @param pt    values for SkIRect fLeft and fTop
75         @param size  values for SkIRect width and height
76         @return      bounds at pt with width and height of size
77     */
MakePtSizeSkIRect78     [[nodiscard]] static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size) {
79         return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
80     }
81 
82     /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
83         result in fLeft greater than fRight, or fTop greater than fBottom.
84 
85         @param l  integer stored in fLeft
86         @param t  integer stored in fTop
87         @param r  integer stored in fRight
88         @param b  integer stored in fBottom
89         @return   bounds (l, t, r, b)
90     */
MakeLTRBSkIRect91     [[nodiscard]] static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
92         return SkIRect{l, t, r, b};
93     }
94 
95     /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
96         Does not validate input; w or h may be negative.
97 
98         @param x  stored in fLeft
99         @param y  stored in fTop
100         @param w  added to x and stored in fRight
101         @param h  added to y and stored in fBottom
102         @return   bounds at (x, y) with width w and height h
103     */
MakeXYWHSkIRect104     [[nodiscard]] static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
105         return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
106     }
107 
108     /** Returns left edge of SkIRect, if sorted.
109         Call sort() to reverse fLeft and fRight if needed.
110 
111         @return  fLeft
112     */
leftSkIRect113     constexpr int32_t left() const { return fLeft; }
114 
115     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
116         and sort() to reverse fTop and fBottom if needed.
117 
118         @return  fTop
119     */
topSkIRect120     constexpr int32_t top() const { return fTop; }
121 
122     /** Returns right edge of SkIRect, if sorted.
123         Call sort() to reverse fLeft and fRight if needed.
124 
125         @return  fRight
126     */
rightSkIRect127     constexpr int32_t right() const { return fRight; }
128 
129     /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
130         and sort() to reverse fTop and fBottom if needed.
131 
132         @return  fBottom
133     */
bottomSkIRect134     constexpr int32_t bottom() const { return fBottom; }
135 
136     /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
137         and sort() to reverse fLeft and fRight if needed.
138 
139         @return  fLeft
140     */
xSkIRect141     constexpr int32_t x() const { return fLeft; }
142 
143     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
144         and sort() to reverse fTop and fBottom if needed.
145 
146         @return  fTop
147     */
ySkIRect148     constexpr int32_t y() const { return fTop; }
149 
150     // Experimental
topLeftSkIRect151     constexpr SkIPoint topLeft() const { return {fLeft, fTop}; }
152 
153     /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
154         result fits in 32-bit signed integer; result may be negative.
155 
156         @return  fRight minus fLeft
157     */
widthSkIRect158     constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
159 
160     /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
161         result fits in 32-bit signed integer; result may be negative.
162 
163         @return  fBottom minus fTop
164     */
heightSkIRect165     constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
166 
167     /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
168         or if result fits in 32-bit signed integer; result may be negative.
169 
170         @return  SkISize (width, height)
171     */
sizeSkIRect172     constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); }
173 
174     /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
175         result may be negative. This is safer than calling width() since width() might
176         overflow in its calculation.
177 
178         @return  fRight minus fLeft cast to int64_t
179     */
width64SkIRect180     constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
181 
182     /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
183         result may be negative. This is safer than calling height() since height() might
184         overflow in its calculation.
185 
186         @return  fBottom minus fTop cast to int64_t
187     */
height64SkIRect188     constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
189 
190     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
191         to or greater than fBottom. Call sort() to reverse rectangles with negative
192         width64() or height64().
193 
194         @return  true if width64() or height64() are zero or negative
195     */
isEmpty64SkIRect196     bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
197 
198     /** Returns true if width() or height() are zero or negative.
199 
200         @return  true if width() or height() are zero or negative
201     */
isEmptySkIRect202     bool isEmpty() const {
203         int64_t w = this->width64();
204         int64_t h = this->height64();
205         if (w <= 0 || h <= 0) {
206             return true;
207         }
208         // Return true if either exceeds int32_t
209         return !SkTFitsIn<int32_t>(w | h);
210     }
211 
212     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
213         identical to corresponding members in b.
214 
215         @param a  SkIRect to compare
216         @param b  SkIRect to compare
217         @return   true if members are equal
218     */
219     friend bool operator==(const SkIRect& a, const SkIRect& b) {
220         return a.fLeft == b.fLeft && a.fTop == b.fTop &&
221                a.fRight == b.fRight && a.fBottom == b.fBottom;
222     }
223 
224     /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
225         identical to the corresponding member in b.
226 
227         @param a  SkIRect to compare
228         @param b  SkIRect to compare
229         @return   true if members are not equal
230     */
231     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
232         return a.fLeft != b.fLeft || a.fTop != b.fTop ||
233                a.fRight != b.fRight || a.fBottom != b.fBottom;
234     }
235 
236     /** Sets SkIRect to (0, 0, 0, 0).
237 
238         Many other rectangles are empty; if left is equal to or greater than right,
239         or if top is equal to or greater than bottom. Setting all members to zero
240         is a convenience, but does not designate a special empty rectangle.
241     */
setEmptySkIRect242     void setEmpty() { memset(this, 0, sizeof(*this)); }
243 
244     /** Sets SkIRect to (left, top, right, bottom).
245         left and right are not sorted; left is not necessarily less than right.
246         top and bottom are not sorted; top is not necessarily less than bottom.
247 
248         @param left    stored in fLeft
249         @param top     stored in fTop
250         @param right   stored in fRight
251         @param bottom  stored in fBottom
252     */
setLTRBSkIRect253     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
254         fLeft   = left;
255         fTop    = top;
256         fRight  = right;
257         fBottom = bottom;
258     }
259 
260     /** Sets SkIRect to: (x, y, x + width, y + height).
261         Does not validate input; width or height may be negative.
262 
263         @param x       stored in fLeft
264         @param y       stored in fTop
265         @param width   added to x and stored in fRight
266         @param height  added to y and stored in fBottom
267     */
setXYWHSkIRect268     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
269         fLeft   = x;
270         fTop    = y;
271         fRight  = Sk32_sat_add(x, width);
272         fBottom = Sk32_sat_add(y, height);
273     }
274 
setWHSkIRect275     void setWH(int32_t width, int32_t height) {
276         fLeft   = 0;
277         fTop    = 0;
278         fRight  = width;
279         fBottom = height;
280     }
281 
setSizeSkIRect282     void setSize(SkISize size) {
283         fLeft = 0;
284         fTop = 0;
285         fRight = size.width();
286         fBottom = size.height();
287     }
288 
289     /** Returns SkIRect offset by (dx, dy).
290 
291         If dx is negative, SkIRect returned is moved to the left.
292         If dx is positive, SkIRect returned is moved to the right.
293         If dy is negative, SkIRect returned is moved upward.
294         If dy is positive, SkIRect returned is moved downward.
295 
296         @param dx  offset added to fLeft and fRight
297         @param dy  offset added to fTop and fBottom
298         @return    SkIRect offset by dx and dy, with original width and height
299     */
makeOffsetSkIRect300     constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
301         return {
302             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
303             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
304         };
305     }
306 
307     /** Returns SkIRect offset by (offset.x(), offset.y()).
308 
309         If offset.x() is negative, SkIRect returned is moved to the left.
310         If offset.x() is positive, SkIRect returned is moved to the right.
311         If offset.y() is negative, SkIRect returned is moved upward.
312         If offset.y() is positive, SkIRect returned is moved downward.
313 
314         @param offset  translation vector
315         @return    SkIRect translated by offset, with original width and height
316     */
makeOffsetSkIRect317     constexpr SkIRect makeOffset(SkIVector offset) const {
318         return this->makeOffset(offset.x(), offset.y());
319     }
320 
321     /** Returns SkIRect, inset by (dx, dy).
322 
323         If dx is negative, SkIRect returned is wider.
324         If dx is positive, SkIRect returned is narrower.
325         If dy is negative, SkIRect returned is taller.
326         If dy is positive, SkIRect returned is shorter.
327 
328         @param dx  offset added to fLeft and subtracted from fRight
329         @param dy  offset added to fTop and subtracted from fBottom
330         @return    SkIRect inset symmetrically left and right, top and bottom
331     */
makeInsetSkIRect332     SkIRect makeInset(int32_t dx, int32_t dy) const {
333         return {
334             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
335             Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
336         };
337     }
338 
339     /** Returns SkIRect, outset by (dx, dy).
340 
341         If dx is negative, SkIRect returned is narrower.
342         If dx is positive, SkIRect returned is wider.
343         If dy is negative, SkIRect returned is shorter.
344         If dy is positive, SkIRect returned is taller.
345 
346         @param dx  offset subtracted to fLeft and added from fRight
347         @param dy  offset subtracted to fTop and added from fBottom
348         @return    SkIRect outset symmetrically left and right, top and bottom
349     */
makeOutsetSkIRect350     SkIRect makeOutset(int32_t dx, int32_t dy) const {
351         return {
352             Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),
353             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
354         };
355     }
356 
357     /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
358 
359         If dx is negative, moves SkIRect returned to the left.
360         If dx is positive, moves SkIRect returned to the right.
361         If dy is negative, moves SkIRect returned upward.
362         If dy is positive, moves SkIRect returned downward.
363 
364         @param dx  offset added to fLeft and fRight
365         @param dy  offset added to fTop and fBottom
366     */
offsetSkIRect367     void offset(int32_t dx, int32_t dy) {
368         fLeft   = Sk32_sat_add(fLeft,   dx);
369         fTop    = Sk32_sat_add(fTop,    dy);
370         fRight  = Sk32_sat_add(fRight,  dx);
371         fBottom = Sk32_sat_add(fBottom, dy);
372     }
373 
374     /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
375         fTop, fBottom.
376 
377         If delta.fX is negative, moves SkIRect returned to the left.
378         If delta.fX is positive, moves SkIRect returned to the right.
379         If delta.fY is negative, moves SkIRect returned upward.
380         If delta.fY is positive, moves SkIRect returned downward.
381 
382         @param delta  offset added to SkIRect
383     */
offsetSkIRect384     void offset(const SkIPoint& delta) {
385         this->offset(delta.fX, delta.fY);
386     }
387 
388     /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
389         are unchanged.
390 
391         @param newX  stored in fLeft, preserving width()
392         @param newY  stored in fTop, preserving height()
393     */
offsetToSkIRect394     void offsetTo(int32_t newX, int32_t newY) {
395         fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
396         fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
397         fLeft   = newX;
398         fTop    = newY;
399     }
400 
401     /** Insets SkIRect by (dx,dy).
402 
403         If dx is positive, makes SkIRect narrower.
404         If dx is negative, makes SkIRect wider.
405         If dy is positive, makes SkIRect shorter.
406         If dy is negative, makes SkIRect taller.
407 
408         @param dx  offset added to fLeft and subtracted from fRight
409         @param dy  offset added to fTop and subtracted from fBottom
410     */
insetSkIRect411     void inset(int32_t dx, int32_t dy) {
412         fLeft   = Sk32_sat_add(fLeft,   dx);
413         fTop    = Sk32_sat_add(fTop,    dy);
414         fRight  = Sk32_sat_sub(fRight,  dx);
415         fBottom = Sk32_sat_sub(fBottom, dy);
416     }
417 
418     /** Outsets SkIRect by (dx, dy).
419 
420         If dx is positive, makes SkIRect wider.
421         If dx is negative, makes SkIRect narrower.
422         If dy is positive, makes SkIRect taller.
423         If dy is negative, makes SkIRect shorter.
424 
425         @param dx  subtracted to fLeft and added from fRight
426         @param dy  subtracted to fTop and added from fBottom
427     */
outsetSkIRect428     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
429 
430     /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
431 
432         If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
433         If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
434         If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
435         If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
436 
437         The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
438         greater than right, the SkIRect will be considered empty. Call sort() after this call
439         if that is not the desired behavior.
440 
441         @param dL  offset added to fLeft
442         @param dT  offset added to fTop
443         @param dR  offset added to fRight
444         @param dB  offset added to fBottom
445     */
adjustSkIRect446     void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
447         fLeft   = Sk32_sat_add(fLeft,   dL);
448         fTop    = Sk32_sat_add(fTop,    dT);
449         fRight  = Sk32_sat_add(fRight,  dR);
450         fBottom = Sk32_sat_add(fBottom, dB);
451     }
452 
453     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
454         Returns false if SkIRect is empty.
455 
456         Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
457         returns true if constructed area is completely enclosed by SkIRect area.
458 
459         @param x  test SkIPoint x-coordinate
460         @param y  test SkIPoint y-coordinate
461         @return   true if (x, y) is inside SkIRect
462     */
containsSkIRect463     bool contains(int32_t x, int32_t y) const {
464         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
465     }
466 
467     /** Returns true if SkIRect contains r.
468      Returns false if SkIRect is empty or r is empty.
469 
470      SkIRect contains r when SkIRect area completely includes r area.
471 
472      @param r  SkIRect contained
473      @return   true if all sides of SkIRect are outside r
474      */
containsSkIRect475     bool contains(const SkIRect& r) const {
476         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
477                 fLeft <= r.fLeft && fTop <= r.fTop &&
478                 fRight >= r.fRight && fBottom >= r.fBottom;
479     }
480 
481     /** Returns true if SkIRect contains r.
482         Returns false if SkIRect is empty or r is empty.
483 
484         SkIRect contains r when SkIRect area completely includes r area.
485 
486         @param r  SkRect contained
487         @return   true if all sides of SkIRect are outside r
488     */
489     inline bool contains(const SkRect& r) const;
490 
491     /** Returns true if SkIRect contains construction.
492         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
493 
494         Return is undefined if SkIRect is empty or construction is empty.
495 
496         @param r  SkIRect contained
497         @return   true if all sides of SkIRect are outside r
498     */
containsNoEmptyCheckSkIRect499     bool containsNoEmptyCheck(const SkIRect& r) const {
500         SkASSERT(fLeft < fRight && fTop < fBottom);
501         SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
502         return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
503     }
504 
505     /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
506         Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
507 
508         Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
509 
510         @param r  limit of result
511         @return   true if r and SkIRect have area in common
512     */
intersectSkIRect513     bool intersect(const SkIRect& r) {
514         return this->intersect(*this, r);
515     }
516 
517     /** Returns true if a intersects b, and sets SkIRect to intersection.
518         Returns false if a does not intersect b, and leaves SkIRect unchanged.
519 
520         Returns false if either a or b is empty, leaving SkIRect unchanged.
521 
522         @param a  SkIRect to intersect
523         @param b  SkIRect to intersect
524         @return   true if a and b have area in common
525     */
526     [[nodiscard]] bool intersect(const SkIRect& a, const SkIRect& b);
527 
528     /** Returns true if a intersects b.
529         Returns false if either a or b is empty, or do not intersect.
530 
531         @param a  SkIRect to intersect
532         @param b  SkIRect to intersect
533         @return   true if a and b have area in common
534     */
IntersectsSkIRect535     static bool Intersects(const SkIRect& a, const SkIRect& b) {
536         return SkIRect{}.intersect(a, b);
537     }
538 
539     /** Sets SkIRect to the union of itself and r.
540 
541      Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
542 
543      @param r  expansion SkIRect
544 
545         example: https://fiddle.skia.org/c/@IRect_join_2
546      */
547     void join(const SkIRect& r);
548 
549     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
550         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
551         and width() and height() will be zero or positive.
552     */
sortSkIRect553     void sort() {
554         using std::swap;
555         if (fLeft > fRight) {
556             swap(fLeft, fRight);
557         }
558         if (fTop > fBottom) {
559             swap(fTop, fBottom);
560         }
561     }
562 
563     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
564         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
565         and width() and height() will be zero or positive.
566 
567         @return  sorted SkIRect
568     */
makeSortedSkIRect569     SkIRect makeSorted() const {
570         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
571                         std::max(fLeft, fRight), std::max(fTop, fBottom));
572     }
573 };
574 
575 /** \struct SkRect
576     SkRect holds four float coordinates describing the upper and
577     lower bounds of a rectangle. SkRect may be created from outer bounds or
578     from position, width, and height. SkRect describes an area; if its right
579     is less than or equal to its left, or if its bottom is less than or equal to
580     its top, it is considered empty.
581 */
582 struct SK_API SkRect {
583     float fLeft   = 0; //!< smaller x-axis bounds
584     float fTop    = 0; //!< smaller y-axis bounds
585     float fRight  = 0; //!< larger x-axis bounds
586     float fBottom = 0; //!< larger y-axis bounds
587 
588     /** Returns constructed SkRect set to (0, 0, 0, 0).
589         Many other rectangles are empty; if left is equal to or greater than right,
590         or if top is equal to or greater than bottom. Setting all members to zero
591         is a convenience, but does not designate a special empty rectangle.
592 
593         @return  bounds (0, 0, 0, 0)
594     */
MakeEmptySkRect595     [[nodiscard]] static constexpr SkRect MakeEmpty() {
596         return SkRect{0, 0, 0, 0};
597     }
598 
599     /** Returns constructed SkRect set to float values (0, 0, w, h). Does not
600         validate input; w or h may be negative.
601 
602         Passing integer values may generate a compiler warning since SkRect cannot
603         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
604 
605         @param w  float width of constructed SkRect
606         @param h  float height of constructed SkRect
607         @return   bounds (0, 0, w, h)
608     */
MakeWHSkRect609     [[nodiscard]] static constexpr SkRect MakeWH(float w, float h) {
610         return SkRect{0, 0, w, h};
611     }
612 
613     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
614         input; w or h may be negative.
615 
616         Use to avoid a compiler warning that input may lose precision when stored.
617         Use SkIRect for an exact integer rectangle.
618 
619         @param w  integer width of constructed SkRect
620         @param h  integer height of constructed SkRect
621         @return   bounds (0, 0, w, h)
622     */
MakeIWHSkRect623     [[nodiscard]] static SkRect MakeIWH(int w, int h) {
624         return {0, 0, static_cast<float>(w), static_cast<float>(h)};
625     }
626 
627     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
628         validate input; size.width() or size.height() may be negative.
629 
630         @param size  float values for SkRect width and height
631         @return      bounds (0, 0, size.width(), size.height())
632     */
MakeSizeSkRect633     [[nodiscard]] static constexpr SkRect MakeSize(const SkSize& size) {
634         return SkRect{0, 0, size.fWidth, size.fHeight};
635     }
636 
637     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
638         result in fLeft greater than fRight, or fTop greater than fBottom.
639 
640         @param l  float stored in fLeft
641         @param t  float stored in fTop
642         @param r  float stored in fRight
643         @param b  float stored in fBottom
644         @return   bounds (l, t, r, b)
645     */
MakeLTRBSkRect646     [[nodiscard]] static constexpr SkRect MakeLTRB(float l, float t, float r, float b) {
647         return SkRect {l, t, r, b};
648     }
649 
650     /** Returns constructed SkRect set to (x, y, x + w, y + h).
651         Does not validate input; w or h may be negative.
652 
653         @param x  stored in fLeft
654         @param y  stored in fTop
655         @param w  added to x and stored in fRight
656         @param h  added to y and stored in fBottom
657         @return   bounds at (x, y) with width w and height h
658     */
MakeXYWHSkRect659     [[nodiscard]] static constexpr SkRect MakeXYWH(float x, float y, float w, float h) {
660         return SkRect {x, y, x + w, y + h};
661     }
662 
663     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
664         Does not validate input; size.width() or size.height() may be negative.
665 
666         @param size  integer values for SkRect width and height
667         @return      bounds (0, 0, size.width(), size.height())
668     */
MakeSkRect669     static SkRect Make(const SkISize& size) {
670         return MakeIWH(size.width(), size.height());
671     }
672 
673     /** Returns constructed SkIRect set to irect, promoting integers to float.
674         Does not validate input; fLeft may be greater than fRight, fTop may be greater
675         than fBottom.
676 
677         @param irect  integer unsorted bounds
678         @return       irect members converted to float
679     */
MakeSkRect680     [[nodiscard]] static SkRect Make(const SkIRect& irect) {
681         return {
682             static_cast<float>(irect.fLeft), static_cast<float>(irect.fTop),
683             static_cast<float>(irect.fRight), static_cast<float>(irect.fBottom)
684         };
685     }
686 
687     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
688         to or greater than fBottom. Call sort() to reverse rectangles with negative
689         width() or height().
690 
691         @return  true if width() or height() are zero or negative
692     */
isEmptySkRect693     bool isEmpty() const {
694         // We write it as the NOT of a non-empty rect, so we will return true if any values
695         // are NaN.
696         return !(fLeft < fRight && fTop < fBottom);
697     }
698 
699     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
700         to or less than fBottom. Call sort() to reverse rectangles with negative
701         width() or height().
702 
703         @return  true if width() or height() are zero or positive
704     */
isSortedSkRect705     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
706 
707     /** Returns true if all values in the rectangle are finite.
708 
709         @return  true if no member is infinite or NaN
710     */
isFiniteSkRect711     bool isFinite() const {
712         return SkIsFinite(fLeft, fTop, fRight, fBottom);
713     }
714 
715     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
716         Call sort() to reverse fLeft and fRight if needed.
717 
718         @return  fLeft
719     */
xSkRect720     constexpr float x() const { return fLeft; }
721 
722     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
723         and sort() to reverse fTop and fBottom if needed.
724 
725         @return  fTop
726     */
ySkRect727     constexpr float y() const { return fTop; }
728 
729     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
730         Call sort() to reverse fLeft and fRight if needed.
731 
732         @return  fLeft
733     */
leftSkRect734     constexpr float left() const { return fLeft; }
735 
736     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
737         and sort() to reverse fTop and fBottom if needed.
738 
739         @return  fTop
740     */
topSkRect741     constexpr float top() const { return fTop; }
742 
743     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
744         Call sort() to reverse fLeft and fRight if needed.
745 
746         @return  fRight
747     */
rightSkRect748     constexpr float right() const { return fRight; }
749 
750     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
751         and sort() to reverse fTop and fBottom if needed.
752 
753         @return  fBottom
754     */
bottomSkRect755     constexpr float bottom() const { return fBottom; }
756 
757     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
758         result fits in 32-bit float; result may be negative or infinity.
759 
760         @return  fRight minus fLeft
761     */
widthSkRect762     constexpr float width() const { return fRight - fLeft; }
763 
764     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
765         result fits in 32-bit float; result may be negative or infinity.
766 
767         @return  fBottom minus fTop
768     */
heightSkRect769     constexpr float height() const { return fBottom - fTop; }
770 
771     /** Returns average of left edge and right edge. Result does not change if SkRect
772         is sorted. Result may overflow to infinity if SkRect is far from the origin.
773 
774         @return  midpoint on x-axis
775     */
centerXSkRect776     constexpr float centerX() const {
777         return sk_float_midpoint(fLeft, fRight);
778     }
779 
780     /** Returns average of top edge and bottom edge. Result does not change if SkRect
781         is sorted.
782 
783         @return  midpoint on y-axis
784     */
centerYSkRect785     constexpr float centerY() const {
786         return sk_float_midpoint(fTop, fBottom);
787     }
788 
789     /** Returns the point this->centerX(), this->centerY().
790         @return  rectangle center
791      */
centerSkRect792     constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; }
793 
794     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
795         equal to the corresponding members in b.
796 
797         a and b are not equal if either contain NaN. a and b are equal if members
798         contain zeroes with different signs.
799 
800         @param a  SkRect to compare
801         @param b  SkRect to compare
802         @return   true if members are equal
803     */
804     friend bool operator==(const SkRect& a, const SkRect& b) {
805         return a.fLeft == b.fLeft &&
806                a.fTop == b.fTop &&
807                a.fRight == b.fRight &&
808                a.fBottom == b.fBottom;
809     }
810 
811     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
812         equal the corresponding members in b.
813 
814         a and b are not equal if either contain NaN. a and b are equal if members
815         contain zeroes with different signs.
816 
817         @param a  SkRect to compare
818         @param b  SkRect to compare
819         @return   true if members are not equal
820     */
821     friend bool operator!=(const SkRect& a, const SkRect& b) {
822         return !(a == b);
823     }
824 
825     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
826         bottom-right, bottom-left.
827 
828         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
829 
830         @param quad  storage for corners of SkRect
831 
832         example: https://fiddle.skia.org/c/@Rect_toQuad
833     */
834     void toQuad(SkPoint quad[4]) const;
835 
836     /** Sets SkRect to (0, 0, 0, 0).
837 
838         Many other rectangles are empty; if left is equal to or greater than right,
839         or if top is equal to or greater than bottom. Setting all members to zero
840         is a convenience, but does not designate a special empty rectangle.
841     */
setEmptySkRect842     void setEmpty() { *this = MakeEmpty(); }
843 
844     /** Sets SkRect to src, promoting src members from integer to float.
845         Very large values in src may lose precision.
846 
847         @param src  integer SkRect
848     */
setSkRect849     void set(const SkIRect& src) {
850         fLeft   = src.fLeft;
851         fTop    = src.fTop;
852         fRight  = src.fRight;
853         fBottom = src.fBottom;
854     }
855 
856     /** Sets SkRect to (left, top, right, bottom).
857         left and right are not sorted; left is not necessarily less than right.
858         top and bottom are not sorted; top is not necessarily less than bottom.
859 
860         @param left    stored in fLeft
861         @param top     stored in fTop
862         @param right   stored in fRight
863         @param bottom  stored in fBottom
864     */
setLTRBSkRect865     void setLTRB(float left, float top, float right, float bottom) {
866         fLeft   = left;
867         fTop    = top;
868         fRight  = right;
869         fBottom = bottom;
870     }
871 
872     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
873         or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
874 
875         Result is either empty or sorted: fLeft is less than or equal to fRight, and
876         fTop is less than or equal to fBottom.
877 
878         @param pts    SkPoint array
879         @param count  entries in array
880     */
setBoundsSkRect881     void setBounds(const SkPoint pts[], int count) {
882         (void)this->setBoundsCheck(pts, count);
883     }
884 
885     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
886         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
887         sets SkRect to (0, 0, 0, 0).
888 
889         Result is either empty or sorted: fLeft is less than or equal to fRight, and
890         fTop is less than or equal to fBottom.
891 
892         @param pts    SkPoint array
893         @param count  entries in array
894         @return       true if all SkPoint values are finite
895 
896         example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
897     */
898     bool setBoundsCheck(const SkPoint pts[], int count);
899 
900     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
901         contains infinity or NaN, all SkRect dimensions are set to NaN.
902 
903         @param pts    SkPoint array
904         @param count  entries in array
905 
906         example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
907     */
908     void setBoundsNoCheck(const SkPoint pts[], int count);
909 
910     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
911         sorted and may be empty. Does not check to see if values are finite.
912 
913         @param p0  corner to include
914         @param p1  corner to include
915     */
setSkRect916     void set(const SkPoint& p0, const SkPoint& p1) {
917         fLeft =   std::min(p0.fX, p1.fX);
918         fRight =  std::max(p0.fX, p1.fX);
919         fTop =    std::min(p0.fY, p1.fY);
920         fBottom = std::max(p0.fY, p1.fY);
921     }
922 
923     /** Sets SkRect to (x, y, x + width, y + height).
924         Does not validate input; width or height may be negative.
925 
926         @param x       stored in fLeft
927         @param y       stored in fTop
928         @param width   added to x and stored in fRight
929         @param height  added to y and stored in fBottom
930     */
setXYWHSkRect931     void setXYWH(float x, float y, float width, float height) {
932         fLeft = x;
933         fTop = y;
934         fRight = x + width;
935         fBottom = y + height;
936     }
937 
938     /** Sets SkRect to (0, 0, width, height). Does not validate input;
939         width or height may be negative.
940 
941         @param width   stored in fRight
942         @param height  stored in fBottom
943     */
setWHSkRect944     void setWH(float width, float height) {
945         fLeft = 0;
946         fTop = 0;
947         fRight = width;
948         fBottom = height;
949     }
setIWHSkRect950     void setIWH(int32_t width, int32_t height) {
951         this->setWH(width, height);
952     }
953 
954     /** Returns SkRect offset by (dx, dy).
955 
956         If dx is negative, SkRect returned is moved to the left.
957         If dx is positive, SkRect returned is moved to the right.
958         If dy is negative, SkRect returned is moved upward.
959         If dy is positive, SkRect returned is moved downward.
960 
961         @param dx  added to fLeft and fRight
962         @param dy  added to fTop and fBottom
963         @return    SkRect offset on axes, with original width and height
964     */
makeOffsetSkRect965     constexpr SkRect makeOffset(float dx, float dy) const {
966         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
967     }
968 
969     /** Returns SkRect offset by v.
970 
971         @param v  added to rect
972         @return    SkRect offset on axes, with original width and height
973     */
makeOffsetSkRect974     constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
975 
976     /** Returns SkRect, inset by (dx, dy).
977 
978         If dx is negative, SkRect returned is wider.
979         If dx is positive, SkRect returned is narrower.
980         If dy is negative, SkRect returned is taller.
981         If dy is positive, SkRect returned is shorter.
982 
983         @param dx  added to fLeft and subtracted from fRight
984         @param dy  added to fTop and subtracted from fBottom
985         @return    SkRect inset symmetrically left and right, top and bottom
986     */
makeInsetSkRect987     SkRect makeInset(float dx, float dy) const {
988         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
989     }
990 
991     /** Returns SkRect, outset by (dx, dy).
992 
993         If dx is negative, SkRect returned is narrower.
994         If dx is positive, SkRect returned is wider.
995         If dy is negative, SkRect returned is shorter.
996         If dy is positive, SkRect returned is taller.
997 
998         @param dx  subtracted to fLeft and added from fRight
999         @param dy  subtracted to fTop and added from fBottom
1000         @return    SkRect outset symmetrically left and right, top and bottom
1001     */
makeOutsetSkRect1002     SkRect makeOutset(float dx, float dy) const {
1003         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1004     }
1005 
1006     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1007 
1008         If dx is negative, moves SkRect to the left.
1009         If dx is positive, moves SkRect to the right.
1010         If dy is negative, moves SkRect upward.
1011         If dy is positive, moves SkRect downward.
1012 
1013         @param dx  offset added to fLeft and fRight
1014         @param dy  offset added to fTop and fBottom
1015     */
offsetSkRect1016     void offset(float dx, float dy) {
1017         fLeft   += dx;
1018         fTop    += dy;
1019         fRight  += dx;
1020         fBottom += dy;
1021     }
1022 
1023     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1024         fTop, fBottom.
1025 
1026         If delta.fX is negative, moves SkRect to the left.
1027         If delta.fX is positive, moves SkRect to the right.
1028         If delta.fY is negative, moves SkRect upward.
1029         If delta.fY is positive, moves SkRect downward.
1030 
1031         @param delta  added to SkRect
1032     */
offsetSkRect1033     void offset(const SkPoint& delta) {
1034         this->offset(delta.fX, delta.fY);
1035     }
1036 
1037     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1038         are unchanged.
1039 
1040         @param newX  stored in fLeft, preserving width()
1041         @param newY  stored in fTop, preserving height()
1042     */
offsetToSkRect1043     void offsetTo(float newX, float newY) {
1044         fRight += newX - fLeft;
1045         fBottom += newY - fTop;
1046         fLeft = newX;
1047         fTop = newY;
1048     }
1049 
1050     /** Insets SkRect by (dx, dy).
1051 
1052         If dx is positive, makes SkRect narrower.
1053         If dx is negative, makes SkRect wider.
1054         If dy is positive, makes SkRect shorter.
1055         If dy is negative, makes SkRect taller.
1056 
1057         @param dx  added to fLeft and subtracted from fRight
1058         @param dy  added to fTop and subtracted from fBottom
1059     */
insetSkRect1060     void inset(float dx, float dy)  {
1061         fLeft   += dx;
1062         fTop    += dy;
1063         fRight  -= dx;
1064         fBottom -= dy;
1065     }
1066 
1067     /** Outsets SkRect by (dx, dy).
1068 
1069         If dx is positive, makes SkRect wider.
1070         If dx is negative, makes SkRect narrower.
1071         If dy is positive, makes SkRect taller.
1072         If dy is negative, makes SkRect shorter.
1073 
1074         @param dx  subtracted to fLeft and added from fRight
1075         @param dy  subtracted to fTop and added from fBottom
1076     */
outsetSkRect1077     void outset(float dx, float dy)  { this->inset(-dx, -dy); }
1078 
1079     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1080         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1081 
1082         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1083 
1084         @param r  limit of result
1085         @return   true if r and SkRect have area in common
1086 
1087         example: https://fiddle.skia.org/c/@Rect_intersect
1088     */
1089     bool intersect(const SkRect& r);
1090 
1091     /** Returns true if a intersects b, and sets SkRect to intersection.
1092         Returns false if a does not intersect b, and leaves SkRect unchanged.
1093 
1094         Returns false if either a or b is empty, leaving SkRect unchanged.
1095 
1096         @param a  SkRect to intersect
1097         @param b  SkRect to intersect
1098         @return   true if a and b have area in common
1099     */
1100     [[nodiscard]] bool intersect(const SkRect& a, const SkRect& b);
1101 
1102 
1103 private:
IntersectsSkRect1104     static bool Intersects(float al, float at, float ar, float ab,
1105                            float bl, float bt, float br, float bb) {
1106         float L = std::max(al, bl);
1107         float R = std::min(ar, br);
1108         float T = std::max(at, bt);
1109         float B = std::min(ab, bb);
1110         return L < R && T < B;
1111     }
1112 
1113 public:
1114 
1115     /** Returns true if SkRect intersects r.
1116      Returns false if either r or SkRect is empty, or do not intersect.
1117 
1118      @param r  SkRect to intersect
1119      @return   true if r and SkRect have area in common
1120      */
intersectsSkRect1121     bool intersects(const SkRect& r) const {
1122         return Intersects(fLeft, fTop, fRight, fBottom,
1123                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1124     }
1125 
1126     /** Returns true if a intersects b.
1127         Returns false if either a or b is empty, or do not intersect.
1128 
1129         @param a  SkRect to intersect
1130         @param b  SkRect to intersect
1131         @return   true if a and b have area in common
1132     */
IntersectsSkRect1133     static bool Intersects(const SkRect& a, const SkRect& b) {
1134         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1135                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1136     }
1137 
1138     /** Sets SkRect to the union of itself and r.
1139 
1140         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1141         SkRect to r.
1142 
1143         @param r  expansion SkRect
1144 
1145         example: https://fiddle.skia.org/c/@Rect_join_2
1146     */
1147     void join(const SkRect& r);
1148 
1149     /** Sets SkRect to the union of itself and r.
1150 
1151         Asserts if r is empty and SK_DEBUG is defined.
1152         If SkRect is empty, sets SkRect to r.
1153 
1154         May produce incorrect results if r is empty.
1155 
1156         @param r  expansion SkRect
1157     */
joinNonEmptyArgSkRect1158     void joinNonEmptyArg(const SkRect& r) {
1159         SkASSERT(!r.isEmpty());
1160         // if we are empty, just assign
1161         if (fLeft >= fRight || fTop >= fBottom) {
1162             *this = r;
1163         } else {
1164             this->joinPossiblyEmptyRect(r);
1165         }
1166     }
1167 
1168     /** Sets SkRect to the union of itself and the construction.
1169 
1170         May produce incorrect results if SkRect or r is empty.
1171 
1172         @param r  expansion SkRect
1173     */
joinPossiblyEmptyRectSkRect1174     void joinPossiblyEmptyRect(const SkRect& r) {
1175         fLeft   = std::min(fLeft, r.left());
1176         fTop    = std::min(fTop, r.top());
1177         fRight  = std::max(fRight, r.right());
1178         fBottom = std::max(fBottom, r.bottom());
1179     }
1180 
1181     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1182         Returns false if SkRect is empty.
1183 
1184         @param x  test SkPoint x-coordinate
1185         @param y  test SkPoint y-coordinate
1186         @return   true if (x, y) is inside SkRect
1187     */
containsSkRect1188     bool contains(float x, float y) const {
1189         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1190     }
1191 
1192     /** Returns true if SkRect contains r.
1193         Returns false if SkRect is empty or r is empty.
1194 
1195         SkRect contains r when SkRect area completely includes r area.
1196 
1197         @param r  SkRect contained
1198         @return   true if all sides of SkRect are outside r
1199     */
containsSkRect1200     bool contains(const SkRect& r) const {
1201         // todo: can we eliminate the this->isEmpty check?
1202         return  !r.isEmpty() && !this->isEmpty() &&
1203                 fLeft <= r.fLeft && fTop <= r.fTop &&
1204                 fRight >= r.fRight && fBottom >= r.fBottom;
1205     }
1206 
1207     /** Returns true if SkRect contains r.
1208         Returns false if SkRect is empty or r is empty.
1209 
1210         SkRect contains r when SkRect area completely includes r area.
1211 
1212         @param r  SkIRect contained
1213         @return   true if all sides of SkRect are outside r
1214     */
containsSkRect1215     bool contains(const SkIRect& r) const {
1216         // todo: can we eliminate the this->isEmpty check?
1217         return  !r.isEmpty() && !this->isEmpty() &&
1218                 fLeft <= r.fLeft && fTop <= r.fTop &&
1219                 fRight >= r.fRight && fBottom >= r.fBottom;
1220     }
1221 
1222     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1223         members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop),
1224                         sk_float_round2int(fRight), sk_float_round2int(fBottom)).
1225 
1226         @param dst  storage for SkIRect
1227     */
roundSkRect1228     void round(SkIRect* dst) const {
1229         SkASSERT(dst);
1230         dst->setLTRB(sk_float_round2int(fLeft),  sk_float_round2int(fTop),
1231                      sk_float_round2int(fRight), sk_float_round2int(fBottom));
1232     }
1233 
1234     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1235         up fRight and fBottom, using
1236         (sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1237          sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)).
1238 
1239         @param dst  storage for SkIRect
1240     */
roundOutSkRect1241     void roundOut(SkIRect* dst) const {
1242         SkASSERT(dst);
1243         dst->setLTRB(sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1244                      sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom));
1245     }
1246 
1247     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1248         up fRight and fBottom, using
1249         (std::floor(fLeft), std::floor(fTop),
1250          std::ceil(fRight), std::ceil(fBottom)).
1251 
1252         @param dst  storage for SkRect
1253     */
roundOutSkRect1254     void roundOut(SkRect* dst) const {
1255         dst->setLTRB(std::floor(fLeft), std::floor(fTop),
1256                      std::ceil(fRight), std::ceil(fBottom));
1257     }
1258 
1259     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1260         of fRight and fBottom, using
1261         (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1262          sk_float_floor2int(fRight), sk_float_floor2int(fBottom)).
1263 
1264         @param dst  storage for SkIRect
1265     */
roundInSkRect1266     void roundIn(SkIRect* dst) const {
1267         SkASSERT(dst);
1268         dst->setLTRB(sk_float_ceil2int(fLeft),   sk_float_ceil2int(fTop),
1269                      sk_float_floor2int(fRight), sk_float_floor2int(fBottom));
1270     }
1271 
1272     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1273         members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop),
1274                         sk_float_round2int(fRight), sk_float_round2int(fBottom)).
1275 
1276         @return  rounded SkIRect
1277     */
roundSkRect1278     SkIRect round() const {
1279         SkIRect ir;
1280         this->round(&ir);
1281         return ir;
1282     }
1283 
1284     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1285         up fRight and fBottom, using
1286         (sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1287          sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)).
1288 
1289         @return  rounded SkIRect
1290     */
roundOutSkRect1291     SkIRect roundOut() const {
1292         SkIRect ir;
1293         this->roundOut(&ir);
1294         return ir;
1295     }
1296     /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1297         of fRight and fBottom, using
1298         (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1299          sk_float_floor2int(fRight), sk_float_floor2int(fBottom)).
1300 
1301         @return  rounded SkIRect
1302     */
roundInSkRect1303     SkIRect roundIn() const {
1304         SkIRect ir;
1305         this->roundIn(&ir);
1306         return ir;
1307     }
1308 
1309     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1310         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1311         and width() and height() will be zero or positive.
1312     */
sortSkRect1313     void sort() {
1314         using std::swap;
1315         if (fLeft > fRight) {
1316             swap(fLeft, fRight);
1317         }
1318 
1319         if (fTop > fBottom) {
1320             swap(fTop, fBottom);
1321         }
1322     }
1323 
1324     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1325         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1326         and width() and height() will be zero or positive.
1327 
1328         @return  sorted SkRect
1329     */
makeSortedSkRect1330     SkRect makeSorted() const {
1331         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1332                         std::max(fLeft, fRight), std::max(fTop, fBottom));
1333     }
1334 
1335     /** Returns pointer to first float in SkRect, to treat it as an array with four
1336         entries.
1337 
1338         @return  pointer to fLeft
1339     */
asScalarsSkRect1340     const float* asScalars() const { return &fLeft; }
1341 
1342     /** Writes text representation of SkRect to standard output. Set asHex to true to
1343         generate exact binary representations of floating point numbers.
1344 
1345         @param asHex  true if SkScalar values are written as hexadecimal
1346 
1347         example: https://fiddle.skia.org/c/@Rect_dump
1348     */
1349     void dump(bool asHex) const;
1350 
1351     /** Writes text representation of SkRect to standard output. The representation may be
1352         directly compiled as C++ code. Floating point values are written
1353         with limited precision; it may not be possible to reconstruct original SkRect
1354         from output.
1355     */
dumpSkRect1356     void dump() const { this->dump(false); }
1357 
1358     /** Writes text representation of SkRect to standard output. The representation may be
1359         directly compiled as C++ code. Floating point values are written
1360         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1361         original SkRect.
1362 
1363         Use instead of dump() when submitting
1364     */
dumpHexSkRect1365     void dumpHex() const { this->dump(true); }
1366 };
1367 
contains(const SkRect & r)1368 inline bool SkIRect::contains(const SkRect& r) const {
1369     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
1370             fLeft <= r.fLeft && fTop <= r.fTop &&
1371             fRight >= r.fRight && fBottom >= r.fBottom;
1372 }
1373 
1374 #endif
1375