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 /* Generated by tools/bookmaker from include/core/SkRect.h and docs/SkRect_Reference.bmh
9 on 2018-09-13 13:59:55. Additional documentation and examples can be found at:
10 https://skia.org/user/api/SkRect_Reference
11
12 You may edit either file directly. Structural changes to public interfaces require
13 editing both files. After editing docs/SkRect_Reference.bmh, run:
14 bookmaker -b docs -i include/core/SkRect.h -p
15 to create an updated version of this file.
16 */
17
18 #ifndef SkRect_DEFINED
19 #define SkRect_DEFINED
20
21 #include "SkPoint.h"
22 #include "SkSize.h"
23 #include "../private/SkSafe32.h"
24 #include "../private/SkTFitsIn.h"
25
26 #include <utility>
27
28 struct SkRect;
29
30 /** \struct SkIRect
31 SkIRect holds four 32-bit integer coordinates describing the upper and
32 lower bounds of a rectangle. SkIRect may be created from outer bounds or
33 from position, width, and height. SkIRect describes an area; if its right
34 is less than or equal to its left, or if its bottom is less than or equal to
35 its top, it is considered empty.
36 */
37 struct SK_API SkIRect {
38 int32_t fLeft; //!< smaller x-axis bounds
39 int32_t fTop; //!< smaller y-axis bounds
40 int32_t fRight; //!< larger x-axis bounds
41 int32_t fBottom; //!< larger y-axis bounds
42
43 /** Returns constructed SkIRect set to (0, 0, 0, 0).
44 Many other rectangles are empty; if left is equal to or greater than right,
45 or if top is equal to or greater than bottom. Setting all members to zero
46 is a convenience, but does not designate a special empty rectangle.
47
48 @return bounds (0, 0, 0, 0)
49 */
MakeEmptySkIRect50 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
51 return SkIRect{0, 0, 0, 0};
52 }
53
54 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
55 may be negative.
56
57 @param w width of constructed SkIRect
58 @param h height of constructed SkIRect
59 @return bounds (0, 0, w, h)
60 */
MakeWHSkIRect61 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
62 return SkIRect{0, 0, w, h};
63 }
64
65 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
66 Does not validate input; size.width() or size.height() may be negative.
67
68 @param size values for SkIRect width and height
69 @return bounds (0, 0, size.width(), size.height())
70 */
MakeSizeSkIRect71 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
72 return SkIRect{0, 0, size.fWidth, size.fHeight};
73 }
74
75 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
76 result in fLeft greater than fRight, or fTop greater than fBottom.
77
78 @param l integer stored in fLeft
79 @param t integer stored in fTop
80 @param r integer stored in fRight
81 @param b integer stored in fBottom
82 @return bounds (l, t, r, b)
83 */
MakeLTRBSkIRect84 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
85 int32_t r, int32_t b) {
86 return SkIRect{l, t, r, b};
87 }
88
89 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
90 Does not validate input; w or h may be negative.
91
92 @param x stored in fLeft
93 @param y stored in fTop
94 @param w added to x and stored in fRight
95 @param h added to y and stored in fBottom
96 @return bounds at (x, y) with width w and height h
97 */
MakeXYWHSkIRect98 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
99 int32_t w, int32_t h) {
100 return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
101 }
102
103 /** Returns left edge of SkIRect, if sorted.
104 Call sort() to reverse fLeft and fRight if needed.
105
106 @return fLeft
107 */
leftSkIRect108 int32_t left() const { return fLeft; }
109
110 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
111 and sort() to reverse fTop and fBottom if needed.
112
113 @return fTop
114 */
topSkIRect115 int32_t top() const { return fTop; }
116
117 /** Returns right edge of SkIRect, if sorted.
118 Call sort() to reverse fLeft and fRight if needed.
119
120 @return fRight
121 */
rightSkIRect122 int32_t right() const { return fRight; }
123
124 /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
125 and sort() to reverse fTop and fBottom if needed.
126
127 @return fBottom
128 */
bottomSkIRect129 int32_t bottom() const { return fBottom; }
130
131 /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
132 and sort() to reverse fLeft and fRight if needed.
133
134 @return fLeft
135 */
xSkIRect136 int32_t x() const { return fLeft; }
137
138 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
139 and sort() to reverse fTop and fBottom if needed.
140
141 @return fTop
142 */
ySkIRect143 int32_t y() const { return fTop; }
144
145 // Experimental
topLeftSkIRect146 SkIPoint topLeft() const { return {fLeft, fTop}; }
147
148 /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
149 result fits in 32-bit signed integer; result may be negative.
150
151 @return fRight minus fLeft
152 */
widthSkIRect153 int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
154
155 /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
156 result fits in 32-bit signed integer; result may be negative.
157
158 @return fBottom minus fTop
159 */
heightSkIRect160 int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
161
162 /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
163 or if result fits in 32-bit signed integer; result may be negative.
164
165 @return SkISize (width, height)
166 */
sizeSkIRect167 SkISize size() const { return SkISize::Make(this->width(), this->height()); }
168
169 /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
170 result may be negative. This is safer than calling width() since width() might
171 overflow in its calculation.
172
173 @return fRight minus fLeft cast to int64_t
174 */
width64SkIRect175 int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
176
177 /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
178 result may be negative. This is safer than calling height() since height() might
179 overflow in its calculation.
180
181 @return fBottom minus fTop cast to int64_t
182 */
height64SkIRect183 int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
184
185 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
186 to or greater than fBottom. Call sort() to reverse rectangles with negative
187 width64() or height64().
188
189 @return true if width64() or height64() are zero or negative
190 */
isEmpty64SkIRect191 bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
192
193 /** Returns true if width() or height() are zero or negative.
194
195 @return true if width() or height() are zero or negative
196 */
isEmptySkIRect197 bool isEmpty() const {
198 int64_t w = this->width64();
199 int64_t h = this->height64();
200 if (w <= 0 || h <= 0) {
201 return true;
202 }
203 // Return true if either exceeds int32_t
204 return !SkTFitsIn<int32_t>(w | h);
205 }
206
207 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
208 identical to corresponding members in b.
209
210 @param a SkIRect to compare
211 @param b SkIRect to compare
212 @return true if members are equal
213 */
214 friend bool operator==(const SkIRect& a, const SkIRect& b) {
215 return !memcmp(&a, &b, sizeof(a));
216 }
217
218 /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
219 identical to the corresponding member in b.
220
221 @param a SkIRect to compare
222 @param b SkIRect to compare
223 @return true if members are not equal
224 */
225 friend bool operator!=(const SkIRect& a, const SkIRect& b) {
226 return !(a == b);
227 }
228
229 /** Sets SkIRect to (0, 0, 0, 0).
230
231 Many other rectangles are empty; if left is equal to or greater than right,
232 or if top is equal to or greater than bottom. Setting all members to zero
233 is a convenience, but does not designate a special empty rectangle.
234 */
setEmptySkIRect235 void setEmpty() { memset(this, 0, sizeof(*this)); }
236
237 /** Sets SkIRect to (left, top, right, bottom).
238 left and right are not sorted; left is not necessarily less than right.
239 top and bottom are not sorted; top is not necessarily less than bottom.
240
241 @param left assigned to fLeft
242 @param top assigned to fTop
243 @param right assigned to fRight
244 @param bottom assigned to fBottom
245 */
setSkIRect246 void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
247 fLeft = left;
248 fTop = top;
249 fRight = right;
250 fBottom = bottom;
251 }
252
253 /** Sets SkIRect to (left, top, right, bottom).
254 left and right are not sorted; left is not necessarily less than right.
255 top and bottom are not sorted; top is not necessarily less than bottom.
256
257 @param left stored in fLeft
258 @param top stored in fTop
259 @param right stored in fRight
260 @param bottom stored in fBottom
261 */
setLTRBSkIRect262 void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
263 this->set(left, top, right, bottom);
264 }
265
266 /** Sets SkIRect to: (x, y, x + width, y + height).
267 Does not validate input; width or height may be negative.
268
269 @param x stored in fLeft
270 @param y stored in fTop
271 @param width added to x and stored in fRight
272 @param height added to y and stored in fBottom
273 */
setXYWHSkIRect274 void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
275 fLeft = x;
276 fTop = y;
277 fRight = Sk32_sat_add(x, width);
278 fBottom = Sk32_sat_add(y, height);
279 }
280
281 /** Returns SkIRect offset by (dx, dy).
282
283 If dx is negative, SkIRect returned is moved to the left.
284 If dx is positive, SkIRect returned is moved to the right.
285 If dy is negative, SkIRect returned is moved upward.
286 If dy is positive, SkIRect returned is moved downward.
287
288 @param dx offset added to fLeft and fRight
289 @param dy offset added to fTop and fBottom
290 @return SkIRect offset by dx and dy, with original width and height
291 */
makeOffsetSkIRect292 SkIRect makeOffset(int32_t dx, int32_t dy) const {
293 return {
294 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
295 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
296 };
297 }
298
299 /** Returns SkIRect, inset by (dx, dy).
300
301 If dx is negative, SkIRect returned is wider.
302 If dx is positive, SkIRect returned is narrower.
303 If dy is negative, SkIRect returned is taller.
304 If dy is positive, SkIRect returned is shorter.
305
306 @param dx offset added to fLeft and subtracted from fRight
307 @param dy offset added to fTop and subtracted from fBottom
308 @return SkIRect inset symmetrically left and right, top and bottom
309 */
makeInsetSkIRect310 SkIRect makeInset(int32_t dx, int32_t dy) const {
311 return {
312 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
313 Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
314 };
315 }
316
317 /** Returns SkIRect, outset by (dx, dy).
318
319 If dx is negative, SkIRect returned is narrower.
320 If dx is positive, SkIRect returned is wider.
321 If dy is negative, SkIRect returned is shorter.
322 If dy is positive, SkIRect returned is taller.
323
324 @param dx offset subtracted to fLeft and added from fRight
325 @param dy offset subtracted to fTop and added from fBottom
326 @return SkIRect outset symmetrically left and right, top and bottom
327 */
makeOutsetSkIRect328 SkIRect makeOutset(int32_t dx, int32_t dy) const {
329 return {
330 Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
331 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
332 };
333 }
334
335 /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
336
337 If dx is negative, moves SkIRect returned to the left.
338 If dx is positive, moves SkIRect returned to the right.
339 If dy is negative, moves SkIRect returned upward.
340 If dy is positive, moves SkIRect returned downward.
341
342 @param dx offset added to fLeft and fRight
343 @param dy offset added to fTop and fBottom
344 */
offsetSkIRect345 void offset(int32_t dx, int32_t dy) {
346 fLeft = Sk32_sat_add(fLeft, dx);
347 fTop = Sk32_sat_add(fTop, dy);
348 fRight = Sk32_sat_add(fRight, dx);
349 fBottom = Sk32_sat_add(fBottom, dy);
350 }
351
352 /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
353 fTop, fBottom.
354
355 If delta.fX is negative, moves SkIRect returned to the left.
356 If delta.fX is positive, moves SkIRect returned to the right.
357 If delta.fY is negative, moves SkIRect returned upward.
358 If delta.fY is positive, moves SkIRect returned downward.
359
360 @param delta offset added to SkIRect
361 */
offsetSkIRect362 void offset(const SkIPoint& delta) {
363 this->offset(delta.fX, delta.fY);
364 }
365
366 /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
367 are unchanged.
368
369 @param newX stored in fLeft, preserving width()
370 @param newY stored in fTop, preserving height()
371 */
offsetToSkIRect372 void offsetTo(int32_t newX, int32_t newY) {
373 fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
374 fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
375 fLeft = newX;
376 fTop = newY;
377 }
378
379 /** Insets SkIRect by (dx,dy).
380
381 If dx is positive, makes SkIRect narrower.
382 If dx is negative, makes SkIRect wider.
383 If dy is positive, makes SkIRect shorter.
384 If dy is negative, makes SkIRect taller.
385
386 @param dx offset added to fLeft and subtracted from fRight
387 @param dy offset added to fTop and subtracted from fBottom
388 */
insetSkIRect389 void inset(int32_t dx, int32_t dy) {
390 fLeft = Sk32_sat_add(fLeft, dx);
391 fTop = Sk32_sat_add(fTop, dy);
392 fRight = Sk32_sat_sub(fRight, dx);
393 fBottom = Sk32_sat_sub(fBottom, dy);
394 }
395
396 /** Outsets SkIRect by (dx, dy).
397
398 If dx is positive, makes SkIRect wider.
399 If dx is negative, makes SkIRect narrower.
400 If dy is positive, makes SkIRect taller.
401 If dy is negative, makes SkIRect shorter.
402
403 @param dx subtracted to fLeft and added from fRight
404 @param dy subtracted to fTop and added from fBottom
405 */
outsetSkIRect406 void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
407
408 /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
409
410 If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
411 If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
412 If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
413 If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
414
415 The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
416 greater than right, the SkIRect will be considered empty. Call sort() after this call
417 if that is not the desired behavior.
418
419 @param dL offset added to fLeft
420 @param dT offset added to fTop
421 @param dR offset added to fRight
422 @param dB offset added to fBottom
423 */
adjustSkIRect424 void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
425 fLeft = Sk32_sat_add(fLeft, dL);
426 fTop = Sk32_sat_add(fTop, dT);
427 fRight = Sk32_sat_add(fRight, dR);
428 fBottom = Sk32_sat_add(fBottom, dB);
429 }
430
431 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
432 Returns false if SkIRect is empty.
433
434 Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
435 returns true if constructed area is completely enclosed by SkIRect area.
436
437 @param x test SkIPoint x-coordinate
438 @param y test SkIPoint y-coordinate
439 @return true if (x, y) is inside SkIRect
440 */
containsSkIRect441 bool contains(int32_t x, int32_t y) const {
442 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
443 }
444
445 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
446 construction.
447
448 Returns true if SkIRect contains construction.
449 Returns false if SkIRect is empty or construction is empty.
450
451 @param left x-axis minimum of constructed SkIRect
452 @param top y-axis minimum of constructed SkIRect
453 @param right x-axis maximum of constructed SkIRect
454 @param bottom y-axis maximum of constructed SkIRect
455 @return true if all sides of SkIRect are outside construction
456 */
containsSkIRect457 bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
458 return left < right && top < bottom && !this->isEmpty() && // check for empties
459 fLeft <= left && fTop <= top &&
460 fRight >= right && fBottom >= bottom;
461 }
462
463 /** Returns true if SkIRect contains r.
464 Returns false if SkIRect is empty or r is empty.
465
466 SkIRect contains r when SkIRect area completely includes r area.
467
468 @param r SkIRect contained
469 @return true if all sides of SkIRect are outside r
470 */
containsSkIRect471 bool contains(const SkIRect& r) const {
472 return !r.isEmpty() && !this->isEmpty() && // check for empties
473 fLeft <= r.fLeft && fTop <= r.fTop &&
474 fRight >= r.fRight && fBottom >= r.fBottom;
475 }
476
477 /** Returns true if SkIRect contains r.
478 Returns false if SkIRect is empty or r is empty.
479
480 SkIRect contains r when SkIRect area completely includes r area.
481
482 @param r SkRect contained
483 @return true if all sides of SkIRect are outside r
484 */
485 bool contains(const SkRect& r) const;
486
487 /** Constructs SkIRect from (left, top, right, bottom). Does not sort
488 construction.
489
490 Returns true if SkIRect contains construction.
491 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
492
493 Return is undefined if SkIRect is empty or construction is empty.
494
495 @param left x-axis minimum of constructed SkIRect
496 @param top y-axis minimum of constructed SkIRect
497 @param right x-axis maximum of constructed SkIRect
498 @param bottom y-axis maximum of constructed SkIRect
499 @return true if all sides of SkIRect are outside construction
500 */
containsNoEmptyCheckSkIRect501 bool containsNoEmptyCheck(int32_t left, int32_t top,
502 int32_t right, int32_t bottom) const {
503 SkASSERT(fLeft < fRight && fTop < fBottom);
504 SkASSERT(left < right && top < bottom);
505
506 return fLeft <= left && fTop <= top &&
507 fRight >= right && fBottom >= bottom;
508 }
509
510 /** Returns true if SkIRect contains construction.
511 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
512
513 Return is undefined if SkIRect is empty or construction is empty.
514
515 @param r SkIRect contained
516 @return true if all sides of SkIRect are outside r
517 */
containsNoEmptyCheckSkIRect518 bool containsNoEmptyCheck(const SkIRect& r) const {
519 return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
520 }
521
522 /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
523 Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
524
525 Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
526
527 @param r limit of result
528 @return true if r and SkIRect have area in common
529 */
intersectSkIRect530 bool intersect(const SkIRect& r) {
531 return this->intersect(*this, r);
532 }
533
534 /** Returns true if a intersects b, and sets SkIRect to intersection.
535 Returns false if a does not intersect b, and leaves SkIRect unchanged.
536
537 Asserts if either a or b is empty, and if SK_DEBUG is defined.
538
539 @param a SkIRect to intersect
540 @param b SkIRect to intersect
541 @return true if a and b have area in common
542 */
intersectNoEmptyCheckSkIRect543 bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
544 SkASSERT(!a.isEmpty64() && !b.isEmpty64());
545 SkIRect r = {
546 SkMax32(a.fLeft, b.fLeft),
547 SkMax32(a.fTop, b.fTop),
548 SkMin32(a.fRight, b.fRight),
549 SkMin32(a.fBottom, b.fBottom)
550 };
551 if (r.isEmpty()) {
552 return false;
553 }
554 *this = r;
555 return true;
556 }
557
558 /** Returns true if a intersects b, and sets SkIRect to intersection.
559 Returns false if a does not intersect b, and leaves SkIRect unchanged.
560
561 Returns false if either a or b is empty, leaving SkIRect unchanged.
562
563 @param a SkIRect to intersect
564 @param b SkIRect to intersect
565 @return true if a and b have area in common
566 */
intersectSkIRect567 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {
568 if (a.isEmpty64() || b.isEmpty64()) {
569 return false;
570 }
571 return this->intersectNoEmptyCheck(a, b);
572 }
573
574 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
575 construction.
576
577 Returns true if SkIRect intersects construction, and sets SkIRect to intersection.
578 Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.
579
580 Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.
581
582 @param left x-axis minimum of constructed SkIRect
583 @param top y-axis minimum of constructed SkIRect
584 @param right x-axis maximum of constructed SkIRect
585 @param bottom y-axis maximum of constructed SkIRect
586 @return true if construction and SkIRect have area in common
587 */
intersectSkIRect588 bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
589 return this->intersect(*this, {left, top, right, bottom});
590 }
591
592 /** Returns true if a intersects b.
593 Returns false if either a or b is empty, or do not intersect.
594
595 @param a SkIRect to intersect
596 @param b SkIRect to intersect
597 @return true if a and b have area in common
598 */
IntersectsSkIRect599 static bool Intersects(const SkIRect& a, const SkIRect& b) {
600 SkIRect dummy;
601 return dummy.intersect(a, b);
602 }
603
604 /** Returns true if a intersects b.
605 Asserts if either a or b is empty, and if SK_DEBUG is defined.
606
607 @param a SkIRect to intersect
608 @param b SkIRect to intersect
609 @return true if a and b have area in common
610 */
IntersectsNoEmptyCheckSkIRect611 static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
612 SkIRect dummy;
613 return dummy.intersectNoEmptyCheck(a, b);
614 }
615
616 /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort
617 construction.
618
619 Sets SkIRect to the union of itself and the construction.
620
621 Has no effect if construction is empty. Otherwise, if SkIRect is empty, sets
622 SkIRect to construction.
623
624 @param left x-axis minimum of constructed SkIRect
625 @param top y-axis minimum of constructed SkIRect
626 @param right x-axis maximum of constructed SkIRect
627 @param bottom y-axis maximum of constructed SkIRect
628 */
629 void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
630
631 /** Sets SkIRect to the union of itself and r.
632
633 Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
634
635 @param r expansion SkIRect
636 */
joinSkIRect637 void join(const SkIRect& r) {
638 this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
639 }
640
641 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
642 fTop and fBottom if fTop is greater than fBottom. Result may be empty,
643 and width() and height() will be zero or positive.
644 */
sortSkIRect645 void sort() {
646 using std::swap;
647 if (fLeft > fRight) {
648 swap(fLeft, fRight);
649 }
650 if (fTop > fBottom) {
651 swap(fTop, fBottom);
652 }
653 }
654
655 /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
656 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
657 and width() and height() will be zero or positive.
658
659 @return sorted SkIRect
660 */
makeSortedSkIRect661 SkIRect makeSorted() const {
662 return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
663 SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
664 }
665
666 /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
667
668 @return global SkIRect set to all zeroes
669 */
EmptyIRectSkIRect670 static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
671 static const SkIRect gEmpty = { 0, 0, 0, 0 };
672 return gEmpty;
673 }
674 };
675
676 /** \struct SkRect
677 SkRect holds four SkScalar coordinates describing the upper and
678 lower bounds of a rectangle. SkRect may be created from outer bounds or
679 from position, width, and height. SkRect describes an area; if its right
680 is less than or equal to its left, or if its bottom is less than or equal to
681 its top, it is considered empty.
682 */
683 struct SK_API SkRect {
684 SkScalar fLeft; //!< smaller x-axis bounds
685 SkScalar fTop; //!< smaller y-axis bounds
686 SkScalar fRight; //!< larger x-axis bounds
687 SkScalar fBottom; //!< larger y-axis bounds
688
689 /** Returns constructed SkRect set to (0, 0, 0, 0).
690 Many other rectangles are empty; if left is equal to or greater than right,
691 or if top is equal to or greater than bottom. Setting all members to zero
692 is a convenience, but does not designate a special empty rectangle.
693
694 @return bounds (0, 0, 0, 0)
695 */
MakeEmptySkRect696 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
697 return SkRect{0, 0, 0, 0};
698 }
699
700 /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
701 validate input; w or h may be negative.
702
703 Passing integer values may generate a compiler warning since SkRect cannot
704 represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
705
706 @param w SkScalar width of constructed SkRect
707 @param h SkScalar height of constructed SkRect
708 @return bounds (0, 0, w, h)
709 */
MakeWHSkRect710 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
711 return SkRect{0, 0, w, h};
712 }
713
714 /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
715 input; w or h may be negative.
716
717 Use to avoid a compiler warning that input may lose precision when stored.
718 Use SkIRect for an exact integer rectangle.
719
720 @param w integer width of constructed SkRect
721 @param h integer height of constructed SkRect
722 @return bounds (0, 0, w, h)
723 */
MakeIWHSkRect724 static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
725 SkRect r;
726 r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
727 return r;
728 }
729
730 /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
731 validate input; size.width() or size.height() may be negative.
732
733 @param size SkScalar values for SkRect width and height
734 @return bounds (0, 0, size.width(), size.height())
735 */
MakeSizeSkRect736 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
737 return SkRect{0, 0, size.fWidth, size.fHeight};
738 }
739
740 /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
741 result in fLeft greater than fRight, or fTop greater than fBottom.
742
743 @param l SkScalar stored in fLeft
744 @param t SkScalar stored in fTop
745 @param r SkScalar stored in fRight
746 @param b SkScalar stored in fBottom
747 @return bounds (l, t, r, b)
748 */
MakeLTRBSkRect749 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
750 SkScalar b) {
751 return SkRect {l, t, r, b};
752 }
753
754 /** Returns constructed SkRect set to (x, y, x + w, y + h).
755 Does not validate input; w or h may be negative.
756
757 @param x stored in fLeft
758 @param y stored in fTop
759 @param w added to x and stored in fRight
760 @param h added to y and stored in fBottom
761 @return bounds at (x, y) with width w and height h
762 */
MakeXYWHSkRect763 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
764 SkScalar h) {
765 return SkRect {x, y, x + w, y + h};
766 }
767
768 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
769 Does not validate input; size.width() or size.height() may be negative.
770
771 @param size integer values for SkRect width and height
772 @return bounds (0, 0, size.width(), size.height())
773 */
MakeSkRect774 static SkRect Make(const SkISize& size) {
775 return MakeIWH(size.width(), size.height());
776 }
777
778 /** Returns constructed SkIRect set to irect, promoting integers to scalar.
779 Does not validate input; fLeft may be greater than fRight, fTop may be greater
780 than fBottom.
781
782 @param irect integer unsorted bounds
783 @return irect members converted to SkScalar
784 */
MakeSkRect785 static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
786 SkRect r;
787 r.set(SkIntToScalar(irect.fLeft),
788 SkIntToScalar(irect.fTop),
789 SkIntToScalar(irect.fRight),
790 SkIntToScalar(irect.fBottom));
791 return r;
792 }
793
794 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
795 to or greater than fBottom. Call sort() to reverse rectangles with negative
796 width() or height().
797
798 @return true if width() or height() are zero or negative
799 */
isEmptySkRect800 bool isEmpty() const {
801 // We write it as the NOT of a non-empty rect, so we will return true if any values
802 // are NaN.
803 return !(fLeft < fRight && fTop < fBottom);
804 }
805
806 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
807 to or less than fBottom. Call sort() to reverse rectangles with negative
808 width() or height().
809
810 @return true if width() or height() are zero or positive
811 */
isSortedSkRect812 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
813
814 /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
815 and SK_ScalarMax or smaller.
816
817 @return true if no member is infinite or NaN
818 */
isFiniteSkRect819 bool isFinite() const {
820 float accum = 0;
821 accum *= fLeft;
822 accum *= fTop;
823 accum *= fRight;
824 accum *= fBottom;
825
826 // accum is either NaN or it is finite (zero).
827 SkASSERT(0 == accum || SkScalarIsNaN(accum));
828
829 // value==value will be true iff value is not NaN
830 // TODO: is it faster to say !accum or accum==accum?
831 return !SkScalarIsNaN(accum);
832 }
833
834 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
835 Call sort() to reverse fLeft and fRight if needed.
836
837 @return fLeft
838 */
xSkRect839 SkScalar x() const { return fLeft; }
840
841 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
842 and sort() to reverse fTop and fBottom if needed.
843
844 @return fTop
845 */
ySkRect846 SkScalar y() const { return fTop; }
847
848 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
849 Call sort() to reverse fLeft and fRight if needed.
850
851 @return fLeft
852 */
leftSkRect853 SkScalar left() const { return fLeft; }
854
855 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
856 and sort() to reverse fTop and fBottom if needed.
857
858 @return fTop
859 */
topSkRect860 SkScalar top() const { return fTop; }
861
862 /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
863 Call sort() to reverse fLeft and fRight if needed.
864
865 @return fRight
866 */
rightSkRect867 SkScalar right() const { return fRight; }
868
869 /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
870 and sort() to reverse fTop and fBottom if needed.
871
872 @return fBottom
873 */
bottomSkRect874 SkScalar bottom() const { return fBottom; }
875
876 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
877 result fits in 32-bit float; result may be negative or infinity.
878
879 @return fRight minus fLeft
880 */
widthSkRect881 SkScalar width() const { return fRight - fLeft; }
882
883 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
884 result fits in 32-bit float; result may be negative or infinity.
885
886 @return fBottom minus fTop
887 */
heightSkRect888 SkScalar height() const { return fBottom - fTop; }
889
890 /** Returns average of left edge and right edge. Result does not change if SkRect
891 is sorted. Result may overflow to infinity if SkRect is far from the origin.
892
893 @return midpoint on x-axis
894 */
centerXSkRect895 SkScalar centerX() const {
896 // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
897 return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
898 }
899
900 /** Returns average of top edge and bottom edge. Result does not change if SkRect
901 is sorted.
902
903 @return midpoint on y-axis
904 */
centerYSkRect905 SkScalar centerY() const {
906 // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
907 return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
908 }
909
910 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
911 equal to the corresponding members in b.
912
913 a and b are not equal if either contain NaN. a and b are equal if members
914 contain zeroes with different signs.
915
916 @param a SkRect to compare
917 @param b SkRect to compare
918 @return true if members are equal
919 */
920 friend bool operator==(const SkRect& a, const SkRect& b) {
921 return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
922 }
923
924 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
925 equal the corresponding members in b.
926
927 a and b are not equal if either contain NaN. a and b are equal if members
928 contain zeroes with different signs.
929
930 @param a SkRect to compare
931 @param b SkRect to compare
932 @return true if members are not equal
933 */
934 friend bool operator!=(const SkRect& a, const SkRect& b) {
935 return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
936 }
937
938 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
939 bottom-right, bottom-left.
940
941 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
942
943 @param quad storage for corners of SkRect
944 */
945 void toQuad(SkPoint quad[4]) const;
946
947 /** Sets SkRect to (0, 0, 0, 0).
948
949 Many other rectangles are empty; if left is equal to or greater than right,
950 or if top is equal to or greater than bottom. Setting all members to zero
951 is a convenience, but does not designate a special empty rectangle.
952 */
setEmptySkRect953 void setEmpty() { *this = MakeEmpty(); }
954
955 /** Sets SkRect to src, promoting src members from integer to scalar.
956 Very large values in src may lose precision.
957
958 @param src integer SkRect
959 */
setSkRect960 void set(const SkIRect& src) {
961 fLeft = SkIntToScalar(src.fLeft);
962 fTop = SkIntToScalar(src.fTop);
963 fRight = SkIntToScalar(src.fRight);
964 fBottom = SkIntToScalar(src.fBottom);
965 }
966
967 /** Sets SkRect to (left, top, right, bottom).
968 left and right are not sorted; left is not necessarily less than right.
969 top and bottom are not sorted; top is not necessarily less than bottom.
970
971 @param left stored in fLeft
972 @param top stored in fTop
973 @param right stored in fRight
974 @param bottom stored in fBottom
975 */
setSkRect976 void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
977 fLeft = left;
978 fTop = top;
979 fRight = right;
980 fBottom = bottom;
981 }
982
983 /** Sets SkRect to (left, top, right, bottom).
984 left and right are not sorted; left is not necessarily less than right.
985 top and bottom are not sorted; top is not necessarily less than bottom.
986
987 @param left stored in fLeft
988 @param top stored in fTop
989 @param right stored in fRight
990 @param bottom stored in fBottom
991 */
setLTRBSkRect992 void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
993 this->set(left, top, right, bottom);
994 }
995
996 /** Sets SkRect to (left, top, right, bottom).
997 All parameters are promoted from integer to scalar.
998 left and right are not sorted; left is not necessarily less than right.
999 top and bottom are not sorted; top is not necessarily less than bottom.
1000
1001 @param left promoted to SkScalar and stored in fLeft
1002 @param top promoted to SkScalar and stored in fTop
1003 @param right promoted to SkScalar and stored in fRight
1004 @param bottom promoted to SkScalar and stored in fBottom
1005 */
isetSkRect1006 void iset(int left, int top, int right, int bottom) {
1007 fLeft = SkIntToScalar(left);
1008 fTop = SkIntToScalar(top);
1009 fRight = SkIntToScalar(right);
1010 fBottom = SkIntToScalar(bottom);
1011 }
1012
1013 /** Sets SkRect to (0, 0, width, height).
1014 width and height may be zero or negative. width and height are promoted from
1015 integer to SkScalar, large values may lose precision.
1016
1017 @param width promoted to SkScalar and stored in fRight
1018 @param height promoted to SkScalar and stored in fBottom
1019 */
isetWHSkRect1020 void isetWH(int width, int height) {
1021 fLeft = fTop = 0;
1022 fRight = SkIntToScalar(width);
1023 fBottom = SkIntToScalar(height);
1024 }
1025
1026 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1027 or if SkPoint array contains an infinity or NaN, sets SkRect to (0, 0, 0, 0).
1028
1029 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1030 fTop is less than or equal to fBottom.
1031
1032 @param pts SkPoint array
1033 @param count entries in array
1034 */
setSkRect1035 void set(const SkPoint pts[], int count) {
1036 // set() had been checking for non-finite values, so keep that behavior
1037 // for now. Now that we have setBoundsCheck(), we may decide to make
1038 // set() be simpler/faster, and not check for those.
1039 (void)this->setBoundsCheck(pts, count);
1040 }
1041
1042 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
1043 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
1044
1045 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1046 fTop is less than or equal to fBottom.
1047
1048 @param pts SkPoint array
1049 @param count entries in array
1050 */
setBoundsSkRect1051 void setBounds(const SkPoint pts[], int count) {
1052 (void)this->setBoundsCheck(pts, count);
1053 }
1054
1055 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
1056 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
1057 sets SkRect to (0, 0, 0, 0).
1058
1059 Result is either empty or sorted: fLeft is less than or equal to fRight, and
1060 fTop is less than or equal to fBottom.
1061
1062 @param pts SkPoint array
1063 @param count entries in array
1064 @return true if all SkPoint values are finite
1065 */
1066 bool setBoundsCheck(const SkPoint pts[], int count);
1067
1068 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
1069 contains infinity or NaN, all SkRect dimensions are set to NaN.
1070
1071 @param pts SkPoint array
1072 @param count entries in array
1073 */
1074 void setBoundsNoCheck(const SkPoint pts[], int count);
1075
1076 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
1077 sorted and may be empty. Does not check to see if values are finite.
1078
1079 @param p0 corner to include
1080 @param p1 corner to include
1081 */
setSkRect1082 void set(const SkPoint& p0, const SkPoint& p1) {
1083 fLeft = SkMinScalar(p0.fX, p1.fX);
1084 fRight = SkMaxScalar(p0.fX, p1.fX);
1085 fTop = SkMinScalar(p0.fY, p1.fY);
1086 fBottom = SkMaxScalar(p0.fY, p1.fY);
1087 }
1088
1089 /** Sets SkRect to (x, y, x + width, y + height).
1090 Does not validate input; width or height may be negative.
1091
1092 @param x stored in fLeft
1093 @param y stored in fTop
1094 @param width added to x and stored in fRight
1095 @param height added to y and stored in fBottom
1096 */
setXYWHSkRect1097 void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
1098 fLeft = x;
1099 fTop = y;
1100 fRight = x + width;
1101 fBottom = y + height;
1102 }
1103
1104 /** Sets SkRect to (0, 0, width, height). Does not validate input;
1105 width or height may be negative.
1106
1107 @param width stored in fRight
1108 @param height stored in fBottom
1109 */
setWHSkRect1110 void setWH(SkScalar width, SkScalar height) {
1111 fLeft = 0;
1112 fTop = 0;
1113 fRight = width;
1114 fBottom = height;
1115 }
1116
1117 /** Returns SkRect offset by (dx, dy).
1118
1119 If dx is negative, SkRect returned is moved to the left.
1120 If dx is positive, SkRect returned is moved to the right.
1121 If dy is negative, SkRect returned is moved upward.
1122 If dy is positive, SkRect returned is moved downward.
1123
1124 @param dx added to fLeft and fRight
1125 @param dy added to fTop and fBottom
1126 @return SkRect offset on axes, with original width and height
1127 */
makeOffsetSkRect1128 SkRect makeOffset(SkScalar dx, SkScalar dy) const {
1129 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
1130 }
1131
1132 /** Returns SkRect, inset by (dx, dy).
1133
1134 If dx is negative, SkRect returned is wider.
1135 If dx is positive, SkRect returned is narrower.
1136 If dy is negative, SkRect returned is taller.
1137 If dy is positive, SkRect returned is shorter.
1138
1139 @param dx added to fLeft and subtracted from fRight
1140 @param dy added to fTop and subtracted from fBottom
1141 @return SkRect inset symmetrically left and right, top and bottom
1142 */
makeInsetSkRect1143 SkRect makeInset(SkScalar dx, SkScalar dy) const {
1144 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1145 }
1146
1147 /** Returns SkRect, outset by (dx, dy).
1148
1149 If dx is negative, SkRect returned is narrower.
1150 If dx is positive, SkRect returned is wider.
1151 If dy is negative, SkRect returned is shorter.
1152 If dy is positive, SkRect returned is taller.
1153
1154 @param dx subtracted to fLeft and added from fRight
1155 @param dy subtracted to fTop and added from fBottom
1156 @return SkRect outset symmetrically left and right, top and bottom
1157 */
makeOutsetSkRect1158 SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1159 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1160 }
1161
1162 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1163
1164 If dx is negative, moves SkRect to the left.
1165 If dx is positive, moves SkRect to the right.
1166 If dy is negative, moves SkRect upward.
1167 If dy is positive, moves SkRect downward.
1168
1169 @param dx offset added to fLeft and fRight
1170 @param dy offset added to fTop and fBottom
1171 */
offsetSkRect1172 void offset(SkScalar dx, SkScalar dy) {
1173 fLeft += dx;
1174 fTop += dy;
1175 fRight += dx;
1176 fBottom += dy;
1177 }
1178
1179 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1180 fTop, fBottom.
1181
1182 If delta.fX is negative, moves SkRect to the left.
1183 If delta.fX is positive, moves SkRect to the right.
1184 If delta.fY is negative, moves SkRect upward.
1185 If delta.fY is positive, moves SkRect downward.
1186
1187 @param delta added to SkRect
1188 */
offsetSkRect1189 void offset(const SkPoint& delta) {
1190 this->offset(delta.fX, delta.fY);
1191 }
1192
1193 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1194 are unchanged.
1195
1196 @param newX stored in fLeft, preserving width()
1197 @param newY stored in fTop, preserving height()
1198 */
offsetToSkRect1199 void offsetTo(SkScalar newX, SkScalar newY) {
1200 fRight += newX - fLeft;
1201 fBottom += newY - fTop;
1202 fLeft = newX;
1203 fTop = newY;
1204 }
1205
1206 /** Insets SkRect by (dx, dy).
1207
1208 If dx is positive, makes SkRect narrower.
1209 If dx is negative, makes SkRect wider.
1210 If dy is positive, makes SkRect shorter.
1211 If dy is negative, makes SkRect taller.
1212
1213 @param dx added to fLeft and subtracted from fRight
1214 @param dy added to fTop and subtracted from fBottom
1215 */
insetSkRect1216 void inset(SkScalar dx, SkScalar dy) {
1217 fLeft += dx;
1218 fTop += dy;
1219 fRight -= dx;
1220 fBottom -= dy;
1221 }
1222
1223 /** Outsets SkRect by (dx, dy).
1224
1225 If dx is positive, makes SkRect wider.
1226 If dx is negative, makes SkRect narrower.
1227 If dy is positive, makes SkRect taller.
1228 If dy is negative, makes SkRect shorter.
1229
1230 @param dx subtracted to fLeft and added from fRight
1231 @param dy subtracted to fTop and added from fBottom
1232 */
outsetSkRect1233 void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
1234
1235 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1236 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1237
1238 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1239
1240 @param r limit of result
1241 @return true if r and SkRect have area in common
1242 */
1243 bool intersect(const SkRect& r);
1244
1245 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1246 construction.
1247
1248 Returns true if SkRect intersects construction, and sets SkRect to intersection.
1249 Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.
1250
1251 Returns false if either construction or SkRect is empty, leaving SkRect unchanged.
1252
1253 @param left x-axis minimum of constructed SkRect
1254 @param top y-axis minimum of constructed SkRect
1255 @param right x-axis maximum of constructed SkRect
1256 @param bottom y-axis maximum of constructed SkRect
1257 @return true if construction and SkRect have area in common
1258 */
1259 bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1260
1261 /** Returns true if a intersects b, and sets SkRect to intersection.
1262 Returns false if a does not intersect b, and leaves SkRect unchanged.
1263
1264 Returns false if either a or b is empty, leaving SkRect unchanged.
1265
1266 @param a SkRect to intersect
1267 @param b SkRect to intersect
1268 @return true if a and b have area in common
1269 */
1270 bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1271
1272
1273 private:
IntersectsSkRect1274 static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1275 SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1276 SkScalar L = SkMaxScalar(al, bl);
1277 SkScalar R = SkMinScalar(ar, br);
1278 SkScalar T = SkMaxScalar(at, bt);
1279 SkScalar B = SkMinScalar(ab, bb);
1280 return L < R && T < B;
1281 }
1282
1283 public:
1284
1285 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1286 construction.
1287
1288 Returns true if SkRect intersects construction.
1289 Returns false if either construction or SkRect is empty, or do not intersect.
1290
1291 @param left x-axis minimum of constructed SkRect
1292 @param top y-axis minimum of constructed SkRect
1293 @param right x-axis maximum of constructed SkRect
1294 @param bottom y-axis maximum of constructed SkRect
1295 @return true if construction and SkRect have area in common
1296 */
intersectsSkRect1297 bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
1298 return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
1299 }
1300
1301 /** Returns true if SkRect intersects r.
1302 Returns false if either r or SkRect is empty, or do not intersect.
1303
1304 @param r SkRect to intersect
1305 @return true if r and SkRect have area in common
1306 */
intersectsSkRect1307 bool intersects(const SkRect& r) const {
1308 return Intersects(fLeft, fTop, fRight, fBottom,
1309 r.fLeft, r.fTop, r.fRight, r.fBottom);
1310 }
1311
1312 /** Returns true if a intersects b.
1313 Returns false if either a or b is empty, or do not intersect.
1314
1315 @param a SkRect to intersect
1316 @param b SkRect to intersect
1317 @return true if a and b have area in common
1318 */
IntersectsSkRect1319 static bool Intersects(const SkRect& a, const SkRect& b) {
1320 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1321 b.fLeft, b.fTop, b.fRight, b.fBottom);
1322 }
1323
1324 /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort
1325 construction.
1326
1327 Sets SkRect to the union of itself and the construction.
1328
1329 Has no effect if construction is empty. Otherwise, if SkRect is empty, sets
1330 SkRect to construction.
1331
1332 @param left x-axis minimum of constructed SkRect
1333 @param top y-axis minimum of constructed SkRect
1334 @param right x-axis maximum of constructed SkRect
1335 @param bottom y-axis maximum of constructed SkRect
1336 */
1337 void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
1338
1339 /** Sets SkRect to the union of itself and r.
1340
1341 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1342 SkRect to r.
1343
1344 @param r expansion SkRect
1345 */
joinSkRect1346 void join(const SkRect& r) {
1347 this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
1348 }
1349
1350 /** Sets SkRect to the union of itself and r.
1351
1352 Asserts if r is empty and SK_DEBUG is defined.
1353 If SkRect is empty, sets SkRect to r.
1354
1355 May produce incorrect results if r is empty.
1356
1357 @param r expansion SkRect
1358 */
joinNonEmptyArgSkRect1359 void joinNonEmptyArg(const SkRect& r) {
1360 SkASSERT(!r.isEmpty());
1361 // if we are empty, just assign
1362 if (fLeft >= fRight || fTop >= fBottom) {
1363 *this = r;
1364 } else {
1365 this->joinPossiblyEmptyRect(r);
1366 }
1367 }
1368
1369 /** Sets SkRect to the union of itself and the construction.
1370
1371 May produce incorrect results if SkRect or r is empty.
1372
1373 @param r expansion SkRect
1374 */
joinPossiblyEmptyRectSkRect1375 void joinPossiblyEmptyRect(const SkRect& r) {
1376 fLeft = SkMinScalar(fLeft, r.left());
1377 fTop = SkMinScalar(fTop, r.top());
1378 fRight = SkMaxScalar(fRight, r.right());
1379 fBottom = SkMaxScalar(fBottom, r.bottom());
1380 }
1381
1382 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1383 Returns false if SkRect is empty.
1384
1385 @param x test SkPoint x-coordinate
1386 @param y test SkPoint y-coordinate
1387 @return true if (x, y) is inside SkRect
1388 */
containsSkRect1389 bool contains(SkScalar x, SkScalar y) const {
1390 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1391 }
1392
1393 /** Returns true if SkRect contains r.
1394 Returns false if SkRect is empty or r is empty.
1395
1396 SkRect contains r when SkRect area completely includes r area.
1397
1398 @param r SkRect contained
1399 @return true if all sides of SkRect are outside r
1400 */
containsSkRect1401 bool contains(const SkRect& r) const {
1402 // todo: can we eliminate the this->isEmpty check?
1403 return !r.isEmpty() && !this->isEmpty() &&
1404 fLeft <= r.fLeft && fTop <= r.fTop &&
1405 fRight >= r.fRight && fBottom >= r.fBottom;
1406 }
1407
1408 /** Returns true if SkRect contains r.
1409 Returns false if SkRect is empty or r is empty.
1410
1411 SkRect contains r when SkRect area completely includes r area.
1412
1413 @param r SkIRect contained
1414 @return true if all sides of SkRect are outside r
1415 */
containsSkRect1416 bool contains(const SkIRect& r) const {
1417 // todo: can we eliminate the this->isEmpty check?
1418 return !r.isEmpty() && !this->isEmpty() &&
1419 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1420 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1421 }
1422
1423 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1424 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1425 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1426
1427 @param dst storage for SkIRect
1428 */
roundSkRect1429 void round(SkIRect* dst) const {
1430 SkASSERT(dst);
1431 dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1432 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1433 }
1434
1435 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1436 up fRight and fBottom, using
1437 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1438 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1439
1440 @param dst storage for SkIRect
1441 */
roundOutSkRect1442 void roundOut(SkIRect* dst) const {
1443 SkASSERT(dst);
1444 dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1445 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1446 }
1447
1448 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1449 up fRight and fBottom, using
1450 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1451 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1452
1453 @param dst storage for SkRect
1454 */
roundOutSkRect1455 void roundOut(SkRect* dst) const {
1456 dst->set(SkScalarFloorToScalar(fLeft),
1457 SkScalarFloorToScalar(fTop),
1458 SkScalarCeilToScalar(fRight),
1459 SkScalarCeilToScalar(fBottom));
1460 }
1461
1462 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1463 of fRight and fBottom, using
1464 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1465 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1466
1467 @param dst storage for SkIRect
1468 */
roundInSkRect1469 void roundIn(SkIRect* dst) const {
1470 SkASSERT(dst);
1471 dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1472 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1473 }
1474
1475 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1476 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1477 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1478
1479 @return rounded SkIRect
1480 */
roundSkRect1481 SkIRect round() const {
1482 SkIRect ir;
1483 this->round(&ir);
1484 return ir;
1485 }
1486
1487 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1488 up fRight and fBottom, using
1489 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1490 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1491
1492 @return rounded SkIRect
1493 */
roundOutSkRect1494 SkIRect roundOut() const {
1495 SkIRect ir;
1496 this->roundOut(&ir);
1497 return ir;
1498 }
1499
1500 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1501 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1502 and width() and height() will be zero or positive.
1503 */
sortSkRect1504 void sort() {
1505 using std::swap;
1506 if (fLeft > fRight) {
1507 swap(fLeft, fRight);
1508 }
1509
1510 if (fTop > fBottom) {
1511 swap(fTop, fBottom);
1512 }
1513 }
1514
1515 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1516 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1517 and width() and height() will be zero or positive.
1518
1519 @return sorted SkRect
1520 */
makeSortedSkRect1521 SkRect makeSorted() const {
1522 return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
1523 SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
1524 }
1525
1526 /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1527 entries.
1528
1529 @return pointer to fLeft
1530 */
asScalarsSkRect1531 const SkScalar* asScalars() const { return &fLeft; }
1532
1533 /** Writes text representation of SkRect to standard output. Set asHex to true to
1534 generate exact binary representations of floating point numbers.
1535
1536 @param asHex true if SkScalar values are written as hexadecimal
1537 */
1538 void dump(bool asHex) const;
1539
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