OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |