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