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/SkScalar.h"
13 #include "include/core/SkSize.h"
14 #include "include/core/SkTypes.h"
15 #include "include/private/base/SkSafe32.h"
16 #include "include/private/base/SkTFitsIn.h"
17
18 #include <string>
19 #include <algorithm>
20 #include <cstdint>
21
22 struct SkRect;
23
24 /** \struct SkIRect
25 SkIRect holds four 32-bit integer coordinates describing the upper and
26 lower bounds of a rectangle. SkIRect may be created from outer bounds or
27 from position, width, and height. SkIRect describes an area; if its right
28 is less than or equal to its left, or if its bottom is less than or equal to
29 its top, it is considered empty.
30 */
31 struct SK_API SkIRect {
32 int32_t fLeft; //!< smaller x-axis bounds
33 int32_t fTop; //!< smaller y-axis bounds
34 int32_t fRight; //!< larger x-axis bounds
35 int32_t fBottom; //!< larger y-axis bounds
36
37 /** Returns constructed SkIRect set to (0, 0, 0, 0).
38 Many other rectangles are empty; if left is equal to or greater than right,
39 or if top is equal to or greater than bottom. Setting all members to zero
40 is a convenience, but does not designate a special empty rectangle.
41
42 @return bounds (0, 0, 0, 0)
43 */
MakeEmptySkIRect44 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
45 return SkIRect{0, 0, 0, 0};
46 }
47
48 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
49 may be negative.
50
51 @param w width of constructed SkIRect
52 @param h height of constructed SkIRect
53 @return bounds (0, 0, w, h)
54 */
MakeWHSkIRect55 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
56 return SkIRect{0, 0, w, h};
57 }
58
59 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
60 Does not validate input; size.width() or size.height() may be negative.
61
62 @param size values for SkIRect width and height
63 @return bounds (0, 0, size.width(), size.height())
64 */
MakeSizeSkIRect65 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
66 return SkIRect{0, 0, size.fWidth, size.fHeight};
67 }
68
69 /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
70 pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
71 negative.
72
73 @param pt values for SkIRect fLeft and fTop
74 @param size values for SkIRect width and height
75 @return bounds at pt with width and height of size
76 */
MakePtSizeSkIRect77 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakePtSize(SkIPoint pt, SkISize size) {
78 return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
79 }
80
81 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
82 result in fLeft greater than fRight, or fTop greater than fBottom.
83
84 @param l integer stored in fLeft
85 @param t integer stored in fTop
86 @param r integer stored in fRight
87 @param b integer stored in fBottom
88 @return bounds (l, t, r, b)
89 */
MakeLTRBSkIRect90 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
91 int32_t r, int32_t b) {
92 return SkIRect{l, t, r, b};
93 }
94
95 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
96 Does not validate input; w or h may be negative.
97
98 @param x stored in fLeft
99 @param y stored in fTop
100 @param w added to x and stored in fRight
101 @param h added to y and stored in fBottom
102 @return bounds at (x, y) with width w and height h
103 */
MakeXYWHSkIRect104 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
105 int32_t w, int32_t h) {
106 return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
107 }
108
109 /** Returns left edge of SkIRect, if sorted.
110 Call sort() to reverse fLeft and fRight if needed.
111
112 @return fLeft
113 */
leftSkIRect114 constexpr int32_t left() const { return fLeft; }
115
116 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
117 and sort() to reverse fTop and fBottom if needed.
118
119 @return fTop
120 */
topSkIRect121 constexpr int32_t top() const { return fTop; }
122
123 /** Returns right edge of SkIRect, if sorted.
124 Call sort() to reverse fLeft and fRight if needed.
125
126 @return fRight
127 */
rightSkIRect128 constexpr int32_t right() const { return fRight; }
129
130 /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
131 and sort() to reverse fTop and fBottom if needed.
132
133 @return fBottom
134 */
bottomSkIRect135 constexpr int32_t bottom() const { return fBottom; }
136
137 /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
138 and sort() to reverse fLeft and fRight if needed.
139
140 @return fLeft
141 */
xSkIRect142 constexpr int32_t x() const { return fLeft; }
143
144 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
145 and sort() to reverse fTop and fBottom if needed.
146
147 @return fTop
148 */
ySkIRect149 constexpr int32_t y() const { return fTop; }
150
151 // Experimental
topLeftSkIRect152 constexpr SkIPoint topLeft() const { return {fLeft, fTop}; }
153
154 /** Returns span on the x-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 fRight minus fLeft
158 */
widthSkIRect159 constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
160
161 /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
162 result fits in 32-bit signed integer; result may be negative.
163
164 @return fBottom minus fTop
165 */
heightSkIRect166 constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
167
168 /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
169 or if result fits in 32-bit signed integer; result may be negative.
170
171 @return SkISize (width, height)
172 */
sizeSkIRect173 constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); }
174
175 /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
176 result may be negative. This is safer than calling width() since width() might
177 overflow in its calculation.
178
179 @return fRight minus fLeft cast to int64_t
180 */
width64SkIRect181 constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
182
183 /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
184 result may be negative. This is safer than calling height() since height() might
185 overflow in its calculation.
186
187 @return fBottom minus fTop cast to int64_t
188 */
height64SkIRect189 constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
190
191 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
192 to or greater than fBottom. Call sort() to reverse rectangles with negative
193 width64() or height64().
194
195 @return true if width64() or height64() are zero or negative
196 */
isEmpty64SkIRect197 bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
198
199 /** Returns true if width() or height() are zero or negative.
200
201 @return true if width() or height() are zero or negative
202 */
isEmptySkIRect203 bool isEmpty() const {
204 int64_t w = this->width64();
205 int64_t h = this->height64();
206 if (w <= 0 || h <= 0) {
207 return true;
208 }
209 // Return true if either exceeds int32_t
210 return !SkTFitsIn<int32_t>(w | h);
211 }
212
213 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
214 identical to corresponding members in b.
215
216 @param a SkIRect to compare
217 @param b SkIRect to compare
218 @return true if members are equal
219 */
220 friend bool operator==(const SkIRect& a, const SkIRect& b) {
221 return a.fLeft == b.fLeft && a.fTop == b.fTop &&
222 a.fRight == b.fRight && a.fBottom == b.fBottom;
223 }
224
225 /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
226 identical to the corresponding member in b.
227
228 @param a SkIRect to compare
229 @param b SkIRect to compare
230 @return true if members are not equal
231 */
232 friend bool operator!=(const SkIRect& a, const SkIRect& b) {
233 return a.fLeft != b.fLeft || a.fTop != b.fTop ||
234 a.fRight != b.fRight || a.fBottom != b.fBottom;
235 }
236
237 /** Sets SkIRect to (0, 0, 0, 0).
238
239 Many other rectangles are empty; if left is equal to or greater than right,
240 or if top is equal to or greater than bottom. Setting all members to zero
241 is a convenience, but does not designate a special empty rectangle.
242 */
setEmptySkIRect243 void setEmpty() { memset(this, 0, sizeof(*this)); }
244
245 /** Sets SkIRect to (left, top, right, bottom).
246 left and right are not sorted; left is not necessarily less than right.
247 top and bottom are not sorted; top is not necessarily less than bottom.
248
249 @param left stored in fLeft
250 @param top stored in fTop
251 @param right stored in fRight
252 @param bottom stored in fBottom
253 */
setLTRBSkIRect254 void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
255 fLeft = left;
256 fTop = top;
257 fRight = right;
258 fBottom = bottom;
259 }
260
261 /** Sets SkIRect to: (x, y, x + width, y + height).
262 Does not validate input; width or height may be negative.
263
264 @param x stored in fLeft
265 @param y stored in fTop
266 @param width added to x and stored in fRight
267 @param height added to y and stored in fBottom
268 */
setXYWHSkIRect269 void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
270 fLeft = x;
271 fTop = y;
272 fRight = Sk32_sat_add(x, width);
273 fBottom = Sk32_sat_add(y, height);
274 }
275
setWHSkIRect276 void setWH(int32_t width, int32_t height) {
277 fLeft = 0;
278 fTop = 0;
279 fRight = width;
280 fBottom = height;
281 }
282
setSizeSkIRect283 void setSize(SkISize size) {
284 fLeft = 0;
285 fTop = 0;
286 fRight = size.width();
287 fBottom = size.height();
288 }
289
290 /** Returns SkIRect offset by (dx, dy).
291
292 If dx is negative, SkIRect returned is moved to the left.
293 If dx is positive, SkIRect returned is moved to the right.
294 If dy is negative, SkIRect returned is moved upward.
295 If dy is positive, SkIRect returned is moved downward.
296
297 @param dx offset added to fLeft and fRight
298 @param dy offset added to fTop and fBottom
299 @return SkIRect offset by dx and dy, with original width and height
300 */
makeOffsetSkIRect301 constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
302 return {
303 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
304 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
305 };
306 }
307
308 /** Returns SkIRect offset by (offset.x(), offset.y()).
309
310 If offset.x() is negative, SkIRect returned is moved to the left.
311 If offset.x() is positive, SkIRect returned is moved to the right.
312 If offset.y() is negative, SkIRect returned is moved upward.
313 If offset.y() is positive, SkIRect returned is moved downward.
314
315 @param offset translation vector
316 @return SkIRect translated by offset, with original width and height
317 */
makeOffsetSkIRect318 constexpr SkIRect makeOffset(SkIVector offset) const {
319 return this->makeOffset(offset.x(), offset.y());
320 }
321
322 /** Returns SkIRect, inset by (dx, dy).
323
324 If dx is negative, SkIRect returned is wider.
325 If dx is positive, SkIRect returned is narrower.
326 If dy is negative, SkIRect returned is taller.
327 If dy is positive, SkIRect returned is shorter.
328
329 @param dx offset added to fLeft and subtracted from fRight
330 @param dy offset added to fTop and subtracted from fBottom
331 @return SkIRect inset symmetrically left and right, top and bottom
332 */
makeInsetSkIRect333 SkIRect makeInset(int32_t dx, int32_t dy) const {
334 return {
335 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
336 Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
337 };
338 }
339
340 /** Returns SkIRect, outset by (dx, dy).
341
342 If dx is negative, SkIRect returned is narrower.
343 If dx is positive, SkIRect returned is wider.
344 If dy is negative, SkIRect returned is shorter.
345 If dy is positive, SkIRect returned is taller.
346
347 @param dx offset subtracted to fLeft and added from fRight
348 @param dy offset subtracted to fTop and added from fBottom
349 @return SkIRect outset symmetrically left and right, top and bottom
350 */
makeOutsetSkIRect351 SkIRect makeOutset(int32_t dx, int32_t dy) const {
352 return {
353 Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
354 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
355 };
356 }
357
358 /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
359
360 If dx is negative, moves SkIRect returned to the left.
361 If dx is positive, moves SkIRect returned to the right.
362 If dy is negative, moves SkIRect returned upward.
363 If dy is positive, moves SkIRect returned downward.
364
365 @param dx offset added to fLeft and fRight
366 @param dy offset added to fTop and fBottom
367 */
offsetSkIRect368 void offset(int32_t dx, int32_t dy) {
369 fLeft = Sk32_sat_add(fLeft, dx);
370 fTop = Sk32_sat_add(fTop, dy);
371 fRight = Sk32_sat_add(fRight, dx);
372 fBottom = Sk32_sat_add(fBottom, dy);
373 }
374
375 /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
376 fTop, fBottom.
377
378 If delta.fX is negative, moves SkIRect returned to the left.
379 If delta.fX is positive, moves SkIRect returned to the right.
380 If delta.fY is negative, moves SkIRect returned upward.
381 If delta.fY is positive, moves SkIRect returned downward.
382
383 @param delta offset added to SkIRect
384 */
offsetSkIRect385 void offset(const SkIPoint& delta) {
386 this->offset(delta.fX, delta.fY);
387 }
388
389 /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
390 are unchanged.
391
392 @param newX stored in fLeft, preserving width()
393 @param newY stored in fTop, preserving height()
394 */
offsetToSkIRect395 void offsetTo(int32_t newX, int32_t newY) {
396 fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
397 fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
398 fLeft = newX;
399 fTop = newY;
400 }
401
402 /** Insets SkIRect by (dx,dy).
403
404 If dx is positive, makes SkIRect narrower.
405 If dx is negative, makes SkIRect wider.
406 If dy is positive, makes SkIRect shorter.
407 If dy is negative, makes SkIRect taller.
408
409 @param dx offset added to fLeft and subtracted from fRight
410 @param dy offset added to fTop and subtracted from fBottom
411 */
insetSkIRect412 void inset(int32_t dx, int32_t dy) {
413 fLeft = Sk32_sat_add(fLeft, dx);
414 fTop = Sk32_sat_add(fTop, dy);
415 fRight = Sk32_sat_sub(fRight, dx);
416 fBottom = Sk32_sat_sub(fBottom, dy);
417 }
418
419 /** Outsets SkIRect by (dx, dy).
420
421 If dx is positive, makes SkIRect wider.
422 If dx is negative, makes SkIRect narrower.
423 If dy is positive, makes SkIRect taller.
424 If dy is negative, makes SkIRect shorter.
425
426 @param dx subtracted to fLeft and added from fRight
427 @param dy subtracted to fTop and added from fBottom
428 */
outsetSkIRect429 void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
430
431 /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
432
433 If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
434 If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
435 If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
436 If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
437
438 The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
439 greater than right, the SkIRect will be considered empty. Call sort() after this call
440 if that is not the desired behavior.
441
442 @param dL offset added to fLeft
443 @param dT offset added to fTop
444 @param dR offset added to fRight
445 @param dB offset added to fBottom
446 */
adjustSkIRect447 void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
448 fLeft = Sk32_sat_add(fLeft, dL);
449 fTop = Sk32_sat_add(fTop, dT);
450 fRight = Sk32_sat_add(fRight, dR);
451 fBottom = Sk32_sat_add(fBottom, dB);
452 }
453
454 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
455 Returns false if SkIRect is empty.
456
457 Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
458 returns true if constructed area is completely enclosed by SkIRect area.
459
460 @param x test SkIPoint x-coordinate
461 @param y test SkIPoint y-coordinate
462 @return true if (x, y) is inside SkIRect
463 */
containsSkIRect464 bool contains(int32_t x, int32_t y) const {
465 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
466 }
467
468 /** Returns true if SkIRect contains r.
469 Returns false if SkIRect is empty or r is empty.
470
471 SkIRect contains r when SkIRect area completely includes r area.
472
473 @param r SkIRect contained
474 @return true if all sides of SkIRect are outside r
475 */
containsSkIRect476 bool contains(const SkIRect& r) const {
477 return !r.isEmpty() && !this->isEmpty() && // check for empties
478 fLeft <= r.fLeft && fTop <= r.fTop &&
479 fRight >= r.fRight && fBottom >= r.fBottom;
480 }
481
482 /** Returns true if SkIRect contains r.
483 Returns false if SkIRect is empty or r is empty.
484
485 SkIRect contains r when SkIRect area completely includes r area.
486
487 @param r SkRect contained
488 @return true if all sides of SkIRect are outside r
489 */
490 inline bool contains(const SkRect& r) const;
491
492 /** Returns true if SkIRect contains construction.
493 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
494
495 Return is undefined if SkIRect is empty or construction is empty.
496
497 @param r SkIRect contained
498 @return true if all sides of SkIRect are outside r
499 */
containsNoEmptyCheckSkIRect500 bool containsNoEmptyCheck(const SkIRect& r) const {
501 SkASSERT(fLeft < fRight && fTop < fBottom);
502 SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
503 return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
504 }
505
506 /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
507 Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
508
509 Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
510
511 @param r limit of result
512 @return true if r and SkIRect have area in common
513 */
intersectSkIRect514 bool intersect(const SkIRect& r) {
515 return this->intersect(*this, r);
516 }
517
518 /** Returns true if a intersects b, and sets SkIRect to intersection.
519 Returns false if a does not intersect b, and leaves SkIRect unchanged.
520
521 Returns false if either a or b is empty, leaving SkIRect unchanged.
522
523 @param a SkIRect to intersect
524 @param b SkIRect to intersect
525 @return true if a and b have area in common
526 */
527 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b);
528
529 /** Returns true if a intersects b.
530 Returns false if either a or b is empty, or do not intersect.
531
532 @param a SkIRect to intersect
533 @param b SkIRect to intersect
534 @return true if a and b have area in common
535 */
IntersectsSkIRect536 static bool Intersects(const SkIRect& a, const SkIRect& b) {
537 return SkIRect{}.intersect(a, b);
538 }
539
540 /** Sets SkIRect to the union of itself and r.
541
542 Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
543
544 @param r expansion SkIRect
545
546 example: https://fiddle.skia.org/c/@IRect_join_2
547 */
548 void join(const SkIRect& r);
549
550 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
551 fTop and fBottom if fTop is greater than fBottom. Result may be empty,
552 and width() and height() will be zero or positive.
553 */
sortSkIRect554 void sort() {
555 using std::swap;
556 if (fLeft > fRight) {
557 swap(fLeft, fRight);
558 }
559 if (fTop > fBottom) {
560 swap(fTop, fBottom);
561 }
562 }
563
564 /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
565 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
566 and width() and height() will be zero or positive.
567
568 @return sorted SkIRect
569 */
makeSortedSkIRect570 SkIRect makeSorted() const {
571 return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
572 std::max(fLeft, fRight), std::max(fTop, fBottom));
573 }
574 };
575
576 /** \struct SkRect
577 SkRect holds four SkScalar coordinates describing the upper and
578 lower bounds of a rectangle. SkRect may be created from outer bounds or
579 from position, width, and height. SkRect describes an area; if its right
580 is less than or equal to its left, or if its bottom is less than or equal to
581 its top, it is considered empty.
582 */
583 struct SK_API SkRect {
584 SkScalar fLeft; //!< smaller x-axis bounds
585 SkScalar fTop; //!< smaller y-axis bounds
586 SkScalar fRight; //!< larger x-axis bounds
587 SkScalar fBottom; //!< larger y-axis bounds
588
589 /** Returns constructed SkRect set to (0, 0, 0, 0).
590 Many other rectangles are empty; if left is equal to or greater than right,
591 or if top is equal to or greater than bottom. Setting all members to zero
592 is a convenience, but does not designate a special empty rectangle.
593
594 @return bounds (0, 0, 0, 0)
595 */
MakeEmptySkRect596 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
597 return SkRect{0, 0, 0, 0};
598 }
599
600 /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
601 validate input; w or h may be negative.
602
603 Passing integer values may generate a compiler warning since SkRect cannot
604 represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
605
606 @param w SkScalar width of constructed SkRect
607 @param h SkScalar height of constructed SkRect
608 @return bounds (0, 0, w, h)
609 */
MakeWHSkRect610 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
611 return SkRect{0, 0, w, h};
612 }
613
614 /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
615 input; w or h may be negative.
616
617 Use to avoid a compiler warning that input may lose precision when stored.
618 Use SkIRect for an exact integer rectangle.
619
620 @param w integer width of constructed SkRect
621 @param h integer height of constructed SkRect
622 @return bounds (0, 0, w, h)
623 */
MakeIWHSkRect624 static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
625 return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
626 }
627
628 /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
629 validate input; size.width() or size.height() may be negative.
630
631 @param size SkScalar values for SkRect width and height
632 @return bounds (0, 0, size.width(), size.height())
633 */
MakeSizeSkRect634 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
635 return SkRect{0, 0, size.fWidth, size.fHeight};
636 }
637
638 /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
639 result in fLeft greater than fRight, or fTop greater than fBottom.
640
641 @param l SkScalar stored in fLeft
642 @param t SkScalar stored in fTop
643 @param r SkScalar stored in fRight
644 @param b SkScalar stored in fBottom
645 @return bounds (l, t, r, b)
646 */
MakeLTRBSkRect647 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
648 SkScalar b) {
649 return SkRect {l, t, r, b};
650 }
651
652 /** Returns constructed SkRect set to (x, y, x + w, y + h).
653 Does not validate input; w or h may be negative.
654
655 @param x stored in fLeft
656 @param y stored in fTop
657 @param w added to x and stored in fRight
658 @param h added to y and stored in fBottom
659 @return bounds at (x, y) with width w and height h
660 */
MakeXYWHSkRect661 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
662 SkScalar h) {
663 return SkRect {x, y, x + w, y + h};
664 }
665
666 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
667 Does not validate input; size.width() or size.height() may be negative.
668
669 @param size integer values for SkRect width and height
670 @return bounds (0, 0, size.width(), size.height())
671 */
MakeSkRect672 static SkRect Make(const SkISize& size) {
673 return MakeIWH(size.width(), size.height());
674 }
675
676 /** Returns constructed SkIRect set to irect, promoting integers to scalar.
677 Does not validate input; fLeft may be greater than fRight, fTop may be greater
678 than fBottom.
679
680 @param irect integer unsorted bounds
681 @return irect members converted to SkScalar
682 */
MakeSkRect683 static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
684 return {
685 SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
686 SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
687 };
688 }
689
690 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
691 to or greater than fBottom. Call sort() to reverse rectangles with negative
692 width() or height().
693
694 @return true if width() or height() are zero or negative
695 */
isEmptySkRect696 bool isEmpty() const {
697 // We write it as the NOT of a non-empty rect, so we will return true if any values
698 // are NaN.
699 return !(fLeft < fRight && fTop < fBottom);
700 }
701
702 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
703 to or less than fBottom. Call sort() to reverse rectangles with negative
704 width() or height().
705
706 @return true if width() or height() are zero or positive
707 */
isSortedSkRect708 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
709
710 /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
711 and SK_ScalarMax or smaller.
712
713 @return true if no member is infinite or NaN
714 */
isFiniteSkRect715 bool isFinite() const {
716 float accum = 0;
717 accum *= fLeft;
718 accum *= fTop;
719 accum *= fRight;
720 accum *= fBottom;
721
722 // accum is either NaN or it is finite (zero).
723 SkASSERT(0 == accum || SkScalarIsNaN(accum));
724
725 // value==value will be true iff value is not NaN
726 // TODO: is it faster to say !accum or accum==accum?
727 return !SkScalarIsNaN(accum);
728 }
729
730 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
731 Call sort() to reverse fLeft and fRight if needed.
732
733 @return fLeft
734 */
xSkRect735 constexpr SkScalar x() const { return fLeft; }
736
737 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
738 and sort() to reverse fTop and fBottom if needed.
739
740 @return fTop
741 */
ySkRect742 constexpr SkScalar y() const { return fTop; }
743
744 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
745 Call sort() to reverse fLeft and fRight if needed.
746
747 @return fLeft
748 */
leftSkRect749 constexpr SkScalar left() const { return fLeft; }
750
751 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
752 and sort() to reverse fTop and fBottom if needed.
753
754 @return fTop
755 */
topSkRect756 constexpr SkScalar top() const { return fTop; }
757
758 /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
759 Call sort() to reverse fLeft and fRight if needed.
760
761 @return fRight
762 */
rightSkRect763 constexpr SkScalar right() const { return fRight; }
764
765 /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
766 and sort() to reverse fTop and fBottom if needed.
767
768 @return fBottom
769 */
bottomSkRect770 constexpr SkScalar bottom() const { return fBottom; }
771
772 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
773 result fits in 32-bit float; result may be negative or infinity.
774
775 @return fRight minus fLeft
776 */
widthSkRect777 constexpr SkScalar width() const { return fRight - fLeft; }
778
779 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
780 result fits in 32-bit float; result may be negative or infinity.
781
782 @return fBottom minus fTop
783 */
heightSkRect784 constexpr SkScalar height() const { return fBottom - fTop; }
785
786 /** Returns average of left edge and right edge. Result does not change if SkRect
787 is sorted. Result may overflow to infinity if SkRect is far from the origin.
788
789 @return midpoint on x-axis
790 */
centerXSkRect791 constexpr SkScalar centerX() const {
792 // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
793 return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
794 }
795
796 /** Returns average of top edge and bottom edge. Result does not change if SkRect
797 is sorted.
798
799 @return midpoint on y-axis
800 */
centerYSkRect801 constexpr SkScalar centerY() const {
802 // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
803 return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
804 }
805
806 /** Returns the point this->centerX(), this->centerY().
807 @return rectangle center
808 */
centerSkRect809 constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; }
810
811 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
812 equal to the corresponding members in b.
813
814 a and b are not equal if either contain NaN. a and b are equal if members
815 contain zeroes with different signs.
816
817 @param a SkRect to compare
818 @param b SkRect to compare
819 @return true if members are equal
820 */
821 friend bool operator==(const SkRect& a, const SkRect& b) {
822 return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
823 }
824
825 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
826 equal the corresponding members in b.
827
828 a and b are not equal if either contain NaN. a and b are equal if members
829 contain zeroes with different signs.
830
831 @param a SkRect to compare
832 @param b SkRect to compare
833 @return true if members are not equal
834 */
835 friend bool operator!=(const SkRect& a, const SkRect& b) {
836 return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
837 }
838
839 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
840 bottom-right, bottom-left.
841
842 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
843
844 @param quad storage for corners of SkRect
845
846 example: https://fiddle.skia.org/c/@Rect_toQuad
847 */
848 void toQuad(SkPoint quad[4]) const;
849
850 /** Sets SkRect to (0, 0, 0, 0).
851
852 Many other rectangles are empty; if left is equal to or greater than right,
853 or if top is equal to or greater than bottom. Setting all members to zero
854 is a convenience, but does not designate a special empty rectangle.
855 */
setEmptySkRect856 void setEmpty() { *this = MakeEmpty(); }
857
858 /** Sets SkRect to src, promoting src members from integer to scalar.
859 Very large values in src may lose precision.
860
861 @param src integer SkRect
862 */
setSkRect863 void set(const SkIRect& src) {
864 fLeft = SkIntToScalar(src.fLeft);
865 fTop = SkIntToScalar(src.fTop);
866 fRight = SkIntToScalar(src.fRight);
867 fBottom = SkIntToScalar(src.fBottom);
868 }
869
870 /** Sets SkRect to (left, top, right, bottom).
871 left and right are not sorted; left is not necessarily less than right.
872 top and bottom are not sorted; top is not necessarily less than bottom.
873
874 @param left stored in fLeft
875 @param top stored in fTop
876 @param right stored in fRight
877 @param bottom stored in fBottom
878 */
setLTRBSkRect879 void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
880 fLeft = left;
881 fTop = top;
882 fRight = right;
883 fBottom = bottom;
884 }
885
886 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
887 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
888
889 Result is either empty or sorted: fLeft is less than or equal to fRight, and
890 fTop is less than or equal to fBottom.
891
892 @param pts SkPoint array
893 @param count entries in array
894 */
setBoundsSkRect895 void setBounds(const SkPoint pts[], int count) {
896 (void)this->setBoundsCheck(pts, count);
897 }
898
899 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
900 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
901 sets SkRect to (0, 0, 0, 0).
902
903 Result is either empty or sorted: fLeft is less than or equal to fRight, and
904 fTop is less than or equal to fBottom.
905
906 @param pts SkPoint array
907 @param count entries in array
908 @return true if all SkPoint values are finite
909
910 example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
911 */
912 bool setBoundsCheck(const SkPoint pts[], int count);
913
914 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
915 contains infinity or NaN, all SkRect dimensions are set to NaN.
916
917 @param pts SkPoint array
918 @param count entries in array
919
920 example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
921 */
922 void setBoundsNoCheck(const SkPoint pts[], int count);
923
924 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
925 sorted and may be empty. Does not check to see if values are finite.
926
927 @param p0 corner to include
928 @param p1 corner to include
929 */
setSkRect930 void set(const SkPoint& p0, const SkPoint& p1) {
931 fLeft = std::min(p0.fX, p1.fX);
932 fRight = std::max(p0.fX, p1.fX);
933 fTop = std::min(p0.fY, p1.fY);
934 fBottom = std::max(p0.fY, p1.fY);
935 }
936
937 /** Sets SkRect to (x, y, x + width, y + height).
938 Does not validate input; width or height may be negative.
939
940 @param x stored in fLeft
941 @param y stored in fTop
942 @param width added to x and stored in fRight
943 @param height added to y and stored in fBottom
944 */
setXYWHSkRect945 void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
946 fLeft = x;
947 fTop = y;
948 fRight = x + width;
949 fBottom = y + height;
950 }
951
952 /** Sets SkRect to (0, 0, width, height). Does not validate input;
953 width or height may be negative.
954
955 @param width stored in fRight
956 @param height stored in fBottom
957 */
setWHSkRect958 void setWH(SkScalar width, SkScalar height) {
959 fLeft = 0;
960 fTop = 0;
961 fRight = width;
962 fBottom = height;
963 }
setIWHSkRect964 void setIWH(int32_t width, int32_t height) {
965 this->setWH(SkIntToScalar(width), SkIntToScalar(height));
966 }
967
968 /** Returns SkRect offset by (dx, dy).
969
970 If dx is negative, SkRect returned is moved to the left.
971 If dx is positive, SkRect returned is moved to the right.
972 If dy is negative, SkRect returned is moved upward.
973 If dy is positive, SkRect returned is moved downward.
974
975 @param dx added to fLeft and fRight
976 @param dy added to fTop and fBottom
977 @return SkRect offset on axes, with original width and height
978 */
makeOffsetSkRect979 constexpr SkRect makeOffset(SkScalar dx, SkScalar dy) const {
980 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
981 }
982
983 /** Returns SkRect offset by v.
984
985 @param v added to rect
986 @return SkRect offset on axes, with original width and height
987 */
makeOffsetSkRect988 constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
989
990 /** Returns SkRect, inset by (dx, dy).
991
992 If dx is negative, SkRect returned is wider.
993 If dx is positive, SkRect returned is narrower.
994 If dy is negative, SkRect returned is taller.
995 If dy is positive, SkRect returned is shorter.
996
997 @param dx added to fLeft and subtracted from fRight
998 @param dy added to fTop and subtracted from fBottom
999 @return SkRect inset symmetrically left and right, top and bottom
1000 */
makeInsetSkRect1001 SkRect makeInset(SkScalar dx, SkScalar dy) const {
1002 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1003 }
1004
1005 /** Returns SkRect, outset by (dx, dy).
1006
1007 If dx is negative, SkRect returned is narrower.
1008 If dx is positive, SkRect returned is wider.
1009 If dy is negative, SkRect returned is shorter.
1010 If dy is positive, SkRect returned is taller.
1011
1012 @param dx subtracted to fLeft and added from fRight
1013 @param dy subtracted to fTop and added from fBottom
1014 @return SkRect outset symmetrically left and right, top and bottom
1015 */
makeOutsetSkRect1016 SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1017 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1018 }
1019
1020 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1021
1022 If dx is negative, moves SkRect to the left.
1023 If dx is positive, moves SkRect to the right.
1024 If dy is negative, moves SkRect upward.
1025 If dy is positive, moves SkRect downward.
1026
1027 @param dx offset added to fLeft and fRight
1028 @param dy offset added to fTop and fBottom
1029 */
offsetSkRect1030 void offset(SkScalar dx, SkScalar dy) {
1031 fLeft += dx;
1032 fTop += dy;
1033 fRight += dx;
1034 fBottom += dy;
1035 }
1036
1037 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1038 fTop, fBottom.
1039
1040 If delta.fX is negative, moves SkRect to the left.
1041 If delta.fX is positive, moves SkRect to the right.
1042 If delta.fY is negative, moves SkRect upward.
1043 If delta.fY is positive, moves SkRect downward.
1044
1045 @param delta added to SkRect
1046 */
offsetSkRect1047 void offset(const SkPoint& delta) {
1048 this->offset(delta.fX, delta.fY);
1049 }
1050
1051 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1052 are unchanged.
1053
1054 @param newX stored in fLeft, preserving width()
1055 @param newY stored in fTop, preserving height()
1056 */
offsetToSkRect1057 void offsetTo(SkScalar newX, SkScalar newY) {
1058 fRight += newX - fLeft;
1059 fBottom += newY - fTop;
1060 fLeft = newX;
1061 fTop = newY;
1062 }
1063
1064 /** Insets SkRect by (dx, dy).
1065
1066 If dx is positive, makes SkRect narrower.
1067 If dx is negative, makes SkRect wider.
1068 If dy is positive, makes SkRect shorter.
1069 If dy is negative, makes SkRect taller.
1070
1071 @param dx added to fLeft and subtracted from fRight
1072 @param dy added to fTop and subtracted from fBottom
1073 */
insetSkRect1074 void inset(SkScalar dx, SkScalar dy) {
1075 fLeft += dx;
1076 fTop += dy;
1077 fRight -= dx;
1078 fBottom -= dy;
1079 }
1080
1081 /** Outsets SkRect by (dx, dy).
1082
1083 If dx is positive, makes SkRect wider.
1084 If dx is negative, makes SkRect narrower.
1085 If dy is positive, makes SkRect taller.
1086 If dy is negative, makes SkRect shorter.
1087
1088 @param dx subtracted to fLeft and added from fRight
1089 @param dy subtracted to fTop and added from fBottom
1090 */
outsetSkRect1091 void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
1092
1093 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1094 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1095
1096 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1097
1098 @param r limit of result
1099 @return true if r and SkRect have area in common
1100
1101 example: https://fiddle.skia.org/c/@Rect_intersect
1102 */
1103 bool intersect(const SkRect& r);
1104
1105 /** Returns true if a intersects b, and sets SkRect to intersection.
1106 Returns false if a does not intersect b, and leaves SkRect unchanged.
1107
1108 Returns false if either a or b is empty, leaving SkRect unchanged.
1109
1110 @param a SkRect to intersect
1111 @param b SkRect to intersect
1112 @return true if a and b have area in common
1113 */
1114 bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1115
1116
1117 private:
IntersectsSkRect1118 static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1119 SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1120 SkScalar L = std::max(al, bl);
1121 SkScalar R = std::min(ar, br);
1122 SkScalar T = std::max(at, bt);
1123 SkScalar B = std::min(ab, bb);
1124 return L < R && T < B;
1125 }
1126
1127 public:
1128
1129 /** Returns true if SkRect intersects r.
1130 Returns false if either r or SkRect is empty, or do not intersect.
1131
1132 @param r SkRect to intersect
1133 @return true if r and SkRect have area in common
1134 */
intersectsSkRect1135 bool intersects(const SkRect& r) const {
1136 return Intersects(fLeft, fTop, fRight, fBottom,
1137 r.fLeft, r.fTop, r.fRight, r.fBottom);
1138 }
1139
1140 /** Returns true if a intersects b.
1141 Returns false if either a or b is empty, or do not intersect.
1142
1143 @param a SkRect to intersect
1144 @param b SkRect to intersect
1145 @return true if a and b have area in common
1146 */
IntersectsSkRect1147 static bool Intersects(const SkRect& a, const SkRect& b) {
1148 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1149 b.fLeft, b.fTop, b.fRight, b.fBottom);
1150 }
1151
1152 /** Sets SkRect to the union of itself and r.
1153
1154 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1155 SkRect to r.
1156
1157 @param r expansion SkRect
1158
1159 example: https://fiddle.skia.org/c/@Rect_join_2
1160 */
1161 void join(const SkRect& r);
1162
1163 /** Sets SkRect to the union of itself and r.
1164
1165 Asserts if r is empty and SK_DEBUG is defined.
1166 If SkRect is empty, sets SkRect to r.
1167
1168 May produce incorrect results if r is empty.
1169
1170 @param r expansion SkRect
1171 */
joinNonEmptyArgSkRect1172 void joinNonEmptyArg(const SkRect& r) {
1173 SkASSERT(!r.isEmpty());
1174 // if we are empty, just assign
1175 if (fLeft >= fRight || fTop >= fBottom) {
1176 *this = r;
1177 } else {
1178 this->joinPossiblyEmptyRect(r);
1179 }
1180 }
1181
1182 /** Sets SkRect to the union of itself and the construction.
1183
1184 May produce incorrect results if SkRect or r is empty.
1185
1186 @param r expansion SkRect
1187 */
joinPossiblyEmptyRectSkRect1188 void joinPossiblyEmptyRect(const SkRect& r) {
1189 fLeft = std::min(fLeft, r.left());
1190 fTop = std::min(fTop, r.top());
1191 fRight = std::max(fRight, r.right());
1192 fBottom = std::max(fBottom, r.bottom());
1193 }
1194
1195 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1196 Returns false if SkRect is empty.
1197
1198 @param x test SkPoint x-coordinate
1199 @param y test SkPoint y-coordinate
1200 @return true if (x, y) is inside SkRect
1201 */
containsSkRect1202 bool contains(SkScalar x, SkScalar y) const {
1203 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1204 }
1205
1206 /** Returns true if SkRect contains r.
1207 Returns false if SkRect is empty or r is empty.
1208
1209 SkRect contains r when SkRect area completely includes r area.
1210
1211 @param r SkRect contained
1212 @return true if all sides of SkRect are outside r
1213 */
containsSkRect1214 bool contains(const SkRect& r) const {
1215 // todo: can we eliminate the this->isEmpty check?
1216 return !r.isEmpty() && !this->isEmpty() &&
1217 fLeft <= r.fLeft && fTop <= r.fTop &&
1218 fRight >= r.fRight && fBottom >= r.fBottom;
1219 }
1220
1221 /** Returns true if SkRect contains r.
1222 Returns false if SkRect is empty or r is empty.
1223
1224 SkRect contains r when SkRect area completely includes r area.
1225
1226 @param r SkIRect contained
1227 @return true if all sides of SkRect are outside r
1228 */
containsSkRect1229 bool contains(const SkIRect& r) const {
1230 // todo: can we eliminate the this->isEmpty check?
1231 return !r.isEmpty() && !this->isEmpty() &&
1232 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1233 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1234 }
1235
1236 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1237 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1238 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1239
1240 @param dst storage for SkIRect
1241 */
roundSkRect1242 void round(SkIRect* dst) const {
1243 SkASSERT(dst);
1244 dst->setLTRB(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1245 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1246 }
1247
1248 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1249 up fRight and fBottom, using
1250 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1251 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1252
1253 @param dst storage for SkIRect
1254 */
roundOutSkRect1255 void roundOut(SkIRect* dst) const {
1256 SkASSERT(dst);
1257 dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1258 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1259 }
1260
1261 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1262 up fRight and fBottom, using
1263 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1264 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1265
1266 @param dst storage for SkRect
1267 */
roundOutSkRect1268 void roundOut(SkRect* dst) const {
1269 dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
1270 SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
1271 }
1272
1273 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1274 of fRight and fBottom, using
1275 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1276 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1277
1278 @param dst storage for SkIRect
1279 */
roundInSkRect1280 void roundIn(SkIRect* dst) const {
1281 SkASSERT(dst);
1282 dst->setLTRB(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1283 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1284 }
1285
1286 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1287 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1288 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1289
1290 @return rounded SkIRect
1291 */
roundSkRect1292 SkIRect round() const {
1293 SkIRect ir;
1294 this->round(&ir);
1295 return ir;
1296 }
1297
1298 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1299 up fRight and fBottom, using
1300 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1301 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1302
1303 @return rounded SkIRect
1304 */
roundOutSkRect1305 SkIRect roundOut() const {
1306 SkIRect ir;
1307 this->roundOut(&ir);
1308 return ir;
1309 }
1310 /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1311 of fRight and fBottom, using
1312 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1313 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1314
1315 @return rounded SkIRect
1316 */
roundInSkRect1317 SkIRect roundIn() const {
1318 SkIRect ir;
1319 this->roundIn(&ir);
1320 return ir;
1321 }
1322
1323 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1324 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1325 and width() and height() will be zero or positive.
1326 */
sortSkRect1327 void sort() {
1328 using std::swap;
1329 if (fLeft > fRight) {
1330 swap(fLeft, fRight);
1331 }
1332
1333 if (fTop > fBottom) {
1334 swap(fTop, fBottom);
1335 }
1336 }
1337
1338 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1339 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1340 and width() and height() will be zero or positive.
1341
1342 @return sorted SkRect
1343 */
makeSortedSkRect1344 SkRect makeSorted() const {
1345 return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1346 std::max(fLeft, fRight), std::max(fTop, fBottom));
1347 }
1348
1349 /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1350 entries.
1351
1352 @return pointer to fLeft
1353 */
asScalarsSkRect1354 const SkScalar* asScalars() const { return &fLeft; }
1355
1356 /** Writes text representation of SkRect to standard output. Set asHex to true to
1357 generate exact binary representations of floating point numbers.
1358
1359 @param asHex true if SkScalar values are written as hexadecimal
1360
1361 example: https://fiddle.skia.org/c/@Rect_dump
1362 */
1363 void dump(bool asHex) const;
1364
1365 /** Writes text representation of SkRect to standard output. The representation may be
1366 directly compiled as C++ code. Floating point values are written
1367 with limited precision; it may not be possible to reconstruct original SkRect
1368 from output.
1369 */
dumpSkRect1370 void dump() const { this->dump(false); }
1371
1372 /** Writes text representation of SkRect to standard output. The representation may be
1373 directly compiled as C++ code. Floating point values are written
1374 in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1375 original SkRect.
1376
1377 Use instead of dump() when submitting
1378 */
dumpHexSkRect1379 void dumpHex() const { this->dump(true); }
1380 };
1381
contains(const SkRect & r)1382 inline bool SkIRect::contains(const SkRect& r) const {
1383 return !r.isEmpty() && !this->isEmpty() && // check for empties
1384 (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1385 (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1386 }
1387
1388 #endif
1389