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/core/SkTypes.h"
14 #include "include/private/base/SkFloatingPoint.h"
15 #include "include/private/base/SkSafe32.h"
16 #include "include/private/base/SkTFitsIn.h"
17
18 #include <algorithm>
19 #include <cmath>
20 #include <cstdint>
21 #include <cstring>
22
23 struct SkRect;
24 class SkString;
25
26 /** \struct SkIRect
27 SkIRect holds four 32-bit integer coordinates describing the upper and
28 lower bounds of a rectangle. SkIRect may be created from outer bounds or
29 from position, width, and height. SkIRect describes an area; if its right
30 is less than or equal to its left, or if its bottom is less than or equal to
31 its top, it is considered empty.
32 */
33 struct SK_API SkIRect {
34 int32_t fLeft = 0; //!< smaller x-axis bounds
35 int32_t fTop = 0; //!< smaller y-axis bounds
36 int32_t fRight = 0; //!< larger x-axis bounds
37 int32_t fBottom = 0; //!< larger y-axis bounds
38
39 /** Returns constructed SkIRect set to (0, 0, 0, 0).
40 Many other rectangles are empty; if left is equal to or greater than right,
41 or if top is equal to or greater than bottom. Setting all members to zero
42 is a convenience, but does not designate a special empty rectangle.
43
44 @return bounds (0, 0, 0, 0)
45 */
MakeEmptySkIRect46 [[nodiscard]] static constexpr SkIRect MakeEmpty() {
47 return SkIRect{0, 0, 0, 0};
48 }
49
50 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
51 may be negative.
52
53 @param w width of constructed SkIRect
54 @param h height of constructed SkIRect
55 @return bounds (0, 0, w, h)
56 */
MakeWHSkIRect57 [[nodiscard]] static constexpr SkIRect MakeWH(int32_t w, int32_t h) {
58 return SkIRect{0, 0, w, h};
59 }
60
61 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
62 Does not validate input; size.width() or size.height() may be negative.
63
64 @param size values for SkIRect width and height
65 @return bounds (0, 0, size.width(), size.height())
66 */
MakeSizeSkIRect67 [[nodiscard]] static constexpr SkIRect MakeSize(const SkISize& size) {
68 return SkIRect{0, 0, size.fWidth, size.fHeight};
69 }
70
71 /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
72 pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
73 negative.
74
75 @param pt values for SkIRect fLeft and fTop
76 @param size values for SkIRect width and height
77 @return bounds at pt with width and height of size
78 */
MakePtSizeSkIRect79 [[nodiscard]] static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size) {
80 return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
81 }
82
83 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
84 result in fLeft greater than fRight, or fTop greater than fBottom.
85
86 @param l integer stored in fLeft
87 @param t integer stored in fTop
88 @param r integer stored in fRight
89 @param b integer stored in fBottom
90 @return bounds (l, t, r, b)
91 */
MakeLTRBSkIRect92 [[nodiscard]] static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
93 return SkIRect{l, t, r, b};
94 }
95
96 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
97 Does not validate input; w or h may be negative.
98
99 @param x stored in fLeft
100 @param y stored in fTop
101 @param w added to x and stored in fRight
102 @param h added to y and stored in fBottom
103 @return bounds at (x, y) with width w and height h
104 */
MakeXYWHSkIRect105 [[nodiscard]] static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, 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 [[nodiscard]] bool 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 float 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 float fLeft = 0; //!< smaller x-axis bounds
585 float fTop = 0; //!< smaller y-axis bounds
586 float fRight = 0; //!< larger x-axis bounds
587 float fBottom = 0; //!< 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 [[nodiscard]] static constexpr SkRect MakeEmpty() {
597 return SkRect{0, 0, 0, 0};
598 }
599
600 /** Returns constructed SkRect set to float 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 float width of constructed SkRect
607 @param h float height of constructed SkRect
608 @return bounds (0, 0, w, h)
609 */
MakeWHSkRect610 [[nodiscard]] static constexpr SkRect MakeWH(float w, float 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 [[nodiscard]] static SkRect MakeIWH(int w, int h) {
625 return {0, 0, static_cast<float>(w), static_cast<float>(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 float values for SkRect width and height
632 @return bounds (0, 0, size.width(), size.height())
633 */
MakeSizeSkRect634 [[nodiscard]] static constexpr SkRect 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 float stored in fLeft
642 @param t float stored in fTop
643 @param r float stored in fRight
644 @param b float stored in fBottom
645 @return bounds (l, t, r, b)
646 */
MakeLTRBSkRect647 [[nodiscard]] static constexpr SkRect MakeLTRB(float l, float t, float r, float b) {
648 return SkRect {l, t, r, b};
649 }
650
651 /** Returns constructed SkRect set to (x, y, x + w, y + h).
652 Does not validate input; w or h may be negative.
653
654 @param x stored in fLeft
655 @param y stored in fTop
656 @param w added to x and stored in fRight
657 @param h added to y and stored in fBottom
658 @return bounds at (x, y) with width w and height h
659 */
MakeXYWHSkRect660 [[nodiscard]] static constexpr SkRect MakeXYWH(float x, float y, float w, float h) {
661 return SkRect {x, y, x + w, y + h};
662 }
663
664 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
665 Does not validate input; size.width() or size.height() may be negative.
666
667 @param size integer values for SkRect width and height
668 @return bounds (0, 0, size.width(), size.height())
669 */
MakeSkRect670 static SkRect Make(const SkISize& size) {
671 return MakeIWH(size.width(), size.height());
672 }
673
674 /** Returns constructed SkIRect set to irect, promoting integers to float.
675 Does not validate input; fLeft may be greater than fRight, fTop may be greater
676 than fBottom.
677
678 @param irect integer unsorted bounds
679 @return irect members converted to float
680 */
MakeSkRect681 [[nodiscard]] static SkRect Make(const SkIRect& irect) {
682 return {
683 static_cast<float>(irect.fLeft), static_cast<float>(irect.fTop),
684 static_cast<float>(irect.fRight), static_cast<float>(irect.fBottom)
685 };
686 }
687
688 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
689 to or greater than fBottom. Call sort() to reverse rectangles with negative
690 width() or height().
691
692 @return true if width() or height() are zero or negative
693 */
isEmptySkRect694 bool isEmpty() const {
695 // We write it as the NOT of a non-empty rect, so we will return true if any values
696 // are NaN.
697 return !(fLeft < fRight && fTop < fBottom);
698 }
699
700 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
701 to or less than fBottom. Call sort() to reverse rectangles with negative
702 width() or height().
703
704 @return true if width() or height() are zero or positive
705 */
isSortedSkRect706 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
707
708 /** Returns true if all values in the rectangle are finite.
709
710 @return true if no member is infinite or NaN
711 */
isFiniteSkRect712 bool isFinite() const {
713 return SkIsFinite(fLeft, fTop, fRight, fBottom);
714 }
715
716 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
717 Call sort() to reverse fLeft and fRight if needed.
718
719 @return fLeft
720 */
xSkRect721 constexpr float x() const { return fLeft; }
722
723 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
724 and sort() to reverse fTop and fBottom if needed.
725
726 @return fTop
727 */
ySkRect728 constexpr float y() const { return fTop; }
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 */
leftSkRect735 constexpr float left() 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 */
topSkRect742 constexpr float top() const { return fTop; }
743
744 /** Returns right 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 fRight
748 */
rightSkRect749 constexpr float right() const { return fRight; }
750
751 /** Returns bottom 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 fBottom
755 */
bottomSkRect756 constexpr float bottom() const { return fBottom; }
757
758 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
759 result fits in 32-bit float; result may be negative or infinity.
760
761 @return fRight minus fLeft
762 */
widthSkRect763 constexpr float width() const { return fRight - fLeft; }
764
765 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
766 result fits in 32-bit float; result may be negative or infinity.
767
768 @return fBottom minus fTop
769 */
heightSkRect770 constexpr float height() const { return fBottom - fTop; }
771
772 /** Returns average of left edge and right edge. Result does not change if SkRect
773 is sorted. Result may overflow to infinity if SkRect is far from the origin.
774
775 @return midpoint on x-axis
776 */
centerXSkRect777 constexpr float centerX() const {
778 return sk_float_midpoint(fLeft, fRight);
779 }
780
781 /** Returns average of top edge and bottom edge. Result does not change if SkRect
782 is sorted.
783
784 @return midpoint on y-axis
785 */
centerYSkRect786 constexpr float centerY() const {
787 return sk_float_midpoint(fTop, fBottom);
788 }
789
790 /** Returns the point this->centerX(), this->centerY().
791 @return rectangle center
792 */
centerSkRect793 constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; }
794
795 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
796 equal to the corresponding members in b.
797
798 a and b are not equal if either contain NaN. a and b are equal if members
799 contain zeroes with different signs.
800
801 @param a SkRect to compare
802 @param b SkRect to compare
803 @return true if members are equal
804 */
805 friend bool operator==(const SkRect& a, const SkRect& b) {
806 return a.fLeft == b.fLeft &&
807 a.fTop == b.fTop &&
808 a.fRight == b.fRight &&
809 a.fBottom == b.fBottom;
810 }
811
812 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
813 equal the corresponding members in b.
814
815 a and b are not equal if either contain NaN. a and b are equal if members
816 contain zeroes with different signs.
817
818 @param a SkRect to compare
819 @param b SkRect to compare
820 @return true if members are not equal
821 */
822 friend bool operator!=(const SkRect& a, const SkRect& b) {
823 return !(a == b);
824 }
825
826 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
827 bottom-right, bottom-left.
828
829 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
830
831 @param quad storage for corners of SkRect
832
833 example: https://fiddle.skia.org/c/@Rect_toQuad
834 */
835 void toQuad(SkPoint quad[4]) const;
836
837 /** Sets SkRect to (0, 0, 0, 0).
838
839 Many other rectangles are empty; if left is equal to or greater than right,
840 or if top is equal to or greater than bottom. Setting all members to zero
841 is a convenience, but does not designate a special empty rectangle.
842 */
setEmptySkRect843 void setEmpty() { *this = MakeEmpty(); }
844
845 /** Sets SkRect to src, promoting src members from integer to float.
846 Very large values in src may lose precision.
847
848 @param src integer SkRect
849 */
setSkRect850 void set(const SkIRect& src) {
851 fLeft = src.fLeft;
852 fTop = src.fTop;
853 fRight = src.fRight;
854 fBottom = src.fBottom;
855 }
856
857 /** Sets SkRect to (left, top, right, bottom).
858 left and right are not sorted; left is not necessarily less than right.
859 top and bottom are not sorted; top is not necessarily less than bottom.
860
861 @param left stored in fLeft
862 @param top stored in fTop
863 @param right stored in fRight
864 @param bottom stored in fBottom
865 */
setLTRBSkRect866 void setLTRB(float left, float top, float right, float bottom) {
867 fLeft = left;
868 fTop = top;
869 fRight = right;
870 fBottom = bottom;
871 }
872
873 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
874 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
875
876 Result is either empty or sorted: fLeft is less than or equal to fRight, and
877 fTop is less than or equal to fBottom.
878
879 @param pts SkPoint array
880 @param count entries in array
881 */
setBoundsSkRect882 void setBounds(const SkPoint pts[], int count) {
883 (void)this->setBoundsCheck(pts, count);
884 }
885
886 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
887 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
888 sets SkRect to (0, 0, 0, 0).
889
890 Result is either empty or sorted: fLeft is less than or equal to fRight, and
891 fTop is less than or equal to fBottom.
892
893 @param pts SkPoint array
894 @param count entries in array
895 @return true if all SkPoint values are finite
896
897 example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
898 */
899 bool setBoundsCheck(const SkPoint pts[], int count);
900
901 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
902 contains infinity or NaN, all SkRect dimensions are set to NaN.
903
904 @param pts SkPoint array
905 @param count entries in array
906
907 example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
908 */
909 void setBoundsNoCheck(const SkPoint pts[], int count);
910
911 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
912 sorted and may be empty. Does not check to see if values are finite.
913
914 @param p0 corner to include
915 @param p1 corner to include
916 */
setSkRect917 void set(const SkPoint& p0, const SkPoint& p1) {
918 fLeft = std::min(p0.fX, p1.fX);
919 fRight = std::max(p0.fX, p1.fX);
920 fTop = std::min(p0.fY, p1.fY);
921 fBottom = std::max(p0.fY, p1.fY);
922 }
923
924 /** Sets SkRect to (x, y, x + width, y + height).
925 Does not validate input; width or height may be negative.
926
927 @param x stored in fLeft
928 @param y stored in fTop
929 @param width added to x and stored in fRight
930 @param height added to y and stored in fBottom
931 */
setXYWHSkRect932 void setXYWH(float x, float y, float width, float height) {
933 fLeft = x;
934 fTop = y;
935 fRight = x + width;
936 fBottom = y + height;
937 }
938
939 /** Sets SkRect to (0, 0, width, height). Does not validate input;
940 width or height may be negative.
941
942 @param width stored in fRight
943 @param height stored in fBottom
944 */
setWHSkRect945 void setWH(float width, float height) {
946 fLeft = 0;
947 fTop = 0;
948 fRight = width;
949 fBottom = height;
950 }
setIWHSkRect951 void setIWH(int32_t width, int32_t height) {
952 this->setWH(width, height);
953 }
954
955 /** Returns SkRect offset by (dx, dy).
956
957 If dx is negative, SkRect returned is moved to the left.
958 If dx is positive, SkRect returned is moved to the right.
959 If dy is negative, SkRect returned is moved upward.
960 If dy is positive, SkRect returned is moved downward.
961
962 @param dx added to fLeft and fRight
963 @param dy added to fTop and fBottom
964 @return SkRect offset on axes, with original width and height
965 */
makeOffsetSkRect966 constexpr SkRect makeOffset(float dx, float dy) const {
967 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
968 }
969
970 /** Returns SkRect offset by v.
971
972 @param v added to rect
973 @return SkRect offset on axes, with original width and height
974 */
makeOffsetSkRect975 constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
976
977 /** Returns SkRect, inset by (dx, dy).
978
979 If dx is negative, SkRect returned is wider.
980 If dx is positive, SkRect returned is narrower.
981 If dy is negative, SkRect returned is taller.
982 If dy is positive, SkRect returned is shorter.
983
984 @param dx added to fLeft and subtracted from fRight
985 @param dy added to fTop and subtracted from fBottom
986 @return SkRect inset symmetrically left and right, top and bottom
987 */
makeInsetSkRect988 SkRect makeInset(float dx, float dy) const {
989 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
990 }
991
992 /** Returns SkRect, outset by (dx, dy).
993
994 If dx is negative, SkRect returned is narrower.
995 If dx is positive, SkRect returned is wider.
996 If dy is negative, SkRect returned is shorter.
997 If dy is positive, SkRect returned is taller.
998
999 @param dx subtracted to fLeft and added from fRight
1000 @param dy subtracted to fTop and added from fBottom
1001 @return SkRect outset symmetrically left and right, top and bottom
1002 */
makeOutsetSkRect1003 SkRect makeOutset(float dx, float dy) const {
1004 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1005 }
1006
1007 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1008
1009 If dx is negative, moves SkRect to the left.
1010 If dx is positive, moves SkRect to the right.
1011 If dy is negative, moves SkRect upward.
1012 If dy is positive, moves SkRect downward.
1013
1014 @param dx offset added to fLeft and fRight
1015 @param dy offset added to fTop and fBottom
1016 */
offsetSkRect1017 void offset(float dx, float dy) {
1018 fLeft += dx;
1019 fTop += dy;
1020 fRight += dx;
1021 fBottom += dy;
1022 }
1023
1024 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1025 fTop, fBottom.
1026
1027 If delta.fX is negative, moves SkRect to the left.
1028 If delta.fX is positive, moves SkRect to the right.
1029 If delta.fY is negative, moves SkRect upward.
1030 If delta.fY is positive, moves SkRect downward.
1031
1032 @param delta added to SkRect
1033 */
offsetSkRect1034 void offset(const SkPoint& delta) {
1035 this->offset(delta.fX, delta.fY);
1036 }
1037
1038 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1039 are unchanged.
1040
1041 @param newX stored in fLeft, preserving width()
1042 @param newY stored in fTop, preserving height()
1043 */
offsetToSkRect1044 void offsetTo(float newX, float newY) {
1045 fRight += newX - fLeft;
1046 fBottom += newY - fTop;
1047 fLeft = newX;
1048 fTop = newY;
1049 }
1050
1051 /** Insets SkRect by (dx, dy).
1052
1053 If dx is positive, makes SkRect narrower.
1054 If dx is negative, makes SkRect wider.
1055 If dy is positive, makes SkRect shorter.
1056 If dy is negative, makes SkRect taller.
1057
1058 @param dx added to fLeft and subtracted from fRight
1059 @param dy added to fTop and subtracted from fBottom
1060 */
insetSkRect1061 void inset(float dx, float dy) {
1062 fLeft += dx;
1063 fTop += dy;
1064 fRight -= dx;
1065 fBottom -= dy;
1066 }
1067
1068 /** Outsets SkRect by (dx, dy).
1069
1070 If dx is positive, makes SkRect wider.
1071 If dx is negative, makes SkRect narrower.
1072 If dy is positive, makes SkRect taller.
1073 If dy is negative, makes SkRect shorter.
1074
1075 @param dx subtracted to fLeft and added from fRight
1076 @param dy subtracted to fTop and added from fBottom
1077 */
outsetSkRect1078 void outset(float dx, float dy) { this->inset(-dx, -dy); }
1079
1080 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1081 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1082
1083 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1084
1085 @param r limit of result
1086 @return true if r and SkRect have area in common
1087
1088 example: https://fiddle.skia.org/c/@Rect_intersect
1089 */
1090 bool intersect(const SkRect& r);
1091
1092 /** Returns true if a intersects b, and sets SkRect to intersection.
1093 Returns false if a does not intersect b, and leaves SkRect unchanged.
1094
1095 Returns false if either a or b is empty, leaving SkRect unchanged.
1096
1097 @param a SkRect to intersect
1098 @param b SkRect to intersect
1099 @return true if a and b have area in common
1100 */
1101 [[nodiscard]] bool intersect(const SkRect& a, const SkRect& b);
1102
1103
1104 private:
IntersectsSkRect1105 static bool Intersects(float al, float at, float ar, float ab,
1106 float bl, float bt, float br, float bb) {
1107 float L = std::max(al, bl);
1108 float R = std::min(ar, br);
1109 float T = std::max(at, bt);
1110 float B = std::min(ab, bb);
1111 return L < R && T < B;
1112 }
1113
1114 public:
1115
1116 /** Returns true if SkRect intersects r.
1117 Returns false if either r or SkRect is empty, or do not intersect.
1118
1119 @param r SkRect to intersect
1120 @return true if r and SkRect have area in common
1121 */
intersectsSkRect1122 bool intersects(const SkRect& r) const {
1123 return Intersects(fLeft, fTop, fRight, fBottom,
1124 r.fLeft, r.fTop, r.fRight, r.fBottom);
1125 }
1126
1127 /** Returns true if a intersects b.
1128 Returns false if either a or b is empty, or do not intersect.
1129
1130 @param a SkRect to intersect
1131 @param b SkRect to intersect
1132 @return true if a and b have area in common
1133 */
IntersectsSkRect1134 static bool Intersects(const SkRect& a, const SkRect& b) {
1135 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1136 b.fLeft, b.fTop, b.fRight, b.fBottom);
1137 }
1138
1139 /** Sets SkRect to the union of itself and r.
1140
1141 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1142 SkRect to r.
1143
1144 @param r expansion SkRect
1145
1146 example: https://fiddle.skia.org/c/@Rect_join_2
1147 */
1148 void join(const SkRect& r);
1149
1150 /** Sets SkRect to the union of itself and r.
1151
1152 Asserts if r is empty and SK_DEBUG is defined.
1153 If SkRect is empty, sets SkRect to r.
1154
1155 May produce incorrect results if r is empty.
1156
1157 @param r expansion SkRect
1158 */
joinNonEmptyArgSkRect1159 void joinNonEmptyArg(const SkRect& r) {
1160 SkASSERT(!r.isEmpty());
1161 // if we are empty, just assign
1162 if (fLeft >= fRight || fTop >= fBottom) {
1163 *this = r;
1164 } else {
1165 this->joinPossiblyEmptyRect(r);
1166 }
1167 }
1168
1169 /** Sets SkRect to the union of itself and the construction.
1170
1171 May produce incorrect results if SkRect or r is empty.
1172
1173 @param r expansion SkRect
1174 */
joinPossiblyEmptyRectSkRect1175 void joinPossiblyEmptyRect(const SkRect& r) {
1176 fLeft = std::min(fLeft, r.left());
1177 fTop = std::min(fTop, r.top());
1178 fRight = std::max(fRight, r.right());
1179 fBottom = std::max(fBottom, r.bottom());
1180 }
1181
1182 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1183 Returns false if SkRect is empty.
1184
1185 @param x test SkPoint x-coordinate
1186 @param y test SkPoint y-coordinate
1187 @return true if (x, y) is inside SkRect
1188 */
containsSkRect1189 bool contains(float x, float y) const {
1190 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1191 }
1192
1193 /** Returns true if SkRect contains r.
1194 Returns false if SkRect is empty or r is empty.
1195
1196 SkRect contains r when SkRect area completely includes r area.
1197
1198 @param r SkRect contained
1199 @return true if all sides of SkRect are outside r
1200 */
containsSkRect1201 bool contains(const SkRect& r) const {
1202 // todo: can we eliminate the this->isEmpty check?
1203 return !r.isEmpty() && !this->isEmpty() &&
1204 fLeft <= r.fLeft && fTop <= r.fTop &&
1205 fRight >= r.fRight && fBottom >= r.fBottom;
1206 }
1207
1208 /** Returns true if SkRect contains r.
1209 Returns false if SkRect is empty or r is empty.
1210
1211 SkRect contains r when SkRect area completely includes r area.
1212
1213 @param r SkIRect contained
1214 @return true if all sides of SkRect are outside r
1215 */
containsSkRect1216 bool contains(const SkIRect& r) const {
1217 // todo: can we eliminate the this->isEmpty check?
1218 return !r.isEmpty() && !this->isEmpty() &&
1219 fLeft <= r.fLeft && fTop <= r.fTop &&
1220 fRight >= r.fRight && fBottom >= r.fBottom;
1221 }
1222
1223 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1224 members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop),
1225 sk_float_round2int(fRight), sk_float_round2int(fBottom)).
1226
1227 @param dst storage for SkIRect
1228 */
roundSkRect1229 void round(SkIRect* dst) const {
1230 SkASSERT(dst);
1231 dst->setLTRB(sk_float_round2int(fLeft), sk_float_round2int(fTop),
1232 sk_float_round2int(fRight), sk_float_round2int(fBottom));
1233 }
1234
1235 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1236 up fRight and fBottom, using
1237 (sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1238 sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)).
1239
1240 @param dst storage for SkIRect
1241 */
roundOutSkRect1242 void roundOut(SkIRect* dst) const {
1243 SkASSERT(dst);
1244 dst->setLTRB(sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1245 sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom));
1246 }
1247
1248 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1249 up fRight and fBottom, using
1250 (std::floor(fLeft), std::floor(fTop),
1251 std::ceil(fRight), std::ceil(fBottom)).
1252
1253 @param dst storage for SkRect
1254 */
roundOutSkRect1255 void roundOut(SkRect* dst) const {
1256 dst->setLTRB(std::floor(fLeft), std::floor(fTop),
1257 std::ceil(fRight), std::ceil(fBottom));
1258 }
1259
1260 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1261 of fRight and fBottom, using
1262 (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1263 sk_float_floor2int(fRight), sk_float_floor2int(fBottom)).
1264
1265 @param dst storage for SkIRect
1266 */
roundInSkRect1267 void roundIn(SkIRect* dst) const {
1268 SkASSERT(dst);
1269 dst->setLTRB(sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1270 sk_float_floor2int(fRight), sk_float_floor2int(fBottom));
1271 }
1272
1273 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1274 members, using (sk_float_round2int(fLeft), sk_float_round2int(fTop),
1275 sk_float_round2int(fRight), sk_float_round2int(fBottom)).
1276
1277 @return rounded SkIRect
1278 */
roundSkRect1279 SkIRect round() const {
1280 SkIRect ir;
1281 this->round(&ir);
1282 return ir;
1283 }
1284
1285 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1286 up fRight and fBottom, using
1287 (sk_float_floor2int(fLeft), sk_float_floor2int(fTop),
1288 sk_float_ceil2int(fRight), sk_float_ceil2int(fBottom)).
1289
1290 @return rounded SkIRect
1291 */
roundOutSkRect1292 SkIRect roundOut() const {
1293 SkIRect ir;
1294 this->roundOut(&ir);
1295 return ir;
1296 }
1297 /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1298 of fRight and fBottom, using
1299 (sk_float_ceil2int(fLeft), sk_float_ceil2int(fTop),
1300 sk_float_floor2int(fRight), sk_float_floor2int(fBottom)).
1301
1302 @return rounded SkIRect
1303 */
roundInSkRect1304 SkIRect roundIn() const {
1305 SkIRect ir;
1306 this->roundIn(&ir);
1307 return ir;
1308 }
1309
1310 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1311 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1312 and width() and height() will be zero or positive.
1313 */
sortSkRect1314 void sort() {
1315 using std::swap;
1316 if (fLeft > fRight) {
1317 swap(fLeft, fRight);
1318 }
1319
1320 if (fTop > fBottom) {
1321 swap(fTop, fBottom);
1322 }
1323 }
1324
1325 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1326 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1327 and width() and height() will be zero or positive.
1328
1329 @return sorted SkRect
1330 */
makeSortedSkRect1331 SkRect makeSorted() const {
1332 return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1333 std::max(fLeft, fRight), std::max(fTop, fBottom));
1334 }
1335
1336 /** Returns pointer to first float in SkRect, to treat it as an array with four
1337 entries.
1338
1339 @return pointer to fLeft
1340 */
asScalarsSkRect1341 const float* asScalars() const { return &fLeft; }
1342
1343 /** Writes text representation of SkRect to standard output. Set asHex to true to
1344 generate exact binary representations of floating point numbers.
1345
1346 @param asHex true if SkScalar values are written as hexadecimal
1347
1348 example: https://fiddle.skia.org/c/@Rect_dump
1349 */
1350 void dump(bool asHex) const;
1351 SkString dumpToString(bool asHex) const;
1352
1353 /** Writes text representation of SkRect to standard output. The representation may be
1354 directly compiled as C++ code. Floating point values are written
1355 with limited precision; it may not be possible to reconstruct original SkRect
1356 from output.
1357 */
dumpSkRect1358 void dump() const { this->dump(false); }
1359
1360 /** Writes text representation of SkRect to standard output. The representation may be
1361 directly compiled as C++ code. Floating point values are written
1362 in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1363 original SkRect.
1364
1365 Use instead of dump() when submitting
1366 */
dumpHexSkRect1367 void dumpHex() const { this->dump(true); }
1368 };
1369
contains(const SkRect & r)1370 inline bool SkIRect::contains(const SkRect& r) const {
1371 return !r.isEmpty() && !this->isEmpty() && // check for empties
1372 fLeft <= r.fLeft && fTop <= r.fTop &&
1373 fRight >= r.fRight && fBottom >= r.fBottom;
1374 }
1375
1376 #endif
1377