OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #ifndef SkPathRef_DEFINED | 9 #ifndef SkPathRef_DEFINED |
10 #define SkPathRef_DEFINED | 10 #define SkPathRef_DEFINED |
11 | 11 |
12 #include "SkMatrix.h" | 12 #include "SkMatrix.h" |
13 #include "SkPoint.h" | 13 #include "SkPoint.h" |
14 #include "SkRect.h" | 14 #include "SkRect.h" |
15 #include "SkRefCnt.h" | 15 #include "SkRefCnt.h" |
16 #include "SkTDArray.h" | 16 #include "SkTDArray.h" |
17 #include <stddef.h> // ptrdiff_t | 17 #include <stddef.h> // ptrdiff_t |
18 | 18 |
19 class SkRBuffer; | 19 class SkRBuffer; |
20 class SkWBuffer; | 20 class SkWBuffer; |
21 | 21 |
22 /** | 22 /** |
23 * Holds the path verbs and points. It is versioned by a generation ID. None of
its public methods | 23 * Holds the path verbs and points. It is versioned by a generation ID. None of
its public methods |
24 * modify the contents. To modify or append to the verbs/points wrap the SkPathR
ef in an | 24 * modify the contents. To modify or append to the verbs/points wrap the SkPathR
ef in an |
25 * SkPathRef::Editor object. Installing the editor resets the generation ID. It
also performs | 25 * SkPathRef::Editor object. Installing the editor resets the generation ID. It
also performs |
26 * copy-on-write if the SkPathRef is shared by multipls SkPaths. The caller pass
es the Editor's | 26 * copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller pass
es the Editor's |
27 * constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef
after the editor's | 27 * constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef
after the editor's |
28 * constructor returns. | 28 * constructor returns. |
29 * | 29 * |
30 * The points and verbs are stored in a single allocation. The points are at the
begining of the | 30 * The points and verbs are stored in a single allocation. The points are at the
begining of the |
31 * allocation while the verbs are stored at end of the allocation, in reverse or
der. Thus the points | 31 * allocation while the verbs are stored at end of the allocation, in reverse or
der. Thus the points |
32 * and verbs both grow into the middle of the allocation until the meet. To acce
ss verb i in the | 32 * and verbs both grow into the middle of the allocation until the meet. To acce
ss verb i in the |
33 * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond
the first | 33 * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond
the first |
34 * logical verb or the last verb in memory). | 34 * logical verb or the last verb in memory). |
35 */ | 35 */ |
36 | 36 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 * uninitialized. | 93 * uninitialized. |
94 */ | 94 */ |
95 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { | 95 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { |
96 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); | 96 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); |
97 } | 97 } |
98 /** | 98 /** |
99 * Gets the path ref that is wrapped in the Editor. | 99 * Gets the path ref that is wrapped in the Editor. |
100 */ | 100 */ |
101 SkPathRef* pathRef() { return fPathRef; } | 101 SkPathRef* pathRef() { return fPathRef; } |
102 | 102 |
| 103 void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); } |
| 104 |
103 private: | 105 private: |
104 SkPathRef* fPathRef; | 106 SkPathRef* fPathRef; |
105 }; | 107 }; |
106 | 108 |
107 public: | 109 public: |
108 /** | 110 /** |
109 * Gets a path ref with no verbs or points. | 111 * Gets a path ref with no verbs or points. |
110 */ | 112 */ |
111 static SkPathRef* CreateEmpty(); | 113 static SkPathRef* CreateEmpty(); |
112 | 114 |
113 /** | 115 /** |
114 * Returns true if all of the points in this path are finite, meaning there | 116 * Returns true if all of the points in this path are finite, meaning there |
115 * are no infinities and no NaNs. | 117 * are no infinities and no NaNs. |
116 */ | 118 */ |
117 bool isFinite() const { | 119 bool isFinite() const { |
118 if (fBoundsIsDirty) { | 120 if (fBoundsIsDirty) { |
119 this->computeBounds(); | 121 this->computeBounds(); |
120 } | 122 } |
121 return SkToBool(fIsFinite); | 123 return SkToBool(fIsFinite); |
122 } | 124 } |
123 | 125 |
| 126 /** Returns true if the path is an oval. |
| 127 * |
| 128 * @param rect returns the bounding rect of this oval. It's a circle |
| 129 * if the height and width are the same. |
| 130 * |
| 131 * @return true if this path is an oval. |
| 132 * Tracking whether a path is an oval is considered an |
| 133 * optimization for performance and so some paths that are in |
| 134 * fact ovals can report false. |
| 135 */ |
| 136 bool isOval(SkRect* rect) const { |
| 137 if (fIsOval && NULL != rect) { |
| 138 *rect = getBounds(); |
| 139 } |
| 140 |
| 141 return SkToBool(fIsOval); |
| 142 } |
| 143 |
124 bool hasComputedBounds() const { | 144 bool hasComputedBounds() const { |
125 return !fBoundsIsDirty; | 145 return !fBoundsIsDirty; |
126 } | 146 } |
127 | 147 |
128 /** Returns the bounds of the path's points. If the path contains 0 or 1 | 148 /** Returns the bounds of the path's points. If the path contains 0 or 1 |
129 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. | 149 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. |
130 Note: this bounds may be larger than the actual shape, since curves | 150 Note: this bounds may be larger than the actual shape, since curves |
131 do not extend as far as their control points. | 151 do not extend as far as their control points. |
132 */ | 152 */ |
133 const SkRect& getBounds() const { | 153 const SkRect& getBounds() const { |
(...skipping 11 matching lines...) Expand all Loading... |
145 } | 165 } |
146 | 166 |
147 /** | 167 /** |
148 * Transforms a path ref by a matrix, allocating a new one only if necessary
. | 168 * Transforms a path ref by a matrix, allocating a new one only if necessary
. |
149 */ | 169 */ |
150 static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, | 170 static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, |
151 const SkPathRef& src, | 171 const SkPathRef& src, |
152 const SkMatrix& matrix); | 172 const SkMatrix& matrix); |
153 | 173 |
154 static SkPathRef* CreateFromBuffer(SkRBuffer* buffer | 174 static SkPathRef* CreateFromBuffer(SkRBuffer* buffer |
155 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O | 175 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O |
156 , bool newFormat, int32_t oldPacked | 176 , bool newFormat, int32_t oldPacked |
157 #endif | 177 #endif |
158 ); | 178 ); |
159 | 179 |
160 /** | 180 /** |
161 * Rollsback a path ref to zero verbs and points with the assumption that th
e path ref will be | 181 * Rollsback a path ref to zero verbs and points with the assumption that th
e path ref will be |
162 * repopulated with approximately the same number of verbs and points. A new
path ref is created | 182 * repopulated with approximately the same number of verbs and points. A new
path ref is created |
163 * only if necessary. | 183 * only if necessary. |
164 */ | 184 */ |
165 static void Rewind(SkAutoTUnref<SkPathRef>* pathRef); | 185 static void Rewind(SkAutoTUnref<SkPathRef>* pathRef); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 /** | 250 /** |
231 * Gets an ID that uniquely identifies the contents of the path ref. If two
path refs have the | 251 * Gets an ID that uniquely identifies the contents of the path ref. If two
path refs have the |
232 * same ID then they have the same verbs and points. However, two path refs
may have the same | 252 * same ID then they have the same verbs and points. However, two path refs
may have the same |
233 * contents but different genIDs. | 253 * contents but different genIDs. |
234 */ | 254 */ |
235 uint32_t genID() const; | 255 uint32_t genID() const; |
236 | 256 |
237 private: | 257 private: |
238 enum SerializationOffsets { | 258 enum SerializationOffsets { |
239 kIsFinite_SerializationShift = 25, // requires 1 bit | 259 kIsFinite_SerializationShift = 25, // requires 1 bit |
| 260 kIsOval_SerializationShift = 24, // requires 1 bit |
240 }; | 261 }; |
241 | 262 |
242 SkPathRef() { | 263 SkPathRef() { |
243 fBoundsIsDirty = true; // this also invalidates fIsFinite | 264 fBoundsIsDirty = true; // this also invalidates fIsFinite |
244 fPointCnt = 0; | 265 fPointCnt = 0; |
245 fVerbCnt = 0; | 266 fVerbCnt = 0; |
246 fVerbs = NULL; | 267 fVerbs = NULL; |
247 fPoints = NULL; | 268 fPoints = NULL; |
248 fFreeSpace = 0; | 269 fFreeSpace = 0; |
249 fGenerationID = kEmptyGenID; | 270 fGenerationID = kEmptyGenID; |
| 271 fIsOval = false; |
250 SkDEBUGCODE(fEditorsAttached = 0;) | 272 SkDEBUGCODE(fEditorsAttached = 0;) |
251 SkDEBUGCODE(this->validate();) | 273 SkDEBUGCODE(this->validate();) |
252 } | 274 } |
253 | 275 |
254 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe
servePoints); | 276 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe
servePoints); |
255 | 277 |
256 // Return true if the computed bounds are finite. | 278 // Return true if the computed bounds are finite. |
257 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { | 279 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { |
258 int count = ref.countPoints(); | 280 int count = ref.countPoints(); |
259 if (count <= 1) { // we ignore just 1 point (moveto) | 281 if (count <= 1) { // we ignore just 1 point (moveto) |
(...skipping 22 matching lines...) Expand all Loading... |
282 } | 304 } |
283 | 305 |
284 /** Resets the path ref with verbCount verbs and pointCount points, all unin
itialized. Also | 306 /** Resets the path ref with verbCount verbs and pointCount points, all unin
itialized. Also |
285 * allocates space for reserveVerb additional verbs and reservePoints addit
ional points.*/ | 307 * allocates space for reserveVerb additional verbs and reservePoints addit
ional points.*/ |
286 void resetToSize(int verbCount, int pointCount, int conicCount, | 308 void resetToSize(int verbCount, int pointCount, int conicCount, |
287 int reserveVerbs = 0, int reservePoints = 0) { | 309 int reserveVerbs = 0, int reservePoints = 0) { |
288 SkDEBUGCODE(this->validate();) | 310 SkDEBUGCODE(this->validate();) |
289 fBoundsIsDirty = true; // this also invalidates fIsFinite | 311 fBoundsIsDirty = true; // this also invalidates fIsFinite |
290 fGenerationID = 0; | 312 fGenerationID = 0; |
291 | 313 |
| 314 fIsOval = false; |
| 315 |
292 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo
unt; | 316 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo
unt; |
293 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r
eservePoints; | 317 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r
eservePoints; |
294 size_t minSize = newSize + newReserve; | 318 size_t minSize = newSize + newReserve; |
295 | 319 |
296 ptrdiff_t sizeDelta = this->currSize() - minSize; | 320 ptrdiff_t sizeDelta = this->currSize() - minSize; |
297 | 321 |
298 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) { | 322 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) { |
299 sk_free(fPoints); | 323 sk_free(fPoints); |
300 fPoints = NULL; | 324 fPoints = NULL; |
301 fVerbs = NULL; | 325 fVerbs = NULL; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(f
Points); | 411 return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(f
Points); |
388 } | 412 } |
389 | 413 |
390 SkDEBUGCODE(void validate() const;) | 414 SkDEBUGCODE(void validate() const;) |
391 | 415 |
392 /** | 416 /** |
393 * Called the first time someone calls CreateEmpty to actually create the si
ngleton. | 417 * Called the first time someone calls CreateEmpty to actually create the si
ngleton. |
394 */ | 418 */ |
395 static void CreateEmptyImpl(SkPathRef** empty); | 419 static void CreateEmptyImpl(SkPathRef** empty); |
396 | 420 |
| 421 void setIsOval(bool isOval) { fIsOval = isOval; } |
| 422 |
397 enum { | 423 enum { |
398 kMinSize = 256, | 424 kMinSize = 256, |
399 }; | 425 }; |
400 | 426 |
401 mutable SkRect fBounds; | 427 mutable SkRect fBounds; |
402 mutable uint8_t fBoundsIsDirty; | 428 mutable uint8_t fBoundsIsDirty; |
403 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid | 429 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid |
| 430 mutable SkBool8 fIsOval; |
404 | 431 |
405 SkPoint* fPoints; // points to begining of the allocation | 432 SkPoint* fPoints; // points to begining of the allocation |
406 uint8_t* fVerbs; // points just past the end of the allocation (v
erbs grow backwards) | 433 uint8_t* fVerbs; // points just past the end of the allocation (v
erbs grow backwards) |
407 int fVerbCnt; | 434 int fVerbCnt; |
408 int fPointCnt; | 435 int fPointCnt; |
409 size_t fFreeSpace; // redundant but saves computation | 436 size_t fFreeSpace; // redundant but saves computation |
410 SkTDArray<SkScalar> fConicWeights; | 437 SkTDArray<SkScalar> fConicWeights; |
411 | 438 |
412 enum { | 439 enum { |
413 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer
o verbs. | 440 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer
o verbs. |
414 }; | 441 }; |
415 mutable uint32_t fGenerationID; | 442 mutable uint32_t fGenerationID; |
416 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use
at any time. | 443 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use
at any time. |
417 | 444 |
418 typedef SkRefCnt INHERITED; | 445 typedef SkRefCnt INHERITED; |
419 }; | 446 }; |
420 | 447 |
421 #endif | 448 #endif |
OLD | NEW |