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

source code of flutter_engine/third_party/skia/include/core/SkRect.h