1 /* 2 * Copyright 2012 Google Inc. 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/SkRRect.h and docs/SkRRect_Reference.bmh 9 on 2018-08-10 12:59:44. Additional documentation and examples can be found at: 10 https://skia.org/user/api/SkRRect_Reference 11 12 You may edit either file directly. Structural changes to public interfaces require 13 editing both files. After editing docs/SkRRect_Reference.bmh, run: 14 bookmaker -b docs -i include/core/SkRRect.h -p 15 to create an updated version of this file. 16 */ 17 18 #ifndef SkRRect_DEFINED 19 #define SkRRect_DEFINED 20 21 #include "SkRect.h" 22 #include "SkPoint.h" 23 24 class SkPath; 25 class SkMatrix; 26 27 /** \class SkRRect 28 SkRRect describes a rounded rectangle with a bounds and a pair of radii for each corner. 29 The bounds and radii can be set so that SkRRect describes: a rectangle with sharp corners; 30 a circle; an oval; or a rectangle with one or more rounded corners. 31 32 SkRRect allows implementing CSS properties that describe rounded corners. 33 SkRRect may have up to eight different radii, one for each axis on each of its four 34 corners. 35 36 SkRRect may modify the provided parameters when initializing bounds and radii. 37 If either axis radii is zero or less: radii are stored as zero; corner is square. 38 If corner curves overlap, radii are proportionally reduced to fit within bounds. 39 */ 40 class SK_API SkRRect { 41 public: 42 43 /** Initializes bounds at (0, 0), the origin, with zero width and height. 44 Initializes corner radii to (0, 0), and sets type of kEmpty_Type. 45 46 @return empty SkRRect 47 */ 48 SkRRect() = default; 49 50 /** Initializes to copy of rrect bounds and corner radii. 51 52 @param rrect bounds and corner to copy 53 @return copy of rrect 54 */ 55 SkRRect(const SkRRect& rrect) = default; 56 57 /** Copies rrect bounds and corner radii. 58 59 @param rrect bounds and corner to copy 60 @return copy of rrect 61 */ 62 SkRRect& operator=(const SkRRect& rrect) = default; 63 64 /** \enum SkRRect::Type 65 Type describes possible specializations of SkRRect. Each Type is 66 exclusive; a SkRRect may only have one type. 67 68 Type members become progressively less restrictive; larger values of 69 Type have more degrees of freedom than smaller values. 70 */ 71 enum Type { 72 kEmpty_Type, //!< zero width or height 73 kRect_Type, //!< non-zero width and height, and zeroed radii 74 kOval_Type, //!< non-zero width and height filled with radii 75 kSimple_Type, //!< non-zero width and height with equal radii 76 kNinePatch_Type, //!< non-zero width and height with axis-aligned radii 77 kComplex_Type, //!< non-zero width and height with arbitrary radii 78 kLastType = kComplex_Type, //!< largest Type value 79 }; 80 81 /** Returns SkRRect::Type, one of: 82 kEmpty_Type, kRect_Type, kOval_Type, kSimple_Type, kNinePatch_Type, 83 kComplex_Type. 84 85 @return SkRRect::Type 86 */ getType()87 Type getType() const { 88 SkASSERT(this->isValid()); 89 return static_cast<Type>(fType); 90 } 91 92 /** Returns SkRRect::Type, one of: 93 kEmpty_Type, kRect_Type, kOval_Type, kSimple_Type, kNinePatch_Type, 94 kComplex_Type. 95 96 @return SkRRect::Type 97 */ type()98 Type type() const { return this->getType(); } 99 isEmpty()100 inline bool isEmpty() const { return kEmpty_Type == this->getType(); } isRect()101 inline bool isRect() const { return kRect_Type == this->getType(); } isOval()102 inline bool isOval() const { return kOval_Type == this->getType(); } isSimple()103 inline bool isSimple() const { return kSimple_Type == this->getType(); } isNinePatch()104 inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); } isComplex()105 inline bool isComplex() const { return kComplex_Type == this->getType(); } 106 107 /** Returns span on the x-axis. This does not check if result fits in 32-bit float; 108 result may be infinity. 109 110 @return rect().fRight minus rect().fLeft 111 */ width()112 SkScalar width() const { return fRect.width(); } 113 114 /** Returns span on the y-axis. This does not check if result fits in 32-bit float; 115 result may be infinity. 116 117 @return rect().fBottom minus rect().fTop 118 */ height()119 SkScalar height() const { return fRect.height(); } 120 121 /** Returns top-left corner radii. If type() returns kEmpty_Type, kRect_Type, 122 kOval_Type, or kSimple_Type, returns a value representative of all corner radii. 123 If type() returns kNinePatch_Type or kComplex_Type, at least one of the 124 remaining three corners has a different value. 125 126 @return corner radii for simple types 127 */ getSimpleRadii()128 SkVector getSimpleRadii() const { 129 return fRadii[0]; 130 } 131 132 /** Sets bounds to zero width and height at (0, 0), the origin. Sets 133 corner radii to zero and sets type to kEmpty_Type. 134 */ setEmpty()135 void setEmpty() { *this = SkRRect(); } 136 137 /** Sets bounds to sorted rect, and sets corner radii to zero. 138 If set bounds has width and height, and sets type to kRect_Type; 139 otherwise, sets type to kEmpty_Type. 140 141 @param rect bounds to set 142 */ setRect(const SkRect & rect)143 void setRect(const SkRect& rect) { 144 if (!this->initializeRect(rect)) { 145 return; 146 } 147 148 memset(fRadii, 0, sizeof(fRadii)); 149 fType = kRect_Type; 150 151 SkASSERT(this->isValid()); 152 } 153 154 /** Initializes bounds at (0, 0), the origin, with zero width and height. 155 Initializes corner radii to (0, 0), and sets type of kEmpty_Type. 156 157 @return empty SkRRect 158 */ MakeEmpty()159 static SkRRect MakeEmpty() { return SkRRect(); } 160 161 /** Initializes to copy of r bounds and zeroes corner radii. 162 163 @param r bounds to copy 164 @return copy of r 165 */ MakeRect(const SkRect & r)166 static SkRRect MakeRect(const SkRect& r) { 167 SkRRect rr; 168 rr.setRect(r); 169 return rr; 170 } 171 172 /** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii 173 to half oval.height(). If oval bounds is empty, sets to kEmpty_Type. 174 Otherwise, sets to kOval_Type. 175 176 @param oval bounds of oval 177 @return oval 178 */ MakeOval(const SkRect & oval)179 static SkRRect MakeOval(const SkRect& oval) { 180 SkRRect rr; 181 rr.setOval(oval); 182 return rr; 183 } 184 185 /** Sets to rounded rectangle with the same radii for all four corners. 186 If rect is empty, sets to kEmpty_Type. 187 Otherwise, if xRad and yRad are zero, sets to kRect_Type. 188 Otherwise, if xRad is at least half rect.width() and yRad is at least half 189 rect.height(), sets to kOval_Type. 190 Otherwise, sets to kSimple_Type. 191 192 @param rect bounds of rounded rectangle 193 @param xRad x-axis radius of corners 194 @param yRad y-axis radius of corners 195 @return rounded rectangle 196 */ MakeRectXY(const SkRect & rect,SkScalar xRad,SkScalar yRad)197 static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { 198 SkRRect rr; 199 rr.setRectXY(rect, xRad, yRad); 200 return rr; 201 } 202 203 /** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii 204 to half oval.height(). If oval bounds is empty, sets to kEmpty_Type. 205 Otherwise, sets to kOval_Type. 206 207 @param oval bounds of oval 208 */ setOval(const SkRect & oval)209 void setOval(const SkRect& oval) { 210 if (!this->initializeRect(oval)) { 211 return; 212 } 213 214 SkScalar xRad = SkScalarHalf(fRect.width()); 215 SkScalar yRad = SkScalarHalf(fRect.height()); 216 217 for (int i = 0; i < 4; ++i) { 218 fRadii[i].set(xRad, yRad); 219 } 220 fType = kOval_Type; 221 222 SkASSERT(this->isValid()); 223 } 224 225 /** Sets to rounded rectangle with the same radii for all four corners. 226 If rect is empty, sets to kEmpty_Type. 227 Otherwise, if xRad or yRad is zero, sets to kRect_Type. 228 Otherwise, if xRad is at least half rect.width() and yRad is at least half 229 rect.height(), sets to kOval_Type. 230 Otherwise, sets to kSimple_Type. 231 232 @param rect bounds of rounded rectangle 233 @param xRad x-axis radius of corners 234 @param yRad y-axis radius of corners 235 */ 236 void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad); 237 238 /** Sets bounds to rect. Sets radii to (leftRad, topRad), (rightRad, topRad), 239 (rightRad, bottomRad), (leftRad, bottomRad). 240 241 If rect is empty, sets to kEmpty_Type. 242 Otherwise, if leftRad and rightRad are zero, sets to kRect_Type. 243 Otherwise, if topRad and bottomRad are zero, sets to kRect_Type. 244 Otherwise, if leftRad and rightRad are equal and at least half rect.width(), and 245 topRad and bottomRad are equal at least half rect.height(), sets to kOval_Type. 246 Otherwise, if leftRad and rightRad are equal, and topRad and bottomRad are equal, 247 sets to kSimple_Type. Otherwise, sets to kNinePatch_Type. 248 249 Nine patch refers to the nine parts defined by the radii: one center rectangle, 250 four edge patches, and four corner patches. 251 252 @param rect bounds of rounded rectangle 253 @param leftRad left-top and left-bottom x-axis radius 254 @param topRad left-top and right-top y-axis radius 255 @param rightRad right-top and right-bottom x-axis radius 256 @param bottomRad left-bottom and right-bottom y-axis radius 257 */ 258 void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad, 259 SkScalar rightRad, SkScalar bottomRad); 260 261 /** Sets bounds to rect. Sets radii array for individual control of all for corners. 262 263 If rect is empty, sets to kEmpty_Type. 264 Otherwise, if one of each corner radii are zero, sets to kRect_Type. 265 Otherwise, if all x-axis radii are equal and at least half rect.width(), and 266 all y-axis radii are equal at least half rect.height(), sets to kOval_Type. 267 Otherwise, if all x-axis radii are equal, and all y-axis radii are equal, 268 sets to kSimple_Type. Otherwise, sets to kNinePatch_Type. 269 270 @param rect bounds of rounded rectangle 271 @param radii corner x-axis and y-axis radii 272 */ 273 void setRectRadii(const SkRect& rect, const SkVector radii[4]); 274 275 /** \enum SkRRect::Corner 276 The radii are stored: top-left, top-right, bottom-right, bottom-left. 277 */ 278 enum Corner { 279 kUpperLeft_Corner, //!< index of top-left corner radii 280 kUpperRight_Corner, //!< index of top-right corner radii 281 kLowerRight_Corner, //!< index of bottom-right corner radii 282 kLowerLeft_Corner, //!< index of bottom-left corner radii 283 }; 284 285 /** Returns bounds. Bounds may have zero width or zero height. Bounds right is 286 greater than or equal to left; bounds bottom is greater than or equal to top. 287 Result is identical to getBounds(). 288 289 @return bounding box 290 */ rect()291 const SkRect& rect() const { return fRect; } 292 293 /** Returns scalar pair for radius of curve on x-axis and y-axis for one corner. 294 Both radii may be zero. If not zero, both are positive and finite. 295 296 @param corner one of: kUpperLeft_Corner, kUpperRight_Corner, 297 kLowerRight_Corner, kLowerLeft_Corner 298 @return x-axis and y-axis radii for one corner 299 */ radii(Corner corner)300 SkVector radii(Corner corner) const { return fRadii[corner]; } 301 302 /** Returns bounds. Bounds may have zero width or zero height. Bounds right is 303 greater than or equal to left; bounds bottom is greater than or equal to top. 304 Result is identical to rect(). 305 306 @return bounding box 307 */ getBounds()308 const SkRect& getBounds() const { return fRect; } 309 310 /** Returns true if bounds and radii in a are equal to bounds and radii in b. 311 312 a and b are not equal if either contain NaN. a and b are equal if members 313 contain zeroes with different signs. 314 315 @param a SkRect bounds and radii to compare 316 @param b SkRect bounds and radii to compare 317 @return true if members are equal 318 */ 319 friend bool operator==(const SkRRect& a, const SkRRect& b) { 320 return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8); 321 } 322 323 /** Returns true if bounds and radii in a are not equal to bounds and radii in b. 324 325 a and b are not equal if either contain NaN. a and b are equal if members 326 contain zeroes with different signs. 327 328 @param a SkRect bounds and radii to compare 329 @param b SkRect bounds and radii to compare 330 @return true if members are not equal 331 */ 332 friend bool operator!=(const SkRRect& a, const SkRRect& b) { 333 return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8); 334 } 335 336 /** Copies SkRRect to dst, then insets dst bounds by dx and dy, and adjusts dst 337 radii by dx and dy. dx and dy may be positive, negative, or zero. dst may be 338 SkRRect. 339 340 If either corner radius is zero, the corner has no curvature and is unchanged. 341 Otherwise, if adjusted radius becomes negative, pins radius to zero. 342 If dx exceeds half dst bounds width, dst bounds left and right are set to 343 bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and 344 bottom are set to bounds y-axis center. 345 346 If dx or dy cause the bounds to become infinite, dst bounds is zeroed. 347 348 @param dx added to rect().fLeft, and subtracted from rect().fRight 349 @param dy added to rect().fTop, and subtracted from rect().fBottom 350 @param dst insets bounds and radii 351 */ 352 void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const; 353 354 /** Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be 355 positive, negative, or zero. 356 357 If either corner radius is zero, the corner has no curvature and is unchanged. 358 Otherwise, if adjusted radius becomes negative, pins radius to zero. 359 If dx exceeds half bounds width, bounds left and right are set to 360 bounds x-axis center. If dy exceeds half bounds height, bounds top and 361 bottom are set to bounds y-axis center. 362 363 If dx or dy cause the bounds to become infinite, bounds is zeroed. 364 365 @param dx added to rect().fLeft, and subtracted from rect().fRight 366 @param dy added to rect().fTop, and subtracted from rect().fBottom 367 */ inset(SkScalar dx,SkScalar dy)368 void inset(SkScalar dx, SkScalar dy) { 369 this->inset(dx, dy, this); 370 } 371 372 /** Outsets dst bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be 373 positive, negative, or zero. 374 375 If either corner radius is zero, the corner has no curvature and is unchanged. 376 Otherwise, if adjusted radius becomes negative, pins radius to zero. 377 If dx exceeds half dst bounds width, dst bounds left and right are set to 378 bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and 379 bottom are set to bounds y-axis center. 380 381 If dx or dy cause the bounds to become infinite, dst bounds is zeroed. 382 383 @param dx subtracted from rect().fLeft, and added to rect().fRight 384 @param dy subtracted from rect().fTop, and added to rect().fBottom 385 @param dst outset bounds and radii 386 */ outset(SkScalar dx,SkScalar dy,SkRRect * dst)387 void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const { 388 this->inset(-dx, -dy, dst); 389 } 390 391 /** Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be 392 positive, negative, or zero. 393 394 If either corner radius is zero, the corner has no curvature and is unchanged. 395 Otherwise, if adjusted radius becomes negative, pins radius to zero. 396 If dx exceeds half bounds width, bounds left and right are set to 397 bounds x-axis center. If dy exceeds half bounds height, bounds top and 398 bottom are set to bounds y-axis center. 399 400 If dx or dy cause the bounds to become infinite, bounds is zeroed. 401 402 @param dx subtracted from rect().fLeft, and added to rect().fRight 403 @param dy subtracted from rect().fTop, and added to rect().fBottom 404 */ outset(SkScalar dx,SkScalar dy)405 void outset(SkScalar dx, SkScalar dy) { 406 this->inset(-dx, -dy, this); 407 } 408 409 /** Translates SkRRect by (dx, dy). 410 411 @param dx offset added to rect().fLeft and rect().fRight 412 @param dy offset added to rect().fTop and rect().fBottom 413 */ offset(SkScalar dx,SkScalar dy)414 void offset(SkScalar dx, SkScalar dy) { 415 fRect.offset(dx, dy); 416 } 417 418 /** Returns SkRRect translated by (dx, dy). 419 420 @param dx offset added to rect().fLeft and rect().fRight 421 @param dy offset added to rect().fTop and rect().fBottom 422 @return SkRRect bounds offset by (dx, dy), with unchanged corner radii 423 */ makeOffset(SkScalar dx,SkScalar dy)424 SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const { 425 return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType); 426 } 427 428 /** Returns true if rect is inside the bounds and corner radii, and if 429 SkRRect and rect are not empty. 430 431 @param rect area tested for containment 432 @return true if SkRRect contains rect 433 */ 434 bool contains(const SkRect& rect) const; 435 436 /** Returns true if bounds and radii values are finite and describe a SkRRect 437 SkRRect::Type that matches getType(). All SkRRect methods construct valid types, 438 even if the input values are not valid. Invalid SkRRect data can only 439 be generated by corrupting memory. 440 441 @return true if bounds and radii match type() 442 */ 443 bool isValid() const; 444 445 static constexpr size_t kSizeInMemory = 12 * sizeof(SkScalar); 446 447 /** Writes SkRRect to buffer. Writes kSizeInMemory bytes, and returns 448 kSizeInMemory, the number of bytes written. 449 450 @param buffer storage for SkRRect 451 @return bytes written, kSizeInMemory 452 */ 453 size_t writeToMemory(void* buffer) const; 454 455 /** Reads SkRRect from buffer, reading kSizeInMemory bytes. 456 Returns kSizeInMemory, bytes read if length is at least kSizeInMemory. 457 Otherwise, returns zero. 458 459 @param buffer memory to read from 460 @param length size of buffer 461 @return bytes read, or 0 if length is less than kSizeInMemory 462 */ 463 size_t readFromMemory(const void* buffer, size_t length); 464 465 /** Transforms by SkRRect by matrix, storing result in dst. 466 Returns true if SkRRect transformed can be represented by another SkRRect. 467 Returns false if matrix contains transformations other than scale and translate. 468 469 Asserts in debug builds if SkRRect equals dst. 470 471 @param matrix SkMatrix specifying the transform 472 @param dst SkRRect to store the result 473 @return true if transformation succeeded. 474 */ 475 bool transform(const SkMatrix& matrix, SkRRect* dst) const; 476 477 /** Writes text representation of SkRRect to standard output. 478 Set asHex true to generate exact binary representations 479 of floating point numbers. 480 481 @param asHex true if SkScalar values are written as hexadecimal 482 */ 483 void dump(bool asHex) const; 484 485 /** Writes text representation of SkRRect to standard output. The representation 486 may be directly compiled as C++ code. Floating point values are written 487 with limited precision; it may not be possible to reconstruct original 488 SkRRect from output. 489 */ dump()490 void dump() const { this->dump(false); } 491 492 /** Writes text representation of SkRRect to standard output. The representation 493 may be directly compiled as C++ code. Floating point values are written 494 in hexadecimal to preserve their exact bit pattern. The output reconstructs the 495 original SkRRect. 496 */ dumpHex()497 void dumpHex() const { this->dump(true); } 498 499 private: 500 static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4]); 501 SkRRect(const SkRect & rect,const SkVector radii[4],int32_t type)502 SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type) 503 : fRect(rect) 504 , fRadii{radii[0], radii[1], radii[2], radii[3]} 505 , fType(type) {} 506 507 /** 508 * Initializes fRect. If the passed in rect is not finite or empty the rrect will be fully 509 * initialized and false is returned. Otherwise, just fRect is initialized and true is returned. 510 */ 511 bool initializeRect(const SkRect&); 512 513 void computeType(); 514 bool checkCornerContainment(SkScalar x, SkScalar y) const; 515 void scaleRadii(const SkRect& rect); 516 517 SkRect fRect = SkRect::MakeEmpty(); 518 // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[] 519 SkVector fRadii[4] = {{0, 0}, {0, 0}, {0,0}, {0,0}}; 520 // use an explicitly sized type so we're sure the class is dense (no uninitialized bytes) 521 int32_t fType = kEmpty_Type; 522 // TODO: add padding so we can use memcpy for flattening and not copy uninitialized data 523 524 // to access fRadii directly 525 friend class SkPath; 526 friend class SkRRectPriv; 527 }; 528 529 #endif 530