gfx/skia/trunk/include/core/SkRRect.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial