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

Side by Side Diff: src/core/SkPathRef.cpp

Issue 105083003: Move segment mask from SkPath to SkPathRef (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Added const Created 7 years 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 | « src/core/SkPath.cpp ('k') | tests/PathTest.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 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBuffer.h" 8 #include "SkBuffer.h"
9 #include "SkOnce.h" 9 #include "SkOnce.h"
10 #include "SkPath.h" 10 #include "SkPath.h"
(...skipping 10 matching lines...) Expand all
21 SkPathRef* copy = SkNEW(SkPathRef); 21 SkPathRef* copy = SkNEW(SkPathRef);
22 copy->copy(**pathRef, incReserveVerbs, incReservePoints); 22 copy->copy(**pathRef, incReserveVerbs, incReservePoints);
23 pathRef->reset(copy); 23 pathRef->reset(copy);
24 } 24 }
25 fPathRef = *pathRef; 25 fPathRef = *pathRef;
26 fPathRef->fGenerationID = 0; 26 fPathRef->fGenerationID = 0;
27 fPathRef->fIsOval = false; 27 fPathRef->fIsOval = false;
28 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) 28 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
29 } 29 }
30 30
31 SkPoint* SkPathRef::Editor::growForConic(SkScalar w) {
32 SkDEBUGCODE(fPathRef->validate();)
33 SkPoint* pts = fPathRef->growForVerb(SkPath::kConic_Verb);
34 *fPathRef->fConicWeights.append() = w;
35 return pts;
36 }
37
38 ////////////////////////////////////////////////////////////////////////////// 31 //////////////////////////////////////////////////////////////////////////////
39 void SkPathRef::CreateEmptyImpl(SkPathRef** empty) { 32 void SkPathRef::CreateEmptyImpl(SkPathRef** empty) {
40 *empty = SkNEW(SkPathRef); 33 *empty = SkNEW(SkPathRef);
41 (*empty)->computeBounds(); // Preemptively avoid a race to clear fBoundsIsD irty. 34 (*empty)->computeBounds(); // Preemptively avoid a race to clear fBoundsIsD irty.
42 } 35 }
43 36
44 SkPathRef* SkPathRef::CreateEmpty() { 37 SkPathRef* SkPathRef::CreateEmpty() {
45 static SkPathRef* gEmptyPathRef; 38 static SkPathRef* gEmptyPathRef;
46 SK_DECLARE_STATIC_ONCE(once); 39 SK_DECLARE_STATIC_ONCE(once);
47 SkOnce(&once, SkPathRef::CreateEmptyImpl, &gEmptyPathRef); 40 SkOnce(&once, SkPathRef::CreateEmptyImpl, &gEmptyPathRef);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 (*dst)->fBounds.setEmpty(); 91 (*dst)->fBounds.setEmpty();
99 } 92 }
100 } else { 93 } else {
101 (*dst)->fIsFinite = false; 94 (*dst)->fIsFinite = false;
102 (*dst)->fBounds.setEmpty(); 95 (*dst)->fBounds.setEmpty();
103 } 96 }
104 } else { 97 } else {
105 (*dst)->fBoundsIsDirty = true; 98 (*dst)->fBoundsIsDirty = true;
106 } 99 }
107 100
101 (*dst)->fSegmentMask = src.fSegmentMask;
102
108 // It's an oval only if it stays a rect. 103 // It's an oval only if it stays a rect.
109 (*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect(); 104 (*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect();
110 105
111 SkDEBUGCODE((*dst)->validate();) 106 SkDEBUGCODE((*dst)->validate();)
112 } 107 }
113 108
114 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer 109 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
115 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO O 110 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO O
116 , bool newFormat, int32_t oldPacked 111 , bool newFormat, int32_t oldPacked
117 #endif 112 #endif
118 ) { 113 ) {
119 SkPathRef* ref = SkNEW(SkPathRef); 114 SkPathRef* ref = SkNEW(SkPathRef);
120 bool isOval; 115 bool isOval;
116 uint8_t segmentMask;
121 117
122 int32_t packed; 118 int32_t packed;
123 if (!buffer->readS32(&packed)) { 119 if (!buffer->readS32(&packed)) {
124 SkDELETE(ref); 120 SkDELETE(ref);
125 return NULL; 121 return NULL;
126 } 122 }
127 123
128 ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; 124 ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
129 125
130 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO O 126 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO O
131 if (newFormat) { 127 if (newFormat) {
132 #endif 128 #endif
129 segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
133 isOval = (packed >> kIsOval_SerializationShift) & 1; 130 isOval = (packed >> kIsOval_SerializationShift) & 1;
134 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO O 131 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO O
135 } else { 132 } else {
133 segmentMask = (oldPacked >> SkPath::kOldSegmentMask_SerializationShift) & 0xF;
136 isOval = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1; 134 isOval = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1;
137 } 135 }
138 #endif 136 #endif
139 137
140 int32_t verbCount, pointCount, conicCount; 138 int32_t verbCount, pointCount, conicCount;
141 if (!buffer->readU32(&(ref->fGenerationID)) || 139 if (!buffer->readU32(&(ref->fGenerationID)) ||
142 !buffer->readS32(&verbCount) || 140 !buffer->readS32(&verbCount) ||
143 !buffer->readS32(&pointCount) || 141 !buffer->readS32(&pointCount) ||
144 !buffer->readS32(&conicCount)) { 142 !buffer->readS32(&conicCount)) {
145 SkDELETE(ref); 143 SkDELETE(ref);
146 return NULL; 144 return NULL;
147 } 145 }
148 146
149 ref->resetToSize(verbCount, pointCount, conicCount); 147 ref->resetToSize(verbCount, pointCount, conicCount);
150 SkASSERT(verbCount == ref->countVerbs()); 148 SkASSERT(verbCount == ref->countVerbs());
151 SkASSERT(pointCount == ref->countPoints()); 149 SkASSERT(pointCount == ref->countPoints());
152 SkASSERT(conicCount == ref->fConicWeights.count()); 150 SkASSERT(conicCount == ref->fConicWeights.count());
153 151
154 if (!buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)) || 152 if (!buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)) ||
155 !buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)) || 153 !buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)) ||
156 !buffer->read(ref->fConicWeights.begin(), conicCount * sizeof(SkScalar)) || 154 !buffer->read(ref->fConicWeights.begin(), conicCount * sizeof(SkScalar)) ||
157 !buffer->read(&ref->fBounds, sizeof(SkRect))) { 155 !buffer->read(&ref->fBounds, sizeof(SkRect))) {
158 SkDELETE(ref); 156 SkDELETE(ref);
159 return NULL; 157 return NULL;
160 } 158 }
161 ref->fBoundsIsDirty = false; 159 ref->fBoundsIsDirty = false;
160
161 // resetToSize clears fSegmentMask and fIsOval
162 ref->fSegmentMask = segmentMask;
162 ref->fIsOval = isOval; 163 ref->fIsOval = isOval;
163 return ref; 164 return ref;
164 } 165 }
165 166
166 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { 167 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
167 if ((*pathRef)->unique()) { 168 if ((*pathRef)->unique()) {
168 SkDEBUGCODE((*pathRef)->validate();) 169 SkDEBUGCODE((*pathRef)->validate();)
169 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite 170 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite
170 (*pathRef)->fVerbCnt = 0; 171 (*pathRef)->fVerbCnt = 0;
171 (*pathRef)->fPointCnt = 0; 172 (*pathRef)->fPointCnt = 0;
172 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); 173 (*pathRef)->fFreeSpace = (*pathRef)->currSize();
173 (*pathRef)->fGenerationID = 0; 174 (*pathRef)->fGenerationID = 0;
174 (*pathRef)->fConicWeights.rewind(); 175 (*pathRef)->fConicWeights.rewind();
176 (*pathRef)->fSegmentMask = 0;
175 (*pathRef)->fIsOval = false; 177 (*pathRef)->fIsOval = false;
176 SkDEBUGCODE((*pathRef)->validate();) 178 SkDEBUGCODE((*pathRef)->validate();)
177 } else { 179 } else {
178 int oldVCnt = (*pathRef)->countVerbs(); 180 int oldVCnt = (*pathRef)->countVerbs();
179 int oldPCnt = (*pathRef)->countPoints(); 181 int oldPCnt = (*pathRef)->countPoints();
180 pathRef->reset(SkNEW(SkPathRef)); 182 pathRef->reset(SkNEW(SkPathRef));
181 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt); 183 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
182 } 184 }
183 } 185 }
184 186
185 bool SkPathRef::operator== (const SkPathRef& ref) const { 187 bool SkPathRef::operator== (const SkPathRef& ref) const {
186 SkDEBUGCODE(this->validate();) 188 SkDEBUGCODE(this->validate();)
187 SkDEBUGCODE(ref.validate();) 189 SkDEBUGCODE(ref.validate();)
190
191 // We explicitly check fSegmentMask as a quick-reject. We could skip it,
192 // since it is only a cache of info in the fVerbs, but its a fast way to
193 // notice a difference
194 if (fSegmentMask != ref.fSegmentMask) {
195 return false;
196 }
197
188 bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID; 198 bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
189 #ifdef SK_RELEASE 199 #ifdef SK_RELEASE
190 if (genIDMatch) { 200 if (genIDMatch) {
191 return true; 201 return true;
192 } 202 }
193 #endif 203 #endif
194 if (fPointCnt != ref.fPointCnt || 204 if (fPointCnt != ref.fPointCnt ||
195 fVerbCnt != ref.fVerbCnt) { 205 fVerbCnt != ref.fVerbCnt) {
196 SkASSERT(!genIDMatch); 206 SkASSERT(!genIDMatch);
197 return false; 207 return false;
(...skipping 17 matching lines...) Expand all
215 // We've done the work to determine that these are equal. If either has a ze ro genID, copy 225 // We've done the work to determine that these are equal. If either has a ze ro genID, copy
216 // the other's. If both are 0 then genID() will compute the next ID. 226 // the other's. If both are 0 then genID() will compute the next ID.
217 if (0 == fGenerationID) { 227 if (0 == fGenerationID) {
218 fGenerationID = ref.genID(); 228 fGenerationID = ref.genID();
219 } else if (0 == ref.fGenerationID) { 229 } else if (0 == ref.fGenerationID) {
220 ref.fGenerationID = this->genID(); 230 ref.fGenerationID = this->genID();
221 } 231 }
222 return true; 232 return true;
223 } 233 }
224 234
225 void SkPathRef::writeToBuffer(SkWBuffer* buffer) { 235 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const {
226 SkDEBUGCODE(this->validate();) 236 SkDEBUGCODE(this->validate();)
227 SkDEBUGCODE(size_t beforePos = buffer->pos();) 237 SkDEBUGCODE(size_t beforePos = buffer->pos();)
228 238
229 // Call getBounds() to ensure (as a side-effect) that fBounds 239 // Call getBounds() to ensure (as a side-effect) that fBounds
230 // and fIsFinite are computed. 240 // and fIsFinite are computed.
231 const SkRect& bounds = this->getBounds(); 241 const SkRect& bounds = this->getBounds();
232 242
233 int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) | 243 int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
234 ((fIsOval & 1) << kIsOval_SerializationShift); 244 ((fIsOval & 1) << kIsOval_SerializationShift) |
245 (fSegmentMask << kSegmentMask_SerializationShift);
235 buffer->write32(packed); 246 buffer->write32(packed);
236 247
237 // TODO: write gen ID here. Problem: We don't know if we're cross process or not from 248 // TODO: write gen ID here. Problem: We don't know if we're cross process or not from
238 // SkWBuffer. Until this is fixed we write 0. 249 // SkWBuffer. Until this is fixed we write 0.
239 buffer->write32(0); 250 buffer->write32(0);
240 buffer->write32(fVerbCnt); 251 buffer->write32(fVerbCnt);
241 buffer->write32(fPointCnt); 252 buffer->write32(fPointCnt);
242 buffer->write32(fConicWeights.count()); 253 buffer->write32(fConicWeights.count());
243 buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t)); 254 buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t));
244 buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); 255 buffer->write(fPoints, fPointCnt * sizeof(SkPoint));
245 buffer->write(fConicWeights.begin(), fConicWeights.bytes()); 256 buffer->write(fConicWeights.begin(), fConicWeights.bytes());
246 buffer->write(&bounds, sizeof(bounds)); 257 buffer->write(&bounds, sizeof(bounds));
247 258
248 SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize()); 259 SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize());
249 } 260 }
250 261
251 uint32_t SkPathRef::writeSize() { 262 uint32_t SkPathRef::writeSize() const {
252 return uint32_t(5 * sizeof(uint32_t) + 263 return uint32_t(5 * sizeof(uint32_t) +
253 fVerbCnt * sizeof(uint8_t) + 264 fVerbCnt * sizeof(uint8_t) +
254 fPointCnt * sizeof(SkPoint) + 265 fPointCnt * sizeof(SkPoint) +
255 fConicWeights.bytes() + 266 fConicWeights.bytes() +
256 sizeof(SkRect)); 267 sizeof(SkRect));
257 } 268 }
258 269
259 void SkPathRef::copy(const SkPathRef& ref, 270 void SkPathRef::copy(const SkPathRef& ref,
260 int additionalReserveVerbs, 271 int additionalReserveVerbs,
261 int additionalReservePoints) { 272 int additionalReservePoints) {
262 SkDEBUGCODE(this->validate();) 273 SkDEBUGCODE(this->validate();)
263 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), 274 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(),
264 additionalReserveVerbs, additionalReservePoints); 275 additionalReserveVerbs, additionalReservePoints);
265 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof( uint8_t)); 276 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof( uint8_t));
266 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); 277 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint));
267 fConicWeights = ref.fConicWeights; 278 fConicWeights = ref.fConicWeights;
268 // We could call genID() here to force a real ID (instead of 0). However, if we're making 279 // We could call genID() here to force a real ID (instead of 0). However, if we're making
269 // a copy then presumably we intend to make a modification immediately after wards. 280 // a copy then presumably we intend to make a modification immediately after wards.
270 fGenerationID = ref.fGenerationID; 281 fGenerationID = ref.fGenerationID;
271 fBoundsIsDirty = ref.fBoundsIsDirty; 282 fBoundsIsDirty = ref.fBoundsIsDirty;
272 if (!fBoundsIsDirty) { 283 if (!fBoundsIsDirty) {
273 fBounds = ref.fBounds; 284 fBounds = ref.fBounds;
274 fIsFinite = ref.fIsFinite; 285 fIsFinite = ref.fIsFinite;
275 } 286 }
287 fSegmentMask = ref.fSegmentMask;
276 fIsOval = ref.fIsOval; 288 fIsOval = ref.fIsOval;
277 SkDEBUGCODE(this->validate();) 289 SkDEBUGCODE(this->validate();)
278 } 290 }
279 291
280 SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) { 292 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
bsalomon 2013/12/10 20:10:11 It seems a little odd that we return a pointer for
robertphillips 2013/12/12 13:59:53 Was just matching push style interface of growForV
bsalomon 2013/12/12 17:57:09 I see.. I still think the new signature is slightl
293 int numVbs,
294 const SkScalar* weights) {
295 // This value is just made-up for now. When count is 4, calling memset was m uch
296 // slower than just writing the loop. This seems odd, and hopefully in the
297 // future this will appear to have been a fluke...
298 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
299
300 SkDEBUGCODE(this->validate();)
301 int pCnt;
302 bool dirtyAfterEdit = true;
303 switch (verb) {
304 case SkPath::kMove_Verb:
305 pCnt = numVbs;
306 dirtyAfterEdit = false;
307 break;
308 case SkPath::kLine_Verb:
309 fSegmentMask |= SkPath::kLine_SegmentMask;
310 pCnt = numVbs;
311 break;
312 case SkPath::kQuad_Verb:
313 fSegmentMask |= SkPath::kQuad_SegmentMask;
314 pCnt = 2 * numVbs;
315 break;
316 case SkPath::kConic_Verb:
317 fSegmentMask |= SkPath::kConic_SegmentMask;
318 pCnt = 2 * numVbs;
319 break;
320 case SkPath::kCubic_Verb:
321 fSegmentMask |= SkPath::kCubic_SegmentMask;
322 pCnt = 3 * numVbs;
323 break;
324 case SkPath::kClose_Verb:
325 SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb");
326 pCnt = 0;
327 dirtyAfterEdit = false;
328 break;
329 case SkPath::kDone_Verb:
330 SkDEBUGFAIL("growForRepeatedVerb called for kDone");
331 // fall through
332 default:
333 SkDEBUGFAIL("default should not be reached");
334 pCnt = 0;
335 dirtyAfterEdit = false;
336 }
337
338 size_t space = numVbs * sizeof(uint8_t) + pCnt * sizeof (SkPoint);
339 this->makeSpace(space);
340
341 SkPoint* ret = fPoints + fPointCnt;
342 uint8_t* vb = fVerbs - fVerbCnt;
343
344 // cast to unsigned, so if kMIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
345 // be 0, the compiler will remove the test/branch entirely.
346 if ((unsigned)numVbs >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
347 memset(vb - numVbs, verb, numVbs);
348 } else {
349 for (int i = 0; i < numVbs; ++i) {
350 vb[~i] = verb;
351 }
352 }
353
354 fVerbCnt += numVbs;
355 fPointCnt += pCnt;
356 fFreeSpace -= space;
357 fBoundsIsDirty = true; // this also invalidates fIsFinite
358 if (dirtyAfterEdit) {
359 fIsOval = false;
360 }
361
362 if (SkPath::kConic_Verb == verb) {
363 SkASSERT(NULL != weights);
364 fConicWeights.append(numVbs, weights);
365 }
366
367 SkDEBUGCODE(this->validate();)
368 return ret;
369 }
370
371 SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
281 SkDEBUGCODE(this->validate();) 372 SkDEBUGCODE(this->validate();)
282 int pCnt; 373 int pCnt;
283 bool dirtyAfterEdit = true; 374 bool dirtyAfterEdit = true;
284 switch (verb) { 375 switch (verb) {
285 case SkPath::kMove_Verb: 376 case SkPath::kMove_Verb:
286 pCnt = 1; 377 pCnt = 1;
287 dirtyAfterEdit = false; 378 dirtyAfterEdit = false;
288 break; 379 break;
289 case SkPath::kLine_Verb: 380 case SkPath::kLine_Verb:
381 fSegmentMask |= SkPath::kLine_SegmentMask;
290 pCnt = 1; 382 pCnt = 1;
291 break; 383 break;
292 case SkPath::kQuad_Verb: 384 case SkPath::kQuad_Verb:
293 // fall through 385 fSegmentMask |= SkPath::kQuad_SegmentMask;
386 pCnt = 2;
387 break;
294 case SkPath::kConic_Verb: 388 case SkPath::kConic_Verb:
389 fSegmentMask |= SkPath::kConic_SegmentMask;
295 pCnt = 2; 390 pCnt = 2;
296 break; 391 break;
297 case SkPath::kCubic_Verb: 392 case SkPath::kCubic_Verb:
393 fSegmentMask |= SkPath::kCubic_SegmentMask;
298 pCnt = 3; 394 pCnt = 3;
299 break; 395 break;
300 case SkPath::kClose_Verb: 396 case SkPath::kClose_Verb:
301 pCnt = 0; 397 pCnt = 0;
302 dirtyAfterEdit = false; 398 dirtyAfterEdit = false;
303 break; 399 break;
304 case SkPath::kDone_Verb: 400 case SkPath::kDone_Verb:
305 SkDEBUGFAIL("growForVerb called for kDone"); 401 SkDEBUGFAIL("growForVerb called for kDone");
306 // fall through 402 // fall through
307 default: 403 default:
308 SkDEBUGFAIL("default is not reached"); 404 SkDEBUGFAIL("default is not reached");
309 dirtyAfterEdit = false; 405 dirtyAfterEdit = false;
310 pCnt = 0; 406 pCnt = 0;
311 } 407 }
312 size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint); 408 size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint);
313 this->makeSpace(space); 409 this->makeSpace(space);
314 this->fVerbs[~fVerbCnt] = verb; 410 this->fVerbs[~fVerbCnt] = verb;
315 SkPoint* ret = fPoints + fPointCnt; 411 SkPoint* ret = fPoints + fPointCnt;
316 fVerbCnt += 1; 412 fVerbCnt += 1;
317 fPointCnt += pCnt; 413 fPointCnt += pCnt;
318 fFreeSpace -= space; 414 fFreeSpace -= space;
319 fBoundsIsDirty = true; // this also invalidates fIsFinite 415 fBoundsIsDirty = true; // this also invalidates fIsFinite
320 if (dirtyAfterEdit) { 416 if (dirtyAfterEdit) {
321 fIsOval = false; 417 fIsOval = false;
322 } 418 }
419
420 if (SkPath::kConic_Verb == verb) {
421 *fConicWeights.append() = weight;
422 }
423
323 SkDEBUGCODE(this->validate();) 424 SkDEBUGCODE(this->validate();)
324 return ret; 425 return ret;
325 } 426 }
326 427
327 uint32_t SkPathRef::genID() const { 428 uint32_t SkPathRef::genID() const {
328 SkASSERT(!fEditorsAttached); 429 SkASSERT(!fEditorsAttached);
329 static const uint32_t kMask = (static_cast<int64_t>(1) << SkPath::kPathRefGe nIDBitCnt) - 1; 430 static const uint32_t kMask = (static_cast<int64_t>(1) << SkPath::kPathRefGe nIDBitCnt) - 1;
330 if (!fGenerationID) { 431 if (!fGenerationID) {
331 if (0 == fPointCnt && 0 == fVerbCnt) { 432 if (0 == fPointCnt && 0 == fVerbCnt) {
332 fGenerationID = kEmptyGenID; 433 fGenerationID = kEmptyGenID;
(...skipping 29 matching lines...) Expand all
362 fBounds.fLeft - fPoints[i].fX < SK_ScalarNearlyZero && 463 fBounds.fLeft - fPoints[i].fX < SK_ScalarNearlyZero &&
363 fPoints[i].fX - fBounds.fRight < SK_ScalarNearlyZero && 464 fPoints[i].fX - fBounds.fRight < SK_ScalarNearlyZero &&
364 fBounds.fTop - fPoints[i].fY < SK_ScalarNearlyZero && 465 fBounds.fTop - fPoints[i].fY < SK_ScalarNearlyZero &&
365 fPoints[i].fY - fBounds.fBottom < SK_ScalarNearlyZero)); 466 fPoints[i].fY - fBounds.fBottom < SK_ScalarNearlyZero));
366 if (!fPoints[i].isFinite()) { 467 if (!fPoints[i].isFinite()) {
367 isFinite = false; 468 isFinite = false;
368 } 469 }
369 } 470 }
370 SkASSERT(SkToBool(fIsFinite) == isFinite); 471 SkASSERT(SkToBool(fIsFinite) == isFinite);
371 } 472 }
473
474 #ifdef SK_DEBUG_PATH
475 uint32_t mask = 0;
476 for (int i = 0; i < fVerbCnt; ++i) {
477 switch (fVerbs[~i]) {
478 case SkPath::kMove_Verb:
479 break;
480 case SkPath::kLine_Verb:
481 mask |= SkPath::kLine_SegmentMask;
482 break;
483 case SkPath::kQuad_Verb:
484 mask |= SkPath::kQuad_SegmentMask;
485 break;
486 case SkPath::kConic_Verb:
487 mask |= SkPath::kConic_SegmentMask;
488 break;
489 case SkPath::kCubic_Verb:
490 mask |= SkPath::kCubic_SegmentMask;
491 break;
492 case SkPath::kClose_Verb:
493 break;
494 case SkPath::kDone_Verb:
495 SkDEBUGFAIL("Done verb shouldn't be recorded.");
496 break;
497 default:
498 SkDEBUGFAIL("Unknown Verb");
499 break;
500 }
501 }
502 SkASSERT(mask == fSegmentMask);
503 #endif // SK_DEBUG_PATH
372 } 504 }
373 #endif 505 #endif
OLDNEW
« no previous file with comments | « src/core/SkPath.cpp ('k') | tests/PathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698