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