• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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