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