/*
* Copyright 2012 Google Inc .
*
* Use of this source code is governed by a BSD - style license that can be
* found in the LICENSE file .
*/
#ifndef SkRRect_DEFINED
#define SkRRect_DEFINED
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkMacros.h"
#include <cstdint>
#include <cstring>
#include <optional>
class SkMatrix;
class SkString;
/** \class SkRRect
SkRRect describes a rounded rectangle with a bounds and a pair of radii for each corner .
The bounds and radii can be set so that SkRRect describes : a rectangle with sharp corners ;
a circle ; an oval ; or a rectangle with one or more rounded corners .
SkRRect allows implementing CSS properties that describe rounded corners .
SkRRect may have up to eight different radii , one for each axis on each of its four
corners .
SkRRect may modify the provided parameters when initializing bounds and radii .
If either axis radii is zero or less : radii are stored as zero ; corner is square .
If corner curves overlap , radii are proportionally reduced to fit within bounds .
*/
SK_BEGIN_REQUIRE_DENSE
class SK_API SkRRect {
public:
/** Initializes bounds at (0, 0), the origin, with zero width and height.
Initializes corner radii to ( 0 , 0 ) , and sets type of kEmpty_Type .
@ return empty SkRRect
*/
SkRRect() = default ;
/** Initializes to copy of rrect bounds and corner radii.
@ param rrect bounds and corner to copy
@ return copy of rrect
*/
SkRRect(const SkRRect& rrect) = default ;
/** Copies rrect bounds and corner radii.
@ param rrect bounds and corner to copy
@ return copy of rrect
*/
SkRRect& operator =(const SkRRect& rrect) = default ;
/** \enum SkRRect::Type
Type describes possible specializations of SkRRect . Each Type is
exclusive ; a SkRRect may only have one type .
Type members become progressively less restrictive ; larger values of
Type have more degrees of freedom than smaller values .
*/
enum Type {
kEmpty_Type, //!< zero width or height
kRect_Type, //!< non-zero width and height, and zeroed radii
kOval_Type, //!< non-zero width and height filled with radii
kSimple_Type, //!< non-zero width and height with equal radii
kNinePatch_Type, //!< non-zero width and height with axis-aligned radii
kComplex_Type, //!< non-zero width and height with arbitrary radii
kLastType = kComplex_Type, //!< largest Type value
};
Type getType() const {
SkASSERT(this->isValid());
return static_cast<Type>(fType);
}
Type type() const { return this->getType(); }
inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
inline bool isRect() const { return kRect_Type == this->getType(); }
inline bool isOval() const { return kOval_Type == this->getType(); }
inline bool isSimple() const { return kSimple_Type == this->getType(); }
inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
inline bool isComplex() const { return kComplex_Type == this->getType(); }
/** Returns span on the x-axis. This does not check if result fits in 32-bit float;
result may be infinity .
@ return rect ( ) . fRight minus rect ( ) . fLeft
*/
SkScalar width() const { return fRect.width(); }
/** Returns span on the y-axis. This does not check if result fits in 32-bit float;
result may be infinity .
@ return rect ( ) . fBottom minus rect ( ) . fTop
*/
SkScalar height() const { return fRect.height(); }
/** Returns top-left corner radii. If type() returns kEmpty_Type, kRect_Type,
kOval_Type , or kSimple_Type , returns a value representative of all corner radii .
If type ( ) returns kNinePatch_Type or kComplex_Type , at least one of the
remaining three corners has a different value .
@ return corner radii for simple types
*/
SkVector getSimpleRadii() const {
return fRadii[0 ];
}
/** Sets bounds to zero width and height at (0, 0), the origin. Sets
corner radii to zero and sets type to kEmpty_Type .
*/
void setEmpty() { *this = SkRRect(); }
/** Sets bounds to sorted rect, and sets corner radii to zero.
If set bounds has width and height , and sets type to kRect_Type ;
otherwise , sets type to kEmpty_Type .
@ param rect bounds to set
*/
void setRect(const SkRect& rect) {
if (!this->initializeRect(rect)) {
return ;
}
memset(fRadii, 0 , sizeof (fRadii));
fType = kRect_Type;
SkASSERT(this->isValid());
}
/** Initializes bounds at (0, 0), the origin, with zero width and height.
Initializes corner radii to ( 0 , 0 ) , and sets type of kEmpty_Type .
@ return empty SkRRect
*/
static SkRRect MakeEmpty() { return SkRRect(); }
/** Initializes to copy of r bounds and zeroes corner radii.
@ param r bounds to copy
@ return copy of r
*/
static SkRRect MakeRect(const SkRect& r) {
SkRRect rr;
rr.setRect(r);
return rr;
}
/** Initializes to oval, x-axis radii to half oval.width(), and all y-axis radii
to half oval . height ( ) . If oval bounds is empty , sets to kEmpty_Type .
Otherwise , sets to kOval_Type .
@ param oval bounds of oval
@ return oval
*/
static SkRRect MakeOval(const SkRect& oval) {
SkRRect rr;
rr.setOval(oval);
return rr;
}
/** Initializes to rounded rectangle with the same radii for all four corners.
If rect is empty , sets to kEmpty_Type .
Otherwise , if xRad and yRad are zero , sets to kRect_Type .
Otherwise , if xRad is at least half rect . width ( ) and yRad is at least half
rect . height ( ) , sets to kOval_Type .
Otherwise , sets to kSimple_Type .
@ param rect bounds of rounded rectangle
@ param xRad x - axis radius of corners
@ param yRad y - axis radius of corners
@ return rounded rectangle
*/
static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
SkRRect rr;
rr.setRectXY(rect, xRad, yRad);
return rr;
}
/** Initializes to rounded rectangle with a radii array for individual control
of all four corners .
If rect is empty , sets to kEmpty_Type .
Otherwise , if one of each corner radii are zero , sets to kRect_Type .
Otherwise , if all x - axis radii are equal and at least half rect . width ( ) , and
all y - axis radii are equal at least half rect . height ( ) , sets to kOval_Type .
Otherwise , if all x - axis radii are equal , and all y - axis radii are equal ,
sets to kSimple_Type . Otherwise , sets to kNinePatch_Type .
@ param rect bounds of rounded rectangle
@ param radii corner x - axis and y - axis radii
example : https : //fiddle.skia.org/c/@RRect_setRectRadii
*/
static SkRRect MakeRectRadii(const SkRect& rect, const SkVector radii[4 ]) {
SkRRect rr;
rr.setRectRadii(rect, radii);
return rr;
}
/** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
to half oval . height ( ) . If oval bounds is empty , sets to kEmpty_Type .
Otherwise , sets to kOval_Type .
@ param oval bounds of oval
*/
void setOval(const SkRect& oval);
/** Sets to rounded rectangle with the same radii for all four corners.
If rect is empty , sets to kEmpty_Type .
Otherwise , if xRad or yRad is zero , sets to kRect_Type .
Otherwise , if xRad is at least half rect . width ( ) and yRad is at least half
rect . height ( ) , sets to kOval_Type .
Otherwise , sets to kSimple_Type .
@ param rect bounds of rounded rectangle
@ param xRad x - axis radius of corners
@ param yRad y - axis radius of corners
example : https : //fiddle.skia.org/c/@RRect_setRectXY
*/
void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
/** Sets bounds to rect. Sets radii to (leftRad, topRad), (rightRad, topRad),
( rightRad , bottomRad ) , ( leftRad , bottomRad ) .
If rect is empty , sets to kEmpty_Type .
Otherwise , if leftRad and rightRad are zero , sets to kRect_Type .
Otherwise , if topRad and bottomRad are zero , sets to kRect_Type .
Otherwise , if leftRad and rightRad are equal and at least half rect . width ( ) , and
topRad and bottomRad are equal at least half rect . height ( ) , sets to kOval_Type .
Otherwise , if leftRad and rightRad are equal , and topRad and bottomRad are equal ,
sets to kSimple_Type . Otherwise , sets to kNinePatch_Type .
Nine patch refers to the nine parts defined by the radii : one center rectangle ,
four edge patches , and four corner patches .
@ param rect bounds of rounded rectangle
@ param leftRad left - top and left - bottom x - axis radius
@ param topRad left - top and right - top y - axis radius
@ param rightRad right - top and right - bottom x - axis radius
@ param bottomRad left - bottom and right - bottom y - axis radius
*/
void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
SkScalar rightRad, SkScalar bottomRad);
/** Sets bounds to rect. Sets radii array for individual control of all four corners.
If rect is empty , sets to kEmpty_Type .
Otherwise , if one of each corner radii are zero , sets to kRect_Type .
Otherwise , if all x - axis radii are equal and at least half rect . width ( ) , and
all y - axis radii are equal at least half rect . height ( ) , sets to kOval_Type .
Otherwise , if all x - axis radii are equal , and all y - axis radii are equal ,
sets to kSimple_Type . Otherwise , sets to kNinePatch_Type .
@ param rect bounds of rounded rectangle
@ param radii corner x - axis and y - axis radii
example : https : //fiddle.skia.org/c/@RRect_setRectRadii
*/
void setRectRadii(const SkRect& rect, const SkVector radii[4 ]);
/** \enum SkRRect::Corner
The radii are stored : top - left , top - right , bottom - right , bottom - left .
*/
enum Corner {
kUpperLeft_Corner, //!< index of top-left corner radii
kUpperRight_Corner, //!< index of top-right corner radii
kLowerRight_Corner, //!< index of bottom-right corner radii
kLowerLeft_Corner, //!< index of bottom-left corner radii
};
/** Returns bounds. Bounds may have zero width or zero height. Bounds right is
greater than or equal to left ; bounds bottom is greater than or equal to top .
Result is identical to getBounds ( ) .
@ return bounding box
*/
const SkRect& rect() const { return fRect; }
/** Returns scalar pair for radius of curve on x-axis and y-axis for one corner.
Both radii may be zero . If not zero , both are positive and finite .
@ return x - axis and y - axis radii for one corner
*/
SkVector radii(Corner corner) const { return fRadii[corner]; }
/**
* Returns the corner radii for all four corners , in the same order as ` Corner ` .
*/
SkSpan<const SkVector> radii() const { return SkSpan(fRadii, 4 ); }
/** Returns bounds. Bounds may have zero width or zero height. Bounds right is
greater than or equal to left ; bounds bottom is greater than or equal to top .
Result is identical to rect ( ) .
@ return bounding box
*/
const SkRect& getBounds() const { return fRect; }
/** Returns true if bounds and radii in a are equal to bounds and radii in b.
a and b are not equal if either contain NaN . a and b are equal if members
contain zeroes with different signs .
@ param a SkRect bounds and radii to compare
@ param b SkRect bounds and radii to compare
@ return true if members are equal
*/
friend bool operator ==(const SkRRect& a, const SkRRect& b) {
return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0 ].fX, &b.fRadii['color: green'>0 ].fX, 8 );
}
/** Returns true if bounds and radii in a are not equal to bounds and radii in b.
a and b are not equal if either contain NaN . a and b are equal if members
contain zeroes with different signs .
@ param a SkRect bounds and radii to compare
@ param b SkRect bounds and radii to compare
@ return true if members are not equal
*/
friend bool operator !=(const SkRRect& a, const SkRRect& b) {
return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0 ].fX, &b.fRadii[le='color: green'>0 ].fX, 8 );
}
/** Copies SkRRect to dst, then insets dst bounds by dx and dy, and adjusts dst
radii by dx and dy . dx and dy may be positive , negative , or zero . dst may be
SkRRect .
If either corner radius is zero , the corner has no curvature and is unchanged .
Otherwise , if adjusted radius becomes negative , pins radius to zero .
If dx exceeds half dst bounds width , dst bounds left and right are set to
bounds x - axis center . If dy exceeds half dst bounds height , dst bounds top and
bottom are set to bounds y - axis center .
If dx or dy cause the bounds to become infinite , dst bounds is zeroed .
@ param dx added to rect ( ) . fLeft , and subtracted from rect ( ) . fRight
@ param dy added to rect ( ) . fTop , and subtracted from rect ( ) . fBottom
@ param dst insets bounds and radii
example : https : //fiddle.skia.org/c/@RRect_inset
*/
void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const ;
/** Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
positive , negative , or zero .
If either corner radius is zero , the corner has no curvature and is unchanged .
Otherwise , if adjusted radius becomes negative , pins radius to zero .
If dx exceeds half bounds width , bounds left and right are set to
bounds x - axis center . If dy exceeds half bounds height , bounds top and
bottom are set to bounds y - axis center .
If dx or dy cause the bounds to become infinite , bounds is zeroed .
@ param dx added to rect ( ) . fLeft , and subtracted from rect ( ) . fRight
@ param dy added to rect ( ) . fTop , and subtracted from rect ( ) . fBottom
*/
void inset(SkScalar dx, SkScalar dy) {
this->inset(dx, dy, this);
}
/** Outsets dst bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
positive , negative , or zero .
If either corner radius is zero , the corner has no curvature and is unchanged .
Otherwise , if adjusted radius becomes negative , pins radius to zero .
If dx exceeds half dst bounds width , dst bounds left and right are set to
bounds x - axis center . If dy exceeds half dst bounds height , dst bounds top and
bottom are set to bounds y - axis center .
If dx or dy cause the bounds to become infinite , dst bounds is zeroed .
@ param dx subtracted from rect ( ) . fLeft , and added to rect ( ) . fRight
@ param dy subtracted from rect ( ) . fTop , and added to rect ( ) . fBottom
@ param dst outset bounds and radii
*/
void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
this->inset(-dx, -dy, dst);
}
/** Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
positive , negative , or zero .
If either corner radius is zero , the corner has no curvature and is unchanged .
Otherwise , if adjusted radius becomes negative , pins radius to zero .
If dx exceeds half bounds width , bounds left and right are set to
bounds x - axis center . If dy exceeds half bounds height , bounds top and
bottom are set to bounds y - axis center .
If dx or dy cause the bounds to become infinite , bounds is zeroed .
@ param dx subtracted from rect ( ) . fLeft , and added to rect ( ) . fRight
@ param dy subtracted from rect ( ) . fTop , and added to rect ( ) . fBottom
*/
void outset(SkScalar dx, SkScalar dy) {
this->inset(-dx, -dy, this);
}
/** Translates SkRRect by (dx, dy).
@ param dx offset added to rect ( ) . fLeft and rect ( ) . fRight
@ param dy offset added to rect ( ) . fTop and rect ( ) . fBottom
*/
void offset(SkScalar dx, SkScalar dy) {
fRect.offset(dx, dy);
}
/** Returns SkRRect translated by (dx, dy).
@ param dx offset added to rect ( ) . fLeft and rect ( ) . fRight
@ param dy offset added to rect ( ) . fTop and rect ( ) . fBottom
@ return SkRRect bounds offset by ( dx , dy ) , with unchanged corner radii
*/
[[nodiscard]] SkRRect makeOffset(SkScalar dx, SkScalar dy) const {
return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);
}
/** Returns true if rect is inside the bounds and corner radii, and if
SkRRect and rect are not empty .
@ param rect area tested for containment
@ return true if SkRRect contains rect
example : https : //fiddle.skia.org/c/@RRect_contains
*/
bool contains(const SkRect& rect) const ;
/** Returns true if bounds and radii values are finite and describe a SkRRect
SkRRect : : Type that matches getType ( ) . All SkRRect methods construct valid types ,
even if the input values are not valid . Invalid SkRRect data can only
be generated by corrupting memory .
@ return true if bounds and radii match type ( )
example : https : //fiddle.skia.org/c/@RRect_isValid
*/
bool isValid() const ;
static constexpr size_t kSizeInMemory = 12 * sizeof (SkScalar);
/** Writes SkRRect to buffer. Writes kSizeInMemory bytes, and returns
kSizeInMemory , the number of bytes written .
@ param buffer storage for SkRRect
@ return bytes written , kSizeInMemory
example : https : //fiddle.skia.org/c/@RRect_writeToMemory
*/
size_t writeToMemory(void * buffer) const ;
/** Reads SkRRect from buffer, reading kSizeInMemory bytes.
Returns kSizeInMemory , bytes read if length is at least kSizeInMemory .
Otherwise , returns zero .
@ param buffer memory to read from
@ param length size of buffer
@ return bytes read , or 0 if length is less than kSizeInMemory
example : https : //fiddle.skia.org/c/@RRect_readFromMemory
*/
size_t readFromMemory(const void * buffer, size_t length);
/** Transforms by SkRRect by matrix and return it if possible.
* If the matrix does not preserve axis - alignment ( e . g . rotates , skews , etc . )
* then this returns { } .
*/
std::optional<SkRRect> transform(const SkMatrix&) const ;
// Deprecated: use optional form
bool transform(const SkMatrix& matrix, SkRRect* dst) const ;
/** Writes text representation of SkRRect to standard output.
Set asHex true to generate exact binary representations
of floating point numbers .
@ param asHex true if SkScalar values are written as hexadecimal
example : https : //fiddle.skia.org/c/@RRect_dump
*/
void dump(bool asHex) const ;
SkString dumpToString(bool asHex) const ;
/** Writes text representation of SkRRect to standard output. The representation
may be directly compiled as C + + code . Floating point values are written
with limited precision ; it may not be possible to reconstruct original
SkRRect from output .
*/
void dump() const { this->dump(false ); }
/** Writes text representation of SkRRect to standard output. The representation
may be directly compiled as C + + code . Floating point values are written
in hexadecimal to preserve their exact bit pattern . The output reconstructs the
original SkRRect .
*/
void dumpHex() const { this->dump(true); }
private :
static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4 ]);
SkRRect(const SkRect& rect, const SkVector radii[4 ], int32_t type)
: fRect(rect)
, fRadii{radii[0 ], radii[1 ], radii[2 ], radii[3 ]}
, fType(type) {}
/**
* Initializes fRect . If the passed in rect is not finite or empty the rrect will be fully
* initialized and false is returned . Otherwise , just fRect is initialized and true is returned .
*/
bool initializeRect(const SkRect&);
void computeType();
bool checkCornerContainment(SkScalar x, SkScalar y) const ;
// Returns true if the radii had to be scaled to fit rect
bool scaleRadii();
SkRect fRect = SkRect::MakeEmpty();
// Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
SkVector fRadii[4 ] = {{0 , 0 }, {0 , 0 }, {0 ,0 }, {0 ,0 }};
// use an explicitly sized type so we're sure the class is dense (no uninitialized bytes)
int32_t fType = kEmpty_Type;
// to access fRadii directly
friend class SkPath;
friend class SkRRectPriv;
};
SK_END_REQUIRE_DENSE
#endif
Messung V0.5 in Prozent C=90 H=98 G=94
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-08-26)
¤
*© Formatika GbR, Deutschland