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