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 <utility>
17
18 struct SkRect;
19
20 /** \struct SkIRect
21 SkIRect holds four 32-bit integer coordinates describing the upper and
22 lower bounds of a rectangle. SkIRect may be created from outer bounds or
23 from position, width, and height. SkIRect describes an area; if its right
24 is less than or equal to its left, or if its bottom is less than or equal to
25 its top, it is considered empty.
26 */
27 struct SK_API SkIRect {
28 int32_t fLeft; //!< smaller x-axis bounds
29 int32_t fTop; //!< smaller y-axis bounds
30 int32_t fRight; //!< larger x-axis bounds
31 int32_t fBottom; //!< larger y-axis bounds
32
33 /** Returns constructed SkIRect set to (0, 0, 0, 0).
34 Many other rectangles are empty; if left is equal to or greater than right,
35 or if top is equal to or greater than bottom. Setting all members to zero
36 is a convenience, but does not designate a special empty rectangle.
37
38 @return bounds (0, 0, 0, 0)
39 */
MakeEmptySkIRect40 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
41 return SkIRect{0, 0, 0, 0};
42 }
43
44 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
45 may be negative.
46
47 @param w width of constructed SkIRect
48 @param h height of constructed SkIRect
49 @return bounds (0, 0, w, h)
50 */
MakeWHSkIRect51 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
52 return SkIRect{0, 0, w, h};
53 }
54
55 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
56 Does not validate input; size.width() or size.height() may be negative.
57
58 @param size values for SkIRect width and height
59 @return bounds (0, 0, size.width(), size.height())
60 */
MakeSizeSkIRect61 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
62 return SkIRect{0, 0, size.fWidth, size.fHeight};
63 }
64
65 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
66 result in fLeft greater than fRight, or fTop greater than fBottom.
67
68 @param l integer stored in fLeft
69 @param t integer stored in fTop
70 @param r integer stored in fRight
71 @param b integer stored in fBottom
72 @return bounds (l, t, r, b)
73 */
MakeLTRBSkIRect74 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
75 int32_t r, int32_t b) {
76 return SkIRect{l, t, r, b};
77 }
78
79 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
80 Does not validate input; w or h may be negative.
81
82 @param x stored in fLeft
83 @param y stored in fTop
84 @param w added to x and stored in fRight
85 @param h added to y and stored in fBottom
86 @return bounds at (x, y) with width w and height h
87 */
MakeXYWHSkIRect88 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
89 int32_t w, int32_t h) {
90 return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
91 }
92
93 /** Returns left edge of SkIRect, if sorted.
94 Call sort() to reverse fLeft and fRight if needed.
95
96 @return fLeft
97 */
leftSkIRect98 int32_t left() const { return fLeft; }
99
100 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
101 and sort() to reverse fTop and fBottom if needed.
102
103 @return fTop
104 */
topSkIRect105 int32_t top() const { return fTop; }
106
107 /** Returns right edge of SkIRect, if sorted.
108 Call sort() to reverse fLeft and fRight if needed.
109
110 @return fRight
111 */
rightSkIRect112 int32_t right() const { return fRight; }
113
114 /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
115 and sort() to reverse fTop and fBottom if needed.
116
117 @return fBottom
118 */
bottomSkIRect119 int32_t bottom() const { return fBottom; }
120
121 /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
122 and sort() to reverse fLeft and fRight if needed.
123
124 @return fLeft
125 */
xSkIRect126 int32_t x() const { return fLeft; }
127
128 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
129 and sort() to reverse fTop and fBottom if needed.
130
131 @return fTop
132 */
ySkIRect133 int32_t y() const { return fTop; }
134
135 // Experimental
topLeftSkIRect136 SkIPoint topLeft() const { return {fLeft, fTop}; }
137
138 /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
139 result fits in 32-bit signed integer; result may be negative.
140
141 @return fRight minus fLeft
142 */
widthSkIRect143 int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
144
145 /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
146 result fits in 32-bit signed integer; result may be negative.
147
148 @return fBottom minus fTop
149 */
heightSkIRect150 int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
151
152 /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
153 or if result fits in 32-bit signed integer; result may be negative.
154
155 @return SkISize (width, height)
156 */
sizeSkIRect157 SkISize size() const { return SkISize::Make(this->width(), this->height()); }
158
159 /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
160 result may be negative. This is safer than calling width() since width() might
161 overflow in its calculation.
162
163 @return fRight minus fLeft cast to int64_t
164 */
width64SkIRect165 int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
166
167 /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
168 result may be negative. This is safer than calling height() since height() might
169 overflow in its calculation.
170
171 @return fBottom minus fTop cast to int64_t
172 */
height64SkIRect173 int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
174
175 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
176 to or greater than fBottom. Call sort() to reverse rectangles with negative
177 width64() or height64().
178
179 @return true if width64() or height64() are zero or negative
180 */
isEmpty64SkIRect181 bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
182
183 /** Returns true if width() or height() are zero or negative.
184
185 @return true if width() or height() are zero or negative
186 */
isEmptySkIRect187 bool isEmpty() const {
188 int64_t w = this->width64();
189 int64_t h = this->height64();
190 if (w <= 0 || h <= 0) {
191 return true;
192 }
193 // Return true if either exceeds int32_t
194 return !SkTFitsIn<int32_t>(w | h);
195 }
196
197 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
198 identical to corresponding members in b.
199
200 @param a SkIRect to compare
201 @param b SkIRect to compare
202 @return true if members are equal
203 */
204 friend bool operator==(const SkIRect& a, const SkIRect& b) {
205 return !memcmp(&a, &b, sizeof(a));
206 }
207
208 /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
209 identical to the corresponding member in b.
210
211 @param a SkIRect to compare
212 @param b SkIRect to compare
213 @return true if members are not equal
214 */
215 friend bool operator!=(const SkIRect& a, const SkIRect& b) {
216 return !(a == b);
217 }
218
219 /** Sets SkIRect to (0, 0, 0, 0).
220
221 Many other rectangles are empty; if left is equal to or greater than right,
222 or if top is equal to or greater than bottom. Setting all members to zero
223 is a convenience, but does not designate a special empty rectangle.
224 */
setEmptySkIRect225 void setEmpty() { memset(this, 0, sizeof(*this)); }
226
227 /** Sets SkIRect to (left, top, right, bottom).
228 left and right are not sorted; left is not necessarily less than right.
229 top and bottom are not sorted; top is not necessarily less than bottom.
230
231 @param left assigned to fLeft
232 @param top assigned to fTop
233 @param right assigned to fRight
234 @param bottom assigned to fBottom
235 */
setSkIRect236 void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
237 fLeft = left;
238 fTop = top;
239 fRight = right;
240 fBottom = bottom;
241 }
242
243 /** Sets SkIRect to (left, top, right, bottom).
244 left and right are not sorted; left is not necessarily less than right.
245 top and bottom are not sorted; top is not necessarily less than bottom.
246
247 @param left stored in fLeft
248 @param top stored in fTop
249 @param right stored in fRight
250 @param bottom stored in fBottom
251 */
setLTRBSkIRect252 void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
253 this->set(left, top, right, 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
271 /** Returns SkIRect offset by (dx, dy).
272
273 If dx is negative, SkIRect returned is moved to the left.
274 If dx is positive, SkIRect returned is moved to the right.
275 If dy is negative, SkIRect returned is moved upward.
276 If dy is positive, SkIRect returned is moved downward.
277
278 @param dx offset added to fLeft and fRight
279 @param dy offset added to fTop and fBottom
280 @return SkIRect offset by dx and dy, with original width and height
281 */
makeOffsetSkIRect282 SkIRect makeOffset(int32_t dx, int32_t dy) const {
283 return {
284 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
285 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
286 };
287 }
288
289 /** Returns SkIRect, inset by (dx, dy).
290
291 If dx is negative, SkIRect returned is wider.
292 If dx is positive, SkIRect returned is narrower.
293 If dy is negative, SkIRect returned is taller.
294 If dy is positive, SkIRect returned is shorter.
295
296 @param dx offset added to fLeft and subtracted from fRight
297 @param dy offset added to fTop and subtracted from fBottom
298 @return SkIRect inset symmetrically left and right, top and bottom
299 */
makeInsetSkIRect300 SkIRect makeInset(int32_t dx, int32_t dy) const {
301 return {
302 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
303 Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
304 };
305 }
306
307 /** Returns SkIRect, outset by (dx, dy).
308
309 If dx is negative, SkIRect returned is narrower.
310 If dx is positive, SkIRect returned is wider.
311 If dy is negative, SkIRect returned is shorter.
312 If dy is positive, SkIRect returned is taller.
313
314 @param dx offset subtracted to fLeft and added from fRight
315 @param dy offset subtracted to fTop and added from fBottom
316 @return SkIRect outset symmetrically left and right, top and bottom
317 */
makeOutsetSkIRect318 SkIRect makeOutset(int32_t dx, int32_t dy) const {
319 return {
320 Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
321 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
322 };
323 }
324
325 /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
326
327 If dx is negative, moves SkIRect returned to the left.
328 If dx is positive, moves SkIRect returned to the right.
329 If dy is negative, moves SkIRect returned upward.
330 If dy is positive, moves SkIRect returned downward.
331
332 @param dx offset added to fLeft and fRight
333 @param dy offset added to fTop and fBottom
334 */
offsetSkIRect335 void offset(int32_t dx, int32_t dy) {
336 fLeft = Sk32_sat_add(fLeft, dx);
337 fTop = Sk32_sat_add(fTop, dy);
338 fRight = Sk32_sat_add(fRight, dx);
339 fBottom = Sk32_sat_add(fBottom, dy);
340 }
341
342 /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
343 fTop, fBottom.
344
345 If delta.fX is negative, moves SkIRect returned to the left.
346 If delta.fX is positive, moves SkIRect returned to the right.
347 If delta.fY is negative, moves SkIRect returned upward.
348 If delta.fY is positive, moves SkIRect returned downward.
349
350 @param delta offset added to SkIRect
351 */
offsetSkIRect352 void offset(const SkIPoint& delta) {
353 this->offset(delta.fX, delta.fY);
354 }
355
356 /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
357 are unchanged.
358
359 @param newX stored in fLeft, preserving width()
360 @param newY stored in fTop, preserving height()
361 */
offsetToSkIRect362 void offsetTo(int32_t newX, int32_t newY) {
363 fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
364 fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
365 fLeft = newX;
366 fTop = newY;
367 }
368
369 /** Insets SkIRect by (dx,dy).
370
371 If dx is positive, makes SkIRect narrower.
372 If dx is negative, makes SkIRect wider.
373 If dy is positive, makes SkIRect shorter.
374 If dy is negative, makes SkIRect taller.
375
376 @param dx offset added to fLeft and subtracted from fRight
377 @param dy offset added to fTop and subtracted from fBottom
378 */
insetSkIRect379 void inset(int32_t dx, int32_t dy) {
380 fLeft = Sk32_sat_add(fLeft, dx);
381 fTop = Sk32_sat_add(fTop, dy);
382 fRight = Sk32_sat_sub(fRight, dx);
383 fBottom = Sk32_sat_sub(fBottom, dy);
384 }
385
386 /** Outsets SkIRect by (dx, dy).
387
388 If dx is positive, makes SkIRect wider.
389 If dx is negative, makes SkIRect narrower.
390 If dy is positive, makes SkIRect taller.
391 If dy is negative, makes SkIRect shorter.
392
393 @param dx subtracted to fLeft and added from fRight
394 @param dy subtracted to fTop and added from fBottom
395 */
outsetSkIRect396 void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
397
398 /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
399
400 If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
401 If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
402 If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
403 If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
404
405 The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
406 greater than right, the SkIRect will be considered empty. Call sort() after this call
407 if that is not the desired behavior.
408
409 @param dL offset added to fLeft
410 @param dT offset added to fTop
411 @param dR offset added to fRight
412 @param dB offset added to fBottom
413 */
adjustSkIRect414 void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
415 fLeft = Sk32_sat_add(fLeft, dL);
416 fTop = Sk32_sat_add(fTop, dT);
417 fRight = Sk32_sat_add(fRight, dR);
418 fBottom = Sk32_sat_add(fBottom, dB);
419 }
420
421 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
422 Returns false if SkIRect is empty.
423
424 Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
425 returns true if constructed area is completely enclosed by SkIRect area.
426
427 @param x test SkIPoint x-coordinate
428 @param y test SkIPoint y-coordinate
429 @return true if (x, y) is inside SkIRect
430 */
containsSkIRect431 bool contains(int32_t x, int32_t y) const {
432 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
433 }
434
435 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
436 construction.
437
438 Returns true if SkIRect contains construction.
439 Returns false if SkIRect is empty or construction is empty.
440
441 @param left x-axis minimum of constructed SkIRect
442 @param top y-axis minimum of constructed SkIRect
443 @param right x-axis maximum of constructed SkIRect
444 @param bottom y-axis maximum of constructed SkIRect
445 @return true if all sides of SkIRect are outside construction
446 */
containsSkIRect447 bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
448 return left < right && top < bottom && !this->isEmpty() && // check for empties
449 fLeft <= left && fTop <= top &&
450 fRight >= right && fBottom >= bottom;
451 }
452
453 /** Returns true if SkIRect contains r.
454 Returns false if SkIRect is empty or r is empty.
455
456 SkIRect contains r when SkIRect area completely includes r area.
457
458 @param r SkIRect contained
459 @return true if all sides of SkIRect are outside r
460 */
containsSkIRect461 bool contains(const SkIRect& r) const {
462 return !r.isEmpty() && !this->isEmpty() && // check for empties
463 fLeft <= r.fLeft && fTop <= r.fTop &&
464 fRight >= r.fRight && fBottom >= r.fBottom;
465 }
466
467 /** Returns true if SkIRect contains r.
468 Returns false if SkIRect is empty or r is empty.
469
470 SkIRect contains r when SkIRect area completely includes r area.
471
472 @param r SkRect contained
473 @return true if all sides of SkIRect are outside r
474 */
475 bool contains(const SkRect& r) const;
476
477 /** Constructs SkIRect from (left, top, right, bottom). Does not sort
478 construction.
479
480 Returns true if SkIRect contains construction.
481 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
482
483 Return is undefined if SkIRect is empty or construction is empty.
484
485 @param left x-axis minimum of constructed SkIRect
486 @param top y-axis minimum of constructed SkIRect
487 @param right x-axis maximum of constructed SkIRect
488 @param bottom y-axis maximum of constructed SkIRect
489 @return true if all sides of SkIRect are outside construction
490 */
containsNoEmptyCheckSkIRect491 bool containsNoEmptyCheck(int32_t left, int32_t top,
492 int32_t right, int32_t bottom) const {
493 SkASSERT(fLeft < fRight && fTop < fBottom);
494 SkASSERT(left < right && top < bottom);
495
496 return fLeft <= left && fTop <= top &&
497 fRight >= right && fBottom >= bottom;
498 }
499
500 /** Returns true if SkIRect contains construction.
501 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
502
503 Return is undefined if SkIRect is empty or construction is empty.
504
505 @param r SkIRect contained
506 @return true if all sides of SkIRect are outside r
507 */
containsNoEmptyCheckSkIRect508 bool containsNoEmptyCheck(const SkIRect& r) const {
509 return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
510 }
511
512 /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
513 Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
514
515 Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
516
517 @param r limit of result
518 @return true if r and SkIRect have area in common
519 */
intersectSkIRect520 bool intersect(const SkIRect& r) {
521 return this->intersect(*this, r);
522 }
523
524 /** Returns true if a intersects b, and sets SkIRect to intersection.
525 Returns false if a does not intersect b, and leaves SkIRect unchanged.
526
527 Asserts if either a or b is empty, and if SK_DEBUG is defined.
528
529 @param a SkIRect to intersect
530 @param b SkIRect to intersect
531 @return true if a and b have area in common
532 */
intersectNoEmptyCheckSkIRect533 bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
534 SkASSERT(!a.isEmpty64() && !b.isEmpty64());
535 SkIRect r = {
536 SkMax32(a.fLeft, b.fLeft),
537 SkMax32(a.fTop, b.fTop),
538 SkMin32(a.fRight, b.fRight),
539 SkMin32(a.fBottom, b.fBottom)
540 };
541 if (r.isEmpty()) {
542 return false;
543 }
544 *this = r;
545 return true;
546 }
547
548 /** Returns true if a intersects b, and sets SkIRect to intersection.
549 Returns false if a does not intersect b, and leaves SkIRect unchanged.
550
551 Returns false if either a or b is empty, leaving SkIRect unchanged.
552
553 @param a SkIRect to intersect
554 @param b SkIRect to intersect
555 @return true if a and b have area in common
556 */
intersectSkIRect557 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
558 if (a.isEmpty64() || b.isEmpty64()) {
559 return false;
560 }
561 return this->intersectNoEmptyCheck(a, b);
562 }
563
564 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
565 construction.
566
567 Returns true if SkIRect intersects construction, and sets SkIRect to intersection.
568 Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.
569
570 Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.
571
572 @param left x-axis minimum of constructed SkIRect
573 @param top y-axis minimum of constructed SkIRect
574 @param right x-axis maximum of constructed SkIRect
575 @param bottom y-axis maximum of constructed SkIRect
576 @return true if construction and SkIRect have area in common
577 */
intersectSkIRect578 bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
579 return this->intersect(*this, {left, top, right, bottom});
580 }
581
582 /** Returns true if a intersects b.
583 Returns false if either a or b is empty, or do not intersect.
584
585 @param a SkIRect to intersect
586 @param b SkIRect to intersect
587 @return true if a and b have area in common
588 */
IntersectsSkIRect589 static bool Intersects(const SkIRect& a, const SkIRect& b) {
590 SkIRect dummy;
591 return dummy.intersect(a, b);
592 }
593
594 /** Returns true if a intersects b.
595 Asserts if either a or b is empty, and if SK_DEBUG is defined.
596
597 @param a SkIRect to intersect
598 @param b SkIRect to intersect
599 @return true if a and b have area in common
600 */
IntersectsNoEmptyCheckSkIRect601 static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
602 SkIRect dummy;
603 return dummy.intersectNoEmptyCheck(a, b);
604 }
605
606 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
607 construction.
608
609 Sets SkIRect to the union of itself and the construction.
610
611 Has no effect if construction is empty. Otherwise, if SkIRect is empty, sets
612 SkIRect to construction.
613
614 @param left x-axis minimum of constructed SkIRect
615 @param top y-axis minimum of constructed SkIRect
616 @param right x-axis maximum of constructed SkIRect
617 @param bottom y-axis maximum of constructed SkIRect
618 */
619 void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
620
621 /** Sets SkIRect to the union of itself and r.
622
623 Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
624
625 @param r expansion SkIRect
626 */
joinSkIRect627 void join(const SkIRect& r) {
628 this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
629 }
630
631 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
632 fTop and fBottom if fTop is greater than fBottom. Result may be empty,
633 and width() and height() will be zero or positive.
634 */
sortSkIRect635 void sort() {
636 using std::swap;
637 if (fLeft > fRight) {
638 swap(fLeft, fRight);
639 }
640 if (fTop > fBottom) {
641 swap(fTop, fBottom);
642 }
643 }
644
645 /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
646 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
647 and width() and height() will be zero or positive.
648
649 @return sorted SkIRect
650 */
makeSortedSkIRect651 SkIRect makeSorted() const {
652 return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
653 SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
654 }
655
656 /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
657
658 @return global SkIRect set to all zeroes
659 */
EmptyIRectSkIRect660 static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
661 static const SkIRect gEmpty = { 0, 0, 0, 0 };
662 return gEmpty;
663 }
664 };
665
666 /** \struct SkRect
667 SkRect holds four SkScalar coordinates describing the upper and
668 lower bounds of a rectangle. SkRect may be created from outer bounds or
669 from position, width, and height. SkRect describes an area; if its right
670 is less than or equal to its left, or if its bottom is less than or equal to
671 its top, it is considered empty.
672 */
673 struct SK_API SkRect {
674 SkScalar fLeft; //!< smaller x-axis bounds
675 SkScalar fTop; //!< smaller y-axis bounds
676 SkScalar fRight; //!< larger x-axis bounds
677 SkScalar fBottom; //!< larger y-axis bounds
678
679 /** Returns constructed SkRect set to (0, 0, 0, 0).
680 Many other rectangles are empty; if left is equal to or greater than right,
681 or if top is equal to or greater than bottom. Setting all members to zero
682 is a convenience, but does not designate a special empty rectangle.
683
684 @return bounds (0, 0, 0, 0)
685 */
MakeEmptySkRect686 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
687 return SkRect{0, 0, 0, 0};
688 }
689
690 /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
691 validate input; w or h may be negative.
692
693 Passing integer values may generate a compiler warning since SkRect cannot
694 represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
695
696 @param w SkScalar width of constructed SkRect
697 @param h SkScalar height of constructed SkRect
698 @return bounds (0, 0, w, h)
699 */
MakeWHSkRect700 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
701 return SkRect{0, 0, w, h};
702 }
703
704 /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
705 input; w or h may be negative.
706
707 Use to avoid a compiler warning that input may lose precision when stored.
708 Use SkIRect for an exact integer rectangle.
709
710 @param w integer width of constructed SkRect
711 @param h integer height of constructed SkRect
712 @return bounds (0, 0, w, h)
713 */
MakeIWHSkRect714 static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
715 SkRect r;
716 r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
717 return r;
718 }
719
720 /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
721 validate input; size.width() or size.height() may be negative.
722
723 @param size SkScalar values for SkRect width and height
724 @return bounds (0, 0, size.width(), size.height())
725 */
MakeSizeSkRect726 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
727 return SkRect{0, 0, size.fWidth, size.fHeight};
728 }
729
730 /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
731 result in fLeft greater than fRight, or fTop greater than fBottom.
732
733 @param l SkScalar stored in fLeft
734 @param t SkScalar stored in fTop
735 @param r SkScalar stored in fRight
736 @param b SkScalar stored in fBottom
737 @return bounds (l, t, r, b)
738 */
MakeLTRBSkRect739 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
740 SkScalar b) {
741 return SkRect {l, t, r, b};
742 }
743
744 /** Returns constructed SkRect set to (x, y, x + w, y + h).
745 Does not validate input; w or h may be negative.
746
747 @param x stored in fLeft
748 @param y stored in fTop
749 @param w added to x and stored in fRight
750 @param h added to y and stored in fBottom
751 @return bounds at (x, y) with width w and height h
752 */
MakeXYWHSkRect753 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
754 SkScalar h) {
755 return SkRect {x, y, x + w, y + h};
756 }
757
758 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
759 Does not validate input; size.width() or size.height() may be negative.
760
761 @param size integer values for SkRect width and height
762 @return bounds (0, 0, size.width(), size.height())
763 */
MakeSkRect764 static SkRect Make(const SkISize& size) {
765 return MakeIWH(size.width(), size.height());
766 }
767
768 /** Returns constructed SkIRect set to irect, promoting integers to scalar.
769 Does not validate input; fLeft may be greater than fRight, fTop may be greater
770 than fBottom.
771
772 @param irect integer unsorted bounds
773 @return irect members converted to SkScalar
774 */
MakeSkRect775 static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
776 SkRect r;
777 r.set(SkIntToScalar(irect.fLeft),
778 SkIntToScalar(irect.fTop),
779 SkIntToScalar(irect.fRight),
780 SkIntToScalar(irect.fBottom));
781 return r;
782 }
783
784 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
785 to or greater than fBottom. Call sort() to reverse rectangles with negative
786 width() or height().
787
788 @return true if width() or height() are zero or negative
789 */
isEmptySkRect790 bool isEmpty() const {
791 // We write it as the NOT of a non-empty rect, so we will return true if any values
792 // are NaN.
793 return !(fLeft < fRight && fTop < fBottom);
794 }
795
796 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
797 to or less than fBottom. Call sort() to reverse rectangles with negative
798 width() or height().
799
800 @return true if width() or height() are zero or positive
801 */
isSortedSkRect802 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
803
804 /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
805 and SK_ScalarMax or smaller.
806
807 @return true if no member is infinite or NaN
808 */
isFiniteSkRect809 bool isFinite() const {
810 float accum = 0;
811 accum *= fLeft;
812 accum *= fTop;
813 accum *= fRight;
814 accum *= fBottom;
815
816 // accum is either NaN or it is finite (zero).
817 SkASSERT(0 == accum || SkScalarIsNaN(accum));
818
819 // value==value will be true iff value is not NaN
820 // TODO: is it faster to say !accum or accum==accum?
821 return !SkScalarIsNaN(accum);
822 }
823
824 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
825 Call sort() to reverse fLeft and fRight if needed.
826
827 @return fLeft
828 */
xSkRect829 SkScalar x() const { return fLeft; }
830
831 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
832 and sort() to reverse fTop and fBottom if needed.
833
834 @return fTop
835 */
ySkRect836 SkScalar y() const { return fTop; }
837
838 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
839 Call sort() to reverse fLeft and fRight if needed.
840
841 @return fLeft
842 */
leftSkRect843 SkScalar left() const { return fLeft; }
844
845 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
846 and sort() to reverse fTop and fBottom if needed.
847
848 @return fTop
849 */
topSkRect850 SkScalar top() const { return fTop; }
851
852 /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
853 Call sort() to reverse fLeft and fRight if needed.
854
855 @return fRight
856 */
rightSkRect857 SkScalar right() const { return fRight; }
858
859 /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
860 and sort() to reverse fTop and fBottom if needed.
861
862 @return fBottom
863 */
bottomSkRect864 SkScalar bottom() const { return fBottom; }
865
866 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
867 result fits in 32-bit float; result may be negative or infinity.
868
869 @return fRight minus fLeft
870 */
widthSkRect871 SkScalar width() const { return fRight - fLeft; }
872
873 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
874 result fits in 32-bit float; result may be negative or infinity.
875
876 @return fBottom minus fTop
877 */
heightSkRect878 SkScalar height() const { return fBottom - fTop; }
879
880 /** Returns average of left edge and right edge. Result does not change if SkRect
881 is sorted. Result may overflow to infinity if SkRect is far from the origin.
882
883 @return midpoint on x-axis
884 */
centerXSkRect885 SkScalar centerX() const {
886 // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
887 return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
888 }
889
890 /** Returns average of top edge and bottom edge. Result does not change if SkRect
891 is sorted.
892
893 @return midpoint on y-axis
894 */
centerYSkRect895 SkScalar centerY() const {
896 // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
897 return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
898 }
899
900 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
901 equal to the corresponding members in b.
902
903 a and b are not equal if either contain NaN. a and b are equal if members
904 contain zeroes with different signs.
905
906 @param a SkRect to compare
907 @param b SkRect to compare
908 @return true if members are equal
909 */
910 friend bool operator==(const SkRect& a, const SkRect& b) {
911 return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
912 }
913
914 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
915 equal the corresponding members in b.
916
917 a and b are not equal if either contain NaN. a and b are equal if members
918 contain zeroes with different signs.
919
920 @param a SkRect to compare
921 @param b SkRect to compare
922 @return true if members are not equal
923 */
924 friend bool operator!=(const SkRect& a, const SkRect& b) {
925 return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
926 }
927
928 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
929 bottom-right, bottom-left.
930
931 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
932
933 @param quad storage for corners of SkRect
934 */
935 void toQuad(SkPoint quad[4]) const;
936
937 /** Sets SkRect to (0, 0, 0, 0).
938
939 Many other rectangles are empty; if left is equal to or greater than right,
940 or if top is equal to or greater than bottom. Setting all members to zero
941 is a convenience, but does not designate a special empty rectangle.
942 */
setEmptySkRect943 void setEmpty() { *this = MakeEmpty(); }
944
945 /** Sets SkRect to src, promoting src members from integer to scalar.
946 Very large values in src may lose precision.
947
948 @param src integer SkRect
949 */
setSkRect950 void set(const SkIRect& src) {
951 fLeft = SkIntToScalar(src.fLeft);
952 fTop = SkIntToScalar(src.fTop);
953 fRight = SkIntToScalar(src.fRight);
954 fBottom = SkIntToScalar(src.fBottom);
955 }
956
957 /** Sets SkRect to (left, top, right, bottom).
958 left and right are not sorted; left is not necessarily less than right.
959 top and bottom are not sorted; top is not necessarily less than bottom.
960
961 @param left stored in fLeft
962 @param top stored in fTop
963 @param right stored in fRight
964 @param bottom stored in fBottom
965 */
setSkRect966 void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
967 fLeft = left;
968 fTop = top;
969 fRight = right;
970 fBottom = bottom;
971 }
972
973 /** Sets SkRect to (left, top, right, bottom).
974 left and right are not sorted; left is not necessarily less than right.
975 top and bottom are not sorted; top is not necessarily less than bottom.
976
977 @param left stored in fLeft
978 @param top stored in fTop
979 @param right stored in fRight
980 @param bottom stored in fBottom
981 */
setLTRBSkRect982 void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
983 this->set(left, top, right, bottom);
984 }
985
986 /** Sets SkRect to (left, top, right, bottom).
987 All parameters are promoted from integer to scalar.
988 left and right are not sorted; left is not necessarily less than right.
989 top and bottom are not sorted; top is not necessarily less than bottom.
990
991 @param left promoted to SkScalar and stored in fLeft
992 @param top promoted to SkScalar and stored in fTop
993 @param right promoted to SkScalar and stored in fRight
994 @param bottom promoted to SkScalar and stored in fBottom
995 */
isetSkRect996 void iset(int left, int top, int right, int bottom) {
997 fLeft = SkIntToScalar(left);
998 fTop = SkIntToScalar(top);
999 fRight = SkIntToScalar(right);
1000 fBottom = SkIntToScalar(bottom);
1001 }
1002
1003 /** Sets SkRect to (0, 0, width, height).
1004 width and height may be zero or negative. width and height are promoted from
1005 integer to SkScalar, large values may lose precision.
1006
1007 @param width promoted to SkScalar and stored in fRight
1008 @param height promoted to SkScalar and stored in fBottom
1009 */
isetWHSkRect1010 void isetWH(int width, int height) {
1011 fLeft = fTop = 0;
1012 fRight = SkIntToScalar(width);
1013 fBottom = SkIntToScalar(height);
1014 }
1015
1016 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1017 or if SkPoint array contains an infinity or NaN, sets SkRect to (0, 0, 0, 0).
1018
1019 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1020 fTop is less than or equal to fBottom.
1021
1022 @param pts SkPoint array
1023 @param count entries in array
1024 */
setSkRect1025 void set(const SkPoint pts[], int count) {
1026 // set() had been checking for non-finite values, so keep that behavior
1027 // for now. Now that we have setBoundsCheck(), we may decide to make
1028 // set() be simpler/faster, and not check for those.
1029 (void)this->setBoundsCheck(pts, count);
1030 }
1031
1032 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1033 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
1034
1035 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1036 fTop is less than or equal to fBottom.
1037
1038 @param pts SkPoint array
1039 @param count entries in array
1040 */
setBoundsSkRect1041 void setBounds(const SkPoint pts[], int count) {
1042 (void)this->setBoundsCheck(pts, count);
1043 }
1044
1045 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
1046 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
1047 sets SkRect to (0, 0, 0, 0).
1048
1049 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1050 fTop is less than or equal to fBottom.
1051
1052 @param pts SkPoint array
1053 @param count entries in array
1054 @return true if all SkPoint values are finite
1055 */
1056 bool setBoundsCheck(const SkPoint pts[], int count);
1057
1058 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
1059 contains infinity or NaN, all SkRect dimensions are set to NaN.
1060
1061 @param pts SkPoint array
1062 @param count entries in array
1063 */
1064 void setBoundsNoCheck(const SkPoint pts[], int count);
1065
1066 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
1067 sorted and may be empty. Does not check to see if values are finite.
1068
1069 @param p0 corner to include
1070 @param p1 corner to include
1071 */
setSkRect1072 void set(const SkPoint& p0, const SkPoint& p1) {
1073 fLeft = SkMinScalar(p0.fX, p1.fX);
1074 fRight = SkMaxScalar(p0.fX, p1.fX);
1075 fTop = SkMinScalar(p0.fY, p1.fY);
1076 fBottom = SkMaxScalar(p0.fY, p1.fY);
1077 }
1078
1079 /** Sets SkRect to (x, y, x + width, y + height).
1080 Does not validate input; width or height may be negative.
1081
1082 @param x stored in fLeft
1083 @param y stored in fTop
1084 @param width added to x and stored in fRight
1085 @param height added to y and stored in fBottom
1086 */
setXYWHSkRect1087 void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
1088 fLeft = x;
1089 fTop = y;
1090 fRight = x + width;
1091 fBottom = y + height;
1092 }
1093
1094 /** Sets SkRect to (0, 0, width, height). Does not validate input;
1095 width or height may be negative.
1096
1097 @param width stored in fRight
1098 @param height stored in fBottom
1099 */
setWHSkRect1100 void setWH(SkScalar width, SkScalar height) {
1101 fLeft = 0;
1102 fTop = 0;
1103 fRight = width;
1104 fBottom = height;
1105 }
1106
1107 /** Returns SkRect offset by (dx, dy).
1108
1109 If dx is negative, SkRect returned is moved to the left.
1110 If dx is positive, SkRect returned is moved to the right.
1111 If dy is negative, SkRect returned is moved upward.
1112 If dy is positive, SkRect returned is moved downward.
1113
1114 @param dx added to fLeft and fRight
1115 @param dy added to fTop and fBottom
1116 @return SkRect offset on axes, with original width and height
1117 */
makeOffsetSkRect1118 SkRect makeOffset(SkScalar dx, SkScalar dy) const {
1119 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1120 }
1121
1122 /** Returns SkRect, inset by (dx, dy).
1123
1124 If dx is negative, SkRect returned is wider.
1125 If dx is positive, SkRect returned is narrower.
1126 If dy is negative, SkRect returned is taller.
1127 If dy is positive, SkRect returned is shorter.
1128
1129 @param dx added to fLeft and subtracted from fRight
1130 @param dy added to fTop and subtracted from fBottom
1131 @return SkRect inset symmetrically left and right, top and bottom
1132 */
makeInsetSkRect1133 SkRect makeInset(SkScalar dx, SkScalar dy) const {
1134 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1135 }
1136
1137 /** Returns SkRect, outset by (dx, dy).
1138
1139 If dx is negative, SkRect returned is narrower.
1140 If dx is positive, SkRect returned is wider.
1141 If dy is negative, SkRect returned is shorter.
1142 If dy is positive, SkRect returned is taller.
1143
1144 @param dx subtracted to fLeft and added from fRight
1145 @param dy subtracted to fTop and added from fBottom
1146 @return SkRect outset symmetrically left and right, top and bottom
1147 */
makeOutsetSkRect1148 SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1149 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1150 }
1151
1152 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1153
1154 If dx is negative, moves SkRect to the left.
1155 If dx is positive, moves SkRect to the right.
1156 If dy is negative, moves SkRect upward.
1157 If dy is positive, moves SkRect downward.
1158
1159 @param dx offset added to fLeft and fRight
1160 @param dy offset added to fTop and fBottom
1161 */
offsetSkRect1162 void offset(SkScalar dx, SkScalar dy) {
1163 fLeft += dx;
1164 fTop += dy;
1165 fRight += dx;
1166 fBottom += dy;
1167 }
1168
1169 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1170 fTop, fBottom.
1171
1172 If delta.fX is negative, moves SkRect to the left.
1173 If delta.fX is positive, moves SkRect to the right.
1174 If delta.fY is negative, moves SkRect upward.
1175 If delta.fY is positive, moves SkRect downward.
1176
1177 @param delta added to SkRect
1178 */
offsetSkRect1179 void offset(const SkPoint& delta) {
1180 this->offset(delta.fX, delta.fY);
1181 }
1182
1183 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1184 are unchanged.
1185
1186 @param newX stored in fLeft, preserving width()
1187 @param newY stored in fTop, preserving height()
1188 */
offsetToSkRect1189 void offsetTo(SkScalar newX, SkScalar newY) {
1190 fRight += newX - fLeft;
1191 fBottom += newY - fTop;
1192 fLeft = newX;
1193 fTop = newY;
1194 }
1195
1196 /** Insets SkRect by (dx, dy).
1197
1198 If dx is positive, makes SkRect narrower.
1199 If dx is negative, makes SkRect wider.
1200 If dy is positive, makes SkRect shorter.
1201 If dy is negative, makes SkRect taller.
1202
1203 @param dx added to fLeft and subtracted from fRight
1204 @param dy added to fTop and subtracted from fBottom
1205 */
insetSkRect1206 void inset(SkScalar dx, SkScalar dy) {
1207 fLeft += dx;
1208 fTop += dy;
1209 fRight -= dx;
1210 fBottom -= dy;
1211 }
1212
1213 /** Outsets SkRect by (dx, dy).
1214
1215 If dx is positive, makes SkRect wider.
1216 If dx is negative, makes SkRect narrower.
1217 If dy is positive, makes SkRect taller.
1218 If dy is negative, makes SkRect shorter.
1219
1220 @param dx subtracted to fLeft and added from fRight
1221 @param dy subtracted to fTop and added from fBottom
1222 */
outsetSkRect1223 void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
1224
1225 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1226 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1227
1228 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1229
1230 @param r limit of result
1231 @return true if r and SkRect have area in common
1232 */
1233 bool intersect(const SkRect& r);
1234
1235 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1236 construction.
1237
1238 Returns true if SkRect intersects construction, and sets SkRect to intersection.
1239 Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.
1240
1241 Returns false if either construction or SkRect is empty, leaving SkRect unchanged.
1242
1243 @param left x-axis minimum of constructed SkRect
1244 @param top y-axis minimum of constructed SkRect
1245 @param right x-axis maximum of constructed SkRect
1246 @param bottom y-axis maximum of constructed SkRect
1247 @return true if construction and SkRect have area in common
1248 */
1249 bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1250
1251 /** Returns true if a intersects b, and sets SkRect to intersection.
1252 Returns false if a does not intersect b, and leaves SkRect unchanged.
1253
1254 Returns false if either a or b is empty, leaving SkRect unchanged.
1255
1256 @param a SkRect to intersect
1257 @param b SkRect to intersect
1258 @return true if a and b have area in common
1259 */
1260 bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1261
1262
1263 private:
IntersectsSkRect1264 static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1265 SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1266 SkScalar L = SkMaxScalar(al, bl);
1267 SkScalar R = SkMinScalar(ar, br);
1268 SkScalar T = SkMaxScalar(at, bt);
1269 SkScalar B = SkMinScalar(ab, bb);
1270 return L < R && T < B;
1271 }
1272
1273 public:
1274
1275 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1276 construction.
1277
1278 Returns true if SkRect intersects construction.
1279 Returns false if either construction or SkRect is empty, or do not intersect.
1280
1281 @param left x-axis minimum of constructed SkRect
1282 @param top y-axis minimum of constructed SkRect
1283 @param right x-axis maximum of constructed SkRect
1284 @param bottom y-axis maximum of constructed SkRect
1285 @return true if construction and SkRect have area in common
1286 */
intersectsSkRect1287 bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
1288 return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
1289 }
1290
1291 /** Returns true if SkRect intersects r.
1292 Returns false if either r or SkRect is empty, or do not intersect.
1293
1294 @param r SkRect to intersect
1295 @return true if r and SkRect have area in common
1296 */
intersectsSkRect1297 bool intersects(const SkRect& r) const {
1298 return Intersects(fLeft, fTop, fRight, fBottom,
1299 r.fLeft, r.fTop, r.fRight, r.fBottom);
1300 }
1301
1302 /** Returns true if a intersects b.
1303 Returns false if either a or b is empty, or do not intersect.
1304
1305 @param a SkRect to intersect
1306 @param b SkRect to intersect
1307 @return true if a and b have area in common
1308 */
IntersectsSkRect1309 static bool Intersects(const SkRect& a, const SkRect& b) {
1310 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1311 b.fLeft, b.fTop, b.fRight, b.fBottom);
1312 }
1313
1314 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1315 construction.
1316
1317 Sets SkRect to the union of itself and the construction.
1318
1319 Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
1320 SkRect to construction.
1321
1322 @param left x-axis minimum of constructed SkRect
1323 @param top y-axis minimum of constructed SkRect
1324 @param right x-axis maximum of constructed SkRect
1325 @param bottom y-axis maximum of constructed SkRect
1326 */
1327 void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1328
1329 /** Sets SkRect to the union of itself and r.
1330
1331 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1332 SkRect to r.
1333
1334 @param r expansion SkRect
1335 */
joinSkRect1336 void join(const SkRect& r) {
1337 this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
1338 }
1339
1340 /** Sets SkRect to the union of itself and r.
1341
1342 Asserts if r is empty and SK_DEBUG is defined.
1343 If SkRect is empty, sets SkRect to r.
1344
1345 May produce incorrect results if r is empty.
1346
1347 @param r expansion SkRect
1348 */
joinNonEmptyArgSkRect1349 void joinNonEmptyArg(const SkRect& r) {
1350 SkASSERT(!r.isEmpty());
1351 // if we are empty, just assign
1352 if (fLeft >= fRight || fTop >= fBottom) {
1353 *this = r;
1354 } else {
1355 this->joinPossiblyEmptyRect(r);
1356 }
1357 }
1358
1359 /** Sets SkRect to the union of itself and the construction.
1360
1361 May produce incorrect results if SkRect or r is empty.
1362
1363 @param r expansion SkRect
1364 */
joinPossiblyEmptyRectSkRect1365 void joinPossiblyEmptyRect(const SkRect& r) {
1366 fLeft = SkMinScalar(fLeft, r.left());
1367 fTop = SkMinScalar(fTop, r.top());
1368 fRight = SkMaxScalar(fRight, r.right());
1369 fBottom = SkMaxScalar(fBottom, r.bottom());
1370 }
1371
1372 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1373 Returns false if SkRect is empty.
1374
1375 @param x test SkPoint x-coordinate
1376 @param y test SkPoint y-coordinate
1377 @return true if (x, y) is inside SkRect
1378 */
containsSkRect1379 bool contains(SkScalar x, SkScalar y) const {
1380 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1381 }
1382
1383 /** Returns true if SkRect contains r.
1384 Returns false if SkRect is empty or r is empty.
1385
1386 SkRect contains r when SkRect area completely includes r area.
1387
1388 @param r SkRect contained
1389 @return true if all sides of SkRect are outside r
1390 */
containsSkRect1391 bool contains(const SkRect& r) const {
1392 // todo: can we eliminate the this->isEmpty check?
1393 return !r.isEmpty() && !this->isEmpty() &&
1394 fLeft <= r.fLeft && fTop <= r.fTop &&
1395 fRight >= r.fRight && fBottom >= r.fBottom;
1396 }
1397
1398 /** Returns true if SkRect contains r.
1399 Returns false if SkRect is empty or r is empty.
1400
1401 SkRect contains r when SkRect area completely includes r area.
1402
1403 @param r SkIRect contained
1404 @return true if all sides of SkRect are outside r
1405 */
containsSkRect1406 bool contains(const SkIRect& r) const {
1407 // todo: can we eliminate the this->isEmpty check?
1408 return !r.isEmpty() && !this->isEmpty() &&
1409 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1410 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1411 }
1412
1413 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1414 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1415 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1416
1417 @param dst storage for SkIRect
1418 */
roundSkRect1419 void round(SkIRect* dst) const {
1420 SkASSERT(dst);
1421 dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1422 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1423 }
1424
1425 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1426 up fRight and fBottom, using
1427 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1428 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1429
1430 @param dst storage for SkIRect
1431 */
roundOutSkRect1432 void roundOut(SkIRect* dst) const {
1433 SkASSERT(dst);
1434 dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1435 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1436 }
1437
1438 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1439 up fRight and fBottom, using
1440 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1441 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1442
1443 @param dst storage for SkRect
1444 */
roundOutSkRect1445 void roundOut(SkRect* dst) const {
1446 dst->set(SkScalarFloorToScalar(fLeft),
1447 SkScalarFloorToScalar(fTop),
1448 SkScalarCeilToScalar(fRight),
1449 SkScalarCeilToScalar(fBottom));
1450 }
1451
1452 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1453 of fRight and fBottom, using
1454 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1455 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1456
1457 @param dst storage for SkIRect
1458 */
roundInSkRect1459 void roundIn(SkIRect* dst) const {
1460 SkASSERT(dst);
1461 dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1462 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1463 }
1464
1465 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1466 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1467 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1468
1469 @return rounded SkIRect
1470 */
roundSkRect1471 SkIRect round() const {
1472 SkIRect ir;
1473 this->round(&ir);
1474 return ir;
1475 }
1476
1477 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1478 up fRight and fBottom, using
1479 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1480 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1481
1482 @return rounded SkIRect
1483 */
roundOutSkRect1484 SkIRect roundOut() const {
1485 SkIRect ir;
1486 this->roundOut(&ir);
1487 return ir;
1488 }
1489
1490 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1491 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1492 and width() and height() will be zero or positive.
1493 */
sortSkRect1494 void sort() {
1495 using std::swap;
1496 if (fLeft > fRight) {
1497 swap(fLeft, fRight);
1498 }
1499
1500 if (fTop > fBottom) {
1501 swap(fTop, fBottom);
1502 }
1503 }
1504
1505 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1506 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1507 and width() and height() will be zero or positive.
1508
1509 @return sorted SkRect
1510 */
makeSortedSkRect1511 SkRect makeSorted() const {
1512 return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
1513 SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
1514 }
1515
1516 /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1517 entries.
1518
1519 @return pointer to fLeft
1520 */
asScalarsSkRect1521 const SkScalar* asScalars() const { return &fLeft; }
1522
1523 /** Writes text representation of SkRect to standard output. Set asHex to true to
1524 generate exact binary representations of floating point numbers.
1525
1526 @param asHex true if SkScalar values are written as hexadecimal
1527 */
1528 void dump(bool asHex) const;
1529
1530 /** Writes text representation of SkRect to standard output. The representation may be
1531 directly compiled as C++ code. Floating point values are written
1532 with limited precision; it may not be possible to reconstruct original SkRect
1533 from output.
1534 */
dumpSkRect1535 void dump() const { this->dump(false); }
1536
1537 /** Writes text representation of SkRect to standard output. The representation may be
1538 directly compiled as C++ code. Floating point values are written
1539 in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1540 original SkRect.
1541
1542 Use instead of dump() when submitting
1543 */
dumpHexSkRect1544 void dumpHex() const { this->dump(true); }
1545 };
1546
contains(const SkRect & r)1547 inline bool SkIRect::contains(const SkRect& r) const {
1548 return !r.isEmpty() && !this->isEmpty() && // check for empties
1549 (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1550 (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1551 }
1552
1553 #endif
1554