Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: include/core/SkPathRef.h

Issue 24998004: Move unlikely-to-be-inlined code from SkPathRef.h to SkPathRef.cpp (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/core/SkPathRef.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // TODO: refactor this header to move more of the implementation into the .cpp
23
24 /** 22 /**
25 * 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
26 * 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
27 * 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
28 * 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 multipls SkPaths. The caller pass es the Editor's
29 * 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
30 * constructor returns. 28 * constructor returns.
31 * 29 *
32 * 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
33 * 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
34 * 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
35 * 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
36 * logical verb or the last verb in memory). 34 * logical verb or the last verb in memory).
37 */ 35 */
38 36
39 class SkPathRef : public ::SkRefCnt { 37 class SkPathRef : public ::SkRefCnt {
40 public: 38 public:
41 SK_DECLARE_INST_COUNT(SkPathRef); 39 SK_DECLARE_INST_COUNT(SkPathRef);
42 40
43 class Editor { 41 class Editor {
44 public: 42 public:
45 Editor(SkAutoTUnref<SkPathRef>* pathRef, 43 Editor(SkAutoTUnref<SkPathRef>* pathRef,
46 int incReserveVerbs = 0, 44 int incReserveVerbs = 0,
47 int incReservePoints = 0) 45 int incReservePoints = 0);
48 {
49 if ((*pathRef)->unique()) {
50 (*pathRef)->incReserve(incReserveVerbs, incReservePoints);
51 } else {
52 SkPathRef* copy = SkNEW(SkPathRef);
53 copy->copy(**pathRef, incReserveVerbs, incReservePoints);
54 pathRef->reset(copy);
55 }
56 fPathRef = *pathRef;
57 fPathRef->fGenerationID = 0;
58 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
59 }
60 46
61 ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) } 47 ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) }
62 48
63 /** 49 /**
64 * Returns the array of points. 50 * Returns the array of points.
65 */ 51 */
66 SkPoint* points() { return fPathRef->fPoints; } 52 SkPoint* points() { return fPathRef->fPoints; }
67 53
68 /** 54 /**
69 * Gets the ith point. Shortcut for this->points() + i 55 * Gets the ith point. Shortcut for this->points() + i
70 */ 56 */
71 SkPoint* atPoint(int i) { 57 SkPoint* atPoint(int i) {
72 SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); 58 SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
73 return this->points() + i; 59 return this->points() + i;
74 }; 60 };
75 61
76 /** 62 /**
77 * Adds the verb and allocates space for the number of points indicated by the verb. The 63 * Adds the verb and allocates space for the number of points indicated by the verb. The
78 * return value is a pointer to where the points for the verb should be written. 64 * return value is a pointer to where the points for the verb should be written.
79 */ 65 */
80 SkPoint* growForVerb(int /*SkPath::Verb*/ verb); 66 SkPoint* growForVerb(int /*SkPath::Verb*/ verb) {
67 fPathRef->validate();
68 return fPathRef->growForVerb(verb);
69 }
81 70
82 SkPoint* growForConic(SkScalar w); 71 SkPoint* growForConic(SkScalar w);
83 72
84 /** 73 /**
85 * Allocates space for additional verbs and points and returns pointers to the new verbs and 74 * Allocates space for additional verbs and points and returns pointers to the new verbs and
86 * points. verbs will point one beyond the first new verb (index it usin g [~<i>]). pts points 75 * points. verbs will point one beyond the first new verb (index it usin g [~<i>]). pts points
87 * at the first new point (indexed normally [<i>]). 76 * at the first new point (indexed normally [<i>]).
88 */ 77 */
89 void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) { 78 void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts);
bsalomon 2013/09/27 15:58:51 I somewhat question this one. In release build thi
robertphillips 2013/09/27 16:13:30 Done.
90 SkASSERT(NULL != verbs);
91 SkASSERT(NULL != pts);
92 fPathRef->validate();
93 int oldVerbCnt = fPathRef->fVerbCnt;
94 int oldPointCnt = fPathRef->fPointCnt;
95 SkASSERT(verbs && pts);
96 fPathRef->grow(newVerbs, newPts);
97 *verbs = fPathRef->fVerbs - oldVerbCnt;
98 *pts = fPathRef->fPoints + oldPointCnt;
99 fPathRef->validate();
100 }
101 79
102 /** 80 /**
103 * Resets the path ref to a new verb and point count. The new verbs and points are 81 * Resets the path ref to a new verb and point count. The new verbs and points are
104 * uninitialized. 82 * uninitialized.
105 */ 83 */
106 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { 84 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) {
107 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); 85 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount);
108 } 86 }
109 /** 87 /**
110 * Gets the path ref that is wrapped in the Editor. 88 * Gets the path ref that is wrapped in the Editor.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 fBounds = rect; 137 fBounds = rect;
160 fBoundsIsDirty = false; 138 fBoundsIsDirty = false;
161 fIsFinite = fBounds.isFinite(); 139 fIsFinite = fBounds.isFinite();
162 } 140 }
163 141
164 /** 142 /**
165 * Transforms a path ref by a matrix, allocating a new one only if necessary . 143 * Transforms a path ref by a matrix, allocating a new one only if necessary .
166 */ 144 */
167 static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, 145 static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
168 const SkPathRef& src, 146 const SkPathRef& src,
169 const SkMatrix& matrix) { 147 const SkMatrix& matrix);
170 src.validate();
171 if (matrix.isIdentity()) {
172 if (*dst != &src) {
173 src.ref();
174 dst->reset(const_cast<SkPathRef*>(&src));
175 (*dst)->validate();
176 }
177 return;
178 }
179
180 bool dstUnique = (*dst)->unique();
181 if (!dstUnique) {
182 dst->reset(SkNEW(SkPathRef));
183 (*dst)->resetToSize(src.fVerbCnt, src.fPointCnt, src.fConicWeights.c ount());
184 memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(), src.fVerbCnt * sizeof(uint8_t));
185 (*dst)->fConicWeights = src.fConicWeights;
186 }
187
188 // Need to check this here in case (&src == dst)
189 bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && s rc.countPoints() > 1;
190
191 matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt);
192
193 /*
194 * Here we optimize the bounds computation, by noting if the bounds are
195 * already known, and if so, we just transform those as well and mark
196 * them as "known", rather than force the transformed path to have to
197 * recompute them.
198 *
199 * Special gotchas if the path is effectively empty (<= 1 point) or
200 * if it is non-finite. In those cases bounds need to stay empty,
201 * regardless of the matrix.
202 */
203 if (canXformBounds) {
204 (*dst)->fBoundsIsDirty = false;
205 if (src.fIsFinite) {
206 matrix.mapRect(&(*dst)->fBounds, src.fBounds);
207 if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) {
208 (*dst)->fBounds.setEmpty();
209 }
210 } else {
211 (*dst)->fIsFinite = false;
212 (*dst)->fBounds.setEmpty();
213 }
214 } else {
215 (*dst)->fBoundsIsDirty = true;
216 }
217
218 (*dst)->validate();
219 }
220 148
221 static SkPathRef* CreateFromBuffer(SkRBuffer* buffer 149 static SkPathRef* CreateFromBuffer(SkRBuffer* buffer
222 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO O 150 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO O
223 , bool newFormat, int32_t oldPacked 151 , bool newFormat, int32_t oldPacked
224 #endif 152 #endif
225 ); 153 );
226 154
227 /** 155 /**
228 * Rollsback a path ref to zero verbs and points with the assumption that th e path ref will be 156 * Rollsback a path ref to zero verbs and points with the assumption that th e path ref will be
229 * repopulated with approximately the same number of verbs and points. A new path ref is created 157 * repopulated with approximately the same number of verbs and points. A new path ref is created
230 * only if necessary. 158 * only if necessary.
231 */ 159 */
232 static void Rewind(SkAutoTUnref<SkPathRef>* pathRef) { 160 static void Rewind(SkAutoTUnref<SkPathRef>* pathRef);
233 if ((*pathRef)->unique()) {
234 (*pathRef)->validate();
235 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFini te
236 (*pathRef)->fVerbCnt = 0;
237 (*pathRef)->fPointCnt = 0;
238 (*pathRef)->fFreeSpace = (*pathRef)->currSize();
239 (*pathRef)->fGenerationID = 0;
240 (*pathRef)->fConicWeights.rewind();
241 (*pathRef)->validate();
242 } else {
243 int oldVCnt = (*pathRef)->countVerbs();
244 int oldPCnt = (*pathRef)->countPoints();
245 pathRef->reset(SkNEW(SkPathRef));
246 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
247 }
248 }
249 161
250 virtual ~SkPathRef() { 162 virtual ~SkPathRef() {
251 this->validate(); 163 this->validate();
252 sk_free(fPoints); 164 sk_free(fPoints);
253 165
254 SkDEBUGCODE(fPoints = NULL;) 166 SkDEBUGCODE(fPoints = NULL;)
255 SkDEBUGCODE(fVerbs = NULL;) 167 SkDEBUGCODE(fVerbs = NULL;)
256 SkDEBUGCODE(fVerbCnt = 0x9999999;) 168 SkDEBUGCODE(fVerbCnt = 0x9999999;)
257 SkDEBUGCODE(fPointCnt = 0xAAAAAAA;) 169 SkDEBUGCODE(fPointCnt = 0xAAAAAAA;)
258 SkDEBUGCODE(fPointCnt = 0xBBBBBBB;) 170 SkDEBUGCODE(fPointCnt = 0xBBBBBBB;)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 */ 203 */
292 uint8_t atVerb(int index) { 204 uint8_t atVerb(int index) {
293 SkASSERT((unsigned) index < (unsigned) fVerbCnt); 205 SkASSERT((unsigned) index < (unsigned) fVerbCnt);
294 return this->verbs()[~index]; 206 return this->verbs()[~index];
295 } 207 }
296 const SkPoint& atPoint(int index) const { 208 const SkPoint& atPoint(int index) const {
297 SkASSERT((unsigned) index < (unsigned) fPointCnt); 209 SkASSERT((unsigned) index < (unsigned) fPointCnt);
298 return this->points()[index]; 210 return this->points()[index];
299 } 211 }
300 212
301 bool operator== (const SkPathRef& ref) const { 213 bool operator== (const SkPathRef& ref) const;
302 this->validate();
303 ref.validate();
304 bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
305 #ifdef SK_RELEASE
306 if (genIDMatch) {
307 return true;
308 }
309 #endif
310 if (fPointCnt != ref.fPointCnt ||
311 fVerbCnt != ref.fVerbCnt) {
312 SkASSERT(!genIDMatch);
313 return false;
314 }
315 if (0 != memcmp(this->verbsMemBegin(),
316 ref.verbsMemBegin(),
317 ref.fVerbCnt * sizeof(uint8_t))) {
318 SkASSERT(!genIDMatch);
319 return false;
320 }
321 if (0 != memcmp(this->points(),
322 ref.points(),
323 ref.fPointCnt * sizeof(SkPoint))) {
324 SkASSERT(!genIDMatch);
325 return false;
326 }
327 if (fConicWeights != ref.fConicWeights) {
328 SkASSERT(!genIDMatch);
329 return false;
330 }
331 // We've done the work to determine that these are equal. If either has a zero genID, copy
332 // the other's. If both are 0 then genID() will compute the next ID.
333 if (0 == fGenerationID) {
334 fGenerationID = ref.genID();
335 } else if (0 == ref.fGenerationID) {
336 ref.fGenerationID = this->genID();
337 }
338 return true;
339 }
340 214
341 /** 215 /**
342 * Writes the path points and verbs to a buffer. 216 * Writes the path points and verbs to a buffer.
343 */ 217 */
344 void writeToBuffer(SkWBuffer* buffer); 218 void writeToBuffer(SkWBuffer* buffer);
345 219
346 /** 220 /**
347 * Gets the number of bytes that would be written in writeBuffer() 221 * Gets the number of bytes that would be written in writeBuffer()
348 */ 222 */
349 uint32_t writeSize() { 223 uint32_t writeSize();
350 return uint32_t(5 * sizeof(uint32_t) +
351 fVerbCnt * sizeof(uint8_t) +
352 fPointCnt * sizeof(SkPoint) +
353 fConicWeights.bytes() +
354 sizeof(SkRect));
355 }
356 224
357 private: 225 private:
358 enum SerializationOffsets { 226 enum SerializationOffsets {
359 kIsFinite_SerializationShift = 25, // requires 1 bit 227 kIsFinite_SerializationShift = 25, // requires 1 bit
360 }; 228 };
361 229
362 SkPathRef() { 230 SkPathRef() {
363 fBoundsIsDirty = true; // this also invalidates fIsFinite 231 fBoundsIsDirty = true; // this also invalidates fIsFinite
364 fPointCnt = 0; 232 fPointCnt = 0;
365 fVerbCnt = 0; 233 fVerbCnt = 0;
366 fVerbs = NULL; 234 fVerbs = NULL;
367 fPoints = NULL; 235 fPoints = NULL;
368 fFreeSpace = 0; 236 fFreeSpace = 0;
369 fGenerationID = kEmptyGenID; 237 fGenerationID = kEmptyGenID;
370 SkDEBUGCODE(fEditorsAttached = 0;) 238 SkDEBUGCODE(fEditorsAttached = 0;)
371 this->validate(); 239 this->validate();
372 } 240 }
373 241
374 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe servePoints) { 242 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe servePoints);
375 this->validate();
376 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count() ,
377 additionalReserveVerbs, additionalReservePoints);
378 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * siz eof(uint8_t));
379 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint));
380 fConicWeights = ref.fConicWeights;
381 // We could call genID() here to force a real ID (instead of 0). However , if we're making
382 // a copy then presumably we intend to make a modification immediately a fterwards.
383 fGenerationID = ref.fGenerationID;
384 fBoundsIsDirty = ref.fBoundsIsDirty;
385 if (!fBoundsIsDirty) {
386 fBounds = ref.fBounds;
387 fIsFinite = ref.fIsFinite;
388 }
389 this->validate();
390 }
391 243
392 // Return true if the computed bounds are finite. 244 // Return true if the computed bounds are finite.
393 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { 245 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) {
394 int count = ref.countPoints(); 246 int count = ref.countPoints();
395 if (count <= 1) { // we ignore just 1 point (moveto) 247 if (count <= 1) { // we ignore just 1 point (moveto)
396 bounds->setEmpty(); 248 bounds->setEmpty();
397 return count ? ref.points()->isFinite() : true; 249 return count ? ref.points()->isFinite() : true;
398 } else { 250 } else {
399 return bounds->setBoundsCheck(ref.points(), count); 251 return bounds->setBoundsCheck(ref.points(), count);
400 } 252 }
(...skipping 12 matching lines...) Expand all
413 void incReserve(int additionalVerbs, int additionalPoints) { 265 void incReserve(int additionalVerbs, int additionalPoints) {
414 this->validate(); 266 this->validate();
415 size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * si zeof (SkPoint); 267 size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * si zeof (SkPoint);
416 this->makeSpace(space); 268 this->makeSpace(space);
417 this->validate(); 269 this->validate();
418 } 270 }
419 271
420 /** Resets the path ref with verbCount verbs and pointCount points, all unin itialized. Also 272 /** Resets the path ref with verbCount verbs and pointCount points, all unin itialized. Also
421 * allocates space for reserveVerb additional verbs and reservePoints addit ional points.*/ 273 * allocates space for reserveVerb additional verbs and reservePoints addit ional points.*/
422 void resetToSize(int verbCount, int pointCount, int conicCount, 274 void resetToSize(int verbCount, int pointCount, int conicCount,
423 int reserveVerbs = 0, int reservePoints = 0) { 275 int reserveVerbs = 0, int reservePoints = 0);
424 this->validate();
425 fBoundsIsDirty = true; // this also invalidates fIsFinite
426 fGenerationID = 0;
427
428 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo unt;
429 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r eservePoints;
430 size_t minSize = newSize + newReserve;
431
432 ptrdiff_t sizeDelta = this->currSize() - minSize;
433
434 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) {
435 sk_free(fPoints);
436 fPoints = NULL;
437 fVerbs = NULL;
438 fFreeSpace = 0;
439 fVerbCnt = 0;
440 fPointCnt = 0;
441 this->makeSpace(minSize);
442 fVerbCnt = verbCount;
443 fPointCnt = pointCount;
444 fFreeSpace -= newSize;
445 } else {
446 fPointCnt = pointCount;
447 fVerbCnt = verbCount;
448 fFreeSpace = this->currSize() - minSize;
449 }
450 fConicWeights.setCount(conicCount);
451 this->validate();
452 }
453 276
454 /** 277 /**
455 * Increases the verb count by newVerbs and the point count be newPoints. Ne w verbs and points 278 * Increases the verb count by newVerbs and the point count be newPoints. Ne w verbs and points
456 * are uninitialized. 279 * are uninitialized.
457 */ 280 */
458 void grow(int newVerbs, int newPoints) { 281 void grow(int newVerbs, int newPoints);
459 this->validate();
460 size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint) ;
bsalomon 2013/09/27 15:58:51 also wondering about this one.
robertphillips 2013/09/27 16:13:30 Done.
461 this->makeSpace(space);
462 fVerbCnt += newVerbs;
463 fPointCnt += newPoints;
464 fFreeSpace -= space;
465 fBoundsIsDirty = true; // this also invalidates fIsFinite
466 this->validate();
467 }
468 282
469 /** 283 /**
470 * Increases the verb count 1, records the new verb, and creates room for th e requisite number 284 * Increases the verb count 1, records the new verb, and creates room for th e requisite number
471 * of additional points. A pointer to the first point is returned. Any new p oints are 285 * of additional points. A pointer to the first point is returned. Any new p oints are
472 * uninitialized. 286 * uninitialized.
473 */ 287 */
474 SkPoint* growForVerb(int /*SkPath::Verb*/ verb); 288 SkPoint* growForVerb(int /*SkPath::Verb*/ verb);
475 289
476 /** 290 /**
477 * Ensures that the free space available in the path ref is >= size. The ver b and point counts 291 * Ensures that the free space available in the path ref is >= size. The ver b and point counts
478 * are not changed. 292 * are not changed.
479 */ 293 */
480 void makeSpace(size_t size) { 294 void makeSpace(size_t size);
481 this->validate();
482 ptrdiff_t growSize = size - fFreeSpace;
483 if (growSize <= 0) {
484 return;
485 }
486 size_t oldSize = this->currSize();
487 // round to next multiple of 8 bytes
488 growSize = (growSize + 7) & ~static_cast<size_t>(7);
489 // we always at least double the allocation
490 if (static_cast<size_t>(growSize) < oldSize) {
491 growSize = oldSize;
492 }
493 if (growSize < kMinSize) {
494 growSize = kMinSize;
495 }
496 size_t newSize = oldSize + growSize;
497 // Note that realloc could memcpy more than we need. It seems to be a wi n anyway. TODO:
498 // encapsulate this.
499 fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize)) ;
500 size_t oldVerbSize = fVerbCnt * sizeof(uint8_t);
501 void* newVerbsDst = reinterpret_cast<void*>(
502 reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize);
503 void* oldVerbsSrc = reinterpret_cast<void*>(
504 reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize);
505 memmove(newVerbsDst, oldVerbsSrc, oldVerbSize);
506 fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize);
507 fFreeSpace += growSize;
508 this->validate();
509 }
510 295
511 /** 296 /**
512 * Private, non-const-ptr version of the public function verbsMemBegin(). 297 * Private, non-const-ptr version of the public function verbsMemBegin().
513 */ 298 */
514 uint8_t* verbsMemWritable() { 299 uint8_t* verbsMemWritable() {
515 this->validate(); 300 this->validate();
516 return fVerbs - fVerbCnt; 301 return fVerbs - fVerbCnt;
517 } 302 }
518 303
519 /** 304 /**
520 * Gets the total amount of space allocated for verbs, points, and reserve. 305 * Gets the total amount of space allocated for verbs, points, and reserve.
521 */ 306 */
522 size_t currSize() const { 307 size_t currSize() const {
523 return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(f Points); 308 return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(f Points);
524 } 309 }
525 310
526 /** 311 /**
527 * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the 312 * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
528 * same ID then they have the same verbs and points. However, two path refs may have the same 313 * same ID then they have the same verbs and points. However, two path refs may have the same
529 * contents but different genIDs. Zero is reserved and means an ID has not y et been determined 314 * contents but different genIDs. Zero is reserved and means an ID has not y et been determined
530 * for the path ref. 315 * for the path ref.
531 */ 316 */
532 int32_t genID() const { 317 int32_t genID() const;
533 SkASSERT(!fEditorsAttached);
534 if (!fGenerationID) {
535 if (0 == fPointCnt && 0 == fVerbCnt) {
536 fGenerationID = kEmptyGenID;
537 } else {
538 static int32_t gPathRefGenerationID;
539 // do a loop in case our global wraps around, as we never want t o return a 0 or the
540 // empty ID
541 do {
542 fGenerationID = sk_atomic_inc(&gPathRefGenerationID) + 1;
543 } while (fGenerationID <= kEmptyGenID);
544 }
545 }
546 return fGenerationID;
547 }
548 318
549 void validate() const { 319 void validate() const;
550 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0);
551 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t> (fPoints) >= 0);
552 SkASSERT((NULL == fPoints) == (NULL == fVerbs));
553 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace));
554 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace));
555 SkASSERT(!(NULL == fPoints && fPointCnt));
556 SkASSERT(!(NULL == fVerbs && fVerbCnt));
557 SkASSERT(this->currSize() ==
558 fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fV erbCnt);
559
560 #ifdef SK_DEBUG
561 if (!fBoundsIsDirty && !fBounds.isEmpty()) {
562 bool isFinite = true;
563 for (int i = 0; i < fPointCnt; ++i) {
564 SkASSERT(fPoints[i].fX >= fBounds.fLeft && fPoints[i].fX <= fBou nds.fRight &&
565 fPoints[i].fY >= fBounds.fTop && fPoints[i].fY <= fBoun ds.fBottom);
566 if (!fPoints[i].isFinite()) {
567 isFinite = false;
568 }
569 }
570 SkASSERT(SkToBool(fIsFinite) == isFinite);
571 }
572 #endif
573 }
574 320
575 enum { 321 enum {
576 kMinSize = 256, 322 kMinSize = 256,
577 }; 323 };
578 324
579 mutable SkRect fBounds; 325 mutable SkRect fBounds;
580 mutable uint8_t fBoundsIsDirty; 326 mutable uint8_t fBoundsIsDirty;
581 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid 327 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
582 328
583 SkPoint* fPoints; // points to begining of the allocation 329 SkPoint* fPoints; // points to begining of the allocation
584 uint8_t* fVerbs; // points just past the end of the allocation (v erbs grow backwards) 330 uint8_t* fVerbs; // points just past the end of the allocation (v erbs grow backwards)
585 int fVerbCnt; 331 int fVerbCnt;
586 int fPointCnt; 332 int fPointCnt;
587 size_t fFreeSpace; // redundant but saves computation 333 size_t fFreeSpace; // redundant but saves computation
588 SkTDArray<SkScalar> fConicWeights; 334 SkTDArray<SkScalar> fConicWeights;
589 335
590 enum { 336 enum {
591 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer o verbs. 337 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer o verbs.
592 }; 338 };
593 mutable int32_t fGenerationID; 339 mutable int32_t fGenerationID;
594 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time. 340 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time.
595 341
596 typedef SkRefCnt INHERITED; 342 typedef SkRefCnt INHERITED;
597 }; 343 };
598 344
599 #endif 345 #endif
OLDNEW
« no previous file with comments | « no previous file | src/core/SkPathRef.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698