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

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

Issue 25787002: Move more of SkPath into SkPathRef (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: cleaned up 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
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 /** 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
37 class SK_API SkPathRef : public ::SkRefCnt { 37 class SK_API SkPathRef : public ::SkRefCnt {
38 public: 38 public:
39 SK_DECLARE_INST_COUNT(SkPathRef); 39 SK_DECLARE_INST_COUNT(SkPathRef);
40 40
41 enum Verb {
42 kMove_Verb, //!< iter.next returns 1 point
43 kLine_Verb, //!< iter.next returns 2 points
44 kQuad_Verb, //!< iter.next returns 3 points
45 kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight()
46 kCubic_Verb, //!< iter.next returns 4 points
47 kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt)
48 kDone_Verb, //!< iter.next returns 0 points
49 };
50
41 class Editor { 51 class Editor {
42 public: 52 public:
43 Editor(SkAutoTUnref<SkPathRef>* pathRef, 53 Editor(SkAutoTUnref<SkPathRef>* pathRef,
44 int incReserveVerbs = 0, 54 int incReserveVerbs = 0,
45 int incReservePoints = 0); 55 int incReservePoints = 0);
46 56
47 ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) } 57 ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) }
48 58
49 /** 59 /**
50 * Returns the array of points. 60 * Returns the array of points.
51 */ 61 */
52 SkPoint* points() { return fPathRef->fPoints; } 62 SkPoint* points() { return fPathRef->fPoints; }
53 63
54 /** 64 /**
55 * Gets the ith point. Shortcut for this->points() + i 65 * Gets the ith point. Shortcut for this->points() + i
56 */ 66 */
57 SkPoint* atPoint(int i) { 67 SkPoint* atPoint(int i) {
58 SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); 68 SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
59 return this->points() + i; 69 return this->points() + i;
60 }; 70 };
61 71
62 /** 72 /**
63 * Adds the verb and allocates space for the number of points indicated by the verb. The 73 * Adds the verb and allocates space for the number of points indicated by the verb. The
64 * return value is a pointer to where the points for the verb should be written. 74 * return value is a pointer to where the points for the verb should be written.
65 */ 75 */
66 SkPoint* growForVerb(int /*SkPath::Verb*/ verb) { 76 SkPoint* growForVerb(Verb verb) {
67 SkDEBUGCODE(fPathRef->validate();) 77 SkDEBUGCODE(fPathRef->validate();)
68 return fPathRef->growForVerb(verb); 78 return fPathRef->growForVerb(verb);
69 } 79 }
70 80
71 SkPoint* growForConic(SkScalar w); 81 SkPoint* growForConic(SkScalar w) {
72 82 SkDEBUGCODE(fPathRef->validate();)
83 SkPoint* pts = fPathRef->growForVerb(kConic_Verb);
84 *fPathRef->fConicWeights.append() = w;
85 return pts;
86 }
73 /** 87 /**
74 * Allocates space for additional verbs and points and returns pointers to the new verbs and 88 * Allocates space for additional lines and returns a pointer to the new
75 * points. verbs will point one beyond the first new verb (index it usin g [~<i>]). pts points 89 * points. The return pointer points at the first new point (indexed nor mally [<i>]).
76 * at the first new point (indexed normally [<i>]).
77 */ 90 */
78 void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) { 91 SkPoint* growForLines(int numLines) {
79 SkASSERT(NULL != verbs);
80 SkASSERT(NULL != pts);
81 SkDEBUGCODE(fPathRef->validate();) 92 SkDEBUGCODE(fPathRef->validate();)
82 int oldVerbCnt = fPathRef->fVerbCnt; 93 return fPathRef->growForLines(numLines);
83 int oldPointCnt = fPathRef->fPointCnt;
84 SkASSERT(verbs && pts);
85 fPathRef->grow(newVerbs, newPts);
86 *verbs = fPathRef->fVerbs - oldVerbCnt;
87 *pts = fPathRef->fPoints + oldPointCnt;
88 SkDEBUGCODE(fPathRef->validate();)
89 } 94 }
90 95
91 /** 96 /**
92 * Resets the path ref to a new verb and point count. The new verbs and points are 97 * Resets the path ref to a new verb and point count. The new verbs and points are
93 * uninitialized. 98 * uninitialized.
94 */ 99 */
95 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { 100 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) {
96 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); 101 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount);
97 } 102 }
103
98 /** 104 /**
99 * Gets the path ref that is wrapped in the Editor. 105 * Gets the path ref that is wrapped in the Editor.
100 */ 106 */
101 SkPathRef* pathRef() { return fPathRef; } 107 SkPathRef* pathRef() { return fPathRef; }
102 108
103 private: 109 private:
104 SkPathRef* fPathRef; 110 SkPathRef* fPathRef;
105 }; 111 };
106 112
107 public: 113 public:
108 /** 114 /**
109 * Gets a path ref with no verbs or points. 115 * Gets a path ref with no verbs or points.
110 */ 116 */
111 static SkPathRef* CreateEmpty() { 117 static SkPathRef* CreateEmpty() {
112 static SkPathRef* gEmptyPathRef; 118 static SkPathRef* gEmptyPathRef;
113 if (!gEmptyPathRef) { 119 if (!gEmptyPathRef) {
114 gEmptyPathRef = SkNEW(SkPathRef); // leak! 120 gEmptyPathRef = SkNEW(SkPathRef); // leak!
115 gEmptyPathRef->computeBounds(); // Premptively avoid a race to cle ar fBoundsIsDirty. 121 gEmptyPathRef->computeBounds(); // Premptively avoid a race to cle ar fBoundsIsDirty.
116 } 122 }
117 return SkRef(gEmptyPathRef); 123 return SkRef(gEmptyPathRef);
118 } 124 }
119 125
126 enum Direction {
127 /** Direction either has not been or could not be computed */
128 kUnknown_Direction,
129 /** clockwise direction for adding closed contours */
130 kCW_Direction,
131 /** counter-clockwise direction for adding closed contours */
132 kCCW_Direction,
133 };
134
135 /**
136 * Return the opposite of the specified direction. kUnknown is its own
137 * opposite.
138 */
139 static Direction OppositeDirection(Direction dir) {
140 static const Direction gOppositeDir[] = {
141 kUnknown_Direction,
142 kCCW_Direction,
143 kCW_Direction
144 };
145 return gOppositeDir[dir];
146 }
147
148 Direction getDirection() const { return (Direction) fDirection; }
149
150 enum Convexity {
151 kUnknown_Convexity,
152 kConvex_Convexity,
153 kConcave_Convexity
154 };
155
156 /**
157 * Return the path's convexity, as stored in the path. If it is currently u nknown,
158 * then this function will attempt to compute the convexity (and cache the result).
159 */
160 Convexity getConvexity() const {
161 if (kUnknown_Convexity != fConvexity) {
162 return static_cast<Convexity>(fConvexity);
163 } else {
164 return this->internalGetConvexity();
165 }
166 }
167
168 /**
169 * Return the currently cached value for convexity, even if that is set to
170 * kUnknown_Convexity. Note: getConvexity() will automatically call
171 * ComputeConvexity and cache its return value if the current setting is
172 * kUnknown.
173 */
174 Convexity getConvexityOrUnknown() const {
175 return (Convexity) fConvexity;
176 }
177
178 /**
179 * Store a convexity setting in the path. There is no automatic check to
180 * see if this value actually agrees with the return value that would be
181 * computed by getConvexity().
182 *
183 * Note: even if this is set to a "known" value, if the path is later
184 * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
185 * reset to kUnknown_Convexity.
186 */
187 void setConvexity(Convexity convexity) {
188 fConvexity = convexity;
189 }
190
191 /** Returns true if the path is an oval.
192 *
193 * @param rect returns the bounding rect of this oval. It's a circle
194 * if the height and width are the same.
195 *
196 * @return true if this path is an oval.
197 * Tracking whether a path is an oval is considered an
198 * optimization for performance and so some paths that are in
199 * fact ovals can report false.
200 */
201 bool isOval(SkRect* rect) const {
202 if (fIsOval && NULL != rect) {
203 *rect = this->getBounds();
204 }
205 return SkToBool(fIsOval);
206 }
207
120 /** 208 /**
121 * Returns true if all of the points in this path are finite, meaning there 209 * Returns true if all of the points in this path are finite, meaning there
122 * are no infinities and no NaNs. 210 * are no infinities and no NaNs.
123 */ 211 */
124 bool isFinite() const { 212 bool isFinite() const {
125 if (fBoundsIsDirty) { 213 if (fBoundsIsDirty) {
126 this->computeBounds(); 214 this->computeBounds();
127 } 215 }
128 return SkToBool(fIsFinite); 216 return SkToBool(fIsFinite);
129 } 217 }
130 218
219 enum SegmentMask {
220 kLine_SegmentMask = 1 << 0,
221 kQuad_SegmentMask = 1 << 1,
222 kConic_SegmentMask = 1 << 2,
223 kCubic_SegmentMask = 1 << 3,
224 };
225
226 /**
227 * Returns a mask, where each bit corresponding to a SegmentMask is
228 * set if the path contains 1 or more segments of that type.
229 * Returns 0 for an empty path (no segments).
230 */
231 uint32_t getSegmentMasks() const { return fSegmentMask; }
232
131 bool hasComputedBounds() const { 233 bool hasComputedBounds() const {
132 return !fBoundsIsDirty; 234 return !fBoundsIsDirty;
133 } 235 }
134 236
135 /** Returns the bounds of the path's points. If the path contains 0 or 1 237 /** Returns the bounds of the path's points. If the path contains 0 or 1
136 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. 238 points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
137 Note: this bounds may be larger than the actual shape, since curves 239 Note: this bounds may be larger than the actual shape, since curves
138 do not extend as far as their control points. 240 do not extend as far as their control points.
139 */ 241 */
140 const SkRect& getBounds() const { 242 const SkRect& getBounds() const {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 */ 331 */
230 void writeToBuffer(SkWBuffer* buffer); 332 void writeToBuffer(SkWBuffer* buffer);
231 333
232 /** 334 /**
233 * Gets the number of bytes that would be written in writeBuffer() 335 * Gets the number of bytes that would be written in writeBuffer()
234 */ 336 */
235 uint32_t writeSize(); 337 uint32_t writeSize();
236 338
237 private: 339 private:
238 enum SerializationOffsets { 340 enum SerializationOffsets {
341 kDirection_SerializationShift = 26, // requires 2 bits
239 kIsFinite_SerializationShift = 25, // requires 1 bit 342 kIsFinite_SerializationShift = 25, // requires 1 bit
343 kIsOval_SerializationShift = 24, // requires 1 bit
344 kConvexity_SerializationShift = 16, // requires 8 bits
345 // FillType (in SkPath) takes up 8
346 kSegmentMask_SerializationShift = 0 // requires 4 bits
240 }; 347 };
241 348
349 // flag to require a moveTo if we begin with something else, like lineTo etc .
350 static const int kINITIAL_LASTMOVETOINDEX_VALUE = ~0;
351
242 SkPathRef() { 352 SkPathRef() {
243 fBoundsIsDirty = true; // this also invalidates fIsFinite 353 fBoundsIsDirty = true; // this also invalidates fIsFinite
244 fPointCnt = 0; 354 fPointCnt = 0;
245 fVerbCnt = 0; 355 fVerbCnt = 0;
246 fVerbs = NULL; 356 fVerbs = NULL;
247 fPoints = NULL; 357 fPoints = NULL;
248 fFreeSpace = 0; 358 fFreeSpace = 0;
249 fGenerationID = kEmptyGenID; 359 fGenerationID = kEmptyGenID;
250 SkDEBUGCODE(fEditorsAttached = 0;) 360 SkDEBUGCODE(fEditorsAttached = 0;)
361 fLastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE;
362 fSegmentMask = 0;
363 fConvexity = kUnknown_Convexity;
364 fDirection = kUnknown_Direction;
365 fIsOval = false;
251 SkDEBUGCODE(this->validate();) 366 SkDEBUGCODE(this->validate();)
252 } 367 }
253 368
254 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe servePoints); 369 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe servePoints);
255 370
256 // Return true if the computed bounds are finite. 371 // Return true if the computed bounds are finite.
257 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { 372 static bool ComputePtBounds(SkRect* bounds, const SkPoint* points, int count ) {
258 int count = ref.countPoints();
259 if (count <= 1) { // we ignore just 1 point (moveto) 373 if (count <= 1) { // we ignore just 1 point (moveto)
260 bounds->setEmpty(); 374 bounds->setEmpty();
261 return count ? ref.points()->isFinite() : true; 375 return count ? points->isFinite() : true;
262 } else { 376 } else {
263 return bounds->setBoundsCheck(ref.points(), count); 377 return bounds->setBoundsCheck(points, count);
264 } 378 }
265 } 379 }
266 380
267 // called, if dirty, by getBounds() 381 // called, if dirty, by getBounds()
268 void computeBounds() const { 382 void computeBounds() const {
269 SkDEBUGCODE(this->validate();) 383 SkDEBUGCODE(this->validate();)
270 SkASSERT(fBoundsIsDirty); 384 SkASSERT(fBoundsIsDirty);
271 385
272 fIsFinite = ComputePtBounds(&fBounds, *this); 386 fIsFinite = ComputePtBounds(&fBounds, this->points(), this->countPoints( ));
273 fBoundsIsDirty = false; 387 fBoundsIsDirty = false;
274 } 388 }
275 389
276 /** Makes additional room but does not change the counts or change the genID */ 390 /** Makes additional room but does not change the counts or change the genID */
277 void incReserve(int additionalVerbs, int additionalPoints) { 391 void incReserve(int additionalVerbs, int additionalPoints) {
278 SkDEBUGCODE(this->validate();) 392 SkDEBUGCODE(this->validate();)
279 size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * si zeof (SkPoint); 393 size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * si zeof (SkPoint);
280 this->makeSpace(space); 394 this->makeSpace(space);
281 SkDEBUGCODE(this->validate();) 395 SkDEBUGCODE(this->validate();)
282 } 396 }
283 397
284 /** Resets the path ref with verbCount verbs and pointCount points, all unin itialized. Also 398 /** 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.*/ 399 * allocates space for reserveVerb additional verbs and reservePoints addit ional points.*/
286 void resetToSize(int verbCount, int pointCount, int conicCount, 400 void resetToSize(int verbCount, int pointCount, int conicCount,
287 int reserveVerbs = 0, int reservePoints = 0) { 401 int reserveVerbs = 0, int reservePoints = 0) {
288 SkDEBUGCODE(this->validate();) 402 SkDEBUGCODE(this->validate();)
289 fBoundsIsDirty = true; // this also invalidates fIsFinite 403 fBoundsIsDirty = true; // this also invalidates fIsFinite
290 fGenerationID = 0; 404 fGenerationID = 0;
291 405
406 fLastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE;
407 fSegmentMask = 0;
408 fConvexity = kUnknown_Convexity;
409 fDirection = kUnknown_Direction;
410 fIsOval = false;
411
292 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo unt; 412 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo unt;
293 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r eservePoints; 413 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r eservePoints;
294 size_t minSize = newSize + newReserve; 414 size_t minSize = newSize + newReserve;
295 415
296 ptrdiff_t sizeDelta = this->currSize() - minSize; 416 ptrdiff_t sizeDelta = this->currSize() - minSize;
297 417
298 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) { 418 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) {
299 sk_free(fPoints); 419 sk_free(fPoints);
300 fPoints = NULL; 420 fPoints = NULL;
301 fVerbs = NULL; 421 fVerbs = NULL;
302 fFreeSpace = 0; 422 fFreeSpace = 0;
303 fVerbCnt = 0; 423 fVerbCnt = 0;
304 fPointCnt = 0; 424 fPointCnt = 0;
305 this->makeSpace(minSize); 425 this->makeSpace(minSize);
306 fVerbCnt = verbCount; 426 fVerbCnt = verbCount;
307 fPointCnt = pointCount; 427 fPointCnt = pointCount;
308 fFreeSpace -= newSize; 428 fFreeSpace -= newSize;
309 } else { 429 } else {
310 fPointCnt = pointCount; 430 fPointCnt = pointCount;
311 fVerbCnt = verbCount; 431 fVerbCnt = verbCount;
312 fFreeSpace = this->currSize() - minSize; 432 fFreeSpace = this->currSize() - minSize;
313 } 433 }
314 fConicWeights.setCount(conicCount); 434 fConicWeights.setCount(conicCount);
315 SkDEBUGCODE(this->validate();) 435 SkDEBUGCODE(this->validate();)
316 } 436 }
317 437
438 // This method assumes space has already been allocated for the new
439 // verb and point.
440 void injectMove() {
441 SkScalar x, y;
442 if (this->countVerbs() == 0) {
443 x = y = 0;
444 } else {
445 const SkPoint& pt = this->atPoint(~fLastMoveToIndex);
446 x = pt.fX;
447 y = pt.fY;
448 }
449 fPoints[fPointCnt].set(x, y);
450 fLastMoveToIndex = fPointCnt;
451 ++fPointCnt;
452 fVerbs[~fVerbCnt] = kMove_Verb;
453 ++fVerbCnt;
454 }
455
456
318 /** 457 /**
319 * Increases the verb count by newVerbs and the point count be newPoints. Ne w verbs and points 458 * Increases the verb and point count by numLines. The new points
320 * are uninitialized. 459 * are uninitialized. All the new verbs are set to kLine_SegmentMask.
321 */ 460 */
322 void grow(int newVerbs, int newPoints) { 461 SkPoint* growForLines(int numLines) {
462 // This value is just made-up for now. When numLines is 3, calling memse t was much
463 // slower than just writing the loop. This seems odd, and hopefully in t he
464 // future this will appear to have been a fluke...
465 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
466
467 // TODO: The following isn't hyper-optimized for the lines case since
468 // it should be expanded to handle quads, conics and cubics
323 SkDEBUGCODE(this->validate();) 469 SkDEBUGCODE(this->validate();)
324 size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint) ; 470 bool dirtyAfterEdit = true;
471 bool moveInjectionNeeded = false;
472
473 moveInjectionNeeded = fLastMoveToIndex < 0;
474
475 size_t space = numLines * sizeof(uint8_t) + numLines * sizeof (SkPoint);
476 if (moveInjectionNeeded) {
477 space += sizeof(uint8_t) + sizeof(SkPoint);
478 }
325 this->makeSpace(space); 479 this->makeSpace(space);
326 fVerbCnt += newVerbs; 480 if (moveInjectionNeeded) {
327 fPointCnt += newPoints; 481 SkASSERT(dirtyAfterEdit);
482 this->injectMove();
483 }
484 SkPoint* ret = fPoints + fPointCnt;
485 uint8_t* vb = fVerbs - fVerbCnt;
486
487 // cast to unsigned, so if MIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
488 // be 0, the compiler will remove the test/branch entirely.
489 if ((unsigned)numLines >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
490 memset(vb - numLines, kLine_Verb, numLines);
491 } else {
492 for (int i = 0; i < numLines; ++i) {
493 vb[~i] = kLine_Verb;
494 }
495 }
496 fSegmentMask |= kLine_SegmentMask;
497
498 fVerbCnt += numLines;
499 fPointCnt += numLines;
328 fFreeSpace -= space; 500 fFreeSpace -= space;
329 fBoundsIsDirty = true; // this also invalidates fIsFinite 501 fBoundsIsDirty = true; // this also invalidates fIsFinite
502
503 if (dirtyAfterEdit) {
504 fConvexity = kUnknown_Convexity;
505 fDirection = kUnknown_Direction;
506 fIsOval = false;
507 }
508
330 SkDEBUGCODE(this->validate();) 509 SkDEBUGCODE(this->validate();)
510 return ret;
331 } 511 }
332 512
333 /** 513 /**
334 * Increases the verb count 1, records the new verb, and creates room for th e requisite number 514 * Increases the verb count 1, records the new verb, and creates room for th e requisite number
335 * of additional points. A pointer to the first point is returned. Any new p oints are 515 * of additional points. A pointer to the first point is returned. Any new p oints are
336 * uninitialized. 516 * uninitialized.
337 */ 517 */
338 SkPoint* growForVerb(int /*SkPath::Verb*/ verb); 518 SkPoint* growForVerb(Verb verb);
339 519
340 /** 520 /**
341 * Ensures that the free space available in the path ref is >= size. The ver b and point counts 521 * Ensures that the free space available in the path ref is >= size. The ver b and point counts
342 * are not changed. 522 * are not changed.
343 */ 523 */
344 void makeSpace(size_t size) { 524 void makeSpace(size_t size) {
345 SkDEBUGCODE(this->validate();) 525 SkDEBUGCODE(this->validate();)
346 ptrdiff_t growSize = size - fFreeSpace; 526 ptrdiff_t growSize = size - fFreeSpace;
347 if (growSize <= 0) { 527 if (growSize <= 0) {
348 return; 528 return;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 /** 570 /**
391 * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the 571 * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
392 * same ID then they have the same verbs and points. However, two path refs may have the same 572 * same ID then they have the same verbs and points. However, two path refs may have the same
393 * contents but different genIDs. Zero is reserved and means an ID has not y et been determined 573 * contents but different genIDs. Zero is reserved and means an ID has not y et been determined
394 * for the path ref. 574 * for the path ref.
395 */ 575 */
396 int32_t genID() const; 576 int32_t genID() const;
397 577
398 SkDEBUGCODE(void validate() const;) 578 SkDEBUGCODE(void validate() const;)
399 579
580 Convexity internalGetConvexity() const;
581
582 void setIsOval(bool isOval) { fIsOval = isOval; }
583 void setDirection(Direction direction) { fDirection = direction; }
584
585 /**
586 * Tries to quickly compute the direction of the first non-degenerate
587 * contour. If it can be computed, return true and set dir to that
588 * direction. If it cannot be (quickly) determined, return false and ignore
589 * the dir parameter. If the direction was determined, it is cached to make
590 * subsequent calls return quickly.
591 */
592 bool cheapComputeDirection(Direction* dir) const;
593
400 enum { 594 enum {
401 kMinSize = 256, 595 kMinSize = 256,
402 }; 596 };
403 597
404 mutable SkRect fBounds; 598 mutable SkRect fBounds;
599 int fLastMoveToIndex;
600
601 uint8_t fSegmentMask;
405 mutable uint8_t fBoundsIsDirty; 602 mutable uint8_t fBoundsIsDirty;
603 mutable uint8_t fConvexity;
604 mutable uint8_t fDirection;
406 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid 605 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
606 mutable SkBool8 fIsOval;
407 607
408 SkPoint* fPoints; // points to begining of the allocation 608 SkPoint* fPoints; // points to begining of the allocation
409 uint8_t* fVerbs; // points just past the end of the allocation (v erbs grow backwards) 609 uint8_t* fVerbs; // points just past the end of the allocation (v erbs grow backwards)
410 int fVerbCnt; 610 int fVerbCnt;
411 int fPointCnt; 611 int fPointCnt;
412 size_t fFreeSpace; // redundant but saves computation 612 size_t fFreeSpace; // redundant but saves computation
413 SkTDArray<SkScalar> fConicWeights; 613 SkTDArray<SkScalar> fConicWeights;
414 614
415 enum { 615 enum {
416 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer o verbs. 616 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer o verbs.
417 }; 617 };
418 mutable int32_t fGenerationID; 618 mutable int32_t fGenerationID;
419 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time. 619 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time.
420 620
621 friend class SkPath;
622
421 typedef SkRefCnt INHERITED; 623 typedef SkRefCnt INHERITED;
422 }; 624 };
423 625
424 #endif 626 #endif
OLDNEW
« include/core/SkPath.h ('K') | « include/core/SkPath.h ('k') | src/core/SkPath.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698