• 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/private/SkSafe32.h"
14 #include "include/private/SkTFitsIn.h"
15 
16 #include <algorithm>
17 #include <utility>
18 
19 struct 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 */
28 struct 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     */
MakeEmptySkIRect47     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     */
MakeWHSkIRect58     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     */
MakeSizeSkIRect68     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     */
MakePtSizeSkIRect80     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     */
MakeLTRBSkIRect93     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     */
MakeXYWHSkIRect107     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     */
leftSkIRect117     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     */
topSkIRect124     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     */
rightSkIRect131     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     */
bottomSkIRect138     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     */
xSkIRect145     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     */
ySkIRect152     int32_t y() const { return fTop; }
153 
154     // Experimental
topLeftSkIRect155     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     */
widthSkIRect162     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     */
heightSkIRect169     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     */
sizeSkIRect176     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     */
width64SkIRect184     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     */
height64SkIRect192     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     */
isEmpty64SkIRect200     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     */
isEmptySkIRect206     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     */
setEmptySkIRect244     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     */
setLTRBSkIRect255     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     */
setXYWHSkIRect270     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 
setWHSkIRect277     void setWH(int32_t width, int32_t height) {
278         fLeft   = 0;
279         fTop    = 0;
280         fRight  = width;
281         fBottom = height;
282     }
283 
setSizeSkIRect284     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     */
makeOffsetSkIRect302     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     */
makeOffsetSkIRect319     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     */
makeInsetSkIRect334     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     */
makeOutsetSkIRect352     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     */
offsetSkIRect369     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     */
offsetSkIRect386     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     */
offsetToSkIRect396     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     */
insetSkIRect413     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     */
outsetSkIRect430     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     */
adjustSkIRect448     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     */
containsSkIRect465     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      */
containsSkIRect477     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     */
containsNoEmptyCheckSkIRect501     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     */
intersectSkIRect515     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     */
IntersectsSkIRect537     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     */
sortSkIRect555     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     */
makeSortedSkIRect571     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 */
584 struct 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     */
MakeEmptySkRect597     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     */
MakeWHSkRect611     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     */
MakeIWHSkRect625     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     */
MakeSizeSkRect635     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     */
MakeLTRBSkRect648     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     */
MakeXYWHSkRect662     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     */
MakeSkRect673     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     */
MakeSkRect684     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     */
isEmptySkRect697     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     */
isSortedSkRect709     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     */
isFiniteSkRect716     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     */
xSkRect736     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     */
ySkRect743     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     */
leftSkRect750     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     */
topSkRect757     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     */
rightSkRect764     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     */
bottomSkRect771     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     */
widthSkRect778     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     */
heightSkRect785     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     */
centerXSkRect792     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     */
centerYSkRect802     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     */
setEmptySkRect852     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     */
setSkRect859     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     */
setLTRBSkRect875     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     */
setBoundsSkRect891     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     */
setSkRect926     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     */
setXYWHSkRect941     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     */
setWHSkRect954     void setWH(SkScalar width, SkScalar height) {
955         fLeft = 0;
956         fTop = 0;
957         fRight = width;
958         fBottom = height;
959     }
setIWHSkRect960     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     */
makeOffsetSkRect975     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     */
makeOffsetSkRect984     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     */
makeInsetSkRect997     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     */
makeOutsetSkRect1012     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     */
offsetSkRect1026     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     */
offsetSkRect1043     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     */
offsetToSkRect1053     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     */
insetSkRect1070     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     */
outsetSkRect1087     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 
1113 private:
IntersectsSkRect1114     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 
1123 public:
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      */
intersectsSkRect1131     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     */
IntersectsSkRect1143     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     */
joinNonEmptyArgSkRect1168     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     */
joinPossiblyEmptyRectSkRect1184     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     */
containsSkRect1198     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     */
containsSkRect1210     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     */
containsSkRect1225     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     */
roundSkRect1238     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     */
roundOutSkRect1251     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     */
roundOutSkRect1264     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     */
roundInSkRect1276     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     */
roundSkRect1288     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     */
roundOutSkRect1301     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     */
roundInSkRect1313     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     */
sortSkRect1323     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     */
makeSortedSkRect1340     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     */
asScalarsSkRect1350     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     */
dumpSkRect1373     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     */
dumpHexSkRect1382     void dumpHex() const { this->dump(true); }
1383 };
1384 
contains(const SkRect & r)1385 inline 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