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