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
dumpSkIRect33 void dump(std::string& desc, int depth) const {
34 std::string split(depth, '\t');
35 desc += split + "\n SkIRect:{ \n";
36 desc += split + "\t fLeft:" + std::to_string(fLeft) + "\n";
37 desc += split + "\t fTop:" + std::to_string(fTop) + "\n";
38 desc += split + "\t fRight:" + std::to_string(fRight) + "\n";
39 desc += split + "\t fBottom:" + std::to_string(fBottom) + "\n";
40 desc += split + "}\n";
41 }
42 /** Returns constructed SkIRect set to (0, 0, 0, 0).
43 Many other rectangles are empty; if left is equal to or greater than right,
44 or if top is equal to or greater than bottom. Setting all members to zero
45 is a convenience, but does not designate a special empty rectangle.
46
47 @return bounds (0, 0, 0, 0)
48 */
MakeEmptySkIRect49 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
50 return SkIRect{0, 0, 0, 0};
51 }
52
53 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
54 may be negative.
55
56 @param w width of constructed SkIRect
57 @param h height of constructed SkIRect
58 @return bounds (0, 0, w, h)
59 */
MakeWHSkIRect60 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
61 return SkIRect{0, 0, w, h};
62 }
63
64 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
65 Does not validate input; size.width() or size.height() may be negative.
66
67 @param size values for SkIRect width and height
68 @return bounds (0, 0, size.width(), size.height())
69 */
MakeSizeSkIRect70 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
71 return SkIRect{0, 0, size.fWidth, size.fHeight};
72 }
73
74 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
75 result in fLeft greater than fRight, or fTop greater than fBottom.
76
77 @param l integer stored in fLeft
78 @param t integer stored in fTop
79 @param r integer stored in fRight
80 @param b integer stored in fBottom
81 @return bounds (l, t, r, b)
82 */
MakeLTRBSkIRect83 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
84 int32_t r, int32_t b) {
85 return SkIRect{l, t, r, b};
86 }
87
88 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
89 Does not validate input; w or h may be negative.
90
91 @param x stored in fLeft
92 @param y stored in fTop
93 @param w added to x and stored in fRight
94 @param h added to y and stored in fBottom
95 @return bounds at (x, y) with width w and height h
96 */
MakeXYWHSkIRect97 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
98 int32_t w, int32_t h) {
99 return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
100 }
101
102 /** Returns left edge of SkIRect, if sorted.
103 Call sort() to reverse fLeft and fRight if needed.
104
105 @return fLeft
106 */
leftSkIRect107 int32_t left() const { return fLeft; }
108
109 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
110 and sort() to reverse fTop and fBottom if needed.
111
112 @return fTop
113 */
topSkIRect114 int32_t top() const { return fTop; }
115
116 /** Returns right edge of SkIRect, if sorted.
117 Call sort() to reverse fLeft and fRight if needed.
118
119 @return fRight
120 */
rightSkIRect121 int32_t right() const { return fRight; }
122
123 /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
124 and sort() to reverse fTop and fBottom if needed.
125
126 @return fBottom
127 */
bottomSkIRect128 int32_t bottom() const { return fBottom; }
129
130 /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
131 and sort() to reverse fLeft and fRight if needed.
132
133 @return fLeft
134 */
xSkIRect135 int32_t x() const { return fLeft; }
136
137 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
138 and sort() to reverse fTop and fBottom if needed.
139
140 @return fTop
141 */
ySkIRect142 int32_t y() const { return fTop; }
143
144 // Experimental
topLeftSkIRect145 SkIPoint topLeft() const { return {fLeft, fTop}; }
146
147 /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
148 result fits in 32-bit signed integer; result may be negative.
149
150 @return fRight minus fLeft
151 */
widthSkIRect152 int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
153
154 /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
155 result fits in 32-bit signed integer; result may be negative.
156
157 @return fBottom minus fTop
158 */
heightSkIRect159 int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
160
161 /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
162 or if result fits in 32-bit signed integer; result may be negative.
163
164 @return SkISize (width, height)
165 */
sizeSkIRect166 SkISize size() const { return SkISize::Make(this->width(), this->height()); }
167
168 /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
169 result may be negative. This is safer than calling width() since width() might
170 overflow in its calculation.
171
172 @return fRight minus fLeft cast to int64_t
173 */
width64SkIRect174 int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
175
176 /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
177 result may be negative. This is safer than calling height() since height() might
178 overflow in its calculation.
179
180 @return fBottom minus fTop cast to int64_t
181 */
height64SkIRect182 int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
183
184 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
185 to or greater than fBottom. Call sort() to reverse rectangles with negative
186 width64() or height64().
187
188 @return true if width64() or height64() are zero or negative
189 */
isEmpty64SkIRect190 bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
191
192 /** Returns true if width() or height() are zero or negative.
193
194 @return true if width() or height() are zero or negative
195 */
isEmptySkIRect196 bool isEmpty() const {
197 int64_t w = this->width64();
198 int64_t h = this->height64();
199 if (w <= 0 || h <= 0) {
200 return true;
201 }
202 // Return true if either exceeds int32_t
203 return !SkTFitsIn<int32_t>(w | h);
204 }
205
206 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
207 identical to corresponding members in b.
208
209 @param a SkIRect to compare
210 @param b SkIRect to compare
211 @return true if members are equal
212 */
213 friend bool operator==(const SkIRect& a, const SkIRect& b) {
214 return !memcmp(&a, &b, sizeof(a));
215 }
216
217 /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
218 identical to the corresponding member in b.
219
220 @param a SkIRect to compare
221 @param b SkIRect to compare
222 @return true if members are not equal
223 */
224 friend bool operator!=(const SkIRect& a, const SkIRect& b) {
225 return !(a == b);
226 }
227
228 /** Sets SkIRect to (0, 0, 0, 0).
229
230 Many other rectangles are empty; if left is equal to or greater than right,
231 or if top is equal to or greater than bottom. Setting all members to zero
232 is a convenience, but does not designate a special empty rectangle.
233 */
setEmptySkIRect234 void setEmpty() { memset(this, 0, sizeof(*this)); }
235
236 /** Sets SkIRect to (left, top, right, bottom).
237 left and right are not sorted; left is not necessarily less than right.
238 top and bottom are not sorted; top is not necessarily less than bottom.
239
240 @param left assigned to fLeft
241 @param top assigned to fTop
242 @param right assigned to fRight
243 @param bottom assigned to fBottom
244 */
setSkIRect245 void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
246 fLeft = left;
247 fTop = top;
248 fRight = right;
249 fBottom = bottom;
250 }
251
252 /** Sets SkIRect to (left, top, right, bottom).
253 left and right are not sorted; left is not necessarily less than right.
254 top and bottom are not sorted; top is not necessarily less than bottom.
255
256 @param left stored in fLeft
257 @param top stored in fTop
258 @param right stored in fRight
259 @param bottom stored in fBottom
260 */
setLTRBSkIRect261 void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
262 this->set(left, top, right, bottom);
263 }
264
265 /** Sets SkIRect to: (x, y, x + width, y + height).
266 Does not validate input; width or height may be negative.
267
268 @param x stored in fLeft
269 @param y stored in fTop
270 @param width added to x and stored in fRight
271 @param height added to y and stored in fBottom
272 */
setXYWHSkIRect273 void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
274 fLeft = x;
275 fTop = y;
276 fRight = Sk32_sat_add(x, width);
277 fBottom = Sk32_sat_add(y, height);
278 }
279
280 /** Returns SkIRect offset by (dx, dy).
281
282 If dx is negative, SkIRect returned is moved to the left.
283 If dx is positive, SkIRect returned is moved to the right.
284 If dy is negative, SkIRect returned is moved upward.
285 If dy is positive, SkIRect returned is moved downward.
286
287 @param dx offset added to fLeft and fRight
288 @param dy offset added to fTop and fBottom
289 @return SkIRect offset by dx and dy, with original width and height
290 */
makeOffsetSkIRect291 SkIRect makeOffset(int32_t dx, int32_t dy) const {
292 return {
293 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
294 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
295 };
296 }
297
298 /** Returns SkIRect, inset by (dx, dy).
299
300 If dx is negative, SkIRect returned is wider.
301 If dx is positive, SkIRect returned is narrower.
302 If dy is negative, SkIRect returned is taller.
303 If dy is positive, SkIRect returned is shorter.
304
305 @param dx offset added to fLeft and subtracted from fRight
306 @param dy offset added to fTop and subtracted from fBottom
307 @return SkIRect inset symmetrically left and right, top and bottom
308 */
makeInsetSkIRect309 SkIRect makeInset(int32_t dx, int32_t dy) const {
310 return {
311 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
312 Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
313 };
314 }
315
316 /** Returns SkIRect, outset by (dx, dy).
317
318 If dx is negative, SkIRect returned is narrower.
319 If dx is positive, SkIRect returned is wider.
320 If dy is negative, SkIRect returned is shorter.
321 If dy is positive, SkIRect returned is taller.
322
323 @param dx offset subtracted to fLeft and added from fRight
324 @param dy offset subtracted to fTop and added from fBottom
325 @return SkIRect outset symmetrically left and right, top and bottom
326 */
makeOutsetSkIRect327 SkIRect makeOutset(int32_t dx, int32_t dy) const {
328 return {
329 Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
330 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
331 };
332 }
333
334 /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
335
336 If dx is negative, moves SkIRect returned to the left.
337 If dx is positive, moves SkIRect returned to the right.
338 If dy is negative, moves SkIRect returned upward.
339 If dy is positive, moves SkIRect returned downward.
340
341 @param dx offset added to fLeft and fRight
342 @param dy offset added to fTop and fBottom
343 */
offsetSkIRect344 void offset(int32_t dx, int32_t dy) {
345 fLeft = Sk32_sat_add(fLeft, dx);
346 fTop = Sk32_sat_add(fTop, dy);
347 fRight = Sk32_sat_add(fRight, dx);
348 fBottom = Sk32_sat_add(fBottom, dy);
349 }
350
351 /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
352 fTop, fBottom.
353
354 If delta.fX is negative, moves SkIRect returned to the left.
355 If delta.fX is positive, moves SkIRect returned to the right.
356 If delta.fY is negative, moves SkIRect returned upward.
357 If delta.fY is positive, moves SkIRect returned downward.
358
359 @param delta offset added to SkIRect
360 */
offsetSkIRect361 void offset(const SkIPoint& delta) {
362 this->offset(delta.fX, delta.fY);
363 }
364
365 /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
366 are unchanged.
367
368 @param newX stored in fLeft, preserving width()
369 @param newY stored in fTop, preserving height()
370 */
offsetToSkIRect371 void offsetTo(int32_t newX, int32_t newY) {
372 fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
373 fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
374 fLeft = newX;
375 fTop = newY;
376 }
377
378 /** Insets SkIRect by (dx,dy).
379
380 If dx is positive, makes SkIRect narrower.
381 If dx is negative, makes SkIRect wider.
382 If dy is positive, makes SkIRect shorter.
383 If dy is negative, makes SkIRect taller.
384
385 @param dx offset added to fLeft and subtracted from fRight
386 @param dy offset added to fTop and subtracted from fBottom
387 */
insetSkIRect388 void inset(int32_t dx, int32_t dy) {
389 fLeft = Sk32_sat_add(fLeft, dx);
390 fTop = Sk32_sat_add(fTop, dy);
391 fRight = Sk32_sat_sub(fRight, dx);
392 fBottom = Sk32_sat_sub(fBottom, dy);
393 }
394
395 /** Outsets SkIRect by (dx, dy).
396
397 If dx is positive, makes SkIRect wider.
398 If dx is negative, makes SkIRect narrower.
399 If dy is positive, makes SkIRect taller.
400 If dy is negative, makes SkIRect shorter.
401
402 @param dx subtracted to fLeft and added from fRight
403 @param dy subtracted to fTop and added from fBottom
404 */
outsetSkIRect405 void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
406
407 /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
408
409 If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
410 If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
411 If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
412 If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
413
414 The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
415 greater than right, the SkIRect will be considered empty. Call sort() after this call
416 if that is not the desired behavior.
417
418 @param dL offset added to fLeft
419 @param dT offset added to fTop
420 @param dR offset added to fRight
421 @param dB offset added to fBottom
422 */
adjustSkIRect423 void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
424 fLeft = Sk32_sat_add(fLeft, dL);
425 fTop = Sk32_sat_add(fTop, dT);
426 fRight = Sk32_sat_add(fRight, dR);
427 fBottom = Sk32_sat_add(fBottom, dB);
428 }
429
430 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
431 Returns false if SkIRect is empty.
432
433 Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
434 returns true if constructed area is completely enclosed by SkIRect area.
435
436 @param x test SkIPoint x-coordinate
437 @param y test SkIPoint y-coordinate
438 @return true if (x, y) is inside SkIRect
439 */
containsSkIRect440 bool contains(int32_t x, int32_t y) const {
441 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
442 }
443
444 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
445 construction.
446
447 Returns true if SkIRect contains construction.
448 Returns false if SkIRect is empty or construction is empty.
449
450 @param left x-axis minimum of constructed SkIRect
451 @param top y-axis minimum of constructed SkIRect
452 @param right x-axis maximum of constructed SkIRect
453 @param bottom y-axis maximum of constructed SkIRect
454 @return true if all sides of SkIRect are outside construction
455 */
containsSkIRect456 bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
457 return left < right && top < bottom && !this->isEmpty() && // check for empties
458 fLeft <= left && fTop <= top &&
459 fRight >= right && fBottom >= bottom;
460 }
461
462 /** Returns true if SkIRect contains r.
463 Returns false if SkIRect is empty or r is empty.
464
465 SkIRect contains r when SkIRect area completely includes r area.
466
467 @param r SkIRect contained
468 @return true if all sides of SkIRect are outside r
469 */
containsSkIRect470 bool contains(const SkIRect& r) const {
471 return !r.isEmpty() && !this->isEmpty() && // check for empties
472 fLeft <= r.fLeft && fTop <= r.fTop &&
473 fRight >= r.fRight && fBottom >= r.fBottom;
474 }
475
476 /** Returns true if SkIRect contains r.
477 Returns false if SkIRect is empty or r is empty.
478
479 SkIRect contains r when SkIRect area completely includes r area.
480
481 @param r SkRect contained
482 @return true if all sides of SkIRect are outside r
483 */
484 bool contains(const SkRect& r) const;
485
486 /** Constructs SkIRect from (left, top, right, bottom). Does not sort
487 construction.
488
489 Returns true if SkIRect contains construction.
490 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
491
492 Return is undefined if SkIRect is empty or construction is empty.
493
494 @param left x-axis minimum of constructed SkIRect
495 @param top y-axis minimum of constructed SkIRect
496 @param right x-axis maximum of constructed SkIRect
497 @param bottom y-axis maximum of constructed SkIRect
498 @return true if all sides of SkIRect are outside construction
499 */
containsNoEmptyCheckSkIRect500 bool containsNoEmptyCheck(int32_t left, int32_t top,
501 int32_t right, int32_t bottom) const {
502 SkASSERT(fLeft < fRight && fTop < fBottom);
503 SkASSERT(left < right && top < bottom);
504
505 return fLeft <= left && fTop <= top &&
506 fRight >= right && fBottom >= bottom;
507 }
508
509 /** Returns true if SkIRect contains construction.
510 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
511
512 Return is undefined if SkIRect is empty or construction is empty.
513
514 @param r SkIRect contained
515 @return true if all sides of SkIRect are outside r
516 */
containsNoEmptyCheckSkIRect517 bool containsNoEmptyCheck(const SkIRect& r) const {
518 return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
519 }
520
521 /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
522 Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
523
524 Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
525
526 @param r limit of result
527 @return true if r and SkIRect have area in common
528 */
intersectSkIRect529 bool intersect(const SkIRect& r) {
530 return this->intersect(*this, r);
531 }
532
533 /** Returns true if a intersects b, and sets SkIRect to intersection.
534 Returns false if a does not intersect b, and leaves SkIRect unchanged.
535
536 Asserts if either a or b is empty, and if SK_DEBUG is defined.
537
538 @param a SkIRect to intersect
539 @param b SkIRect to intersect
540 @return true if a and b have area in common
541 */
intersectNoEmptyCheckSkIRect542 bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
543 SkASSERT(!a.isEmpty64() && !b.isEmpty64());
544 SkIRect r = {
545 SkMax32(a.fLeft, b.fLeft),
546 SkMax32(a.fTop, b.fTop),
547 SkMin32(a.fRight, b.fRight),
548 SkMin32(a.fBottom, b.fBottom)
549 };
550 if (r.isEmpty()) {
551 return false;
552 }
553 *this = r;
554 return true;
555 }
556
557 /** Returns true if a intersects b, and sets SkIRect to intersection.
558 Returns false if a does not intersect b, and leaves SkIRect unchanged.
559
560 Returns false if either a or b is empty, leaving SkIRect unchanged.
561
562 @param a SkIRect to intersect
563 @param b SkIRect to intersect
564 @return true if a and b have area in common
565 */
intersectSkIRect566 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
567 if (a.isEmpty64() || b.isEmpty64()) {
568 return false;
569 }
570 return this->intersectNoEmptyCheck(a, b);
571 }
572
573 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
574 construction.
575
576 Returns true if SkIRect intersects construction, and sets SkIRect to intersection.
577 Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.
578
579 Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.
580
581 @param left x-axis minimum of constructed SkIRect
582 @param top y-axis minimum of constructed SkIRect
583 @param right x-axis maximum of constructed SkIRect
584 @param bottom y-axis maximum of constructed SkIRect
585 @return true if construction and SkIRect have area in common
586 */
intersectSkIRect587 bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
588 return this->intersect(*this, {left, top, right, bottom});
589 }
590
591 /** Returns true if a intersects b.
592 Returns false if either a or b is empty, or do not intersect.
593
594 @param a SkIRect to intersect
595 @param b SkIRect to intersect
596 @return true if a and b have area in common
597 */
IntersectsSkIRect598 static bool Intersects(const SkIRect& a, const SkIRect& b) {
599 SkIRect dummy;
600 return dummy.intersect(a, b);
601 }
602
603 /** Returns true if a intersects b.
604 Asserts if either a or b is empty, and if SK_DEBUG is defined.
605
606 @param a SkIRect to intersect
607 @param b SkIRect to intersect
608 @return true if a and b have area in common
609 */
IntersectsNoEmptyCheckSkIRect610 static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
611 SkIRect dummy;
612 return dummy.intersectNoEmptyCheck(a, b);
613 }
614
615 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
616 construction.
617
618 Sets SkIRect to the union of itself and the construction.
619
620 Has no effect if construction is empty. Otherwise, if SkIRect is empty, sets
621 SkIRect to construction.
622
623 @param left x-axis minimum of constructed SkIRect
624 @param top y-axis minimum of constructed SkIRect
625 @param right x-axis maximum of constructed SkIRect
626 @param bottom y-axis maximum of constructed SkIRect
627 */
628 void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
629
630 /** Sets SkIRect to the union of itself and r.
631
632 Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
633
634 @param r expansion SkIRect
635 */
joinSkIRect636 void join(const SkIRect& r) {
637 this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
638 }
639
640 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
641 fTop and fBottom if fTop is greater than fBottom. Result may be empty,
642 and width() and height() will be zero or positive.
643 */
sortSkIRect644 void sort() {
645 using std::swap;
646 if (fLeft > fRight) {
647 swap(fLeft, fRight);
648 }
649 if (fTop > fBottom) {
650 swap(fTop, fBottom);
651 }
652 }
653
654 /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
655 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
656 and width() and height() will be zero or positive.
657
658 @return sorted SkIRect
659 */
makeSortedSkIRect660 SkIRect makeSorted() const {
661 return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
662 SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
663 }
664
665 /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
666
667 @return global SkIRect set to all zeroes
668 */
EmptyIRectSkIRect669 static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
670 static const SkIRect gEmpty = { 0, 0, 0, 0 };
671 return gEmpty;
672 }
673 };
674
675 /** \struct SkRect
676 SkRect holds four SkScalar coordinates describing the upper and
677 lower bounds of a rectangle. SkRect may be created from outer bounds or
678 from position, width, and height. SkRect describes an area; if its right
679 is less than or equal to its left, or if its bottom is less than or equal to
680 its top, it is considered empty.
681 */
682 struct SK_API SkRect {
683 SkScalar fLeft; //!< smaller x-axis bounds
684 SkScalar fTop; //!< smaller y-axis bounds
685 SkScalar fRight; //!< larger x-axis bounds
686 SkScalar fBottom; //!< larger y-axis bounds
687
688 /** Returns constructed SkRect set to (0, 0, 0, 0).
689 Many other rectangles are empty; if left is equal to or greater than right,
690 or if top is equal to or greater than bottom. Setting all members to zero
691 is a convenience, but does not designate a special empty rectangle.
692
693 @return bounds (0, 0, 0, 0)
694 */
MakeEmptySkRect695 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
696 return SkRect{0, 0, 0, 0};
697 }
698
699 /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
700 validate input; w or h may be negative.
701
702 Passing integer values may generate a compiler warning since SkRect cannot
703 represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
704
705 @param w SkScalar width of constructed SkRect
706 @param h SkScalar height of constructed SkRect
707 @return bounds (0, 0, w, h)
708 */
MakeWHSkRect709 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
710 return SkRect{0, 0, w, h};
711 }
712
713 /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
714 input; w or h may be negative.
715
716 Use to avoid a compiler warning that input may lose precision when stored.
717 Use SkIRect for an exact integer rectangle.
718
719 @param w integer width of constructed SkRect
720 @param h integer height of constructed SkRect
721 @return bounds (0, 0, w, h)
722 */
MakeIWHSkRect723 static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
724 SkRect r;
725 r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
726 return r;
727 }
728
729 /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
730 validate input; size.width() or size.height() may be negative.
731
732 @param size SkScalar values for SkRect width and height
733 @return bounds (0, 0, size.width(), size.height())
734 */
MakeSizeSkRect735 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
736 return SkRect{0, 0, size.fWidth, size.fHeight};
737 }
738
739 /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
740 result in fLeft greater than fRight, or fTop greater than fBottom.
741
742 @param l SkScalar stored in fLeft
743 @param t SkScalar stored in fTop
744 @param r SkScalar stored in fRight
745 @param b SkScalar stored in fBottom
746 @return bounds (l, t, r, b)
747 */
MakeLTRBSkRect748 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
749 SkScalar b) {
750 return SkRect {l, t, r, b};
751 }
752
753 /** Returns constructed SkRect set to (x, y, x + w, y + h).
754 Does not validate input; w or h may be negative.
755
756 @param x stored in fLeft
757 @param y stored in fTop
758 @param w added to x and stored in fRight
759 @param h added to y and stored in fBottom
760 @return bounds at (x, y) with width w and height h
761 */
MakeXYWHSkRect762 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
763 SkScalar h) {
764 return SkRect {x, y, x + w, y + h};
765 }
766
767 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
768 Does not validate input; size.width() or size.height() may be negative.
769
770 @param size integer values for SkRect width and height
771 @return bounds (0, 0, size.width(), size.height())
772 */
MakeSkRect773 static SkRect Make(const SkISize& size) {
774 return MakeIWH(size.width(), size.height());
775 }
776
777 /** Returns constructed SkIRect set to irect, promoting integers to scalar.
778 Does not validate input; fLeft may be greater than fRight, fTop may be greater
779 than fBottom.
780
781 @param irect integer unsorted bounds
782 @return irect members converted to SkScalar
783 */
MakeSkRect784 static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
785 SkRect r;
786 r.set(SkIntToScalar(irect.fLeft),
787 SkIntToScalar(irect.fTop),
788 SkIntToScalar(irect.fRight),
789 SkIntToScalar(irect.fBottom));
790 return r;
791 }
792
793 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
794 to or greater than fBottom. Call sort() to reverse rectangles with negative
795 width() or height().
796
797 @return true if width() or height() are zero or negative
798 */
isEmptySkRect799 bool isEmpty() const {
800 // We write it as the NOT of a non-empty rect, so we will return true if any values
801 // are NaN.
802 return !(fLeft < fRight && fTop < fBottom);
803 }
804
805 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
806 to or less than fBottom. Call sort() to reverse rectangles with negative
807 width() or height().
808
809 @return true if width() or height() are zero or positive
810 */
isSortedSkRect811 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
812
813 /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
814 and SK_ScalarMax or smaller.
815
816 @return true if no member is infinite or NaN
817 */
isFiniteSkRect818 bool isFinite() const {
819 float accum = 0;
820 accum *= fLeft;
821 accum *= fTop;
822 accum *= fRight;
823 accum *= fBottom;
824
825 // accum is either NaN or it is finite (zero).
826 SkASSERT(0 == accum || SkScalarIsNaN(accum));
827
828 // value==value will be true iff value is not NaN
829 // TODO: is it faster to say !accum or accum==accum?
830 return !SkScalarIsNaN(accum);
831 }
832
833 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
834 Call sort() to reverse fLeft and fRight if needed.
835
836 @return fLeft
837 */
xSkRect838 SkScalar x() const { return fLeft; }
839
840 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
841 and sort() to reverse fTop and fBottom if needed.
842
843 @return fTop
844 */
ySkRect845 SkScalar y() const { return fTop; }
846
847 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
848 Call sort() to reverse fLeft and fRight if needed.
849
850 @return fLeft
851 */
leftSkRect852 SkScalar left() const { return fLeft; }
853
854 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
855 and sort() to reverse fTop and fBottom if needed.
856
857 @return fTop
858 */
topSkRect859 SkScalar top() const { return fTop; }
860
861 /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
862 Call sort() to reverse fLeft and fRight if needed.
863
864 @return fRight
865 */
rightSkRect866 SkScalar right() const { return fRight; }
867
868 /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
869 and sort() to reverse fTop and fBottom if needed.
870
871 @return fBottom
872 */
bottomSkRect873 SkScalar bottom() const { return fBottom; }
874
875 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
876 result fits in 32-bit float; result may be negative or infinity.
877
878 @return fRight minus fLeft
879 */
widthSkRect880 SkScalar width() const { return fRight - fLeft; }
881
882 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
883 result fits in 32-bit float; result may be negative or infinity.
884
885 @return fBottom minus fTop
886 */
heightSkRect887 SkScalar height() const { return fBottom - fTop; }
888
889 /** Returns average of left edge and right edge. Result does not change if SkRect
890 is sorted. Result may overflow to infinity if SkRect is far from the origin.
891
892 @return midpoint on x-axis
893 */
centerXSkRect894 SkScalar centerX() const {
895 // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
896 return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
897 }
898
899 /** Returns average of top edge and bottom edge. Result does not change if SkRect
900 is sorted.
901
902 @return midpoint on y-axis
903 */
centerYSkRect904 SkScalar centerY() const {
905 // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
906 return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
907 }
908
909 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
910 equal to the corresponding members in b.
911
912 a and b are not equal if either contain NaN. a and b are equal if members
913 contain zeroes with different signs.
914
915 @param a SkRect to compare
916 @param b SkRect to compare
917 @return true if members are equal
918 */
919 friend bool operator==(const SkRect& a, const SkRect& b) {
920 return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
921 }
922
923 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
924 equal the corresponding members in b.
925
926 a and b are not equal if either contain NaN. a and b are equal if members
927 contain zeroes with different signs.
928
929 @param a SkRect to compare
930 @param b SkRect to compare
931 @return true if members are not equal
932 */
933 friend bool operator!=(const SkRect& a, const SkRect& b) {
934 return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
935 }
936
937 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
938 bottom-right, bottom-left.
939
940 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
941
942 @param quad storage for corners of SkRect
943 */
944 void toQuad(SkPoint quad[4]) const;
945
946 /** Sets SkRect to (0, 0, 0, 0).
947
948 Many other rectangles are empty; if left is equal to or greater than right,
949 or if top is equal to or greater than bottom. Setting all members to zero
950 is a convenience, but does not designate a special empty rectangle.
951 */
setEmptySkRect952 void setEmpty() { *this = MakeEmpty(); }
953
954 /** Sets SkRect to src, promoting src members from integer to scalar.
955 Very large values in src may lose precision.
956
957 @param src integer SkRect
958 */
setSkRect959 void set(const SkIRect& src) {
960 fLeft = SkIntToScalar(src.fLeft);
961 fTop = SkIntToScalar(src.fTop);
962 fRight = SkIntToScalar(src.fRight);
963 fBottom = SkIntToScalar(src.fBottom);
964 }
965
966 /** Sets SkRect to (left, top, right, bottom).
967 left and right are not sorted; left is not necessarily less than right.
968 top and bottom are not sorted; top is not necessarily less than bottom.
969
970 @param left stored in fLeft
971 @param top stored in fTop
972 @param right stored in fRight
973 @param bottom stored in fBottom
974 */
setSkRect975 void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
976 fLeft = left;
977 fTop = top;
978 fRight = right;
979 fBottom = bottom;
980 }
981
982 /** Sets SkRect to (left, top, right, bottom).
983 left and right are not sorted; left is not necessarily less than right.
984 top and bottom are not sorted; top is not necessarily less than bottom.
985
986 @param left stored in fLeft
987 @param top stored in fTop
988 @param right stored in fRight
989 @param bottom stored in fBottom
990 */
setLTRBSkRect991 void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
992 this->set(left, top, right, bottom);
993 }
994
995 /** Sets SkRect to (left, top, right, bottom).
996 All parameters are promoted from integer to scalar.
997 left and right are not sorted; left is not necessarily less than right.
998 top and bottom are not sorted; top is not necessarily less than bottom.
999
1000 @param left promoted to SkScalar and stored in fLeft
1001 @param top promoted to SkScalar and stored in fTop
1002 @param right promoted to SkScalar and stored in fRight
1003 @param bottom promoted to SkScalar and stored in fBottom
1004 */
isetSkRect1005 void iset(int left, int top, int right, int bottom) {
1006 fLeft = SkIntToScalar(left);
1007 fTop = SkIntToScalar(top);
1008 fRight = SkIntToScalar(right);
1009 fBottom = SkIntToScalar(bottom);
1010 }
1011
1012 /** Sets SkRect to (0, 0, width, height).
1013 width and height may be zero or negative. width and height are promoted from
1014 integer to SkScalar, large values may lose precision.
1015
1016 @param width promoted to SkScalar and stored in fRight
1017 @param height promoted to SkScalar and stored in fBottom
1018 */
isetWHSkRect1019 void isetWH(int width, int height) {
1020 fLeft = fTop = 0;
1021 fRight = SkIntToScalar(width);
1022 fBottom = SkIntToScalar(height);
1023 }
1024
1025 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1026 or if SkPoint array contains an infinity or NaN, sets SkRect to (0, 0, 0, 0).
1027
1028 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1029 fTop is less than or equal to fBottom.
1030
1031 @param pts SkPoint array
1032 @param count entries in array
1033 */
setSkRect1034 void set(const SkPoint pts[], int count) {
1035 // set() had been checking for non-finite values, so keep that behavior
1036 // for now. Now that we have setBoundsCheck(), we may decide to make
1037 // set() be simpler/faster, and not check for those.
1038 (void)this->setBoundsCheck(pts, count);
1039 }
1040
1041 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1042 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
1043
1044 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1045 fTop is less than or equal to fBottom.
1046
1047 @param pts SkPoint array
1048 @param count entries in array
1049 */
setBoundsSkRect1050 void setBounds(const SkPoint pts[], int count) {
1051 (void)this->setBoundsCheck(pts, count);
1052 }
1053
1054 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
1055 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
1056 sets SkRect to (0, 0, 0, 0).
1057
1058 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1059 fTop is less than or equal to fBottom.
1060
1061 @param pts SkPoint array
1062 @param count entries in array
1063 @return true if all SkPoint values are finite
1064 */
1065 bool setBoundsCheck(const SkPoint pts[], int count);
1066
1067 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
1068 contains infinity or NaN, all SkRect dimensions are set to NaN.
1069
1070 @param pts SkPoint array
1071 @param count entries in array
1072 */
1073 void setBoundsNoCheck(const SkPoint pts[], int count);
1074
1075 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
1076 sorted and may be empty. Does not check to see if values are finite.
1077
1078 @param p0 corner to include
1079 @param p1 corner to include
1080 */
setSkRect1081 void set(const SkPoint& p0, const SkPoint& p1) {
1082 fLeft = SkMinScalar(p0.fX, p1.fX);
1083 fRight = SkMaxScalar(p0.fX, p1.fX);
1084 fTop = SkMinScalar(p0.fY, p1.fY);
1085 fBottom = SkMaxScalar(p0.fY, p1.fY);
1086 }
1087
1088 /** Sets SkRect to (x, y, x + width, y + height).
1089 Does not validate input; width or height may be negative.
1090
1091 @param x stored in fLeft
1092 @param y stored in fTop
1093 @param width added to x and stored in fRight
1094 @param height added to y and stored in fBottom
1095 */
setXYWHSkRect1096 void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
1097 fLeft = x;
1098 fTop = y;
1099 fRight = x + width;
1100 fBottom = y + height;
1101 }
1102
1103 /** Sets SkRect to (0, 0, width, height). Does not validate input;
1104 width or height may be negative.
1105
1106 @param width stored in fRight
1107 @param height stored in fBottom
1108 */
setWHSkRect1109 void setWH(SkScalar width, SkScalar height) {
1110 fLeft = 0;
1111 fTop = 0;
1112 fRight = width;
1113 fBottom = height;
1114 }
1115
1116 /** Returns SkRect offset by (dx, dy).
1117
1118 If dx is negative, SkRect returned is moved to the left.
1119 If dx is positive, SkRect returned is moved to the right.
1120 If dy is negative, SkRect returned is moved upward.
1121 If dy is positive, SkRect returned is moved downward.
1122
1123 @param dx added to fLeft and fRight
1124 @param dy added to fTop and fBottom
1125 @return SkRect offset on axes, with original width and height
1126 */
makeOffsetSkRect1127 SkRect makeOffset(SkScalar dx, SkScalar dy) const {
1128 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1129 }
1130
1131 /** Returns SkRect, inset by (dx, dy).
1132
1133 If dx is negative, SkRect returned is wider.
1134 If dx is positive, SkRect returned is narrower.
1135 If dy is negative, SkRect returned is taller.
1136 If dy is positive, SkRect returned is shorter.
1137
1138 @param dx added to fLeft and subtracted from fRight
1139 @param dy added to fTop and subtracted from fBottom
1140 @return SkRect inset symmetrically left and right, top and bottom
1141 */
makeInsetSkRect1142 SkRect makeInset(SkScalar dx, SkScalar dy) const {
1143 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1144 }
1145
1146 /** Returns SkRect, outset by (dx, dy).
1147
1148 If dx is negative, SkRect returned is narrower.
1149 If dx is positive, SkRect returned is wider.
1150 If dy is negative, SkRect returned is shorter.
1151 If dy is positive, SkRect returned is taller.
1152
1153 @param dx subtracted to fLeft and added from fRight
1154 @param dy subtracted to fTop and added from fBottom
1155 @return SkRect outset symmetrically left and right, top and bottom
1156 */
makeOutsetSkRect1157 SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1158 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1159 }
1160
1161 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1162
1163 If dx is negative, moves SkRect to the left.
1164 If dx is positive, moves SkRect to the right.
1165 If dy is negative, moves SkRect upward.
1166 If dy is positive, moves SkRect downward.
1167
1168 @param dx offset added to fLeft and fRight
1169 @param dy offset added to fTop and fBottom
1170 */
offsetSkRect1171 void offset(SkScalar dx, SkScalar dy) {
1172 fLeft += dx;
1173 fTop += dy;
1174 fRight += dx;
1175 fBottom += dy;
1176 }
1177
1178 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1179 fTop, fBottom.
1180
1181 If delta.fX is negative, moves SkRect to the left.
1182 If delta.fX is positive, moves SkRect to the right.
1183 If delta.fY is negative, moves SkRect upward.
1184 If delta.fY is positive, moves SkRect downward.
1185
1186 @param delta added to SkRect
1187 */
offsetSkRect1188 void offset(const SkPoint& delta) {
1189 this->offset(delta.fX, delta.fY);
1190 }
1191
1192 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1193 are unchanged.
1194
1195 @param newX stored in fLeft, preserving width()
1196 @param newY stored in fTop, preserving height()
1197 */
offsetToSkRect1198 void offsetTo(SkScalar newX, SkScalar newY) {
1199 fRight += newX - fLeft;
1200 fBottom += newY - fTop;
1201 fLeft = newX;
1202 fTop = newY;
1203 }
1204
1205 /** Insets SkRect by (dx, dy).
1206
1207 If dx is positive, makes SkRect narrower.
1208 If dx is negative, makes SkRect wider.
1209 If dy is positive, makes SkRect shorter.
1210 If dy is negative, makes SkRect taller.
1211
1212 @param dx added to fLeft and subtracted from fRight
1213 @param dy added to fTop and subtracted from fBottom
1214 */
insetSkRect1215 void inset(SkScalar dx, SkScalar dy) {
1216 fLeft += dx;
1217 fTop += dy;
1218 fRight -= dx;
1219 fBottom -= dy;
1220 }
1221
1222 /** Outsets SkRect by (dx, dy).
1223
1224 If dx is positive, makes SkRect wider.
1225 If dx is negative, makes SkRect narrower.
1226 If dy is positive, makes SkRect taller.
1227 If dy is negative, makes SkRect shorter.
1228
1229 @param dx subtracted to fLeft and added from fRight
1230 @param dy subtracted to fTop and added from fBottom
1231 */
outsetSkRect1232 void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
1233
1234 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1235 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1236
1237 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1238
1239 @param r limit of result
1240 @return true if r and SkRect have area in common
1241 */
1242 bool intersect(const SkRect& r);
1243
1244 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1245 construction.
1246
1247 Returns true if SkRect intersects construction, and sets SkRect to intersection.
1248 Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.
1249
1250 Returns false if either construction or SkRect is empty, leaving SkRect unchanged.
1251
1252 @param left x-axis minimum of constructed SkRect
1253 @param top y-axis minimum of constructed SkRect
1254 @param right x-axis maximum of constructed SkRect
1255 @param bottom y-axis maximum of constructed SkRect
1256 @return true if construction and SkRect have area in common
1257 */
1258 bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1259
1260 /** Returns true if a intersects b, and sets SkRect to intersection.
1261 Returns false if a does not intersect b, and leaves SkRect unchanged.
1262
1263 Returns false if either a or b is empty, leaving SkRect unchanged.
1264
1265 @param a SkRect to intersect
1266 @param b SkRect to intersect
1267 @return true if a and b have area in common
1268 */
1269 bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1270
1271
1272 private:
IntersectsSkRect1273 static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1274 SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1275 SkScalar L = SkMaxScalar(al, bl);
1276 SkScalar R = SkMinScalar(ar, br);
1277 SkScalar T = SkMaxScalar(at, bt);
1278 SkScalar B = SkMinScalar(ab, bb);
1279 return L < R && T < B;
1280 }
1281
1282 public:
1283
1284 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1285 construction.
1286
1287 Returns true if SkRect intersects construction.
1288 Returns false if either construction or SkRect is empty, or do not intersect.
1289
1290 @param left x-axis minimum of constructed SkRect
1291 @param top y-axis minimum of constructed SkRect
1292 @param right x-axis maximum of constructed SkRect
1293 @param bottom y-axis maximum of constructed SkRect
1294 @return true if construction and SkRect have area in common
1295 */
intersectsSkRect1296 bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
1297 return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
1298 }
1299
1300 /** Returns true if SkRect intersects r.
1301 Returns false if either r or SkRect is empty, or do not intersect.
1302
1303 @param r SkRect to intersect
1304 @return true if r and SkRect have area in common
1305 */
intersectsSkRect1306 bool intersects(const SkRect& r) const {
1307 return Intersects(fLeft, fTop, fRight, fBottom,
1308 r.fLeft, r.fTop, r.fRight, r.fBottom);
1309 }
1310
1311 /** Returns true if a intersects b.
1312 Returns false if either a or b is empty, or do not intersect.
1313
1314 @param a SkRect to intersect
1315 @param b SkRect to intersect
1316 @return true if a and b have area in common
1317 */
IntersectsSkRect1318 static bool Intersects(const SkRect& a, const SkRect& b) {
1319 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1320 b.fLeft, b.fTop, b.fRight, b.fBottom);
1321 }
1322
1323 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1324 construction.
1325
1326 Sets SkRect to the union of itself and the construction.
1327
1328 Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
1329 SkRect to construction.
1330
1331 @param left x-axis minimum of constructed SkRect
1332 @param top y-axis minimum of constructed SkRect
1333 @param right x-axis maximum of constructed SkRect
1334 @param bottom y-axis maximum of constructed SkRect
1335 */
1336 void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1337
1338 /** Sets SkRect to the union of itself and r.
1339
1340 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1341 SkRect to r.
1342
1343 @param r expansion SkRect
1344 */
joinSkRect1345 void join(const SkRect& r) {
1346 this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
1347 }
1348
1349 /** Sets SkRect to the union of itself and r.
1350
1351 Asserts if r is empty and SK_DEBUG is defined.
1352 If SkRect is empty, sets SkRect to r.
1353
1354 May produce incorrect results if r is empty.
1355
1356 @param r expansion SkRect
1357 */
joinNonEmptyArgSkRect1358 void joinNonEmptyArg(const SkRect& r) {
1359 SkASSERT(!r.isEmpty());
1360 // if we are empty, just assign
1361 if (fLeft >= fRight || fTop >= fBottom) {
1362 *this = r;
1363 } else {
1364 this->joinPossiblyEmptyRect(r);
1365 }
1366 }
1367
1368 /** Sets SkRect to the union of itself and the construction.
1369
1370 May produce incorrect results if SkRect or r is empty.
1371
1372 @param r expansion SkRect
1373 */
joinPossiblyEmptyRectSkRect1374 void joinPossiblyEmptyRect(const SkRect& r) {
1375 fLeft = SkMinScalar(fLeft, r.left());
1376 fTop = SkMinScalar(fTop, r.top());
1377 fRight = SkMaxScalar(fRight, r.right());
1378 fBottom = SkMaxScalar(fBottom, r.bottom());
1379 }
1380
1381 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1382 Returns false if SkRect is empty.
1383
1384 @param x test SkPoint x-coordinate
1385 @param y test SkPoint y-coordinate
1386 @return true if (x, y) is inside SkRect
1387 */
containsSkRect1388 bool contains(SkScalar x, SkScalar y) const {
1389 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1390 }
1391
1392 /** Returns true if SkRect contains r.
1393 Returns false if SkRect is empty or r is empty.
1394
1395 SkRect contains r when SkRect area completely includes r area.
1396
1397 @param r SkRect contained
1398 @return true if all sides of SkRect are outside r
1399 */
containsSkRect1400 bool contains(const SkRect& r) const {
1401 // todo: can we eliminate the this->isEmpty check?
1402 return !r.isEmpty() && !this->isEmpty() &&
1403 fLeft <= r.fLeft && fTop <= r.fTop &&
1404 fRight >= r.fRight && fBottom >= r.fBottom;
1405 }
1406
1407 /** Returns true if SkRect contains r.
1408 Returns false if SkRect is empty or r is empty.
1409
1410 SkRect contains r when SkRect area completely includes r area.
1411
1412 @param r SkIRect contained
1413 @return true if all sides of SkRect are outside r
1414 */
containsSkRect1415 bool contains(const SkIRect& r) const {
1416 // todo: can we eliminate the this->isEmpty check?
1417 return !r.isEmpty() && !this->isEmpty() &&
1418 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1419 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1420 }
1421
1422 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1423 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1424 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1425
1426 @param dst storage for SkIRect
1427 */
roundSkRect1428 void round(SkIRect* dst) const {
1429 SkASSERT(dst);
1430 dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1431 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1432 }
1433
1434 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1435 up fRight and fBottom, using
1436 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1437 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1438
1439 @param dst storage for SkIRect
1440 */
roundOutSkRect1441 void roundOut(SkIRect* dst) const {
1442 SkASSERT(dst);
1443 dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1444 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1445 }
1446
1447 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1448 up fRight and fBottom, using
1449 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1450 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1451
1452 @param dst storage for SkRect
1453 */
roundOutSkRect1454 void roundOut(SkRect* dst) const {
1455 dst->set(SkScalarFloorToScalar(fLeft),
1456 SkScalarFloorToScalar(fTop),
1457 SkScalarCeilToScalar(fRight),
1458 SkScalarCeilToScalar(fBottom));
1459 }
1460
1461 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1462 of fRight and fBottom, using
1463 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1464 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1465
1466 @param dst storage for SkIRect
1467 */
roundInSkRect1468 void roundIn(SkIRect* dst) const {
1469 SkASSERT(dst);
1470 dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1471 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1472 }
1473
1474 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1475 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1476 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1477
1478 @return rounded SkIRect
1479 */
roundSkRect1480 SkIRect round() const {
1481 SkIRect ir;
1482 this->round(&ir);
1483 return ir;
1484 }
1485
1486 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1487 up fRight and fBottom, using
1488 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1489 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1490
1491 @return rounded SkIRect
1492 */
roundOutSkRect1493 SkIRect roundOut() const {
1494 SkIRect ir;
1495 this->roundOut(&ir);
1496 return ir;
1497 }
1498
1499 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1500 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1501 and width() and height() will be zero or positive.
1502 */
sortSkRect1503 void sort() {
1504 using std::swap;
1505 if (fLeft > fRight) {
1506 swap(fLeft, fRight);
1507 }
1508
1509 if (fTop > fBottom) {
1510 swap(fTop, fBottom);
1511 }
1512 }
1513
1514 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1515 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1516 and width() and height() will be zero or positive.
1517
1518 @return sorted SkRect
1519 */
makeSortedSkRect1520 SkRect makeSorted() const {
1521 return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
1522 SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
1523 }
1524
1525 /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1526 entries.
1527
1528 @return pointer to fLeft
1529 */
asScalarsSkRect1530 const SkScalar* asScalars() const { return &fLeft; }
1531
1532 /** Writes text representation of SkRect to standard output. Set asHex to true to
1533 generate exact binary representations of floating point numbers.
1534
1535 @param asHex true if SkScalar values are written as hexadecimal
1536 */
1537 void dump(bool asHex) const;
1538
1539 void dump(std::string& desc, int depth) const;
1540 /** Writes text representation of SkRect to standard output. The representation may be
1541 directly compiled as C++ code. Floating point values are written
1542 with limited precision; it may not be possible to reconstruct original SkRect
1543 from output.
1544 */
dumpSkRect1545 void dump() const { this->dump(false); }
1546
1547 /** Writes text representation of SkRect to standard output. The representation may be
1548 directly compiled as C++ code. Floating point values are written
1549 in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1550 original SkRect.
1551
1552 Use instead of dump() when submitting
1553 */
dumpHexSkRect1554 void dumpHex() const { this->dump(true); }
1555 };
1556
contains(const SkRect & r)1557 inline bool SkIRect::contains(const SkRect& r) const {
1558 return !r.isEmpty() && !this->isEmpty() && // check for empties
1559 (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1560 (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1561 }
1562
1563 #endif
1564