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 /** Returns constructed SkIRect set to (0, 0, 0, 0).
35 Many other rectangles are empty; if left is equal to or greater than right,
36 or if top is equal to or greater than bottom. Setting all members to zero
37 is a convenience, but does not designate a special empty rectangle.
38
39 @return bounds (0, 0, 0, 0)
40 */
MakeEmptySkIRect41 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
42 return SkIRect{0, 0, 0, 0};
43 }
44
45 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
46 may be negative.
47
48 @param w width of constructed SkIRect
49 @param h height of constructed SkIRect
50 @return bounds (0, 0, w, h)
51 */
MakeWHSkIRect52 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
53 return SkIRect{0, 0, w, h};
54 }
55
56 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
57 Does not validate input; size.width() or size.height() may be negative.
58
59 @param size values for SkIRect width and height
60 @return bounds (0, 0, size.width(), size.height())
61 */
MakeSizeSkIRect62 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
63 return SkIRect{0, 0, size.fWidth, size.fHeight};
64 }
65
66 /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
67 pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
68 negative.
69
70 @param pt values for SkIRect fLeft and fTop
71 @param size values for SkIRect width and height
72 @return bounds at pt with width and height of size
73 */
MakePtSizeSkIRect74 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakePtSize(SkIPoint pt, SkISize size) {
75 return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
76 }
77
78 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
79 result in fLeft greater than fRight, or fTop greater than fBottom.
80
81 @param l integer stored in fLeft
82 @param t integer stored in fTop
83 @param r integer stored in fRight
84 @param b integer stored in fBottom
85 @return bounds (l, t, r, b)
86 */
MakeLTRBSkIRect87 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
88 int32_t r, int32_t b) {
89 return SkIRect{l, t, r, b};
90 }
91
92 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
93 Does not validate input; w or h may be negative.
94
95 @param x stored in fLeft
96 @param y stored in fTop
97 @param w added to x and stored in fRight
98 @param h added to y and stored in fBottom
99 @return bounds at (x, y) with width w and height h
100 */
MakeXYWHSkIRect101 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
102 int32_t w, int32_t h) {
103 return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
104 }
105
106 /** Returns left edge of SkIRect, if sorted.
107 Call sort() to reverse fLeft and fRight if needed.
108
109 @return fLeft
110 */
leftSkIRect111 int32_t left() const { return fLeft; }
112
113 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
114 and sort() to reverse fTop and fBottom if needed.
115
116 @return fTop
117 */
topSkIRect118 int32_t top() const { return fTop; }
119
120 /** Returns right edge of SkIRect, if sorted.
121 Call sort() to reverse fLeft and fRight if needed.
122
123 @return fRight
124 */
rightSkIRect125 int32_t right() const { return fRight; }
126
127 /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
128 and sort() to reverse fTop and fBottom if needed.
129
130 @return fBottom
131 */
bottomSkIRect132 int32_t bottom() const { return fBottom; }
133
134 /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
135 and sort() to reverse fLeft and fRight if needed.
136
137 @return fLeft
138 */
xSkIRect139 int32_t x() const { return fLeft; }
140
141 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
142 and sort() to reverse fTop and fBottom if needed.
143
144 @return fTop
145 */
ySkIRect146 int32_t y() const { return fTop; }
147
148 // Experimental
topLeftSkIRect149 SkIPoint topLeft() const { return {fLeft, fTop}; }
150
151 /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
152 result fits in 32-bit signed integer; result may be negative.
153
154 @return fRight minus fLeft
155 */
widthSkIRect156 int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
157
158 /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
159 result fits in 32-bit signed integer; result may be negative.
160
161 @return fBottom minus fTop
162 */
heightSkIRect163 int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
164
165 /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
166 or if result fits in 32-bit signed integer; result may be negative.
167
168 @return SkISize (width, height)
169 */
sizeSkIRect170 SkISize size() const { return SkISize::Make(this->width(), this->height()); }
171
172 /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
173 result may be negative. This is safer than calling width() since width() might
174 overflow in its calculation.
175
176 @return fRight minus fLeft cast to int64_t
177 */
width64SkIRect178 int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
179
180 /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
181 result may be negative. This is safer than calling height() since height() might
182 overflow in its calculation.
183
184 @return fBottom minus fTop cast to int64_t
185 */
height64SkIRect186 int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
187
188 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
189 to or greater than fBottom. Call sort() to reverse rectangles with negative
190 width64() or height64().
191
192 @return true if width64() or height64() are zero or negative
193 */
isEmpty64SkIRect194 bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
195
196 /** Returns true if width() or height() are zero or negative.
197
198 @return true if width() or height() are zero or negative
199 */
isEmptySkIRect200 bool isEmpty() const {
201 int64_t w = this->width64();
202 int64_t h = this->height64();
203 if (w <= 0 || h <= 0) {
204 return true;
205 }
206 // Return true if either exceeds int32_t
207 return !SkTFitsIn<int32_t>(w | h);
208 }
209
210 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
211 identical to corresponding members in b.
212
213 @param a SkIRect to compare
214 @param b SkIRect to compare
215 @return true if members are equal
216 */
217 friend bool operator==(const SkIRect& a, const SkIRect& b) {
218 return !memcmp(&a, &b, sizeof(a));
219 }
220
221 /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
222 identical to the corresponding member in b.
223
224 @param a SkIRect to compare
225 @param b SkIRect to compare
226 @return true if members are not equal
227 */
228 friend bool operator!=(const SkIRect& a, const SkIRect& b) {
229 return !(a == b);
230 }
231
232 /** Sets SkIRect to (0, 0, 0, 0).
233
234 Many other rectangles are empty; if left is equal to or greater than right,
235 or if top is equal to or greater than bottom. Setting all members to zero
236 is a convenience, but does not designate a special empty rectangle.
237 */
setEmptySkIRect238 void setEmpty() { memset(this, 0, sizeof(*this)); }
239
240 /** Sets SkIRect to (left, top, right, bottom).
241 left and right are not sorted; left is not necessarily less than right.
242 top and bottom are not sorted; top is not necessarily less than bottom.
243
244 @param left stored in fLeft
245 @param top stored in fTop
246 @param right stored in fRight
247 @param bottom stored in fBottom
248 */
setLTRBSkIRect249 void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
250 fLeft = left;
251 fTop = top;
252 fRight = right;
253 fBottom = bottom;
254 }
255
256 /** Sets SkIRect to: (x, y, x + width, y + height).
257 Does not validate input; width or height may be negative.
258
259 @param x stored in fLeft
260 @param y stored in fTop
261 @param width added to x and stored in fRight
262 @param height added to y and stored in fBottom
263 */
setXYWHSkIRect264 void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
265 fLeft = x;
266 fTop = y;
267 fRight = Sk32_sat_add(x, width);
268 fBottom = Sk32_sat_add(y, height);
269 }
270
setWHSkIRect271 void setWH(int32_t width, int32_t height) {
272 fLeft = 0;
273 fTop = 0;
274 fRight = width;
275 fBottom = height;
276 }
277
setSizeSkIRect278 void setSize(SkISize size) {
279 fLeft = 0;
280 fTop = 0;
281 fRight = size.width();
282 fBottom = size.height();
283 }
284
285 /** Returns SkIRect offset by (dx, dy).
286
287 If dx is negative, SkIRect returned is moved to the left.
288 If dx is positive, SkIRect returned is moved to the right.
289 If dy is negative, SkIRect returned is moved upward.
290 If dy is positive, SkIRect returned is moved downward.
291
292 @param dx offset added to fLeft and fRight
293 @param dy offset added to fTop and fBottom
294 @return SkIRect offset by dx and dy, with original width and height
295 */
makeOffsetSkIRect296 constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
297 return {
298 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
299 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
300 };
301 }
302
303 /** Returns SkIRect offset by (offset.x(), offset.y()).
304
305 If offset.x() is negative, SkIRect returned is moved to the left.
306 If offset.x() is positive, SkIRect returned is moved to the right.
307 If offset.y() is negative, SkIRect returned is moved upward.
308 If offset.y() is positive, SkIRect returned is moved downward.
309
310 @param offset translation vector
311 @return SkIRect translated by offset, with original width and height
312 */
makeOffsetSkIRect313 constexpr SkIRect makeOffset(SkIVector offset) const {
314 return this->makeOffset(offset.x(), offset.y());
315 }
316
317 /** Returns SkIRect, inset by (dx, dy).
318
319 If dx is negative, SkIRect returned is wider.
320 If dx is positive, SkIRect returned is narrower.
321 If dy is negative, SkIRect returned is taller.
322 If dy is positive, SkIRect returned is shorter.
323
324 @param dx offset added to fLeft and subtracted from fRight
325 @param dy offset added to fTop and subtracted from fBottom
326 @return SkIRect inset symmetrically left and right, top and bottom
327 */
makeInsetSkIRect328 SkIRect makeInset(int32_t dx, int32_t dy) const {
329 return {
330 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
331 Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
332 };
333 }
334
335 /** Returns SkIRect, outset by (dx, dy).
336
337 If dx is negative, SkIRect returned is narrower.
338 If dx is positive, SkIRect returned is wider.
339 If dy is negative, SkIRect returned is shorter.
340 If dy is positive, SkIRect returned is taller.
341
342 @param dx offset subtracted to fLeft and added from fRight
343 @param dy offset subtracted to fTop and added from fBottom
344 @return SkIRect outset symmetrically left and right, top and bottom
345 */
makeOutsetSkIRect346 SkIRect makeOutset(int32_t dx, int32_t dy) const {
347 return {
348 Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
349 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
350 };
351 }
352
353 /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
354
355 If dx is negative, moves SkIRect returned to the left.
356 If dx is positive, moves SkIRect returned to the right.
357 If dy is negative, moves SkIRect returned upward.
358 If dy is positive, moves SkIRect returned downward.
359
360 @param dx offset added to fLeft and fRight
361 @param dy offset added to fTop and fBottom
362 */
offsetSkIRect363 void offset(int32_t dx, int32_t dy) {
364 fLeft = Sk32_sat_add(fLeft, dx);
365 fTop = Sk32_sat_add(fTop, dy);
366 fRight = Sk32_sat_add(fRight, dx);
367 fBottom = Sk32_sat_add(fBottom, dy);
368 }
369
370 /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
371 fTop, fBottom.
372
373 If delta.fX is negative, moves SkIRect returned to the left.
374 If delta.fX is positive, moves SkIRect returned to the right.
375 If delta.fY is negative, moves SkIRect returned upward.
376 If delta.fY is positive, moves SkIRect returned downward.
377
378 @param delta offset added to SkIRect
379 */
offsetSkIRect380 void offset(const SkIPoint& delta) {
381 this->offset(delta.fX, delta.fY);
382 }
383
384 /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
385 are unchanged.
386
387 @param newX stored in fLeft, preserving width()
388 @param newY stored in fTop, preserving height()
389 */
offsetToSkIRect390 void offsetTo(int32_t newX, int32_t newY) {
391 fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
392 fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
393 fLeft = newX;
394 fTop = newY;
395 }
396
397 /** Insets SkIRect by (dx,dy).
398
399 If dx is positive, makes SkIRect narrower.
400 If dx is negative, makes SkIRect wider.
401 If dy is positive, makes SkIRect shorter.
402 If dy is negative, makes SkIRect taller.
403
404 @param dx offset added to fLeft and subtracted from fRight
405 @param dy offset added to fTop and subtracted from fBottom
406 */
insetSkIRect407 void inset(int32_t dx, int32_t dy) {
408 fLeft = Sk32_sat_add(fLeft, dx);
409 fTop = Sk32_sat_add(fTop, dy);
410 fRight = Sk32_sat_sub(fRight, dx);
411 fBottom = Sk32_sat_sub(fBottom, dy);
412 }
413
414 /** Outsets SkIRect by (dx, dy).
415
416 If dx is positive, makes SkIRect wider.
417 If dx is negative, makes SkIRect narrower.
418 If dy is positive, makes SkIRect taller.
419 If dy is negative, makes SkIRect shorter.
420
421 @param dx subtracted to fLeft and added from fRight
422 @param dy subtracted to fTop and added from fBottom
423 */
outsetSkIRect424 void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
425
426 /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
427
428 If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
429 If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
430 If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
431 If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
432
433 The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
434 greater than right, the SkIRect will be considered empty. Call sort() after this call
435 if that is not the desired behavior.
436
437 @param dL offset added to fLeft
438 @param dT offset added to fTop
439 @param dR offset added to fRight
440 @param dB offset added to fBottom
441 */
adjustSkIRect442 void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
443 fLeft = Sk32_sat_add(fLeft, dL);
444 fTop = Sk32_sat_add(fTop, dT);
445 fRight = Sk32_sat_add(fRight, dR);
446 fBottom = Sk32_sat_add(fBottom, dB);
447 }
448
449 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
450 Returns false if SkIRect is empty.
451
452 Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
453 returns true if constructed area is completely enclosed by SkIRect area.
454
455 @param x test SkIPoint x-coordinate
456 @param y test SkIPoint y-coordinate
457 @return true if (x, y) is inside SkIRect
458 */
containsSkIRect459 bool contains(int32_t x, int32_t y) const {
460 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
461 }
462
463 /** Returns true if SkIRect contains r.
464 Returns false if SkIRect is empty or r is empty.
465
466 SkIRect contains r when SkIRect area completely includes r area.
467
468 @param r SkIRect contained
469 @return true if all sides of SkIRect are outside r
470 */
containsSkIRect471 bool contains(const SkIRect& r) const {
472 return !r.isEmpty() && !this->isEmpty() && // check for empties
473 fLeft <= r.fLeft && fTop <= r.fTop &&
474 fRight >= r.fRight && fBottom >= r.fBottom;
475 }
476
477 /** Returns true if SkIRect contains r.
478 Returns false if SkIRect is empty or r is empty.
479
480 SkIRect contains r when SkIRect area completely includes r area.
481
482 @param r SkRect contained
483 @return true if all sides of SkIRect are outside r
484 */
485 inline bool contains(const SkRect& r) const;
486
487 /** Returns true if SkIRect contains construction.
488 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
489
490 Return is undefined if SkIRect is empty or construction is empty.
491
492 @param r SkIRect contained
493 @return true if all sides of SkIRect are outside r
494 */
containsNoEmptyCheckSkIRect495 bool containsNoEmptyCheck(const SkIRect& r) const {
496 SkASSERT(fLeft < fRight && fTop < fBottom);
497 SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
498 return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
499 }
500
501 /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
502 Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
503
504 Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
505
506 @param r limit of result
507 @return true if r and SkIRect have area in common
508 */
intersectSkIRect509 bool intersect(const SkIRect& r) {
510 return this->intersect(*this, r);
511 }
512
513 /** Returns true if a intersects b, and sets SkIRect to intersection.
514 Returns false if a does not intersect b, and leaves SkIRect unchanged.
515
516 Returns false if either a or b is empty, leaving SkIRect unchanged.
517
518 @param a SkIRect to intersect
519 @param b SkIRect to intersect
520 @return true if a and b have area in common
521 */
522 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b);
523
524 /** Returns true if a intersects b.
525 Returns false if either a or b is empty, or do not intersect.
526
527 @param a SkIRect to intersect
528 @param b SkIRect to intersect
529 @return true if a and b have area in common
530 */
IntersectsSkIRect531 static bool Intersects(const SkIRect& a, const SkIRect& b) {
532 return SkIRect{}.intersect(a, b);
533 }
534
535 /** Sets SkIRect to the union of itself and r.
536
537 Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
538
539 @param r expansion SkIRect
540
541 example: https://fiddle.skia.org/c/@IRect_join_2
542 */
543 void join(const SkIRect& r);
544
545 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
546 fTop and fBottom if fTop is greater than fBottom. Result may be empty,
547 and width() and height() will be zero or positive.
548 */
sortSkIRect549 void sort() {
550 using std::swap;
551 if (fLeft > fRight) {
552 swap(fLeft, fRight);
553 }
554 if (fTop > fBottom) {
555 swap(fTop, fBottom);
556 }
557 }
558
559 /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
560 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
561 and width() and height() will be zero or positive.
562
563 @return sorted SkIRect
564 */
makeSortedSkIRect565 SkIRect makeSorted() const {
566 return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
567 std::max(fLeft, fRight), std::max(fTop, fBottom));
568 }
569 };
570
571 /** \struct SkRect
572 SkRect holds four SkScalar coordinates describing the upper and
573 lower bounds of a rectangle. SkRect may be created from outer bounds or
574 from position, width, and height. SkRect describes an area; if its right
575 is less than or equal to its left, or if its bottom is less than or equal to
576 its top, it is considered empty.
577 */
578 struct SK_API SkRect {
579 SkScalar fLeft; //!< smaller x-axis bounds
580 SkScalar fTop; //!< smaller y-axis bounds
581 SkScalar fRight; //!< larger x-axis bounds
582 SkScalar fBottom; //!< larger y-axis bounds
583
584 /** Returns constructed SkRect set to (0, 0, 0, 0).
585 Many other rectangles are empty; if left is equal to or greater than right,
586 or if top is equal to or greater than bottom. Setting all members to zero
587 is a convenience, but does not designate a special empty rectangle.
588
589 @return bounds (0, 0, 0, 0)
590 */
MakeEmptySkRect591 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
592 return SkRect{0, 0, 0, 0};
593 }
594
595 /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
596 validate input; w or h may be negative.
597
598 Passing integer values may generate a compiler warning since SkRect cannot
599 represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
600
601 @param w SkScalar width of constructed SkRect
602 @param h SkScalar height of constructed SkRect
603 @return bounds (0, 0, w, h)
604 */
MakeWHSkRect605 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
606 return SkRect{0, 0, w, h};
607 }
608
609 /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
610 input; w or h may be negative.
611
612 Use to avoid a compiler warning that input may lose precision when stored.
613 Use SkIRect for an exact integer rectangle.
614
615 @param w integer width of constructed SkRect
616 @param h integer height of constructed SkRect
617 @return bounds (0, 0, w, h)
618 */
MakeIWHSkRect619 static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
620 return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
621 }
622
623 /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
624 validate input; size.width() or size.height() may be negative.
625
626 @param size SkScalar values for SkRect width and height
627 @return bounds (0, 0, size.width(), size.height())
628 */
MakeSizeSkRect629 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
630 return SkRect{0, 0, size.fWidth, size.fHeight};
631 }
632
633 /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
634 result in fLeft greater than fRight, or fTop greater than fBottom.
635
636 @param l SkScalar stored in fLeft
637 @param t SkScalar stored in fTop
638 @param r SkScalar stored in fRight
639 @param b SkScalar stored in fBottom
640 @return bounds (l, t, r, b)
641 */
MakeLTRBSkRect642 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
643 SkScalar b) {
644 return SkRect {l, t, r, b};
645 }
646
647 /** Returns constructed SkRect set to (x, y, x + w, y + h).
648 Does not validate input; w or h may be negative.
649
650 @param x stored in fLeft
651 @param y stored in fTop
652 @param w added to x and stored in fRight
653 @param h added to y and stored in fBottom
654 @return bounds at (x, y) with width w and height h
655 */
MakeXYWHSkRect656 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
657 SkScalar h) {
658 return SkRect {x, y, x + w, y + h};
659 }
660
661 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
662 Does not validate input; size.width() or size.height() may be negative.
663
664 @param size integer values for SkRect width and height
665 @return bounds (0, 0, size.width(), size.height())
666 */
MakeSkRect667 static SkRect Make(const SkISize& size) {
668 return MakeIWH(size.width(), size.height());
669 }
670
671 /** Returns constructed SkIRect set to irect, promoting integers to scalar.
672 Does not validate input; fLeft may be greater than fRight, fTop may be greater
673 than fBottom.
674
675 @param irect integer unsorted bounds
676 @return irect members converted to SkScalar
677 */
MakeSkRect678 static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
679 return {
680 SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
681 SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
682 };
683 }
684
685 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
686 to or greater than fBottom. Call sort() to reverse rectangles with negative
687 width() or height().
688
689 @return true if width() or height() are zero or negative
690 */
isEmptySkRect691 bool isEmpty() const {
692 // We write it as the NOT of a non-empty rect, so we will return true if any values
693 // are NaN.
694 return !(fLeft < fRight && fTop < fBottom);
695 }
696
697 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
698 to or less than fBottom. Call sort() to reverse rectangles with negative
699 width() or height().
700
701 @return true if width() or height() are zero or positive
702 */
isSortedSkRect703 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
704
705 /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
706 and SK_ScalarMax or smaller.
707
708 @return true if no member is infinite or NaN
709 */
isFiniteSkRect710 bool isFinite() const {
711 float accum = 0;
712 accum *= fLeft;
713 accum *= fTop;
714 accum *= fRight;
715 accum *= fBottom;
716
717 // accum is either NaN or it is finite (zero).
718 SkASSERT(0 == accum || SkScalarIsNaN(accum));
719
720 // value==value will be true iff value is not NaN
721 // TODO: is it faster to say !accum or accum==accum?
722 return !SkScalarIsNaN(accum);
723 }
724
725 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
726 Call sort() to reverse fLeft and fRight if needed.
727
728 @return fLeft
729 */
xSkRect730 SkScalar x() const { return fLeft; }
731
732 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
733 and sort() to reverse fTop and fBottom if needed.
734
735 @return fTop
736 */
ySkRect737 SkScalar y() const { return fTop; }
738
739 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
740 Call sort() to reverse fLeft and fRight if needed.
741
742 @return fLeft
743 */
leftSkRect744 SkScalar left() const { return fLeft; }
745
746 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
747 and sort() to reverse fTop and fBottom if needed.
748
749 @return fTop
750 */
topSkRect751 SkScalar top() const { return fTop; }
752
753 /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
754 Call sort() to reverse fLeft and fRight if needed.
755
756 @return fRight
757 */
rightSkRect758 SkScalar right() const { return fRight; }
759
760 /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
761 and sort() to reverse fTop and fBottom if needed.
762
763 @return fBottom
764 */
bottomSkRect765 SkScalar bottom() const { return fBottom; }
766
767 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
768 result fits in 32-bit float; result may be negative or infinity.
769
770 @return fRight minus fLeft
771 */
widthSkRect772 SkScalar width() const { return fRight - fLeft; }
773
774 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
775 result fits in 32-bit float; result may be negative or infinity.
776
777 @return fBottom minus fTop
778 */
heightSkRect779 SkScalar height() const { return fBottom - fTop; }
780
781 /** Returns average of left edge and right edge. Result does not change if SkRect
782 is sorted. Result may overflow to infinity if SkRect is far from the origin.
783
784 @return midpoint on x-axis
785 */
centerXSkRect786 SkScalar centerX() const {
787 // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
788 return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
789 }
790
791 /** Returns average of top edge and bottom edge. Result does not change if SkRect
792 is sorted.
793
794 @return midpoint on y-axis
795 */
centerYSkRect796 SkScalar centerY() const {
797 // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
798 return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
799 }
800
801 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
802 equal to the corresponding members in b.
803
804 a and b are not equal if either contain NaN. a and b are equal if members
805 contain zeroes with different signs.
806
807 @param a SkRect to compare
808 @param b SkRect to compare
809 @return true if members are equal
810 */
811 friend bool operator==(const SkRect& a, const SkRect& b) {
812 return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
813 }
814
815 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
816 equal the corresponding members in b.
817
818 a and b are not equal if either contain NaN. a and b are equal if members
819 contain zeroes with different signs.
820
821 @param a SkRect to compare
822 @param b SkRect to compare
823 @return true if members are not equal
824 */
825 friend bool operator!=(const SkRect& a, const SkRect& b) {
826 return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
827 }
828
829 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
830 bottom-right, bottom-left.
831
832 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
833
834 @param quad storage for corners of SkRect
835
836 example: https://fiddle.skia.org/c/@Rect_toQuad
837 */
838 void toQuad(SkPoint quad[4]) const;
839
840 /** Sets SkRect to (0, 0, 0, 0).
841
842 Many other rectangles are empty; if left is equal to or greater than right,
843 or if top is equal to or greater than bottom. Setting all members to zero
844 is a convenience, but does not designate a special empty rectangle.
845 */
setEmptySkRect846 void setEmpty() { *this = MakeEmpty(); }
847
848 /** Sets SkRect to src, promoting src members from integer to scalar.
849 Very large values in src may lose precision.
850
851 @param src integer SkRect
852 */
setSkRect853 void set(const SkIRect& src) {
854 fLeft = SkIntToScalar(src.fLeft);
855 fTop = SkIntToScalar(src.fTop);
856 fRight = SkIntToScalar(src.fRight);
857 fBottom = SkIntToScalar(src.fBottom);
858 }
859
860 /** Sets SkRect to (left, top, right, bottom).
861 left and right are not sorted; left is not necessarily less than right.
862 top and bottom are not sorted; top is not necessarily less than bottom.
863
864 @param left stored in fLeft
865 @param top stored in fTop
866 @param right stored in fRight
867 @param bottom stored in fBottom
868 */
setLTRBSkRect869 void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
870 fLeft = left;
871 fTop = top;
872 fRight = right;
873 fBottom = bottom;
874 }
875
876 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
877 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
878
879 Result is either empty or sorted: fLeft is less than or equal to fRight, and
880 fTop is less than or equal to fBottom.
881
882 @param pts SkPoint array
883 @param count entries in array
884 */
setBoundsSkRect885 void setBounds(const SkPoint pts[], int count) {
886 (void)this->setBoundsCheck(pts, count);
887 }
888
889 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
890 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
891 sets SkRect to (0, 0, 0, 0).
892
893 Result is either empty or sorted: fLeft is less than or equal to fRight, and
894 fTop is less than or equal to fBottom.
895
896 @param pts SkPoint array
897 @param count entries in array
898 @return true if all SkPoint values are finite
899
900 example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
901 */
902 bool setBoundsCheck(const SkPoint pts[], int count);
903
904 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
905 contains infinity or NaN, all SkRect dimensions are set to NaN.
906
907 @param pts SkPoint array
908 @param count entries in array
909
910 example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
911 */
912 void setBoundsNoCheck(const SkPoint pts[], int count);
913
914 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
915 sorted and may be empty. Does not check to see if values are finite.
916
917 @param p0 corner to include
918 @param p1 corner to include
919 */
setSkRect920 void set(const SkPoint& p0, const SkPoint& p1) {
921 fLeft = std::min(p0.fX, p1.fX);
922 fRight = std::max(p0.fX, p1.fX);
923 fTop = std::min(p0.fY, p1.fY);
924 fBottom = std::max(p0.fY, p1.fY);
925 }
926
927 /** Sets SkRect to (x, y, x + width, y + height).
928 Does not validate input; width or height may be negative.
929
930 @param x stored in fLeft
931 @param y stored in fTop
932 @param width added to x and stored in fRight
933 @param height added to y and stored in fBottom
934 */
setXYWHSkRect935 void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
936 fLeft = x;
937 fTop = y;
938 fRight = x + width;
939 fBottom = y + height;
940 }
941
942 /** Sets SkRect to (0, 0, width, height). Does not validate input;
943 width or height may be negative.
944
945 @param width stored in fRight
946 @param height stored in fBottom
947 */
setWHSkRect948 void setWH(SkScalar width, SkScalar height) {
949 fLeft = 0;
950 fTop = 0;
951 fRight = width;
952 fBottom = height;
953 }
setIWHSkRect954 void setIWH(int32_t width, int32_t height) {
955 this->setWH(SkIntToScalar(width), SkIntToScalar(height));
956 }
957
958 /** Returns SkRect offset by (dx, dy).
959
960 If dx is negative, SkRect returned is moved to the left.
961 If dx is positive, SkRect returned is moved to the right.
962 If dy is negative, SkRect returned is moved upward.
963 If dy is positive, SkRect returned is moved downward.
964
965 @param dx added to fLeft and fRight
966 @param dy added to fTop and fBottom
967 @return SkRect offset on axes, with original width and height
968 */
makeOffsetSkRect969 constexpr SkRect makeOffset(SkScalar dx, SkScalar dy) const {
970 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
971 }
972
973 /** Returns SkRect offset by v.
974
975 @param v added to rect
976 @return SkRect offset on axes, with original width and height
977 */
makeOffsetSkRect978 constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
979
980 /** Returns SkRect, inset by (dx, dy).
981
982 If dx is negative, SkRect returned is wider.
983 If dx is positive, SkRect returned is narrower.
984 If dy is negative, SkRect returned is taller.
985 If dy is positive, SkRect returned is shorter.
986
987 @param dx added to fLeft and subtracted from fRight
988 @param dy added to fTop and subtracted from fBottom
989 @return SkRect inset symmetrically left and right, top and bottom
990 */
makeInsetSkRect991 SkRect makeInset(SkScalar dx, SkScalar dy) const {
992 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
993 }
994
995 /** Returns SkRect, outset by (dx, dy).
996
997 If dx is negative, SkRect returned is narrower.
998 If dx is positive, SkRect returned is wider.
999 If dy is negative, SkRect returned is shorter.
1000 If dy is positive, SkRect returned is taller.
1001
1002 @param dx subtracted to fLeft and added from fRight
1003 @param dy subtracted to fTop and added from fBottom
1004 @return SkRect outset symmetrically left and right, top and bottom
1005 */
makeOutsetSkRect1006 SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1007 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1008 }
1009
1010 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1011
1012 If dx is negative, moves SkRect to the left.
1013 If dx is positive, moves SkRect to the right.
1014 If dy is negative, moves SkRect upward.
1015 If dy is positive, moves SkRect downward.
1016
1017 @param dx offset added to fLeft and fRight
1018 @param dy offset added to fTop and fBottom
1019 */
offsetSkRect1020 void offset(SkScalar dx, SkScalar dy) {
1021 fLeft += dx;
1022 fTop += dy;
1023 fRight += dx;
1024 fBottom += dy;
1025 }
1026
1027 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1028 fTop, fBottom.
1029
1030 If delta.fX is negative, moves SkRect to the left.
1031 If delta.fX is positive, moves SkRect to the right.
1032 If delta.fY is negative, moves SkRect upward.
1033 If delta.fY is positive, moves SkRect downward.
1034
1035 @param delta added to SkRect
1036 */
offsetSkRect1037 void offset(const SkPoint& delta) {
1038 this->offset(delta.fX, delta.fY);
1039 }
1040
1041 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1042 are unchanged.
1043
1044 @param newX stored in fLeft, preserving width()
1045 @param newY stored in fTop, preserving height()
1046 */
offsetToSkRect1047 void offsetTo(SkScalar newX, SkScalar newY) {
1048 fRight += newX - fLeft;
1049 fBottom += newY - fTop;
1050 fLeft = newX;
1051 fTop = newY;
1052 }
1053
1054 /** Insets SkRect by (dx, dy).
1055
1056 If dx is positive, makes SkRect narrower.
1057 If dx is negative, makes SkRect wider.
1058 If dy is positive, makes SkRect shorter.
1059 If dy is negative, makes SkRect taller.
1060
1061 @param dx added to fLeft and subtracted from fRight
1062 @param dy added to fTop and subtracted from fBottom
1063 */
insetSkRect1064 void inset(SkScalar dx, SkScalar dy) {
1065 fLeft += dx;
1066 fTop += dy;
1067 fRight -= dx;
1068 fBottom -= dy;
1069 }
1070
1071 /** Outsets SkRect by (dx, dy).
1072
1073 If dx is positive, makes SkRect wider.
1074 If dx is negative, makes SkRect narrower.
1075 If dy is positive, makes SkRect taller.
1076 If dy is negative, makes SkRect shorter.
1077
1078 @param dx subtracted to fLeft and added from fRight
1079 @param dy subtracted to fTop and added from fBottom
1080 */
outsetSkRect1081 void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
1082
1083 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1084 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1085
1086 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1087
1088 @param r limit of result
1089 @return true if r and SkRect have area in common
1090
1091 example: https://fiddle.skia.org/c/@Rect_intersect
1092 */
1093 bool intersect(const SkRect& r);
1094
1095 /** Returns true if a intersects b, and sets SkRect to intersection.
1096 Returns false if a does not intersect b, and leaves SkRect unchanged.
1097
1098 Returns false if either a or b is empty, leaving SkRect unchanged.
1099
1100 @param a SkRect to intersect
1101 @param b SkRect to intersect
1102 @return true if a and b have area in common
1103 */
1104 bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1105
1106
1107 private:
IntersectsSkRect1108 static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1109 SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1110 SkScalar L = std::max(al, bl);
1111 SkScalar R = std::min(ar, br);
1112 SkScalar T = std::max(at, bt);
1113 SkScalar B = std::min(ab, bb);
1114 return L < R && T < B;
1115 }
1116
1117 public:
1118
1119 /** Returns true if SkRect intersects r.
1120 Returns false if either r or SkRect is empty, or do not intersect.
1121
1122 @param r SkRect to intersect
1123 @return true if r and SkRect have area in common
1124 */
intersectsSkRect1125 bool intersects(const SkRect& r) const {
1126 return Intersects(fLeft, fTop, fRight, fBottom,
1127 r.fLeft, r.fTop, r.fRight, r.fBottom);
1128 }
1129
1130 /** Returns true if a intersects b.
1131 Returns false if either a or b is empty, or do not intersect.
1132
1133 @param a SkRect to intersect
1134 @param b SkRect to intersect
1135 @return true if a and b have area in common
1136 */
IntersectsSkRect1137 static bool Intersects(const SkRect& a, const SkRect& b) {
1138 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1139 b.fLeft, b.fTop, b.fRight, b.fBottom);
1140 }
1141
1142 /** Sets SkRect to the union of itself and r.
1143
1144 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1145 SkRect to r.
1146
1147 @param r expansion SkRect
1148
1149 example: https://fiddle.skia.org/c/@Rect_join_2
1150 */
1151 void join(const SkRect& r);
1152
1153 /** Sets SkRect to the union of itself and r.
1154
1155 Asserts if r is empty and SK_DEBUG is defined.
1156 If SkRect is empty, sets SkRect to r.
1157
1158 May produce incorrect results if r is empty.
1159
1160 @param r expansion SkRect
1161 */
joinNonEmptyArgSkRect1162 void joinNonEmptyArg(const SkRect& r) {
1163 SkASSERT(!r.isEmpty());
1164 // if we are empty, just assign
1165 if (fLeft >= fRight || fTop >= fBottom) {
1166 *this = r;
1167 } else {
1168 this->joinPossiblyEmptyRect(r);
1169 }
1170 }
1171
1172 /** Sets SkRect to the union of itself and the construction.
1173
1174 May produce incorrect results if SkRect or r is empty.
1175
1176 @param r expansion SkRect
1177 */
joinPossiblyEmptyRectSkRect1178 void joinPossiblyEmptyRect(const SkRect& r) {
1179 fLeft = std::min(fLeft, r.left());
1180 fTop = std::min(fTop, r.top());
1181 fRight = std::max(fRight, r.right());
1182 fBottom = std::max(fBottom, r.bottom());
1183 }
1184
1185 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1186 Returns false if SkRect is empty.
1187
1188 @param x test SkPoint x-coordinate
1189 @param y test SkPoint y-coordinate
1190 @return true if (x, y) is inside SkRect
1191 */
containsSkRect1192 bool contains(SkScalar x, SkScalar y) const {
1193 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1194 }
1195
1196 /** Returns true if SkRect contains r.
1197 Returns false if SkRect is empty or r is empty.
1198
1199 SkRect contains r when SkRect area completely includes r area.
1200
1201 @param r SkRect contained
1202 @return true if all sides of SkRect are outside r
1203 */
containsSkRect1204 bool contains(const SkRect& r) const {
1205 // todo: can we eliminate the this->isEmpty check?
1206 return !r.isEmpty() && !this->isEmpty() &&
1207 fLeft <= r.fLeft && fTop <= r.fTop &&
1208 fRight >= r.fRight && fBottom >= r.fBottom;
1209 }
1210
1211 /** Returns true if SkRect contains r.
1212 Returns false if SkRect is empty or r is empty.
1213
1214 SkRect contains r when SkRect area completely includes r area.
1215
1216 @param r SkIRect contained
1217 @return true if all sides of SkRect are outside r
1218 */
containsSkRect1219 bool contains(const SkIRect& r) const {
1220 // todo: can we eliminate the this->isEmpty check?
1221 return !r.isEmpty() && !this->isEmpty() &&
1222 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1223 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1224 }
1225
1226 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1227 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1228 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1229
1230 @param dst storage for SkIRect
1231 */
roundSkRect1232 void round(SkIRect* dst) const {
1233 SkASSERT(dst);
1234 dst->setLTRB(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1235 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1236 }
1237
1238 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1239 up fRight and fBottom, using
1240 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1241 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1242
1243 @param dst storage for SkIRect
1244 */
roundOutSkRect1245 void roundOut(SkIRect* dst) const {
1246 SkASSERT(dst);
1247 dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1248 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1249 }
1250
1251 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1252 up fRight and fBottom, using
1253 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1254 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1255
1256 @param dst storage for SkRect
1257 */
roundOutSkRect1258 void roundOut(SkRect* dst) const {
1259 dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
1260 SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
1261 }
1262
1263 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1264 of fRight and fBottom, using
1265 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1266 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1267
1268 @param dst storage for SkIRect
1269 */
roundInSkRect1270 void roundIn(SkIRect* dst) const {
1271 SkASSERT(dst);
1272 dst->setLTRB(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1273 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1274 }
1275
1276 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1277 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1278 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1279
1280 @return rounded SkIRect
1281 */
roundSkRect1282 SkIRect round() const {
1283 SkIRect ir;
1284 this->round(&ir);
1285 return ir;
1286 }
1287
1288 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1289 up fRight and fBottom, using
1290 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1291 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1292
1293 @return rounded SkIRect
1294 */
roundOutSkRect1295 SkIRect roundOut() const {
1296 SkIRect ir;
1297 this->roundOut(&ir);
1298 return ir;
1299 }
1300 /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1301 of fRight and fBottom, using
1302 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1303 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1304
1305 @return rounded SkIRect
1306 */
roundInSkRect1307 SkIRect roundIn() const {
1308 SkIRect ir;
1309 this->roundIn(&ir);
1310 return ir;
1311 }
1312
1313 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1314 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1315 and width() and height() will be zero or positive.
1316 */
sortSkRect1317 void sort() {
1318 using std::swap;
1319 if (fLeft > fRight) {
1320 swap(fLeft, fRight);
1321 }
1322
1323 if (fTop > fBottom) {
1324 swap(fTop, fBottom);
1325 }
1326 }
1327
1328 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1329 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1330 and width() and height() will be zero or positive.
1331
1332 @return sorted SkRect
1333 */
makeSortedSkRect1334 SkRect makeSorted() const {
1335 return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1336 std::max(fLeft, fRight), std::max(fTop, fBottom));
1337 }
1338
1339 /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1340 entries.
1341
1342 @return pointer to fLeft
1343 */
asScalarsSkRect1344 const SkScalar* asScalars() const { return &fLeft; }
1345
1346 /** Writes text representation of SkRect to standard output. Set asHex to true to
1347 generate exact binary representations of floating point numbers.
1348
1349 @param asHex true if SkScalar values are written as hexadecimal
1350
1351 example: https://fiddle.skia.org/c/@Rect_dump
1352 */
1353 void dump(bool asHex) const;
1354
1355 /** Writes text representation of SkRect to standard output. The representation may be
1356 directly compiled as C++ code. Floating point values are written
1357 with limited precision; it may not be possible to reconstruct original SkRect
1358 from output.
1359 */
dumpSkRect1360 void dump() const { this->dump(false); }
1361
1362 /** Writes text representation of SkRect to standard output. The representation may be
1363 directly compiled as C++ code. Floating point values are written
1364 in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1365 original SkRect.
1366
1367 Use instead of dump() when submitting
1368 */
dumpHexSkRect1369 void dumpHex() const { this->dump(true); }
1370 };
1371
contains(const SkRect & r)1372 inline bool SkIRect::contains(const SkRect& r) const {
1373 return !r.isEmpty() && !this->isEmpty() && // check for empties
1374 (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1375 (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1376 }
1377
1378 #endif
1379