/usr/include/thunderbird/skia/SkRRect.h is in thunderbird-dev 1:38.6.0+build1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | /*
* 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 "SkRect.h"
#include "SkPoint.h"
class SkPath;
class SkMatrix;
// Path forward:
// core work
// add validate method (all radii positive, all radii sums < rect size, etc.)
// add contains(SkRect&) - for clip stack
// add contains(SkRRect&) - for clip stack
// add heart rect computation (max rect inside RR)
// add 9patch rect computation
// add growToInclude(SkPath&)
// analysis
// use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
// check on # of rectorus's the RRs could handle
// rendering work
// update SkPath.addRRect() to only use quads
// add GM and bench
// further out
// detect and triangulate RRectorii rather than falling back to SW in Ganesh
//
/** \class SkRRect
The SkRRect class represents a rounded rect with a potentially different
radii for each corner. It does not have a constructor so must be
initialized with one of the initialization functions (e.g., setEmpty,
setRectRadii, etc.)
This class is intended to roughly match CSS' border-*-*-radius capabilities.
This means:
If either of a corner's radii are 0 the corner will be square.
Negative radii are not allowed (they are clamped to zero).
If the corner curves overlap they will be proportionally reduced to fit.
*/
class SK_API SkRRect {
public:
/**
* Enum to capture the various possible subtypes of RR. Accessed
* by type(). The subtypes become progressively less restrictive.
*/
enum Type {
// !< Internal indicator that the sub type must be computed.
kUnknown_Type = -1,
// !< The RR is empty
kEmpty_Type,
//!< The RR is actually a (non-empty) rect (i.e., at least one radius
//!< at each corner is zero)
kRect_Type,
//!< The RR is actually a (non-empty) oval (i.e., all x radii are equal
//!< and >= width/2 and all the y radii are equal and >= height/2
kOval_Type,
//!< The RR is non-empty and all the x radii are equal & all y radii
//!< are equal but it is not an oval (i.e., there are lines between
//!< the curves) nor a rect (i.e., both radii are non-zero)
kSimple_Type,
//!< The RR is non-empty and the two left x radii are equal, the two top
//!< y radii are equal, and the same for the right and bottom but it is
//!< neither an rect, oval, nor a simple RR. It is called "nine patch"
//!< because the centers of the corner ellipses form an axis aligned
//!< rect with edges that divide the RR into an 9 rectangular patches:
//!< an interior patch, four edge patches, and four corner patches.
kNinePatch_Type,
//!< A fully general (non-empty) RR. Some of the x and/or y radii are
//!< different from the others and there must be one corner where
//!< both radii are non-zero.
kComplex_Type,
};
/**
* Returns the RR's sub type.
*/
Type getType() const {
SkDEBUGCODE(this->validate();)
if (kUnknown_Type == fType) {
this->computeType();
}
SkASSERT(kUnknown_Type != fType);
return 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 isSimpleCircular() const {
return this->isSimple() && fRadii[0].fX == fRadii[0].fY;
}
inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
inline bool isComplex() const { return kComplex_Type == this->getType(); }
bool allCornersCircular() const;
SkScalar width() const { return fRect.width(); }
SkScalar height() const { return fRect.height(); }
/**
* Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
*/
void setEmpty() {
fRect.setEmpty();
memset(fRadii, 0, sizeof(fRadii));
fType = kEmpty_Type;
SkDEBUGCODE(this->validate();)
}
/**
* Set this RR to match the supplied rect. All radii will be 0.
*/
void setRect(const SkRect& rect) {
if (rect.isEmpty()) {
this->setEmpty();
return;
}
fRect = rect;
memset(fRadii, 0, sizeof(fRadii));
fType = kRect_Type;
SkDEBUGCODE(this->validate();)
}
/**
* Set this RR to match the supplied oval. All x radii will equal half the
* width and all y radii will equal half the height.
*/
void setOval(const SkRect& oval) {
if (oval.isEmpty()) {
this->setEmpty();
return;
}
SkScalar xRad = SkScalarHalf(oval.width());
SkScalar yRad = SkScalarHalf(oval.height());
fRect = oval;
for (int i = 0; i < 4; ++i) {
fRadii[i].set(xRad, yRad);
}
fType = kOval_Type;
SkDEBUGCODE(this->validate();)
}
/**
* Initialize the RR with the same radii for all four corners.
*/
void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
/**
* Initialize the rr with one radius per-side.
*/
void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
SkScalar rightRad, SkScalar bottomRad);
/**
* Initialize the RR with potentially different radii for all four corners.
*/
void setRectRadii(const SkRect& rect, const SkVector radii[4]);
// The radii are stored in UL, UR, LR, LL order.
enum Corner {
kUpperLeft_Corner,
kUpperRight_Corner,
kLowerRight_Corner,
kLowerLeft_Corner
};
const SkRect& rect() const { return fRect; }
const SkVector& radii(Corner corner) const { return fRadii[corner]; }
const SkRect& getBounds() const { return fRect; }
/**
* When a rrect is simple, all of its radii are equal. This returns one
* of those radii. This call requires the rrect to be non-complex.
*/
const SkVector& getSimpleRadii() const {
SkASSERT(!this->isComplex());
return fRadii[0];
}
friend bool operator==(const SkRRect& a, const SkRRect& b) {
return a.fRect == b.fRect &&
SkScalarsEqual(a.fRadii[0].asScalars(),
b.fRadii[0].asScalars(), 8);
}
friend bool operator!=(const SkRRect& a, const SkRRect& b) {
return a.fRect != b.fRect ||
!SkScalarsEqual(a.fRadii[0].asScalars(),
b.fRadii[0].asScalars(), 8);
}
/**
* Call inset on the bounds, and adjust the radii to reflect what happens
* in stroking: If the corner is sharp (no curvature), leave it alone,
* otherwise we grow/shrink the radii by the amount of the inset. If a
* given radius becomes negative, it is pinned to 0.
*
* It is valid for dst == this.
*/
void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
void inset(SkScalar dx, SkScalar dy) {
this->inset(dx, dy, this);
}
/**
* Call outset on the bounds, and adjust the radii to reflect what happens
* in stroking: If the corner is sharp (no curvature), leave it alone,
* otherwise we grow/shrink the radii by the amount of the inset. If a
* given radius becomes negative, it is pinned to 0.
*
* It is valid for dst == this.
*/
void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
this->inset(-dx, -dy, dst);
}
void outset(SkScalar dx, SkScalar dy) {
this->inset(-dx, -dy, this);
}
/**
* Translate the rrect by (dx, dy).
*/
void offset(SkScalar dx, SkScalar dy) {
fRect.offset(dx, dy);
}
/**
* Returns true if 'rect' is wholy inside the RR, and both
* are not empty.
*/
bool contains(const SkRect& rect) const;
SkDEBUGCODE(void validate() const;)
enum {
kSizeInMemory = 12 * sizeof(SkScalar)
};
/**
* Write the rrect into the specified buffer. This is guaranteed to always
* write kSizeInMemory bytes, and that value is guaranteed to always be
* a multiple of 4. Return kSizeInMemory.
*/
size_t writeToMemory(void* buffer) const;
/**
* Reads the rrect from the specified buffer
*
* If the specified buffer is large enough, this will read kSizeInMemory bytes,
* and that value is guaranteed to always be a multiple of 4.
*
* @param buffer Memory to read from
* @param length Amount of memory available in the buffer
* @return number of bytes read (must be a multiple of 4) or
* 0 if there was not enough memory available
*/
size_t readFromMemory(const void* buffer, size_t length);
/**
* Transform by the specified matrix, and put the result in dst.
*
* @param matrix SkMatrix specifying the transform. Must only contain
* scale and/or translate, or this call will fail.
* @param dst SkRRect to store the result. It is an error to use this,
* which would make this function no longer const.
* @return true on success, false on failure. If false, dst is unmodified.
*/
bool transform(const SkMatrix& matrix, SkRRect* dst) const;
#ifdef SK_DEVELOPER
/**
* Prints the rrect using SkDebugf. This is intended for Skia development debugging. Don't
* rely on the existence of this function or the formatting of its output.
*/
void dump() const;
#endif
private:
SkRect fRect;
// Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
SkVector fRadii[4];
mutable Type fType;
// TODO: add padding so we can use memcpy for flattening and not copy
// uninitialized data
void computeType() const;
bool checkCornerContainment(SkScalar x, SkScalar y) const;
// to access fRadii directly
friend class SkPath;
};
#endif
|