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