• 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 
dumpSkIRect33     void dump(std::string& desc, int depth) const {
34         std::string split(depth, '\t');
35         desc += split + "\n SkIRect:{ \n";
36         desc += split + "\t fLeft:" + std::to_string(fLeft) + "\n";
37         desc += split + "\t fTop:" + std::to_string(fTop) + "\n";
38         desc += split + "\t fRight:" + std::to_string(fRight) + "\n";
39         desc += split + "\t fBottom:" + std::to_string(fBottom) + "\n";
40         desc += split + "}\n";
41     }
42     /** Returns constructed SkIRect set to (0, 0, 0, 0).
43         Many other rectangles are empty; if left is equal to or greater than right,
44         or if top is equal to or greater than bottom. Setting all members to zero
45         is a convenience, but does not designate a special empty rectangle.
46 
47         @return  bounds (0, 0, 0, 0)
48     */
MakeEmptySkIRect49     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
50         return SkIRect{0, 0, 0, 0};
51     }
52 
53     /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
54         may be negative.
55 
56         @param w  width of constructed SkIRect
57         @param h  height of constructed SkIRect
58         @return   bounds (0, 0, w, h)
59     */
MakeWHSkIRect60     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
61         return SkIRect{0, 0, w, h};
62     }
63 
64     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
65         Does not validate input; size.width() or size.height() may be negative.
66 
67         @param size  values for SkIRect width and height
68         @return      bounds (0, 0, size.width(), size.height())
69     */
MakeSizeSkIRect70     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
71         return SkIRect{0, 0, size.fWidth, size.fHeight};
72     }
73 
74     /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
75         result in fLeft greater than fRight, or fTop greater than fBottom.
76 
77         @param l  integer stored in fLeft
78         @param t  integer stored in fTop
79         @param r  integer stored in fRight
80         @param b  integer stored in fBottom
81         @return   bounds (l, t, r, b)
82     */
MakeLTRBSkIRect83     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
84                                                             int32_t r, int32_t b) {
85         return SkIRect{l, t, r, b};
86     }
87 
88     /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
89         Does not validate input; w or h may be negative.
90 
91         @param x  stored in fLeft
92         @param y  stored in fTop
93         @param w  added to x and stored in fRight
94         @param h  added to y and stored in fBottom
95         @return   bounds at (x, y) with width w and height h
96     */
MakeXYWHSkIRect97     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
98                                                             int32_t w, int32_t h) {
99         return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
100     }
101 
102     /** Returns left edge of SkIRect, if sorted.
103         Call sort() to reverse fLeft and fRight if needed.
104 
105         @return  fLeft
106     */
leftSkIRect107     int32_t left() const { return fLeft; }
108 
109     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
110         and sort() to reverse fTop and fBottom if needed.
111 
112         @return  fTop
113     */
topSkIRect114     int32_t top() const { return fTop; }
115 
116     /** Returns right edge of SkIRect, if sorted.
117         Call sort() to reverse fLeft and fRight if needed.
118 
119         @return  fRight
120     */
rightSkIRect121     int32_t right() const { return fRight; }
122 
123     /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
124         and sort() to reverse fTop and fBottom if needed.
125 
126         @return  fBottom
127     */
bottomSkIRect128     int32_t bottom() const { return fBottom; }
129 
130     /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
131         and sort() to reverse fLeft and fRight if needed.
132 
133         @return  fLeft
134     */
xSkIRect135     int32_t x() const { return fLeft; }
136 
137     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
138         and sort() to reverse fTop and fBottom if needed.
139 
140         @return  fTop
141     */
ySkIRect142     int32_t y() const { return fTop; }
143 
144     // Experimental
topLeftSkIRect145     SkIPoint topLeft() const { return {fLeft, fTop}; }
146 
147     /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
148         result fits in 32-bit signed integer; result may be negative.
149 
150         @return  fRight minus fLeft
151     */
widthSkIRect152     int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
153 
154     /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
155         result fits in 32-bit signed integer; result may be negative.
156 
157         @return  fBottom minus fTop
158     */
heightSkIRect159     int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
160 
161     /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
162         or if result fits in 32-bit signed integer; result may be negative.
163 
164         @return  SkISize (width, height)
165     */
sizeSkIRect166     SkISize size() const { return SkISize::Make(this->width(), this->height()); }
167 
168     /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
169         result may be negative. This is safer than calling width() since width() might
170         overflow in its calculation.
171 
172         @return  fRight minus fLeft cast to int64_t
173     */
width64SkIRect174     int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
175 
176     /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
177         result may be negative. This is safer than calling height() since height() might
178         overflow in its calculation.
179 
180         @return  fBottom minus fTop cast to int64_t
181     */
height64SkIRect182     int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
183 
184     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
185         to or greater than fBottom. Call sort() to reverse rectangles with negative
186         width64() or height64().
187 
188         @return  true if width64() or height64() are zero or negative
189     */
isEmpty64SkIRect190     bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
191 
192     /** Returns true if width() or height() are zero or negative.
193 
194         @return  true if width() or height() are zero or negative
195     */
isEmptySkIRect196     bool isEmpty() const {
197         int64_t w = this->width64();
198         int64_t h = this->height64();
199         if (w <= 0 || h <= 0) {
200             return true;
201         }
202         // Return true if either exceeds int32_t
203         return !SkTFitsIn<int32_t>(w | h);
204     }
205 
206     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
207         identical to corresponding members in b.
208 
209         @param a  SkIRect to compare
210         @param b  SkIRect to compare
211         @return   true if members are equal
212     */
213     friend bool operator==(const SkIRect& a, const SkIRect& b) {
214         return !memcmp(&a, &b, sizeof(a));
215     }
216 
217     /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
218         identical to the corresponding member in b.
219 
220         @param a  SkIRect to compare
221         @param b  SkIRect to compare
222         @return   true if members are not equal
223     */
224     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
225         return !(a == b);
226     }
227 
228     /** Sets SkIRect to (0, 0, 0, 0).
229 
230         Many other rectangles are empty; if left is equal to or greater than right,
231         or if top is equal to or greater than bottom. Setting all members to zero
232         is a convenience, but does not designate a special empty rectangle.
233     */
setEmptySkIRect234     void setEmpty() { memset(this, 0, sizeof(*this)); }
235 
236     /** Sets SkIRect to (left, top, right, bottom).
237         left and right are not sorted; left is not necessarily less than right.
238         top and bottom are not sorted; top is not necessarily less than bottom.
239 
240         @param left    assigned to fLeft
241         @param top     assigned to fTop
242         @param right   assigned to fRight
243         @param bottom  assigned to fBottom
244     */
setSkIRect245     void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
246         fLeft   = left;
247         fTop    = top;
248         fRight  = right;
249         fBottom = bottom;
250     }
251 
252     /** Sets SkIRect to (left, top, right, bottom).
253         left and right are not sorted; left is not necessarily less than right.
254         top and bottom are not sorted; top is not necessarily less than bottom.
255 
256         @param left    stored in fLeft
257         @param top     stored in fTop
258         @param right   stored in fRight
259         @param bottom  stored in fBottom
260     */
setLTRBSkIRect261     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
262         this->set(left, top, right, bottom);
263     }
264 
265     /** Sets SkIRect to: (x, y, x + width, y + height).
266         Does not validate input; width or height may be negative.
267 
268         @param x       stored in fLeft
269         @param y       stored in fTop
270         @param width   added to x and stored in fRight
271         @param height  added to y and stored in fBottom
272     */
setXYWHSkIRect273     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
274         fLeft   = x;
275         fTop    = y;
276         fRight  = Sk32_sat_add(x, width);
277         fBottom = Sk32_sat_add(y, height);
278     }
279 
280     /** Returns SkIRect offset by (dx, dy).
281 
282         If dx is negative, SkIRect returned is moved to the left.
283         If dx is positive, SkIRect returned is moved to the right.
284         If dy is negative, SkIRect returned is moved upward.
285         If dy is positive, SkIRect returned is moved downward.
286 
287         @param dx  offset added to fLeft and fRight
288         @param dy  offset added to fTop and fBottom
289         @return    SkIRect offset by dx and dy, with original width and height
290     */
makeOffsetSkIRect291     SkIRect makeOffset(int32_t dx, int32_t dy) const {
292         return {
293             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
294             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
295         };
296     }
297 
298     /** Returns SkIRect, inset by (dx, dy).
299 
300         If dx is negative, SkIRect returned is wider.
301         If dx is positive, SkIRect returned is narrower.
302         If dy is negative, SkIRect returned is taller.
303         If dy is positive, SkIRect returned is shorter.
304 
305         @param dx  offset added to fLeft and subtracted from fRight
306         @param dy  offset added to fTop and subtracted from fBottom
307         @return    SkIRect inset symmetrically left and right, top and bottom
308     */
makeInsetSkIRect309     SkIRect makeInset(int32_t dx, int32_t dy) const {
310         return {
311             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
312             Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
313         };
314     }
315 
316     /** Returns SkIRect, outset by (dx, dy).
317 
318         If dx is negative, SkIRect returned is narrower.
319         If dx is positive, SkIRect returned is wider.
320         If dy is negative, SkIRect returned is shorter.
321         If dy is positive, SkIRect returned is taller.
322 
323         @param dx  offset subtracted to fLeft and added from fRight
324         @param dy  offset subtracted to fTop and added from fBottom
325         @return    SkIRect outset symmetrically left and right, top and bottom
326     */
makeOutsetSkIRect327     SkIRect makeOutset(int32_t dx, int32_t dy) const {
328         return {
329             Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),
330             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
331         };
332     }
333 
334     /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
335 
336         If dx is negative, moves SkIRect returned to the left.
337         If dx is positive, moves SkIRect returned to the right.
338         If dy is negative, moves SkIRect returned upward.
339         If dy is positive, moves SkIRect returned downward.
340 
341         @param dx  offset added to fLeft and fRight
342         @param dy  offset added to fTop and fBottom
343     */
offsetSkIRect344     void offset(int32_t dx, int32_t dy) {
345         fLeft   = Sk32_sat_add(fLeft,   dx);
346         fTop    = Sk32_sat_add(fTop,    dy);
347         fRight  = Sk32_sat_add(fRight,  dx);
348         fBottom = Sk32_sat_add(fBottom, dy);
349     }
350 
351     /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
352         fTop, fBottom.
353 
354         If delta.fX is negative, moves SkIRect returned to the left.
355         If delta.fX is positive, moves SkIRect returned to the right.
356         If delta.fY is negative, moves SkIRect returned upward.
357         If delta.fY is positive, moves SkIRect returned downward.
358 
359         @param delta  offset added to SkIRect
360     */
offsetSkIRect361     void offset(const SkIPoint& delta) {
362         this->offset(delta.fX, delta.fY);
363     }
364 
365     /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
366         are unchanged.
367 
368         @param newX  stored in fLeft, preserving width()
369         @param newY  stored in fTop, preserving height()
370     */
offsetToSkIRect371     void offsetTo(int32_t newX, int32_t newY) {
372         fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
373         fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
374         fLeft   = newX;
375         fTop    = newY;
376     }
377 
378     /** Insets SkIRect by (dx,dy).
379 
380         If dx is positive, makes SkIRect narrower.
381         If dx is negative, makes SkIRect wider.
382         If dy is positive, makes SkIRect shorter.
383         If dy is negative, makes SkIRect taller.
384 
385         @param dx  offset added to fLeft and subtracted from fRight
386         @param dy  offset added to fTop and subtracted from fBottom
387     */
insetSkIRect388     void inset(int32_t dx, int32_t dy) {
389         fLeft   = Sk32_sat_add(fLeft,   dx);
390         fTop    = Sk32_sat_add(fTop,    dy);
391         fRight  = Sk32_sat_sub(fRight,  dx);
392         fBottom = Sk32_sat_sub(fBottom, dy);
393     }
394 
395     /** Outsets SkIRect by (dx, dy).
396 
397         If dx is positive, makes SkIRect wider.
398         If dx is negative, makes SkIRect narrower.
399         If dy is positive, makes SkIRect taller.
400         If dy is negative, makes SkIRect shorter.
401 
402         @param dx  subtracted to fLeft and added from fRight
403         @param dy  subtracted to fTop and added from fBottom
404     */
outsetSkIRect405     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
406 
407     /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
408 
409         If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
410         If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
411         If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
412         If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
413 
414         The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
415         greater than right, the SkIRect will be considered empty. Call sort() after this call
416         if that is not the desired behavior.
417 
418         @param dL  offset added to fLeft
419         @param dT  offset added to fTop
420         @param dR  offset added to fRight
421         @param dB  offset added to fBottom
422     */
adjustSkIRect423     void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
424         fLeft   = Sk32_sat_add(fLeft,   dL);
425         fTop    = Sk32_sat_add(fTop,    dT);
426         fRight  = Sk32_sat_add(fRight,  dR);
427         fBottom = Sk32_sat_add(fBottom, dB);
428     }
429 
430     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
431         Returns false if SkIRect is empty.
432 
433         Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
434         returns true if constructed area is completely enclosed by SkIRect area.
435 
436         @param x  test SkIPoint x-coordinate
437         @param y  test SkIPoint y-coordinate
438         @return   true if (x, y) is inside SkIRect
439     */
containsSkIRect440     bool contains(int32_t x, int32_t y) const {
441         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
442     }
443 
444     /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
445         construction.
446 
447         Returns true if SkIRect contains construction.
448         Returns false if SkIRect is empty or construction is empty.
449 
450         @param left    x-axis minimum of constructed SkIRect
451         @param top     y-axis minimum of constructed SkIRect
452         @param right   x-axis maximum of constructed SkIRect
453         @param bottom  y-axis maximum of constructed SkIRect
454         @return        true if all sides of SkIRect are outside construction
455     */
containsSkIRect456     bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
457         return  left < right && top < bottom && !this->isEmpty() && // check for empties
458                 fLeft <= left && fTop <= top &&
459                 fRight >= right && fBottom >= bottom;
460     }
461 
462     /** Returns true if SkIRect contains r.
463         Returns false if SkIRect is empty or r is empty.
464 
465         SkIRect contains r when SkIRect area completely includes r area.
466 
467         @param r  SkIRect contained
468         @return   true if all sides of SkIRect are outside r
469     */
containsSkIRect470     bool contains(const SkIRect& r) const {
471         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
472                 fLeft <= r.fLeft && fTop <= r.fTop &&
473                 fRight >= r.fRight && fBottom >= r.fBottom;
474     }
475 
476     /** Returns true if SkIRect contains r.
477         Returns false if SkIRect is empty or r is empty.
478 
479         SkIRect contains r when SkIRect area completely includes r area.
480 
481         @param r  SkRect contained
482         @return   true if all sides of SkIRect are outside r
483     */
484     bool contains(const SkRect& r) const;
485 
486     /** Constructs SkIRect from (left, top, right, bottom). Does not sort
487         construction.
488 
489         Returns true if SkIRect contains construction.
490         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
491 
492         Return is undefined if SkIRect is empty or construction is empty.
493 
494         @param left    x-axis minimum of constructed SkIRect
495         @param top     y-axis minimum of constructed SkIRect
496         @param right   x-axis maximum of constructed SkIRect
497         @param bottom  y-axis maximum of constructed SkIRect
498         @return        true if all sides of SkIRect are outside construction
499     */
containsNoEmptyCheckSkIRect500     bool containsNoEmptyCheck(int32_t left, int32_t top,
501                               int32_t right, int32_t bottom) const {
502         SkASSERT(fLeft < fRight && fTop < fBottom);
503         SkASSERT(left < right && top < bottom);
504 
505         return fLeft <= left && fTop <= top &&
506                fRight >= right && fBottom >= bottom;
507     }
508 
509     /** Returns true if SkIRect contains construction.
510         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
511 
512         Return is undefined if SkIRect is empty or construction is empty.
513 
514         @param r  SkIRect contained
515         @return   true if all sides of SkIRect are outside r
516     */
containsNoEmptyCheckSkIRect517     bool containsNoEmptyCheck(const SkIRect& r) const {
518         return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
519     }
520 
521     /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
522         Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
523 
524         Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
525 
526         @param r  limit of result
527         @return   true if r and SkIRect have area in common
528     */
intersectSkIRect529     bool intersect(const SkIRect& r) {
530         return this->intersect(*this, r);
531     }
532 
533     /** Returns true if a intersects b, and sets SkIRect to intersection.
534         Returns false if a does not intersect b, and leaves SkIRect unchanged.
535 
536         Asserts if either a or b is empty, and if SK_DEBUG is defined.
537 
538         @param a  SkIRect to intersect
539         @param b  SkIRect to intersect
540         @return   true if a and b have area in common
541     */
intersectNoEmptyCheckSkIRect542     bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
543         SkASSERT(!a.isEmpty64() && !b.isEmpty64());
544         SkIRect r = {
545             SkMax32(a.fLeft,   b.fLeft),
546             SkMax32(a.fTop,    b.fTop),
547             SkMin32(a.fRight,  b.fRight),
548             SkMin32(a.fBottom, b.fBottom)
549         };
550         if (r.isEmpty()) {
551             return false;
552         }
553         *this = r;
554         return true;
555     }
556 
557     /** Returns true if a intersects b, and sets SkIRect to intersection.
558         Returns false if a does not intersect b, and leaves SkIRect unchanged.
559 
560         Returns false if either a or b is empty, leaving SkIRect unchanged.
561 
562         @param a  SkIRect to intersect
563         @param b  SkIRect to intersect
564         @return   true if a and b have area in common
565     */
intersectSkIRect566     bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
567         if (a.isEmpty64() || b.isEmpty64()) {
568             return false;
569         }
570         return this->intersectNoEmptyCheck(a, b);
571     }
572 
573     /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
574         construction.
575 
576         Returns true if SkIRect intersects construction, and sets SkIRect to intersection.
577         Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.
578 
579         Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.
580 
581         @param left    x-axis minimum of constructed SkIRect
582         @param top     y-axis minimum of constructed SkIRect
583         @param right   x-axis maximum of constructed SkIRect
584         @param bottom  y-axis maximum of constructed SkIRect
585         @return        true if construction and SkIRect have area in common
586     */
intersectSkIRect587     bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
588         return this->intersect(*this, {left, top, right, bottom});
589     }
590 
591     /** Returns true if a intersects b.
592         Returns false if either a or b is empty, or do not intersect.
593 
594         @param a  SkIRect to intersect
595         @param b  SkIRect to intersect
596         @return   true if a and b have area in common
597     */
IntersectsSkIRect598     static bool Intersects(const SkIRect& a, const SkIRect& b) {
599         SkIRect dummy;
600         return dummy.intersect(a, b);
601     }
602 
603     /** Returns true if a intersects b.
604         Asserts if either a or b is empty, and if SK_DEBUG is defined.
605 
606         @param a  SkIRect to intersect
607         @param b  SkIRect to intersect
608         @return   true if a and b have area in common
609     */
IntersectsNoEmptyCheckSkIRect610     static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
611         SkIRect dummy;
612         return dummy.intersectNoEmptyCheck(a, b);
613     }
614 
615     /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
616         construction.
617 
618         Sets SkIRect to the union of itself and the construction.
619 
620         Has no effect if construction is empty. Otherwise, if SkIRect is empty, sets
621         SkIRect to construction.
622 
623         @param left    x-axis minimum of constructed SkIRect
624         @param top     y-axis minimum of constructed SkIRect
625         @param right   x-axis maximum of constructed SkIRect
626         @param bottom  y-axis maximum of constructed SkIRect
627     */
628     void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
629 
630     /** Sets SkIRect to the union of itself and r.
631 
632         Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
633 
634         @param r  expansion SkIRect
635     */
joinSkIRect636     void join(const SkIRect& r) {
637         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
638     }
639 
640     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
641         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
642         and width() and height() will be zero or positive.
643     */
sortSkIRect644     void sort() {
645         using std::swap;
646         if (fLeft > fRight) {
647             swap(fLeft, fRight);
648         }
649         if (fTop > fBottom) {
650             swap(fTop, fBottom);
651         }
652     }
653 
654     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
655         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
656         and width() and height() will be zero or positive.
657 
658         @return  sorted SkIRect
659     */
makeSortedSkIRect660     SkIRect makeSorted() const {
661         return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
662                         SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
663     }
664 
665     /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
666 
667         @return  global SkIRect set to all zeroes
668     */
EmptyIRectSkIRect669     static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
670         static const SkIRect gEmpty = { 0, 0, 0, 0 };
671         return gEmpty;
672     }
673 };
674 
675 /** \struct SkRect
676     SkRect holds four SkScalar coordinates describing the upper and
677     lower bounds of a rectangle. SkRect may be created from outer bounds or
678     from position, width, and height. SkRect describes an area; if its right
679     is less than or equal to its left, or if its bottom is less than or equal to
680     its top, it is considered empty.
681 */
682 struct SK_API SkRect {
683     SkScalar fLeft;   //!< smaller x-axis bounds
684     SkScalar fTop;    //!< smaller y-axis bounds
685     SkScalar fRight;  //!< larger x-axis bounds
686     SkScalar fBottom; //!< larger y-axis bounds
687 
688     /** Returns constructed SkRect set to (0, 0, 0, 0).
689         Many other rectangles are empty; if left is equal to or greater than right,
690         or if top is equal to or greater than bottom. Setting all members to zero
691         is a convenience, but does not designate a special empty rectangle.
692 
693         @return  bounds (0, 0, 0, 0)
694     */
MakeEmptySkRect695     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
696         return SkRect{0, 0, 0, 0};
697     }
698 
699     /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
700         validate input; w or h may be negative.
701 
702         Passing integer values may generate a compiler warning since SkRect cannot
703         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
704 
705         @param w  SkScalar width of constructed SkRect
706         @param h  SkScalar height of constructed SkRect
707         @return   bounds (0, 0, w, h)
708     */
MakeWHSkRect709     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
710         return SkRect{0, 0, w, h};
711     }
712 
713     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
714         input; w or h may be negative.
715 
716         Use to avoid a compiler warning that input may lose precision when stored.
717         Use SkIRect for an exact integer rectangle.
718 
719         @param w  integer width of constructed SkRect
720         @param h  integer height of constructed SkRect
721         @return   bounds (0, 0, w, h)
722     */
MakeIWHSkRect723     static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
724         SkRect r;
725         r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
726         return r;
727     }
728 
729     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
730         validate input; size.width() or size.height() may be negative.
731 
732         @param size  SkScalar values for SkRect width and height
733         @return      bounds (0, 0, size.width(), size.height())
734     */
MakeSizeSkRect735     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
736         return SkRect{0, 0, size.fWidth, size.fHeight};
737     }
738 
739     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
740         result in fLeft greater than fRight, or fTop greater than fBottom.
741 
742         @param l  SkScalar stored in fLeft
743         @param t  SkScalar stored in fTop
744         @param r  SkScalar stored in fRight
745         @param b  SkScalar stored in fBottom
746         @return   bounds (l, t, r, b)
747     */
MakeLTRBSkRect748     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
749                                                            SkScalar b) {
750         return SkRect {l, t, r, b};
751     }
752 
753     /** Returns constructed SkRect set to (x, y, x + w, y + h).
754         Does not validate input; w or h may be negative.
755 
756         @param x  stored in fLeft
757         @param y  stored in fTop
758         @param w  added to x and stored in fRight
759         @param h  added to y and stored in fBottom
760         @return   bounds at (x, y) with width w and height h
761     */
MakeXYWHSkRect762     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
763                                                            SkScalar h) {
764         return SkRect {x, y, x + w, y + h};
765     }
766 
767     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
768         Does not validate input; size.width() or size.height() may be negative.
769 
770         @param size  integer values for SkRect width and height
771         @return      bounds (0, 0, size.width(), size.height())
772     */
MakeSkRect773     static SkRect Make(const SkISize& size) {
774         return MakeIWH(size.width(), size.height());
775     }
776 
777     /** Returns constructed SkIRect set to irect, promoting integers to scalar.
778         Does not validate input; fLeft may be greater than fRight, fTop may be greater
779         than fBottom.
780 
781         @param irect  integer unsorted bounds
782         @return       irect members converted to SkScalar
783     */
MakeSkRect784     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
785         SkRect r;
786         r.set(SkIntToScalar(irect.fLeft),
787               SkIntToScalar(irect.fTop),
788               SkIntToScalar(irect.fRight),
789               SkIntToScalar(irect.fBottom));
790         return r;
791     }
792 
793     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
794         to or greater than fBottom. Call sort() to reverse rectangles with negative
795         width() or height().
796 
797         @return  true if width() or height() are zero or negative
798     */
isEmptySkRect799     bool isEmpty() const {
800         // We write it as the NOT of a non-empty rect, so we will return true if any values
801         // are NaN.
802         return !(fLeft < fRight && fTop < fBottom);
803     }
804 
805     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
806         to or less than fBottom. Call sort() to reverse rectangles with negative
807         width() or height().
808 
809         @return  true if width() or height() are zero or positive
810     */
isSortedSkRect811     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
812 
813     /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
814         and SK_ScalarMax or smaller.
815 
816         @return  true if no member is infinite or NaN
817     */
isFiniteSkRect818     bool isFinite() const {
819         float accum = 0;
820         accum *= fLeft;
821         accum *= fTop;
822         accum *= fRight;
823         accum *= fBottom;
824 
825         // accum is either NaN or it is finite (zero).
826         SkASSERT(0 == accum || SkScalarIsNaN(accum));
827 
828         // value==value will be true iff value is not NaN
829         // TODO: is it faster to say !accum or accum==accum?
830         return !SkScalarIsNaN(accum);
831     }
832 
833     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
834         Call sort() to reverse fLeft and fRight if needed.
835 
836         @return  fLeft
837     */
xSkRect838     SkScalar    x() const { return fLeft; }
839 
840     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
841         and sort() to reverse fTop and fBottom if needed.
842 
843         @return  fTop
844     */
ySkRect845     SkScalar    y() const { return fTop; }
846 
847     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
848         Call sort() to reverse fLeft and fRight if needed.
849 
850         @return  fLeft
851     */
leftSkRect852     SkScalar    left() const { return fLeft; }
853 
854     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
855         and sort() to reverse fTop and fBottom if needed.
856 
857         @return  fTop
858     */
topSkRect859     SkScalar    top() const { return fTop; }
860 
861     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
862         Call sort() to reverse fLeft and fRight if needed.
863 
864         @return  fRight
865     */
rightSkRect866     SkScalar    right() const { return fRight; }
867 
868     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
869         and sort() to reverse fTop and fBottom if needed.
870 
871         @return  fBottom
872     */
bottomSkRect873     SkScalar    bottom() const { return fBottom; }
874 
875     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
876         result fits in 32-bit float; result may be negative or infinity.
877 
878         @return  fRight minus fLeft
879     */
widthSkRect880     SkScalar    width() const { return fRight - fLeft; }
881 
882     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
883         result fits in 32-bit float; result may be negative or infinity.
884 
885         @return  fBottom minus fTop
886     */
heightSkRect887     SkScalar    height() const { return fBottom - fTop; }
888 
889     /** Returns average of left edge and right edge. Result does not change if SkRect
890         is sorted. Result may overflow to infinity if SkRect is far from the origin.
891 
892         @return  midpoint on x-axis
893     */
centerXSkRect894     SkScalar centerX() const {
895         // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
896         return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
897     }
898 
899     /** Returns average of top edge and bottom edge. Result does not change if SkRect
900         is sorted.
901 
902         @return  midpoint on y-axis
903     */
centerYSkRect904     SkScalar centerY() const {
905         // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
906         return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
907     }
908 
909     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
910         equal to the corresponding members in b.
911 
912         a and b are not equal if either contain NaN. a and b are equal if members
913         contain zeroes with different signs.
914 
915         @param a  SkRect to compare
916         @param b  SkRect to compare
917         @return   true if members are equal
918     */
919     friend bool operator==(const SkRect& a, const SkRect& b) {
920         return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
921     }
922 
923     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
924         equal the corresponding members in b.
925 
926         a and b are not equal if either contain NaN. a and b are equal if members
927         contain zeroes with different signs.
928 
929         @param a  SkRect to compare
930         @param b  SkRect to compare
931         @return   true if members are not equal
932     */
933     friend bool operator!=(const SkRect& a, const SkRect& b) {
934         return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
935     }
936 
937     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
938         bottom-right, bottom-left.
939 
940         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
941 
942         @param quad  storage for corners of SkRect
943     */
944     void toQuad(SkPoint quad[4]) const;
945 
946     /** Sets SkRect to (0, 0, 0, 0).
947 
948         Many other rectangles are empty; if left is equal to or greater than right,
949         or if top is equal to or greater than bottom. Setting all members to zero
950         is a convenience, but does not designate a special empty rectangle.
951     */
setEmptySkRect952     void setEmpty() { *this = MakeEmpty(); }
953 
954     /** Sets SkRect to src, promoting src members from integer to scalar.
955         Very large values in src may lose precision.
956 
957         @param src  integer SkRect
958     */
setSkRect959     void set(const SkIRect& src) {
960         fLeft   = SkIntToScalar(src.fLeft);
961         fTop    = SkIntToScalar(src.fTop);
962         fRight  = SkIntToScalar(src.fRight);
963         fBottom = SkIntToScalar(src.fBottom);
964     }
965 
966     /** Sets SkRect to (left, top, right, bottom).
967         left and right are not sorted; left is not necessarily less than right.
968         top and bottom are not sorted; top is not necessarily less than bottom.
969 
970         @param left    stored in fLeft
971         @param top     stored in fTop
972         @param right   stored in fRight
973         @param bottom  stored in fBottom
974     */
setSkRect975     void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
976         fLeft   = left;
977         fTop    = top;
978         fRight  = right;
979         fBottom = bottom;
980     }
981 
982     /** Sets SkRect to (left, top, right, bottom).
983         left and right are not sorted; left is not necessarily less than right.
984         top and bottom are not sorted; top is not necessarily less than bottom.
985 
986         @param left    stored in fLeft
987         @param top     stored in fTop
988         @param right   stored in fRight
989         @param bottom  stored in fBottom
990     */
setLTRBSkRect991     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
992         this->set(left, top, right, bottom);
993     }
994 
995     /** Sets SkRect to (left, top, right, bottom).
996         All parameters are promoted from integer to scalar.
997         left and right are not sorted; left is not necessarily less than right.
998         top and bottom are not sorted; top is not necessarily less than bottom.
999 
1000         @param left    promoted to SkScalar and stored in fLeft
1001         @param top     promoted to SkScalar and stored in fTop
1002         @param right   promoted to SkScalar and stored in fRight
1003         @param bottom  promoted to SkScalar and stored in fBottom
1004     */
isetSkRect1005     void iset(int left, int top, int right, int bottom) {
1006         fLeft   = SkIntToScalar(left);
1007         fTop    = SkIntToScalar(top);
1008         fRight  = SkIntToScalar(right);
1009         fBottom = SkIntToScalar(bottom);
1010     }
1011 
1012     /** Sets SkRect to (0, 0, width, height).
1013         width and height may be zero or negative. width and height are promoted from
1014         integer to SkScalar, large values may lose precision.
1015 
1016         @param width   promoted to SkScalar and stored in fRight
1017         @param height  promoted to SkScalar and stored in fBottom
1018     */
isetWHSkRect1019     void isetWH(int width, int height) {
1020         fLeft = fTop = 0;
1021         fRight = SkIntToScalar(width);
1022         fBottom = SkIntToScalar(height);
1023     }
1024 
1025     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1026         or if SkPoint array contains an infinity or NaN, sets SkRect to (0, 0, 0, 0).
1027 
1028         Result is either empty or sorted: fLeft is less than or equal to fRight, and
1029         fTop is less than or equal to fBottom.
1030 
1031         @param pts    SkPoint array
1032         @param count  entries in array
1033     */
setSkRect1034     void set(const SkPoint pts[], int count) {
1035         // set() had been checking for non-finite values, so keep that behavior
1036         // for now. Now that we have setBoundsCheck(), we may decide to make
1037         // set() be simpler/faster, and not check for those.
1038         (void)this->setBoundsCheck(pts, count);
1039     }
1040 
1041     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1042         or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
1043 
1044         Result is either empty or sorted: fLeft is less than or equal to fRight, and
1045         fTop is less than or equal to fBottom.
1046 
1047         @param pts    SkPoint array
1048         @param count  entries in array
1049     */
setBoundsSkRect1050     void setBounds(const SkPoint pts[], int count) {
1051         (void)this->setBoundsCheck(pts, count);
1052     }
1053 
1054     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
1055         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
1056         sets SkRect to (0, 0, 0, 0).
1057 
1058         Result is either empty or sorted: fLeft is less than or equal to fRight, and
1059         fTop is less than or equal to fBottom.
1060 
1061         @param pts    SkPoint array
1062         @param count  entries in array
1063         @return       true if all SkPoint values are finite
1064     */
1065     bool setBoundsCheck(const SkPoint pts[], int count);
1066 
1067     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
1068         contains infinity or NaN, all SkRect dimensions are set to NaN.
1069 
1070         @param pts    SkPoint array
1071         @param count  entries in array
1072     */
1073     void setBoundsNoCheck(const SkPoint pts[], int count);
1074 
1075     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
1076         sorted and may be empty. Does not check to see if values are finite.
1077 
1078         @param p0  corner to include
1079         @param p1  corner to include
1080     */
setSkRect1081     void set(const SkPoint& p0, const SkPoint& p1) {
1082         fLeft =   SkMinScalar(p0.fX, p1.fX);
1083         fRight =  SkMaxScalar(p0.fX, p1.fX);
1084         fTop =    SkMinScalar(p0.fY, p1.fY);
1085         fBottom = SkMaxScalar(p0.fY, p1.fY);
1086     }
1087 
1088     /** Sets SkRect to (x, y, x + width, y + height).
1089         Does not validate input; width or height may be negative.
1090 
1091         @param x       stored in fLeft
1092         @param y       stored in fTop
1093         @param width   added to x and stored in fRight
1094         @param height  added to y and stored in fBottom
1095     */
setXYWHSkRect1096     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
1097         fLeft = x;
1098         fTop = y;
1099         fRight = x + width;
1100         fBottom = y + height;
1101     }
1102 
1103     /** Sets SkRect to (0, 0, width, height). Does not validate input;
1104         width or height may be negative.
1105 
1106         @param width   stored in fRight
1107         @param height  stored in fBottom
1108     */
setWHSkRect1109     void setWH(SkScalar width, SkScalar height) {
1110         fLeft = 0;
1111         fTop = 0;
1112         fRight = width;
1113         fBottom = height;
1114     }
1115 
1116     /** Returns SkRect offset by (dx, dy).
1117 
1118         If dx is negative, SkRect returned is moved to the left.
1119         If dx is positive, SkRect returned is moved to the right.
1120         If dy is negative, SkRect returned is moved upward.
1121         If dy is positive, SkRect returned is moved downward.
1122 
1123         @param dx  added to fLeft and fRight
1124         @param dy  added to fTop and fBottom
1125         @return    SkRect offset on axes, with original width and height
1126     */
makeOffsetSkRect1127     SkRect makeOffset(SkScalar dx, SkScalar dy) const {
1128         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1129     }
1130 
1131     /** Returns SkRect, inset by (dx, dy).
1132 
1133         If dx is negative, SkRect returned is wider.
1134         If dx is positive, SkRect returned is narrower.
1135         If dy is negative, SkRect returned is taller.
1136         If dy is positive, SkRect returned is shorter.
1137 
1138         @param dx  added to fLeft and subtracted from fRight
1139         @param dy  added to fTop and subtracted from fBottom
1140         @return    SkRect inset symmetrically left and right, top and bottom
1141     */
makeInsetSkRect1142     SkRect makeInset(SkScalar dx, SkScalar dy) const {
1143         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1144     }
1145 
1146     /** Returns SkRect, outset by (dx, dy).
1147 
1148         If dx is negative, SkRect returned is narrower.
1149         If dx is positive, SkRect returned is wider.
1150         If dy is negative, SkRect returned is shorter.
1151         If dy is positive, SkRect returned is taller.
1152 
1153         @param dx  subtracted to fLeft and added from fRight
1154         @param dy  subtracted to fTop and added from fBottom
1155         @return    SkRect outset symmetrically left and right, top and bottom
1156     */
makeOutsetSkRect1157     SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1158         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1159     }
1160 
1161     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1162 
1163         If dx is negative, moves SkRect to the left.
1164         If dx is positive, moves SkRect to the right.
1165         If dy is negative, moves SkRect upward.
1166         If dy is positive, moves SkRect downward.
1167 
1168         @param dx  offset added to fLeft and fRight
1169         @param dy  offset added to fTop and fBottom
1170     */
offsetSkRect1171     void offset(SkScalar dx, SkScalar dy) {
1172         fLeft   += dx;
1173         fTop    += dy;
1174         fRight  += dx;
1175         fBottom += dy;
1176     }
1177 
1178     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1179         fTop, fBottom.
1180 
1181         If delta.fX is negative, moves SkRect to the left.
1182         If delta.fX is positive, moves SkRect to the right.
1183         If delta.fY is negative, moves SkRect upward.
1184         If delta.fY is positive, moves SkRect downward.
1185 
1186         @param delta  added to SkRect
1187     */
offsetSkRect1188     void offset(const SkPoint& delta) {
1189         this->offset(delta.fX, delta.fY);
1190     }
1191 
1192     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1193         are unchanged.
1194 
1195         @param newX  stored in fLeft, preserving width()
1196         @param newY  stored in fTop, preserving height()
1197     */
offsetToSkRect1198     void offsetTo(SkScalar newX, SkScalar newY) {
1199         fRight += newX - fLeft;
1200         fBottom += newY - fTop;
1201         fLeft = newX;
1202         fTop = newY;
1203     }
1204 
1205     /** Insets SkRect by (dx, dy).
1206 
1207         If dx is positive, makes SkRect narrower.
1208         If dx is negative, makes SkRect wider.
1209         If dy is positive, makes SkRect shorter.
1210         If dy is negative, makes SkRect taller.
1211 
1212         @param dx  added to fLeft and subtracted from fRight
1213         @param dy  added to fTop and subtracted from fBottom
1214     */
insetSkRect1215     void inset(SkScalar dx, SkScalar dy)  {
1216         fLeft   += dx;
1217         fTop    += dy;
1218         fRight  -= dx;
1219         fBottom -= dy;
1220     }
1221 
1222     /** Outsets SkRect by (dx, dy).
1223 
1224         If dx is positive, makes SkRect wider.
1225         If dx is negative, makes SkRect narrower.
1226         If dy is positive, makes SkRect taller.
1227         If dy is negative, makes SkRect shorter.
1228 
1229         @param dx  subtracted to fLeft and added from fRight
1230         @param dy  subtracted to fTop and added from fBottom
1231     */
outsetSkRect1232     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
1233 
1234     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1235         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1236 
1237         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1238 
1239         @param r  limit of result
1240         @return   true if r and SkRect have area in common
1241     */
1242     bool intersect(const SkRect& r);
1243 
1244     /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1245         construction.
1246 
1247         Returns true if SkRect intersects construction, and sets SkRect to intersection.
1248         Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.
1249 
1250         Returns false if either construction or SkRect is empty, leaving SkRect unchanged.
1251 
1252         @param left    x-axis minimum of constructed SkRect
1253         @param top     y-axis minimum of constructed SkRect
1254         @param right   x-axis maximum of constructed SkRect
1255         @param bottom  y-axis maximum of constructed SkRect
1256         @return        true if construction and SkRect have area in common
1257     */
1258     bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1259 
1260     /** Returns true if a intersects b, and sets SkRect to intersection.
1261         Returns false if a does not intersect b, and leaves SkRect unchanged.
1262 
1263         Returns false if either a or b is empty, leaving SkRect unchanged.
1264 
1265         @param a  SkRect to intersect
1266         @param b  SkRect to intersect
1267         @return   true if a and b have area in common
1268     */
1269     bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1270 
1271 
1272 private:
IntersectsSkRect1273     static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1274                            SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1275         SkScalar L = SkMaxScalar(al, bl);
1276         SkScalar R = SkMinScalar(ar, br);
1277         SkScalar T = SkMaxScalar(at, bt);
1278         SkScalar B = SkMinScalar(ab, bb);
1279         return L < R && T < B;
1280     }
1281 
1282 public:
1283 
1284     /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1285         construction.
1286 
1287         Returns true if SkRect intersects construction.
1288         Returns false if either construction or SkRect is empty, or do not intersect.
1289 
1290         @param left    x-axis minimum of constructed SkRect
1291         @param top     y-axis minimum of constructed SkRect
1292         @param right   x-axis maximum of constructed SkRect
1293         @param bottom  y-axis maximum of constructed SkRect
1294         @return        true if construction and SkRect have area in common
1295     */
intersectsSkRect1296     bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
1297         return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
1298     }
1299 
1300     /** Returns true if SkRect intersects r.
1301         Returns false if either r or SkRect is empty, or do not intersect.
1302 
1303         @param r  SkRect to intersect
1304         @return   true if r and SkRect have area in common
1305     */
intersectsSkRect1306     bool intersects(const SkRect& r) const {
1307         return Intersects(fLeft, fTop, fRight, fBottom,
1308                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1309     }
1310 
1311     /** Returns true if a intersects b.
1312         Returns false if either a or b is empty, or do not intersect.
1313 
1314         @param a  SkRect to intersect
1315         @param b  SkRect to intersect
1316         @return   true if a and b have area in common
1317     */
IntersectsSkRect1318     static bool Intersects(const SkRect& a, const SkRect& b) {
1319         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1320                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1321     }
1322 
1323     /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1324         construction.
1325 
1326         Sets SkRect to the union of itself and the construction.
1327 
1328         Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
1329         SkRect to construction.
1330 
1331         @param left    x-axis minimum of constructed SkRect
1332         @param top     y-axis minimum of constructed SkRect
1333         @param right   x-axis maximum of constructed SkRect
1334         @param bottom  y-axis maximum of constructed SkRect
1335     */
1336     void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1337 
1338     /** Sets SkRect to the union of itself and r.
1339 
1340         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1341         SkRect to r.
1342 
1343         @param r  expansion SkRect
1344     */
joinSkRect1345     void join(const SkRect& r) {
1346         this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
1347     }
1348 
1349     /** Sets SkRect to the union of itself and r.
1350 
1351         Asserts if r is empty and SK_DEBUG is defined.
1352         If SkRect is empty, sets SkRect to r.
1353 
1354         May produce incorrect results if r is empty.
1355 
1356         @param r  expansion SkRect
1357     */
joinNonEmptyArgSkRect1358     void joinNonEmptyArg(const SkRect& r) {
1359         SkASSERT(!r.isEmpty());
1360         // if we are empty, just assign
1361         if (fLeft >= fRight || fTop >= fBottom) {
1362             *this = r;
1363         } else {
1364             this->joinPossiblyEmptyRect(r);
1365         }
1366     }
1367 
1368     /** Sets SkRect to the union of itself and the construction.
1369 
1370         May produce incorrect results if SkRect or r is empty.
1371 
1372         @param r  expansion SkRect
1373     */
joinPossiblyEmptyRectSkRect1374     void joinPossiblyEmptyRect(const SkRect& r) {
1375         fLeft   = SkMinScalar(fLeft, r.left());
1376         fTop    = SkMinScalar(fTop, r.top());
1377         fRight  = SkMaxScalar(fRight, r.right());
1378         fBottom = SkMaxScalar(fBottom, r.bottom());
1379     }
1380 
1381     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1382         Returns false if SkRect is empty.
1383 
1384         @param x  test SkPoint x-coordinate
1385         @param y  test SkPoint y-coordinate
1386         @return   true if (x, y) is inside SkRect
1387     */
containsSkRect1388     bool contains(SkScalar x, SkScalar y) const {
1389         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1390     }
1391 
1392     /** Returns true if SkRect contains r.
1393         Returns false if SkRect is empty or r is empty.
1394 
1395         SkRect contains r when SkRect area completely includes r area.
1396 
1397         @param r  SkRect contained
1398         @return   true if all sides of SkRect are outside r
1399     */
containsSkRect1400     bool contains(const SkRect& r) const {
1401         // todo: can we eliminate the this->isEmpty check?
1402         return  !r.isEmpty() && !this->isEmpty() &&
1403                 fLeft <= r.fLeft && fTop <= r.fTop &&
1404                 fRight >= r.fRight && fBottom >= r.fBottom;
1405     }
1406 
1407     /** Returns true if SkRect contains r.
1408         Returns false if SkRect is empty or r is empty.
1409 
1410         SkRect contains r when SkRect area completely includes r area.
1411 
1412         @param r  SkIRect contained
1413         @return   true if all sides of SkRect are outside r
1414     */
containsSkRect1415     bool contains(const SkIRect& r) const {
1416         // todo: can we eliminate the this->isEmpty check?
1417         return  !r.isEmpty() && !this->isEmpty() &&
1418                 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1419                 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1420     }
1421 
1422     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1423         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1424                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1425 
1426         @param dst  storage for SkIRect
1427     */
roundSkRect1428     void round(SkIRect* dst) const {
1429         SkASSERT(dst);
1430         dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1431                  SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1432     }
1433 
1434     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1435         up fRight and fBottom, using
1436         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1437          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1438 
1439         @param dst  storage for SkIRect
1440     */
roundOutSkRect1441     void roundOut(SkIRect* dst) const {
1442         SkASSERT(dst);
1443         dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1444                  SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1445     }
1446 
1447     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1448         up fRight and fBottom, using
1449         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1450          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1451 
1452         @param dst  storage for SkRect
1453     */
roundOutSkRect1454     void roundOut(SkRect* dst) const {
1455         dst->set(SkScalarFloorToScalar(fLeft),
1456                  SkScalarFloorToScalar(fTop),
1457                  SkScalarCeilToScalar(fRight),
1458                  SkScalarCeilToScalar(fBottom));
1459     }
1460 
1461     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1462         of fRight and fBottom, using
1463         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1464          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1465 
1466         @param dst  storage for SkIRect
1467     */
roundInSkRect1468     void roundIn(SkIRect* dst) const {
1469         SkASSERT(dst);
1470         dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1471                  SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1472     }
1473 
1474     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1475         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1476                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1477 
1478         @return  rounded SkIRect
1479     */
roundSkRect1480     SkIRect round() const {
1481         SkIRect ir;
1482         this->round(&ir);
1483         return ir;
1484     }
1485 
1486     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1487         up fRight and fBottom, using
1488         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1489          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1490 
1491         @return  rounded SkIRect
1492     */
roundOutSkRect1493     SkIRect roundOut() const {
1494         SkIRect ir;
1495         this->roundOut(&ir);
1496         return ir;
1497     }
1498 
1499     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1500         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1501         and width() and height() will be zero or positive.
1502     */
sortSkRect1503     void sort() {
1504         using std::swap;
1505         if (fLeft > fRight) {
1506             swap(fLeft, fRight);
1507         }
1508 
1509         if (fTop > fBottom) {
1510             swap(fTop, fBottom);
1511         }
1512     }
1513 
1514     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1515         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1516         and width() and height() will be zero or positive.
1517 
1518         @return  sorted SkRect
1519     */
makeSortedSkRect1520     SkRect makeSorted() const {
1521         return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
1522                         SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
1523     }
1524 
1525     /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1526         entries.
1527 
1528         @return  pointer to fLeft
1529     */
asScalarsSkRect1530     const SkScalar* asScalars() const { return &fLeft; }
1531 
1532     /** Writes text representation of SkRect to standard output. Set asHex to true to
1533         generate exact binary representations of floating point numbers.
1534 
1535         @param asHex  true if SkScalar values are written as hexadecimal
1536     */
1537     void dump(bool asHex) const;
1538 
1539     void dump(std::string& desc, int depth) const;
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