Sat, 03 Jan 2015 20:18:00 +0100
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 | /* |
michael@0 | 3 | * Copyright 2012 Google Inc. |
michael@0 | 4 | * |
michael@0 | 5 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 6 | * found in the LICENSE file. |
michael@0 | 7 | */ |
michael@0 | 8 | |
michael@0 | 9 | #ifndef SkPathRef_DEFINED |
michael@0 | 10 | #define SkPathRef_DEFINED |
michael@0 | 11 | |
michael@0 | 12 | #include "SkMatrix.h" |
michael@0 | 13 | #include "SkPoint.h" |
michael@0 | 14 | #include "SkRect.h" |
michael@0 | 15 | #include "SkRefCnt.h" |
michael@0 | 16 | #include "SkTDArray.h" |
michael@0 | 17 | #include <stddef.h> // ptrdiff_t |
michael@0 | 18 | |
michael@0 | 19 | class SkRBuffer; |
michael@0 | 20 | class SkWBuffer; |
michael@0 | 21 | |
michael@0 | 22 | /** |
michael@0 | 23 | * Holds the path verbs and points. It is versioned by a generation ID. None of its public methods |
michael@0 | 24 | * modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an |
michael@0 | 25 | * SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs |
michael@0 | 26 | * copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller passes the Editor's |
michael@0 | 27 | * constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef after the editor's |
michael@0 | 28 | * constructor returns. |
michael@0 | 29 | * |
michael@0 | 30 | * The points and verbs are stored in a single allocation. The points are at the begining of the |
michael@0 | 31 | * allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points |
michael@0 | 32 | * and verbs both grow into the middle of the allocation until the meet. To access verb i in the |
michael@0 | 33 | * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first |
michael@0 | 34 | * logical verb or the last verb in memory). |
michael@0 | 35 | */ |
michael@0 | 36 | |
michael@0 | 37 | class SK_API SkPathRef : public ::SkRefCnt { |
michael@0 | 38 | public: |
michael@0 | 39 | SK_DECLARE_INST_COUNT(SkPathRef); |
michael@0 | 40 | |
michael@0 | 41 | class Editor { |
michael@0 | 42 | public: |
michael@0 | 43 | Editor(SkAutoTUnref<SkPathRef>* pathRef, |
michael@0 | 44 | int incReserveVerbs = 0, |
michael@0 | 45 | int incReservePoints = 0); |
michael@0 | 46 | |
michael@0 | 47 | ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) } |
michael@0 | 48 | |
michael@0 | 49 | /** |
michael@0 | 50 | * Returns the array of points. |
michael@0 | 51 | */ |
michael@0 | 52 | SkPoint* points() { return fPathRef->getPoints(); } |
michael@0 | 53 | const SkPoint* points() const { return fPathRef->points(); } |
michael@0 | 54 | |
michael@0 | 55 | /** |
michael@0 | 56 | * Gets the ith point. Shortcut for this->points() + i |
michael@0 | 57 | */ |
michael@0 | 58 | SkPoint* atPoint(int i) { |
michael@0 | 59 | SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); |
michael@0 | 60 | return this->points() + i; |
michael@0 | 61 | }; |
michael@0 | 62 | const SkPoint* atPoint(int i) const { |
michael@0 | 63 | SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); |
michael@0 | 64 | return this->points() + i; |
michael@0 | 65 | }; |
michael@0 | 66 | |
michael@0 | 67 | /** |
michael@0 | 68 | * Adds the verb and allocates space for the number of points indicated by the verb. The |
michael@0 | 69 | * return value is a pointer to where the points for the verb should be written. |
michael@0 | 70 | * 'weight' is only used if 'verb' is kConic_Verb |
michael@0 | 71 | */ |
michael@0 | 72 | SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) { |
michael@0 | 73 | SkDEBUGCODE(fPathRef->validate();) |
michael@0 | 74 | return fPathRef->growForVerb(verb, weight); |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | /** |
michael@0 | 78 | * Allocates space for multiple instances of a particular verb and the |
michael@0 | 79 | * requisite points & weights. |
michael@0 | 80 | * The return pointer points at the first new point (indexed normally [<i>]). |
michael@0 | 81 | * If 'verb' is kConic_Verb, 'weights' will return a pointer to the |
michael@0 | 82 | * space for the conic weights (indexed normally). |
michael@0 | 83 | */ |
michael@0 | 84 | SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, |
michael@0 | 85 | int numVbs, |
michael@0 | 86 | SkScalar** weights = NULL) { |
michael@0 | 87 | return fPathRef->growForRepeatedVerb(verb, numVbs, weights); |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | /** |
michael@0 | 91 | * Resets the path ref to a new verb and point count. The new verbs and points are |
michael@0 | 92 | * uninitialized. |
michael@0 | 93 | */ |
michael@0 | 94 | void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { |
michael@0 | 95 | fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | /** |
michael@0 | 99 | * Gets the path ref that is wrapped in the Editor. |
michael@0 | 100 | */ |
michael@0 | 101 | SkPathRef* pathRef() { return fPathRef; } |
michael@0 | 102 | |
michael@0 | 103 | void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); } |
michael@0 | 104 | |
michael@0 | 105 | void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); } |
michael@0 | 106 | |
michael@0 | 107 | private: |
michael@0 | 108 | SkPathRef* fPathRef; |
michael@0 | 109 | }; |
michael@0 | 110 | |
michael@0 | 111 | public: |
michael@0 | 112 | /** |
michael@0 | 113 | * Gets a path ref with no verbs or points. |
michael@0 | 114 | */ |
michael@0 | 115 | static SkPathRef* CreateEmpty(); |
michael@0 | 116 | |
michael@0 | 117 | /** |
michael@0 | 118 | * Returns true if all of the points in this path are finite, meaning there |
michael@0 | 119 | * are no infinities and no NaNs. |
michael@0 | 120 | */ |
michael@0 | 121 | bool isFinite() const { |
michael@0 | 122 | if (fBoundsIsDirty) { |
michael@0 | 123 | this->computeBounds(); |
michael@0 | 124 | } |
michael@0 | 125 | return SkToBool(fIsFinite); |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | /** |
michael@0 | 129 | * Returns a mask, where each bit corresponding to a SegmentMask is |
michael@0 | 130 | * set if the path contains 1 or more segments of that type. |
michael@0 | 131 | * Returns 0 for an empty path (no segments). |
michael@0 | 132 | */ |
michael@0 | 133 | uint32_t getSegmentMasks() const { return fSegmentMask; } |
michael@0 | 134 | |
michael@0 | 135 | /** Returns true if the path is an oval. |
michael@0 | 136 | * |
michael@0 | 137 | * @param rect returns the bounding rect of this oval. It's a circle |
michael@0 | 138 | * if the height and width are the same. |
michael@0 | 139 | * |
michael@0 | 140 | * @return true if this path is an oval. |
michael@0 | 141 | * Tracking whether a path is an oval is considered an |
michael@0 | 142 | * optimization for performance and so some paths that are in |
michael@0 | 143 | * fact ovals can report false. |
michael@0 | 144 | */ |
michael@0 | 145 | bool isOval(SkRect* rect) const { |
michael@0 | 146 | if (fIsOval && NULL != rect) { |
michael@0 | 147 | *rect = getBounds(); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | return SkToBool(fIsOval); |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | bool hasComputedBounds() const { |
michael@0 | 154 | return !fBoundsIsDirty; |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | /** Returns the bounds of the path's points. If the path contains 0 or 1 |
michael@0 | 158 | points, the bounds is set to (0,0,0,0), and isEmpty() will return true. |
michael@0 | 159 | Note: this bounds may be larger than the actual shape, since curves |
michael@0 | 160 | do not extend as far as their control points. |
michael@0 | 161 | */ |
michael@0 | 162 | const SkRect& getBounds() const { |
michael@0 | 163 | if (fBoundsIsDirty) { |
michael@0 | 164 | this->computeBounds(); |
michael@0 | 165 | } |
michael@0 | 166 | return fBounds; |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | /** |
michael@0 | 170 | * Transforms a path ref by a matrix, allocating a new one only if necessary. |
michael@0 | 171 | */ |
michael@0 | 172 | static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, |
michael@0 | 173 | const SkPathRef& src, |
michael@0 | 174 | const SkMatrix& matrix); |
michael@0 | 175 | |
michael@0 | 176 | static SkPathRef* CreateFromBuffer(SkRBuffer* buffer); |
michael@0 | 177 | |
michael@0 | 178 | /** |
michael@0 | 179 | * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be |
michael@0 | 180 | * repopulated with approximately the same number of verbs and points. A new path ref is created |
michael@0 | 181 | * only if necessary. |
michael@0 | 182 | */ |
michael@0 | 183 | static void Rewind(SkAutoTUnref<SkPathRef>* pathRef); |
michael@0 | 184 | |
michael@0 | 185 | virtual ~SkPathRef() { |
michael@0 | 186 | SkDEBUGCODE(this->validate();) |
michael@0 | 187 | sk_free(fPoints); |
michael@0 | 188 | |
michael@0 | 189 | SkDEBUGCODE(fPoints = NULL;) |
michael@0 | 190 | SkDEBUGCODE(fVerbs = NULL;) |
michael@0 | 191 | SkDEBUGCODE(fVerbCnt = 0x9999999;) |
michael@0 | 192 | SkDEBUGCODE(fPointCnt = 0xAAAAAAA;) |
michael@0 | 193 | SkDEBUGCODE(fPointCnt = 0xBBBBBBB;) |
michael@0 | 194 | SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;) |
michael@0 | 195 | SkDEBUGCODE(fEditorsAttached = 0x7777777;) |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; } |
michael@0 | 199 | int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; } |
michael@0 | 200 | int countWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.count(); } |
michael@0 | 201 | |
michael@0 | 202 | /** |
michael@0 | 203 | * Returns a pointer one beyond the first logical verb (last verb in memory order). |
michael@0 | 204 | */ |
michael@0 | 205 | const uint8_t* verbs() const { SkDEBUGCODE(this->validate();) return fVerbs; } |
michael@0 | 206 | |
michael@0 | 207 | /** |
michael@0 | 208 | * Returns a const pointer to the first verb in memory (which is the last logical verb). |
michael@0 | 209 | */ |
michael@0 | 210 | const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; } |
michael@0 | 211 | |
michael@0 | 212 | /** |
michael@0 | 213 | * Returns a const pointer to the first point. |
michael@0 | 214 | */ |
michael@0 | 215 | const SkPoint* points() const { SkDEBUGCODE(this->validate();) return fPoints; } |
michael@0 | 216 | |
michael@0 | 217 | /** |
michael@0 | 218 | * Shortcut for this->points() + this->countPoints() |
michael@0 | 219 | */ |
michael@0 | 220 | const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); } |
michael@0 | 221 | |
michael@0 | 222 | const SkScalar* conicWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.begin(); } |
michael@0 | 223 | const SkScalar* conicWeightsEnd() const { SkDEBUGCODE(this->validate();) return fConicWeights.end(); } |
michael@0 | 224 | |
michael@0 | 225 | /** |
michael@0 | 226 | * Convenience methods for getting to a verb or point by index. |
michael@0 | 227 | */ |
michael@0 | 228 | uint8_t atVerb(int index) const { |
michael@0 | 229 | SkASSERT((unsigned) index < (unsigned) fVerbCnt); |
michael@0 | 230 | return this->verbs()[~index]; |
michael@0 | 231 | } |
michael@0 | 232 | const SkPoint& atPoint(int index) const { |
michael@0 | 233 | SkASSERT((unsigned) index < (unsigned) fPointCnt); |
michael@0 | 234 | return this->points()[index]; |
michael@0 | 235 | } |
michael@0 | 236 | |
michael@0 | 237 | bool operator== (const SkPathRef& ref) const; |
michael@0 | 238 | |
michael@0 | 239 | /** |
michael@0 | 240 | * Writes the path points and verbs to a buffer. |
michael@0 | 241 | */ |
michael@0 | 242 | void writeToBuffer(SkWBuffer* buffer) const; |
michael@0 | 243 | |
michael@0 | 244 | /** |
michael@0 | 245 | * Gets the number of bytes that would be written in writeBuffer() |
michael@0 | 246 | */ |
michael@0 | 247 | uint32_t writeSize() const; |
michael@0 | 248 | |
michael@0 | 249 | /** |
michael@0 | 250 | * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the |
michael@0 | 251 | * same ID then they have the same verbs and points. However, two path refs may have the same |
michael@0 | 252 | * contents but different genIDs. |
michael@0 | 253 | */ |
michael@0 | 254 | uint32_t genID() const; |
michael@0 | 255 | |
michael@0 | 256 | private: |
michael@0 | 257 | enum SerializationOffsets { |
michael@0 | 258 | kIsFinite_SerializationShift = 25, // requires 1 bit |
michael@0 | 259 | kIsOval_SerializationShift = 24, // requires 1 bit |
michael@0 | 260 | kSegmentMask_SerializationShift = 0 // requires 4 bits |
michael@0 | 261 | }; |
michael@0 | 262 | |
michael@0 | 263 | SkPathRef() { |
michael@0 | 264 | fBoundsIsDirty = true; // this also invalidates fIsFinite |
michael@0 | 265 | fPointCnt = 0; |
michael@0 | 266 | fVerbCnt = 0; |
michael@0 | 267 | fVerbs = NULL; |
michael@0 | 268 | fPoints = NULL; |
michael@0 | 269 | fFreeSpace = 0; |
michael@0 | 270 | fGenerationID = kEmptyGenID; |
michael@0 | 271 | fSegmentMask = 0; |
michael@0 | 272 | fIsOval = false; |
michael@0 | 273 | SkDEBUGCODE(fEditorsAttached = 0;) |
michael@0 | 274 | SkDEBUGCODE(this->validate();) |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints); |
michael@0 | 278 | |
michael@0 | 279 | // Return true if the computed bounds are finite. |
michael@0 | 280 | static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { |
michael@0 | 281 | int count = ref.countPoints(); |
michael@0 | 282 | if (count <= 1) { // we ignore just 1 point (moveto) |
michael@0 | 283 | bounds->setEmpty(); |
michael@0 | 284 | return count ? ref.points()->isFinite() : true; |
michael@0 | 285 | } else { |
michael@0 | 286 | return bounds->setBoundsCheck(ref.points(), count); |
michael@0 | 287 | } |
michael@0 | 288 | } |
michael@0 | 289 | |
michael@0 | 290 | // called, if dirty, by getBounds() |
michael@0 | 291 | void computeBounds() const { |
michael@0 | 292 | SkDEBUGCODE(this->validate();) |
michael@0 | 293 | SkASSERT(fBoundsIsDirty); |
michael@0 | 294 | |
michael@0 | 295 | fIsFinite = ComputePtBounds(&fBounds, *this); |
michael@0 | 296 | fBoundsIsDirty = false; |
michael@0 | 297 | } |
michael@0 | 298 | |
michael@0 | 299 | void setBounds(const SkRect& rect) { |
michael@0 | 300 | SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom); |
michael@0 | 301 | fBounds = rect; |
michael@0 | 302 | fBoundsIsDirty = false; |
michael@0 | 303 | fIsFinite = fBounds.isFinite(); |
michael@0 | 304 | } |
michael@0 | 305 | |
michael@0 | 306 | /** Makes additional room but does not change the counts or change the genID */ |
michael@0 | 307 | void incReserve(int additionalVerbs, int additionalPoints) { |
michael@0 | 308 | SkDEBUGCODE(this->validate();) |
michael@0 | 309 | size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint); |
michael@0 | 310 | this->makeSpace(space); |
michael@0 | 311 | SkDEBUGCODE(this->validate();) |
michael@0 | 312 | } |
michael@0 | 313 | |
michael@0 | 314 | /** Resets the path ref with verbCount verbs and pointCount points, all uninitialized. Also |
michael@0 | 315 | * allocates space for reserveVerb additional verbs and reservePoints additional points.*/ |
michael@0 | 316 | void resetToSize(int verbCount, int pointCount, int conicCount, |
michael@0 | 317 | int reserveVerbs = 0, int reservePoints = 0) { |
michael@0 | 318 | SkDEBUGCODE(this->validate();) |
michael@0 | 319 | fBoundsIsDirty = true; // this also invalidates fIsFinite |
michael@0 | 320 | fGenerationID = 0; |
michael@0 | 321 | |
michael@0 | 322 | fSegmentMask = 0; |
michael@0 | 323 | fIsOval = false; |
michael@0 | 324 | |
michael@0 | 325 | size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount; |
michael@0 | 326 | size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints; |
michael@0 | 327 | size_t minSize = newSize + newReserve; |
michael@0 | 328 | |
michael@0 | 329 | ptrdiff_t sizeDelta = this->currSize() - minSize; |
michael@0 | 330 | |
michael@0 | 331 | if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) { |
michael@0 | 332 | sk_free(fPoints); |
michael@0 | 333 | fPoints = NULL; |
michael@0 | 334 | fVerbs = NULL; |
michael@0 | 335 | fFreeSpace = 0; |
michael@0 | 336 | fVerbCnt = 0; |
michael@0 | 337 | fPointCnt = 0; |
michael@0 | 338 | this->makeSpace(minSize); |
michael@0 | 339 | fVerbCnt = verbCount; |
michael@0 | 340 | fPointCnt = pointCount; |
michael@0 | 341 | fFreeSpace -= newSize; |
michael@0 | 342 | } else { |
michael@0 | 343 | fPointCnt = pointCount; |
michael@0 | 344 | fVerbCnt = verbCount; |
michael@0 | 345 | fFreeSpace = this->currSize() - minSize; |
michael@0 | 346 | } |
michael@0 | 347 | fConicWeights.setCount(conicCount); |
michael@0 | 348 | SkDEBUGCODE(this->validate();) |
michael@0 | 349 | } |
michael@0 | 350 | |
michael@0 | 351 | /** |
michael@0 | 352 | * Increases the verb count by numVbs and point count by the required amount. |
michael@0 | 353 | * The new points are uninitialized. All the new verbs are set to the specified |
michael@0 | 354 | * verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the |
michael@0 | 355 | * uninitialized conic weights. |
michael@0 | 356 | */ |
michael@0 | 357 | SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights); |
michael@0 | 358 | |
michael@0 | 359 | /** |
michael@0 | 360 | * Increases the verb count 1, records the new verb, and creates room for the requisite number |
michael@0 | 361 | * of additional points. A pointer to the first point is returned. Any new points are |
michael@0 | 362 | * uninitialized. |
michael@0 | 363 | */ |
michael@0 | 364 | SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight); |
michael@0 | 365 | |
michael@0 | 366 | /** |
michael@0 | 367 | * Ensures that the free space available in the path ref is >= size. The verb and point counts |
michael@0 | 368 | * are not changed. |
michael@0 | 369 | */ |
michael@0 | 370 | void makeSpace(size_t size) { |
michael@0 | 371 | SkDEBUGCODE(this->validate();) |
michael@0 | 372 | ptrdiff_t growSize = size - fFreeSpace; |
michael@0 | 373 | if (growSize <= 0) { |
michael@0 | 374 | return; |
michael@0 | 375 | } |
michael@0 | 376 | size_t oldSize = this->currSize(); |
michael@0 | 377 | // round to next multiple of 8 bytes |
michael@0 | 378 | growSize = (growSize + 7) & ~static_cast<size_t>(7); |
michael@0 | 379 | // we always at least double the allocation |
michael@0 | 380 | if (static_cast<size_t>(growSize) < oldSize) { |
michael@0 | 381 | growSize = oldSize; |
michael@0 | 382 | } |
michael@0 | 383 | if (growSize < kMinSize) { |
michael@0 | 384 | growSize = kMinSize; |
michael@0 | 385 | } |
michael@0 | 386 | size_t newSize = oldSize + growSize; |
michael@0 | 387 | // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO: |
michael@0 | 388 | // encapsulate this. |
michael@0 | 389 | fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize)); |
michael@0 | 390 | size_t oldVerbSize = fVerbCnt * sizeof(uint8_t); |
michael@0 | 391 | void* newVerbsDst = reinterpret_cast<void*>( |
michael@0 | 392 | reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize); |
michael@0 | 393 | void* oldVerbsSrc = reinterpret_cast<void*>( |
michael@0 | 394 | reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize); |
michael@0 | 395 | memmove(newVerbsDst, oldVerbsSrc, oldVerbSize); |
michael@0 | 396 | fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize); |
michael@0 | 397 | fFreeSpace += growSize; |
michael@0 | 398 | SkDEBUGCODE(this->validate();) |
michael@0 | 399 | } |
michael@0 | 400 | |
michael@0 | 401 | /** |
michael@0 | 402 | * Private, non-const-ptr version of the public function verbsMemBegin(). |
michael@0 | 403 | */ |
michael@0 | 404 | uint8_t* verbsMemWritable() { |
michael@0 | 405 | SkDEBUGCODE(this->validate();) |
michael@0 | 406 | return fVerbs - fVerbCnt; |
michael@0 | 407 | } |
michael@0 | 408 | |
michael@0 | 409 | /** |
michael@0 | 410 | * Gets the total amount of space allocated for verbs, points, and reserve. |
michael@0 | 411 | */ |
michael@0 | 412 | size_t currSize() const { |
michael@0 | 413 | return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints); |
michael@0 | 414 | } |
michael@0 | 415 | |
michael@0 | 416 | SkDEBUGCODE(void validate() const;) |
michael@0 | 417 | |
michael@0 | 418 | /** |
michael@0 | 419 | * Called the first time someone calls CreateEmpty to actually create the singleton. |
michael@0 | 420 | */ |
michael@0 | 421 | static void CreateEmptyImpl(int/*unused*/); |
michael@0 | 422 | |
michael@0 | 423 | void setIsOval(bool isOval) { fIsOval = isOval; } |
michael@0 | 424 | |
michael@0 | 425 | SkPoint* getPoints() { |
michael@0 | 426 | SkDEBUGCODE(this->validate();) |
michael@0 | 427 | fIsOval = false; |
michael@0 | 428 | return fPoints; |
michael@0 | 429 | } |
michael@0 | 430 | |
michael@0 | 431 | enum { |
michael@0 | 432 | kMinSize = 256, |
michael@0 | 433 | }; |
michael@0 | 434 | |
michael@0 | 435 | mutable SkRect fBounds; |
michael@0 | 436 | uint8_t fSegmentMask; |
michael@0 | 437 | mutable uint8_t fBoundsIsDirty; |
michael@0 | 438 | mutable SkBool8 fIsFinite; // only meaningful if bounds are valid |
michael@0 | 439 | mutable SkBool8 fIsOval; |
michael@0 | 440 | |
michael@0 | 441 | SkPoint* fPoints; // points to begining of the allocation |
michael@0 | 442 | uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards) |
michael@0 | 443 | int fVerbCnt; |
michael@0 | 444 | int fPointCnt; |
michael@0 | 445 | size_t fFreeSpace; // redundant but saves computation |
michael@0 | 446 | SkTDArray<SkScalar> fConicWeights; |
michael@0 | 447 | |
michael@0 | 448 | enum { |
michael@0 | 449 | kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs. |
michael@0 | 450 | }; |
michael@0 | 451 | mutable uint32_t fGenerationID; |
michael@0 | 452 | SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time. |
michael@0 | 453 | |
michael@0 | 454 | friend class PathRefTest_Private; |
michael@0 | 455 | typedef SkRefCnt INHERITED; |
michael@0 | 456 | }; |
michael@0 | 457 | |
michael@0 | 458 | #endif |