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 /* Generated by tools/bookmaker from include/core/SkRect.h and docs/SkRect_Reference.bmh
9    on 2018-09-13 13:59:55. Additional documentation and examples can be found at:
10    https://skia.org/user/api/SkRect_Reference
11 
12    You may edit either file directly. Structural changes to public interfaces require
13    editing both files. After editing docs/SkRect_Reference.bmh, run:
14        bookmaker -b docs -i include/core/SkRect.h -p
15    to create an updated version of this file.
16  */
17 
18 #ifndef SkRect_DEFINED
19 #define SkRect_DEFINED
20 
21 #include "SkPoint.h"
22 #include "SkSize.h"
23 #include "../private/SkSafe32.h"
24 #include "../private/SkTFitsIn.h"
25 
26 #include <utility>
27 
28 struct SkRect;
29 
30 /** \struct SkIRect
31     SkIRect holds four 32-bit integer coordinates describing the upper and
32     lower bounds of a rectangle. SkIRect may be created from outer bounds or
33     from position, width, and height. SkIRect describes an area; if its right
34     is less than or equal to its left, or if its bottom is less than or equal to
35     its top, it is considered empty.
36 */
37 struct SK_API SkIRect {
38     int32_t fLeft;   //!< smaller x-axis bounds
39     int32_t fTop;    //!< smaller y-axis bounds
40     int32_t fRight;  //!< larger x-axis bounds
41     int32_t fBottom; //!< larger y-axis bounds
42 
43     /** Returns constructed SkIRect set to (0, 0, 0, 0).
44         Many other rectangles are empty; if left is equal to or greater than right,
45         or if top is equal to or greater than bottom. Setting all members to zero
46         is a convenience, but does not designate a special empty rectangle.
47 
48         @return  bounds (0, 0, 0, 0)
49     */
MakeEmptySkIRect50     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
51         return SkIRect{0, 0, 0, 0};
52     }
53 
54     /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
55         may be negative.
56 
57         @param w  width of constructed SkIRect
58         @param h  height of constructed SkIRect
59         @return   bounds (0, 0, w, h)
60     */
MakeWHSkIRect61     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
62         return SkIRect{0, 0, w, h};
63     }
64 
65     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
66         Does not validate input; size.width() or size.height() may be negative.
67 
68         @param size  values for SkIRect width and height
69         @return      bounds (0, 0, size.width(), size.height())
70     */
MakeSizeSkIRect71     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
72         return SkIRect{0, 0, size.fWidth, size.fHeight};
73     }
74 
75     /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
76         result in fLeft greater than fRight, or fTop greater than fBottom.
77 
78         @param l  integer stored in fLeft
79         @param t  integer stored in fTop
80         @param r  integer stored in fRight
81         @param b  integer stored in fBottom
82         @return   bounds (l, t, r, b)
83     */
MakeLTRBSkIRect84     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
85                                                             int32_t r, int32_t b) {
86         return SkIRect{l, t, r, b};
87     }
88 
89     /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
90         Does not validate input; w or h may be negative.
91 
92         @param x  stored in fLeft
93         @param y  stored in fTop
94         @param w  added to x and stored in fRight
95         @param h  added to y and stored in fBottom
96         @return   bounds at (x, y) with width w and height h
97     */
MakeXYWHSkIRect98     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
99                                                             int32_t w, int32_t h) {
100         return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
101     }
102 
103     /** Returns left edge of SkIRect, if sorted.
104         Call sort() to reverse fLeft and fRight if needed.
105 
106         @return  fLeft
107     */
leftSkIRect108     int32_t left() const { return fLeft; }
109 
110     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
111         and sort() to reverse fTop and fBottom if needed.
112 
113         @return  fTop
114     */
topSkIRect115     int32_t top() const { return fTop; }
116 
117     /** Returns right edge of SkIRect, if sorted.
118         Call sort() to reverse fLeft and fRight if needed.
119 
120         @return  fRight
121     */
rightSkIRect122     int32_t right() const { return fRight; }
123 
124     /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
125         and sort() to reverse fTop and fBottom if needed.
126 
127         @return  fBottom
128     */
bottomSkIRect129     int32_t bottom() const { return fBottom; }
130 
131     /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
132         and sort() to reverse fLeft and fRight if needed.
133 
134         @return  fLeft
135     */
xSkIRect136     int32_t x() const { return fLeft; }
137 
138     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
139         and sort() to reverse fTop and fBottom if needed.
140 
141         @return  fTop
142     */
ySkIRect143     int32_t y() const { return fTop; }
144 
145     // Experimental
topLeftSkIRect146     SkIPoint topLeft() const { return {fLeft, fTop}; }
147 
148     /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
149         result fits in 32-bit signed integer; result may be negative.
150 
151         @return  fRight minus fLeft
152     */
widthSkIRect153     int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
154 
155     /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
156         result fits in 32-bit signed integer; result may be negative.
157 
158         @return  fBottom minus fTop
159     */
heightSkIRect160     int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
161 
162     /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
163         or if result fits in 32-bit signed integer; result may be negative.
164 
165         @return  SkISize (width, height)
166     */
sizeSkIRect167     SkISize size() const { return SkISize::Make(this->width(), this->height()); }
168 
169     /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
170         result may be negative. This is safer than calling width() since width() might
171         overflow in its calculation.
172 
173         @return  fRight minus fLeft cast to int64_t
174     */
width64SkIRect175     int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
176 
177     /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
178         result may be negative. This is safer than calling height() since height() might
179         overflow in its calculation.
180 
181         @return  fBottom minus fTop cast to int64_t
182     */
height64SkIRect183     int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
184 
185     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
186         to or greater than fBottom. Call sort() to reverse rectangles with negative
187         width64() or height64().
188 
189         @return  true if width64() or height64() are zero or negative
190     */
isEmpty64SkIRect191     bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
192 
193     /** Returns true if width() or height() are zero or negative.
194 
195         @return  true if width() or height() are zero or negative
196     */
isEmptySkIRect197     bool isEmpty() const {
198         int64_t w = this->width64();
199         int64_t h = this->height64();
200         if (w <= 0 || h <= 0) {
201             return true;
202         }
203         // Return true if either exceeds int32_t
204         return !SkTFitsIn<int32_t>(w | h);
205     }
206 
207     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
208         identical to corresponding members in b.
209 
210         @param a  SkIRect to compare
211         @param b  SkIRect to compare
212         @return   true if members are equal
213     */
214     friend bool operator==(const SkIRect& a, const SkIRect& b) {
215         return !memcmp(&a, &b, sizeof(a));
216     }
217 
218     /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
219         identical to the corresponding member in b.
220 
221         @param a  SkIRect to compare
222         @param b  SkIRect to compare
223         @return   true if members are not equal
224     */
225     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
226         return !(a == b);
227     }
228 
229     /** Sets SkIRect to (0, 0, 0, 0).
230 
231         Many other rectangles are empty; if left is equal to or greater than right,
232         or if top is equal to or greater than bottom. Setting all members to zero
233         is a convenience, but does not designate a special empty rectangle.
234     */
setEmptySkIRect235     void setEmpty() { memset(this, 0, sizeof(*this)); }
236 
237     /** Sets SkIRect to (left, top, right, bottom).
238         left and right are not sorted; left is not necessarily less than right.
239         top and bottom are not sorted; top is not necessarily less than bottom.
240 
241         @param left    assigned to fLeft
242         @param top     assigned to fTop
243         @param right   assigned to fRight
244         @param bottom  assigned to fBottom
245     */
setSkIRect246     void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
247         fLeft   = left;
248         fTop    = top;
249         fRight  = right;
250         fBottom = bottom;
251     }
252 
253     /** Sets SkIRect to (left, top, right, bottom).
254         left and right are not sorted; left is not necessarily less than right.
255         top and bottom are not sorted; top is not necessarily less than bottom.
256 
257         @param left    stored in fLeft
258         @param top     stored in fTop
259         @param right   stored in fRight
260         @param bottom  stored in fBottom
261     */
setLTRBSkIRect262     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
263         this->set(left, top, right, bottom);
264     }
265 
266     /** Sets SkIRect to: (x, y, x + width, y + height).
267         Does not validate input; width or height may be negative.
268 
269         @param x       stored in fLeft
270         @param y       stored in fTop
271         @param width   added to x and stored in fRight
272         @param height  added to y and stored in fBottom
273     */
setXYWHSkIRect274     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
275         fLeft   = x;
276         fTop    = y;
277         fRight  = Sk32_sat_add(x, width);
278         fBottom = Sk32_sat_add(y, height);
279     }
280 
281     /** Returns SkIRect offset by (dx, dy).
282 
283         If dx is negative, SkIRect returned is moved to the left.
284         If dx is positive, SkIRect returned is moved to the right.
285         If dy is negative, SkIRect returned is moved upward.
286         If dy is positive, SkIRect returned is moved downward.
287 
288         @param dx  offset added to fLeft and fRight
289         @param dy  offset added to fTop and fBottom
290         @return    SkIRect offset by dx and dy, with original width and height
291     */
makeOffsetSkIRect292     SkIRect makeOffset(int32_t dx, int32_t dy) const {
293         return {
294             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
295             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
296         };
297     }
298 
299     /** Returns SkIRect, inset by (dx, dy).
300 
301         If dx is negative, SkIRect returned is wider.
302         If dx is positive, SkIRect returned is narrower.
303         If dy is negative, SkIRect returned is taller.
304         If dy is positive, SkIRect returned is shorter.
305 
306         @param dx  offset added to fLeft and subtracted from fRight
307         @param dy  offset added to fTop and subtracted from fBottom
308         @return    SkIRect inset symmetrically left and right, top and bottom
309     */
makeInsetSkIRect310     SkIRect makeInset(int32_t dx, int32_t dy) const {
311         return {
312             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
313             Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
314         };
315     }
316 
317     /** Returns SkIRect, outset by (dx, dy).
318 
319         If dx is negative, SkIRect returned is narrower.
320         If dx is positive, SkIRect returned is wider.
321         If dy is negative, SkIRect returned is shorter.
322         If dy is positive, SkIRect returned is taller.
323 
324         @param dx  offset subtracted to fLeft and added from fRight
325         @param dy  offset subtracted to fTop and added from fBottom
326         @return    SkIRect outset symmetrically left and right, top and bottom
327     */
makeOutsetSkIRect328     SkIRect makeOutset(int32_t dx, int32_t dy) const {
329         return {
330             Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),
331             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
332         };
333     }
334 
335     /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
336 
337         If dx is negative, moves SkIRect returned to the left.
338         If dx is positive, moves SkIRect returned to the right.
339         If dy is negative, moves SkIRect returned upward.
340         If dy is positive, moves SkIRect returned downward.
341 
342         @param dx  offset added to fLeft and fRight
343         @param dy  offset added to fTop and fBottom
344     */
offsetSkIRect345     void offset(int32_t dx, int32_t dy) {
346         fLeft   = Sk32_sat_add(fLeft,   dx);
347         fTop    = Sk32_sat_add(fTop,    dy);
348         fRight  = Sk32_sat_add(fRight,  dx);
349         fBottom = Sk32_sat_add(fBottom, dy);
350     }
351 
352     /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
353         fTop, fBottom.
354 
355         If delta.fX is negative, moves SkIRect returned to the left.
356         If delta.fX is positive, moves SkIRect returned to the right.
357         If delta.fY is negative, moves SkIRect returned upward.
358         If delta.fY is positive, moves SkIRect returned downward.
359 
360         @param delta  offset added to SkIRect
361     */
offsetSkIRect362     void offset(const SkIPoint& delta) {
363         this->offset(delta.fX, delta.fY);
364     }
365 
366     /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
367         are unchanged.
368 
369         @param newX  stored in fLeft, preserving width()
370         @param newY  stored in fTop, preserving height()
371     */
offsetToSkIRect372     void offsetTo(int32_t newX, int32_t newY) {
373         fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
374         fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
375         fLeft   = newX;
376         fTop    = newY;
377     }
378 
379     /** Insets SkIRect by (dx,dy).
380 
381         If dx is positive, makes SkIRect narrower.
382         If dx is negative, makes SkIRect wider.
383         If dy is positive, makes SkIRect shorter.
384         If dy is negative, makes SkIRect taller.
385 
386         @param dx  offset added to fLeft and subtracted from fRight
387         @param dy  offset added to fTop and subtracted from fBottom
388     */
insetSkIRect389     void inset(int32_t dx, int32_t dy) {
390         fLeft   = Sk32_sat_add(fLeft,   dx);
391         fTop    = Sk32_sat_add(fTop,    dy);
392         fRight  = Sk32_sat_sub(fRight,  dx);
393         fBottom = Sk32_sat_sub(fBottom, dy);
394     }
395 
396     /** Outsets SkIRect by (dx, dy).
397 
398         If dx is positive, makes SkIRect wider.
399         If dx is negative, makes SkIRect narrower.
400         If dy is positive, makes SkIRect taller.
401         If dy is negative, makes SkIRect shorter.
402 
403         @param dx  subtracted to fLeft and added from fRight
404         @param dy  subtracted to fTop and added from fBottom
405     */
outsetSkIRect406     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
407 
408     /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
409 
410         If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
411         If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
412         If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
413         If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
414 
415         The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
416         greater than right, the SkIRect will be considered empty. Call sort() after this call
417         if that is not the desired behavior.
418 
419         @param dL  offset added to fLeft
420         @param dT  offset added to fTop
421         @param dR  offset added to fRight
422         @param dB  offset added to fBottom
423     */
adjustSkIRect424     void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
425         fLeft   = Sk32_sat_add(fLeft,   dL);
426         fTop    = Sk32_sat_add(fTop,    dT);
427         fRight  = Sk32_sat_add(fRight,  dR);
428         fBottom = Sk32_sat_add(fBottom, dB);
429     }
430 
431     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
432         Returns false if SkIRect is empty.
433 
434         Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
435         returns true if constructed area is completely enclosed by SkIRect area.
436 
437         @param x  test SkIPoint x-coordinate
438         @param y  test SkIPoint y-coordinate
439         @return   true if (x, y) is inside SkIRect
440     */
containsSkIRect441     bool contains(int32_t x, int32_t y) const {
442         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
443     }
444 
445     /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
446         construction.
447 
448         Returns true if SkIRect contains construction.
449         Returns false if SkIRect is empty or construction is empty.
450 
451         @param left    x-axis minimum of constructed SkIRect
452         @param top     y-axis minimum of constructed SkIRect
453         @param right   x-axis maximum of constructed SkIRect
454         @param bottom  y-axis maximum of constructed SkIRect
455         @return        true if all sides of SkIRect are outside construction
456     */
containsSkIRect457     bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
458         return  left < right && top < bottom && !this->isEmpty() && // check for empties
459                 fLeft <= left && fTop <= top &&
460                 fRight >= right && fBottom >= bottom;
461     }
462 
463     /** Returns true if SkIRect contains r.
464         Returns false if SkIRect is empty or r is empty.
465 
466         SkIRect contains r when SkIRect area completely includes r area.
467 
468         @param r  SkIRect contained
469         @return   true if all sides of SkIRect are outside r
470     */
containsSkIRect471     bool contains(const SkIRect& r) const {
472         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
473                 fLeft <= r.fLeft && fTop <= r.fTop &&
474                 fRight >= r.fRight && fBottom >= r.fBottom;
475     }
476 
477     /** Returns true if SkIRect contains r.
478         Returns false if SkIRect is empty or r is empty.
479 
480         SkIRect contains r when SkIRect area completely includes r area.
481 
482         @param r  SkRect contained
483         @return   true if all sides of SkIRect are outside r
484     */
485     bool contains(const SkRect& r) const;
486 
487     /** Constructs SkIRect from (left, top, right, bottom). Does not sort
488         construction.
489 
490         Returns true if SkIRect contains construction.
491         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
492 
493         Return is undefined if SkIRect is empty or construction is empty.
494 
495         @param left    x-axis minimum of constructed SkIRect
496         @param top     y-axis minimum of constructed SkIRect
497         @param right   x-axis maximum of constructed SkIRect
498         @param bottom  y-axis maximum of constructed SkIRect
499         @return        true if all sides of SkIRect are outside construction
500     */
containsNoEmptyCheckSkIRect501     bool containsNoEmptyCheck(int32_t left, int32_t top,
502                               int32_t right, int32_t bottom) const {
503         SkASSERT(fLeft < fRight && fTop < fBottom);
504         SkASSERT(left < right && top < bottom);
505 
506         return fLeft <= left && fTop <= top &&
507                fRight >= right && fBottom >= bottom;
508     }
509 
510     /** Returns true if SkIRect contains construction.
511         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
512 
513         Return is undefined if SkIRect is empty or construction is empty.
514 
515         @param r  SkIRect contained
516         @return   true if all sides of SkIRect are outside r
517     */
containsNoEmptyCheckSkIRect518     bool containsNoEmptyCheck(const SkIRect& r) const {
519         return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
520     }
521 
522     /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
523         Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
524 
525         Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
526 
527         @param r  limit of result
528         @return   true if r and SkIRect have area in common
529     */
intersectSkIRect530     bool intersect(const SkIRect& r) {
531         return this->intersect(*this, r);
532     }
533 
534     /** Returns true if a intersects b, and sets SkIRect to intersection.
535         Returns false if a does not intersect b, and leaves SkIRect unchanged.
536 
537         Asserts if either a or b is empty, and if SK_DEBUG is defined.
538 
539         @param a  SkIRect to intersect
540         @param b  SkIRect to intersect
541         @return   true if a and b have area in common
542     */
intersectNoEmptyCheckSkIRect543     bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
544         SkASSERT(!a.isEmpty64() && !b.isEmpty64());
545         SkIRect r = {
546             SkMax32(a.fLeft,   b.fLeft),
547             SkMax32(a.fTop,    b.fTop),
548             SkMin32(a.fRight,  b.fRight),
549             SkMin32(a.fBottom, b.fBottom)
550         };
551         if (r.isEmpty()) {
552             return false;
553         }
554         *this = r;
555         return true;
556     }
557 
558     /** Returns true if a intersects b, and sets SkIRect to intersection.
559         Returns false if a does not intersect b, and leaves SkIRect unchanged.
560 
561         Returns false if either a or b is empty, leaving SkIRect unchanged.
562 
563         @param a  SkIRect to intersect
564         @param b  SkIRect to intersect
565         @return   true if a and b have area in common
566     */
intersectSkIRect567     bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
568         if (a.isEmpty64() || b.isEmpty64()) {
569             return false;
570         }
571         return this->intersectNoEmptyCheck(a, b);
572     }
573 
574     /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
575         construction.
576 
577         Returns true if SkIRect intersects construction, and sets SkIRect to intersection.
578         Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.
579 
580         Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.
581 
582         @param left    x-axis minimum of constructed SkIRect
583         @param top     y-axis minimum of constructed SkIRect
584         @param right   x-axis maximum of constructed SkIRect
585         @param bottom  y-axis maximum of constructed SkIRect
586         @return        true if construction and SkIRect have area in common
587     */
intersectSkIRect588     bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
589         return this->intersect(*this, {left, top, right, bottom});
590     }
591 
592     /** Returns true if a intersects b.
593         Returns false if either a or b is empty, or do not intersect.
594 
595         @param a  SkIRect to intersect
596         @param b  SkIRect to intersect
597         @return   true if a and b have area in common
598     */
IntersectsSkIRect599     static bool Intersects(const SkIRect& a, const SkIRect& b) {
600         SkIRect dummy;
601         return dummy.intersect(a, b);
602     }
603 
604     /** Returns true if a intersects b.
605         Asserts if either a or b is empty, and if SK_DEBUG is defined.
606 
607         @param a  SkIRect to intersect
608         @param b  SkIRect to intersect
609         @return   true if a and b have area in common
610     */
IntersectsNoEmptyCheckSkIRect611     static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
612         SkIRect dummy;
613         return dummy.intersectNoEmptyCheck(a, b);
614     }
615 
616     /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
617         construction.
618 
619         Sets SkIRect to the union of itself and the construction.
620 
621         Has no effect if construction is empty. Otherwise, if SkIRect is empty, sets
622         SkIRect to construction.
623 
624         @param left    x-axis minimum of constructed SkIRect
625         @param top     y-axis minimum of constructed SkIRect
626         @param right   x-axis maximum of constructed SkIRect
627         @param bottom  y-axis maximum of constructed SkIRect
628     */
629     void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
630 
631     /** Sets SkIRect to the union of itself and r.
632 
633         Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
634 
635         @param r  expansion SkIRect
636     */
joinSkIRect637     void join(const SkIRect& r) {
638         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
639     }
640 
641     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
642         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
643         and width() and height() will be zero or positive.
644     */
sortSkIRect645     void sort() {
646         using std::swap;
647         if (fLeft > fRight) {
648             swap(fLeft, fRight);
649         }
650         if (fTop > fBottom) {
651             swap(fTop, fBottom);
652         }
653     }
654 
655     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
656         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
657         and width() and height() will be zero or positive.
658 
659         @return  sorted SkIRect
660     */
makeSortedSkIRect661     SkIRect makeSorted() const {
662         return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
663                         SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
664     }
665 
666     /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
667 
668         @return  global SkIRect set to all zeroes
669     */
EmptyIRectSkIRect670     static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
671         static const SkIRect gEmpty = { 0, 0, 0, 0 };
672         return gEmpty;
673     }
674 };
675 
676 /** \struct SkRect
677     SkRect holds four SkScalar coordinates describing the upper and
678     lower bounds of a rectangle. SkRect may be created from outer bounds or
679     from position, width, and height. SkRect describes an area; if its right
680     is less than or equal to its left, or if its bottom is less than or equal to
681     its top, it is considered empty.
682 */
683 struct SK_API SkRect {
684     SkScalar fLeft;   //!< smaller x-axis bounds
685     SkScalar fTop;    //!< smaller y-axis bounds
686     SkScalar fRight;  //!< larger x-axis bounds
687     SkScalar fBottom; //!< larger y-axis bounds
688 
689     /** Returns constructed SkRect set to (0, 0, 0, 0).
690         Many other rectangles are empty; if left is equal to or greater than right,
691         or if top is equal to or greater than bottom. Setting all members to zero
692         is a convenience, but does not designate a special empty rectangle.
693 
694         @return  bounds (0, 0, 0, 0)
695     */
MakeEmptySkRect696     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
697         return SkRect{0, 0, 0, 0};
698     }
699 
700     /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
701         validate input; w or h may be negative.
702 
703         Passing integer values may generate a compiler warning since SkRect cannot
704         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
705 
706         @param w  SkScalar width of constructed SkRect
707         @param h  SkScalar height of constructed SkRect
708         @return   bounds (0, 0, w, h)
709     */
MakeWHSkRect710     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
711         return SkRect{0, 0, w, h};
712     }
713 
714     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
715         input; w or h may be negative.
716 
717         Use to avoid a compiler warning that input may lose precision when stored.
718         Use SkIRect for an exact integer rectangle.
719 
720         @param w  integer width of constructed SkRect
721         @param h  integer height of constructed SkRect
722         @return   bounds (0, 0, w, h)
723     */
MakeIWHSkRect724     static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
725         SkRect r;
726         r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
727         return r;
728     }
729 
730     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
731         validate input; size.width() or size.height() may be negative.
732 
733         @param size  SkScalar values for SkRect width and height
734         @return      bounds (0, 0, size.width(), size.height())
735     */
MakeSizeSkRect736     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
737         return SkRect{0, 0, size.fWidth, size.fHeight};
738     }
739 
740     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
741         result in fLeft greater than fRight, or fTop greater than fBottom.
742 
743         @param l  SkScalar stored in fLeft
744         @param t  SkScalar stored in fTop
745         @param r  SkScalar stored in fRight
746         @param b  SkScalar stored in fBottom
747         @return   bounds (l, t, r, b)
748     */
MakeLTRBSkRect749     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
750                                                            SkScalar b) {
751         return SkRect {l, t, r, b};
752     }
753 
754     /** Returns constructed SkRect set to (x, y, x + w, y + h).
755         Does not validate input; w or h may be negative.
756 
757         @param x  stored in fLeft
758         @param y  stored in fTop
759         @param w  added to x and stored in fRight
760         @param h  added to y and stored in fBottom
761         @return   bounds at (x, y) with width w and height h
762     */
MakeXYWHSkRect763     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
764                                                            SkScalar h) {
765         return SkRect {x, y, x + w, y + h};
766     }
767 
768     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
769         Does not validate input; size.width() or size.height() may be negative.
770 
771         @param size  integer values for SkRect width and height
772         @return      bounds (0, 0, size.width(), size.height())
773     */
MakeSkRect774     static SkRect Make(const SkISize& size) {
775         return MakeIWH(size.width(), size.height());
776     }
777 
778     /** Returns constructed SkIRect set to irect, promoting integers to scalar.
779         Does not validate input; fLeft may be greater than fRight, fTop may be greater
780         than fBottom.
781 
782         @param irect  integer unsorted bounds
783         @return       irect members converted to SkScalar
784     */
MakeSkRect785     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
786         SkRect r;
787         r.set(SkIntToScalar(irect.fLeft),
788               SkIntToScalar(irect.fTop),
789               SkIntToScalar(irect.fRight),
790               SkIntToScalar(irect.fBottom));
791         return r;
792     }
793 
794     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
795         to or greater than fBottom. Call sort() to reverse rectangles with negative
796         width() or height().
797 
798         @return  true if width() or height() are zero or negative
799     */
isEmptySkRect800     bool isEmpty() const {
801         // We write it as the NOT of a non-empty rect, so we will return true if any values
802         // are NaN.
803         return !(fLeft < fRight && fTop < fBottom);
804     }
805 
806     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
807         to or less than fBottom. Call sort() to reverse rectangles with negative
808         width() or height().
809 
810         @return  true if width() or height() are zero or positive
811     */
isSortedSkRect812     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
813 
814     /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
815         and SK_ScalarMax or smaller.
816 
817         @return  true if no member is infinite or NaN
818     */
isFiniteSkRect819     bool isFinite() const {
820         float accum = 0;
821         accum *= fLeft;
822         accum *= fTop;
823         accum *= fRight;
824         accum *= fBottom;
825 
826         // accum is either NaN or it is finite (zero).
827         SkASSERT(0 == accum || SkScalarIsNaN(accum));
828 
829         // value==value will be true iff value is not NaN
830         // TODO: is it faster to say !accum or accum==accum?
831         return !SkScalarIsNaN(accum);
832     }
833 
834     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
835         Call sort() to reverse fLeft and fRight if needed.
836 
837         @return  fLeft
838     */
xSkRect839     SkScalar    x() const { return fLeft; }
840 
841     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
842         and sort() to reverse fTop and fBottom if needed.
843 
844         @return  fTop
845     */
ySkRect846     SkScalar    y() const { return fTop; }
847 
848     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
849         Call sort() to reverse fLeft and fRight if needed.
850 
851         @return  fLeft
852     */
leftSkRect853     SkScalar    left() const { return fLeft; }
854 
855     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
856         and sort() to reverse fTop and fBottom if needed.
857 
858         @return  fTop
859     */
topSkRect860     SkScalar    top() const { return fTop; }
861 
862     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
863         Call sort() to reverse fLeft and fRight if needed.
864 
865         @return  fRight
866     */
rightSkRect867     SkScalar    right() const { return fRight; }
868 
869     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
870         and sort() to reverse fTop and fBottom if needed.
871 
872         @return  fBottom
873     */
bottomSkRect874     SkScalar    bottom() const { return fBottom; }
875 
876     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
877         result fits in 32-bit float; result may be negative or infinity.
878 
879         @return  fRight minus fLeft
880     */
widthSkRect881     SkScalar    width() const { return fRight - fLeft; }
882 
883     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
884         result fits in 32-bit float; result may be negative or infinity.
885 
886         @return  fBottom minus fTop
887     */
heightSkRect888     SkScalar    height() const { return fBottom - fTop; }
889 
890     /** Returns average of left edge and right edge. Result does not change if SkRect
891         is sorted. Result may overflow to infinity if SkRect is far from the origin.
892 
893         @return  midpoint on x-axis
894     */
centerXSkRect895     SkScalar centerX() const {
896         // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
897         return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
898     }
899 
900     /** Returns average of top edge and bottom edge. Result does not change if SkRect
901         is sorted.
902 
903         @return  midpoint on y-axis
904     */
centerYSkRect905     SkScalar centerY() const {
906         // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
907         return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
908     }
909 
910     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
911         equal to the corresponding members in b.
912 
913         a and b are not equal if either contain NaN. a and b are equal if members
914         contain zeroes with different signs.
915 
916         @param a  SkRect to compare
917         @param b  SkRect to compare
918         @return   true if members are equal
919     */
920     friend bool operator==(const SkRect& a, const SkRect& b) {
921         return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
922     }
923 
924     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
925         equal the corresponding members in b.
926 
927         a and b are not equal if either contain NaN. a and b are equal if members
928         contain zeroes with different signs.
929 
930         @param a  SkRect to compare
931         @param b  SkRect to compare
932         @return   true if members are not equal
933     */
934     friend bool operator!=(const SkRect& a, const SkRect& b) {
935         return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
936     }
937 
938     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
939         bottom-right, bottom-left.
940 
941         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
942 
943         @param quad  storage for corners of SkRect
944     */
945     void toQuad(SkPoint quad[4]) const;
946 
947     /** Sets SkRect to (0, 0, 0, 0).
948 
949         Many other rectangles are empty; if left is equal to or greater than right,
950         or if top is equal to or greater than bottom. Setting all members to zero
951         is a convenience, but does not designate a special empty rectangle.
952     */
setEmptySkRect953     void setEmpty() { *this = MakeEmpty(); }
954 
955     /** Sets SkRect to src, promoting src members from integer to scalar.
956         Very large values in src may lose precision.
957 
958         @param src  integer SkRect
959     */
setSkRect960     void set(const SkIRect& src) {
961         fLeft   = SkIntToScalar(src.fLeft);
962         fTop    = SkIntToScalar(src.fTop);
963         fRight  = SkIntToScalar(src.fRight);
964         fBottom = SkIntToScalar(src.fBottom);
965     }
966 
967     /** Sets SkRect to (left, top, right, bottom).
968         left and right are not sorted; left is not necessarily less than right.
969         top and bottom are not sorted; top is not necessarily less than bottom.
970 
971         @param left    stored in fLeft
972         @param top     stored in fTop
973         @param right   stored in fRight
974         @param bottom  stored in fBottom
975     */
setSkRect976     void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
977         fLeft   = left;
978         fTop    = top;
979         fRight  = right;
980         fBottom = bottom;
981     }
982 
983     /** Sets SkRect to (left, top, right, bottom).
984         left and right are not sorted; left is not necessarily less than right.
985         top and bottom are not sorted; top is not necessarily less than bottom.
986 
987         @param left    stored in fLeft
988         @param top     stored in fTop
989         @param right   stored in fRight
990         @param bottom  stored in fBottom
991     */
setLTRBSkRect992     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
993         this->set(left, top, right, bottom);
994     }
995 
996     /** Sets SkRect to (left, top, right, bottom).
997         All parameters are promoted from integer to scalar.
998         left and right are not sorted; left is not necessarily less than right.
999         top and bottom are not sorted; top is not necessarily less than bottom.
1000 
1001         @param left    promoted to SkScalar and stored in fLeft
1002         @param top     promoted to SkScalar and stored in fTop
1003         @param right   promoted to SkScalar and stored in fRight
1004         @param bottom  promoted to SkScalar and stored in fBottom
1005     */
isetSkRect1006     void iset(int left, int top, int right, int bottom) {
1007         fLeft   = SkIntToScalar(left);
1008         fTop    = SkIntToScalar(top);
1009         fRight  = SkIntToScalar(right);
1010         fBottom = SkIntToScalar(bottom);
1011     }
1012 
1013     /** Sets SkRect to (0, 0, width, height).
1014         width and height may be zero or negative. width and height are promoted from
1015         integer to SkScalar, large values may lose precision.
1016 
1017         @param width   promoted to SkScalar and stored in fRight
1018         @param height  promoted to SkScalar and stored in fBottom
1019     */
isetWHSkRect1020     void isetWH(int width, int height) {
1021         fLeft = fTop = 0;
1022         fRight = SkIntToScalar(width);
1023         fBottom = SkIntToScalar(height);
1024     }
1025 
1026     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1027         or if SkPoint array contains an infinity or NaN, sets SkRect to (0, 0, 0, 0).
1028 
1029         Result is either empty or sorted: fLeft is less than or equal to fRight, and
1030         fTop is less than or equal to fBottom.
1031 
1032         @param pts    SkPoint array
1033         @param count  entries in array
1034     */
setSkRect1035     void set(const SkPoint pts[], int count) {
1036         // set() had been checking for non-finite values, so keep that behavior
1037         // for now. Now that we have setBoundsCheck(), we may decide to make
1038         // set() be simpler/faster, and not check for those.
1039         (void)this->setBoundsCheck(pts, count);
1040     }
1041 
1042     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1043         or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
1044 
1045         Result is either empty or sorted: fLeft is less than or equal to fRight, and
1046         fTop is less than or equal to fBottom.
1047 
1048         @param pts    SkPoint array
1049         @param count  entries in array
1050     */
setBoundsSkRect1051     void setBounds(const SkPoint pts[], int count) {
1052         (void)this->setBoundsCheck(pts, count);
1053     }
1054 
1055     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
1056         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
1057         sets SkRect to (0, 0, 0, 0).
1058 
1059         Result is either empty or sorted: fLeft is less than or equal to fRight, and
1060         fTop is less than or equal to fBottom.
1061 
1062         @param pts    SkPoint array
1063         @param count  entries in array
1064         @return       true if all SkPoint values are finite
1065     */
1066     bool setBoundsCheck(const SkPoint pts[], int count);
1067 
1068     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
1069         contains infinity or NaN, all SkRect dimensions are set to NaN.
1070 
1071         @param pts    SkPoint array
1072         @param count  entries in array
1073     */
1074     void setBoundsNoCheck(const SkPoint pts[], int count);
1075 
1076     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
1077         sorted and may be empty. Does not check to see if values are finite.
1078 
1079         @param p0  corner to include
1080         @param p1  corner to include
1081     */
setSkRect1082     void set(const SkPoint& p0, const SkPoint& p1) {
1083         fLeft =   SkMinScalar(p0.fX, p1.fX);
1084         fRight =  SkMaxScalar(p0.fX, p1.fX);
1085         fTop =    SkMinScalar(p0.fY, p1.fY);
1086         fBottom = SkMaxScalar(p0.fY, p1.fY);
1087     }
1088 
1089     /** Sets SkRect to (x, y, x + width, y + height).
1090         Does not validate input; width or height may be negative.
1091 
1092         @param x       stored in fLeft
1093         @param y       stored in fTop
1094         @param width   added to x and stored in fRight
1095         @param height  added to y and stored in fBottom
1096     */
setXYWHSkRect1097     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
1098         fLeft = x;
1099         fTop = y;
1100         fRight = x + width;
1101         fBottom = y + height;
1102     }
1103 
1104     /** Sets SkRect to (0, 0, width, height). Does not validate input;
1105         width or height may be negative.
1106 
1107         @param width   stored in fRight
1108         @param height  stored in fBottom
1109     */
setWHSkRect1110     void setWH(SkScalar width, SkScalar height) {
1111         fLeft = 0;
1112         fTop = 0;
1113         fRight = width;
1114         fBottom = height;
1115     }
1116 
1117     /** Returns SkRect offset by (dx, dy).
1118 
1119         If dx is negative, SkRect returned is moved to the left.
1120         If dx is positive, SkRect returned is moved to the right.
1121         If dy is negative, SkRect returned is moved upward.
1122         If dy is positive, SkRect returned is moved downward.
1123 
1124         @param dx  added to fLeft and fRight
1125         @param dy  added to fTop and fBottom
1126         @return    SkRect offset on axes, with original width and height
1127     */
makeOffsetSkRect1128     SkRect makeOffset(SkScalar dx, SkScalar dy) const {
1129         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1130     }
1131 
1132     /** Returns SkRect, inset by (dx, dy).
1133 
1134         If dx is negative, SkRect returned is wider.
1135         If dx is positive, SkRect returned is narrower.
1136         If dy is negative, SkRect returned is taller.
1137         If dy is positive, SkRect returned is shorter.
1138 
1139         @param dx  added to fLeft and subtracted from fRight
1140         @param dy  added to fTop and subtracted from fBottom
1141         @return    SkRect inset symmetrically left and right, top and bottom
1142     */
makeInsetSkRect1143     SkRect makeInset(SkScalar dx, SkScalar dy) const {
1144         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1145     }
1146 
1147     /** Returns SkRect, outset by (dx, dy).
1148 
1149         If dx is negative, SkRect returned is narrower.
1150         If dx is positive, SkRect returned is wider.
1151         If dy is negative, SkRect returned is shorter.
1152         If dy is positive, SkRect returned is taller.
1153 
1154         @param dx  subtracted to fLeft and added from fRight
1155         @param dy  subtracted to fTop and added from fBottom
1156         @return    SkRect outset symmetrically left and right, top and bottom
1157     */
makeOutsetSkRect1158     SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1159         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1160     }
1161 
1162     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1163 
1164         If dx is negative, moves SkRect to the left.
1165         If dx is positive, moves SkRect to the right.
1166         If dy is negative, moves SkRect upward.
1167         If dy is positive, moves SkRect downward.
1168 
1169         @param dx  offset added to fLeft and fRight
1170         @param dy  offset added to fTop and fBottom
1171     */
offsetSkRect1172     void offset(SkScalar dx, SkScalar dy) {
1173         fLeft   += dx;
1174         fTop    += dy;
1175         fRight  += dx;
1176         fBottom += dy;
1177     }
1178 
1179     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1180         fTop, fBottom.
1181 
1182         If delta.fX is negative, moves SkRect to the left.
1183         If delta.fX is positive, moves SkRect to the right.
1184         If delta.fY is negative, moves SkRect upward.
1185         If delta.fY is positive, moves SkRect downward.
1186 
1187         @param delta  added to SkRect
1188     */
offsetSkRect1189     void offset(const SkPoint& delta) {
1190         this->offset(delta.fX, delta.fY);
1191     }
1192 
1193     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1194         are unchanged.
1195 
1196         @param newX  stored in fLeft, preserving width()
1197         @param newY  stored in fTop, preserving height()
1198     */
offsetToSkRect1199     void offsetTo(SkScalar newX, SkScalar newY) {
1200         fRight += newX - fLeft;
1201         fBottom += newY - fTop;
1202         fLeft = newX;
1203         fTop = newY;
1204     }
1205 
1206     /** Insets SkRect by (dx, dy).
1207 
1208         If dx is positive, makes SkRect narrower.
1209         If dx is negative, makes SkRect wider.
1210         If dy is positive, makes SkRect shorter.
1211         If dy is negative, makes SkRect taller.
1212 
1213         @param dx  added to fLeft and subtracted from fRight
1214         @param dy  added to fTop and subtracted from fBottom
1215     */
insetSkRect1216     void inset(SkScalar dx, SkScalar dy)  {
1217         fLeft   += dx;
1218         fTop    += dy;
1219         fRight  -= dx;
1220         fBottom -= dy;
1221     }
1222 
1223     /** Outsets SkRect by (dx, dy).
1224 
1225         If dx is positive, makes SkRect wider.
1226         If dx is negative, makes SkRect narrower.
1227         If dy is positive, makes SkRect taller.
1228         If dy is negative, makes SkRect shorter.
1229 
1230         @param dx  subtracted to fLeft and added from fRight
1231         @param dy  subtracted to fTop and added from fBottom
1232     */
outsetSkRect1233     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
1234 
1235     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1236         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1237 
1238         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1239 
1240         @param r  limit of result
1241         @return   true if r and SkRect have area in common
1242     */
1243     bool intersect(const SkRect& r);
1244 
1245     /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1246         construction.
1247 
1248         Returns true if SkRect intersects construction, and sets SkRect to intersection.
1249         Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.
1250 
1251         Returns false if either construction or SkRect is empty, leaving SkRect unchanged.
1252 
1253         @param left    x-axis minimum of constructed SkRect
1254         @param top     y-axis minimum of constructed SkRect
1255         @param right   x-axis maximum of constructed SkRect
1256         @param bottom  y-axis maximum of constructed SkRect
1257         @return        true if construction and SkRect have area in common
1258     */
1259     bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1260 
1261     /** Returns true if a intersects b, and sets SkRect to intersection.
1262         Returns false if a does not intersect b, and leaves SkRect unchanged.
1263 
1264         Returns false if either a or b is empty, leaving SkRect unchanged.
1265 
1266         @param a  SkRect to intersect
1267         @param b  SkRect to intersect
1268         @return   true if a and b have area in common
1269     */
1270     bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1271 
1272 
1273 private:
IntersectsSkRect1274     static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1275                            SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1276         SkScalar L = SkMaxScalar(al, bl);
1277         SkScalar R = SkMinScalar(ar, br);
1278         SkScalar T = SkMaxScalar(at, bt);
1279         SkScalar B = SkMinScalar(ab, bb);
1280         return L < R && T < B;
1281     }
1282 
1283 public:
1284 
1285     /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1286         construction.
1287 
1288         Returns true if SkRect intersects construction.
1289         Returns false if either construction or SkRect is empty, or do not intersect.
1290 
1291         @param left    x-axis minimum of constructed SkRect
1292         @param top     y-axis minimum of constructed SkRect
1293         @param right   x-axis maximum of constructed SkRect
1294         @param bottom  y-axis maximum of constructed SkRect
1295         @return        true if construction and SkRect have area in common
1296     */
intersectsSkRect1297     bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
1298         return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
1299     }
1300 
1301     /** Returns true if SkRect intersects r.
1302         Returns false if either r or SkRect is empty, or do not intersect.
1303 
1304         @param r  SkRect to intersect
1305         @return   true if r and SkRect have area in common
1306     */
intersectsSkRect1307     bool intersects(const SkRect& r) const {
1308         return Intersects(fLeft, fTop, fRight, fBottom,
1309                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1310     }
1311 
1312     /** Returns true if a intersects b.
1313         Returns false if either a or b is empty, or do not intersect.
1314 
1315         @param a  SkRect to intersect
1316         @param b  SkRect to intersect
1317         @return   true if a and b have area in common
1318     */
IntersectsSkRect1319     static bool Intersects(const SkRect& a, const SkRect& b) {
1320         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1321                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1322     }
1323 
1324     /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1325         construction.
1326 
1327         Sets SkRect to the union of itself and the construction.
1328 
1329         Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
1330         SkRect to construction.
1331 
1332         @param left    x-axis minimum of constructed SkRect
1333         @param top     y-axis minimum of constructed SkRect
1334         @param right   x-axis maximum of constructed SkRect
1335         @param bottom  y-axis maximum of constructed SkRect
1336     */
1337     void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1338 
1339     /** Sets SkRect to the union of itself and r.
1340 
1341         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1342         SkRect to r.
1343 
1344         @param r  expansion SkRect
1345     */
joinSkRect1346     void join(const SkRect& r) {
1347         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
1348     }
1349 
1350     /** Sets SkRect to the union of itself and r.
1351 
1352         Asserts if r is empty and SK_DEBUG is defined.
1353         If SkRect is empty, sets SkRect to r.
1354 
1355         May produce incorrect results if r is empty.
1356 
1357         @param r  expansion SkRect
1358     */
joinNonEmptyArgSkRect1359     void joinNonEmptyArg(const SkRect& r) {
1360         SkASSERT(!r.isEmpty());
1361         // if we are empty, just assign
1362         if (fLeft >= fRight || fTop >= fBottom) {
1363             *this = r;
1364         } else {
1365             this->joinPossiblyEmptyRect(r);
1366         }
1367     }
1368 
1369     /** Sets SkRect to the union of itself and the construction.
1370 
1371         May produce incorrect results if SkRect or r is empty.
1372 
1373         @param r  expansion SkRect
1374     */
joinPossiblyEmptyRectSkRect1375     void joinPossiblyEmptyRect(const SkRect& r) {
1376         fLeft   = SkMinScalar(fLeft, r.left());
1377         fTop    = SkMinScalar(fTop, r.top());
1378         fRight  = SkMaxScalar(fRight, r.right());
1379         fBottom = SkMaxScalar(fBottom, r.bottom());
1380     }
1381 
1382     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1383         Returns false if SkRect is empty.
1384 
1385         @param x  test SkPoint x-coordinate
1386         @param y  test SkPoint y-coordinate
1387         @return   true if (x, y) is inside SkRect
1388     */
containsSkRect1389     bool contains(SkScalar x, SkScalar y) const {
1390         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1391     }
1392 
1393     /** Returns true if SkRect contains r.
1394         Returns false if SkRect is empty or r is empty.
1395 
1396         SkRect contains r when SkRect area completely includes r area.
1397 
1398         @param r  SkRect contained
1399         @return   true if all sides of SkRect are outside r
1400     */
containsSkRect1401     bool contains(const SkRect& r) const {
1402         // todo: can we eliminate the this->isEmpty check?
1403         return  !r.isEmpty() && !this->isEmpty() &&
1404                 fLeft <= r.fLeft && fTop <= r.fTop &&
1405                 fRight >= r.fRight && fBottom >= r.fBottom;
1406     }
1407 
1408     /** Returns true if SkRect contains r.
1409         Returns false if SkRect is empty or r is empty.
1410 
1411         SkRect contains r when SkRect area completely includes r area.
1412 
1413         @param r  SkIRect contained
1414         @return   true if all sides of SkRect are outside r
1415     */
containsSkRect1416     bool contains(const SkIRect& r) const {
1417         // todo: can we eliminate the this->isEmpty check?
1418         return  !r.isEmpty() && !this->isEmpty() &&
1419                 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1420                 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1421     }
1422 
1423     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1424         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1425                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1426 
1427         @param dst  storage for SkIRect
1428     */
roundSkRect1429     void round(SkIRect* dst) const {
1430         SkASSERT(dst);
1431         dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1432                  SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1433     }
1434 
1435     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1436         up fRight and fBottom, using
1437         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1438          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1439 
1440         @param dst  storage for SkIRect
1441     */
roundOutSkRect1442     void roundOut(SkIRect* dst) const {
1443         SkASSERT(dst);
1444         dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1445                  SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1446     }
1447 
1448     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1449         up fRight and fBottom, using
1450         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1451          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1452 
1453         @param dst  storage for SkRect
1454     */
roundOutSkRect1455     void roundOut(SkRect* dst) const {
1456         dst->set(SkScalarFloorToScalar(fLeft),
1457                  SkScalarFloorToScalar(fTop),
1458                  SkScalarCeilToScalar(fRight),
1459                  SkScalarCeilToScalar(fBottom));
1460     }
1461 
1462     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1463         of fRight and fBottom, using
1464         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1465          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1466 
1467         @param dst  storage for SkIRect
1468     */
roundInSkRect1469     void roundIn(SkIRect* dst) const {
1470         SkASSERT(dst);
1471         dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1472                  SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1473     }
1474 
1475     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1476         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1477                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1478 
1479         @return  rounded SkIRect
1480     */
roundSkRect1481     SkIRect round() const {
1482         SkIRect ir;
1483         this->round(&ir);
1484         return ir;
1485     }
1486 
1487     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1488         up fRight and fBottom, using
1489         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1490          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1491 
1492         @return  rounded SkIRect
1493     */
roundOutSkRect1494     SkIRect roundOut() const {
1495         SkIRect ir;
1496         this->roundOut(&ir);
1497         return ir;
1498     }
1499 
1500     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1501         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1502         and width() and height() will be zero or positive.
1503     */
sortSkRect1504     void sort() {
1505         using std::swap;
1506         if (fLeft > fRight) {
1507             swap(fLeft, fRight);
1508         }
1509 
1510         if (fTop > fBottom) {
1511             swap(fTop, fBottom);
1512         }
1513     }
1514 
1515     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1516         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1517         and width() and height() will be zero or positive.
1518 
1519         @return  sorted SkRect
1520     */
makeSortedSkRect1521     SkRect makeSorted() const {
1522         return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
1523                         SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
1524     }
1525 
1526     /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1527         entries.
1528 
1529         @return  pointer to fLeft
1530     */
asScalarsSkRect1531     const SkScalar* asScalars() const { return &fLeft; }
1532 
1533     /** Writes text representation of SkRect to standard output. Set asHex to true to
1534         generate exact binary representations of floating point numbers.
1535 
1536         @param asHex  true if SkScalar values are written as hexadecimal
1537     */
1538     void dump(bool asHex) const;
1539 
1540     /** Writes text representation of SkRect to standard output. The representation may be
1541         directly compiled as C++ code. Floating point values are written
1542         with limited precision; it may not be possible to reconstruct original SkRect
1543         from output.
1544     */
dumpSkRect1545     void dump() const { this->dump(false); }
1546 
1547     /** Writes text representation of SkRect to standard output. The representation may be
1548         directly compiled as C++ code. Floating point values are written
1549         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1550         original SkRect.
1551 
1552         Use instead of dump() when submitting
1553     */
dumpHexSkRect1554     void dumpHex() const { this->dump(true); }
1555 };
1556 
contains(const SkRect & r)1557 inline bool SkIRect::contains(const SkRect& r) const {
1558     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
1559             (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1560             (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1561 }
1562 
1563 #endif
1564