1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkBuffer.h" 9 #include "SkLazyPtr.h" 10 #include "SkPath.h" 11 #include "SkPathRef.h" 12 13 ////////////////////////////////////////////////////////////////////////////// 14 SkPathRef::Editor::Editor(SkAutoTUnref<SkPathRef>* pathRef, 15 int incReserveVerbs, 16 int incReservePoints) 17 { 18 if ((*pathRef)->unique()) { 19 (*pathRef)->incReserve(incReserveVerbs, incReservePoints); 20 } else { 21 SkPathRef* copy = SkNEW(SkPathRef); 22 copy->copy(**pathRef, incReserveVerbs, incReservePoints); 23 pathRef->reset(copy); 24 } 25 fPathRef = *pathRef; 26 fPathRef->fGenerationID = 0; 27 SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) 28 } 29 30 ////////////////////////////////////////////////////////////////////////////// 31 32 // As a template argument, this must have external linkage. 33 SkPathRef* sk_create_empty_pathref() { 34 SkPathRef* empty = SkNEW(SkPathRef); 35 empty->computeBounds(); // Avoids races later to be the first to do this. 36 return empty; 37 } 38 39 SK_DECLARE_STATIC_LAZY_PTR(SkPathRef, empty, sk_create_empty_pathref); 40 41 SkPathRef* SkPathRef::CreateEmpty() { 42 return SkRef(empty.get()); 43 } 44 45 void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, 46 const SkPathRef& src, 47 const SkMatrix& matrix) { 48 SkDEBUGCODE(src.validate();) 49 if (matrix.isIdentity()) { 50 if (*dst != &src) { 51 src.ref(); 52 dst->reset(const_cast<SkPathRef*>(&src)); 53 SkDEBUGCODE((*dst)->validate();) 54 } 55 return; 56 } 57 58 if (!(*dst)->unique()) { 59 dst->reset(SkNEW(SkPathRef)); 60 } 61 62 if (*dst != &src) { 63 (*dst)->resetToSize(src.fVerbCnt, src.fPointCnt, src.fConicWeights.count()); 64 memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(), src.fVerbCnt * sizeof(uint8_t)); 65 (*dst)->fConicWeights = src.fConicWeights; 66 } 67 68 SkASSERT((*dst)->countPoints() == src.countPoints()); 69 SkASSERT((*dst)->countVerbs() == src.countVerbs()); 70 SkASSERT((*dst)->fConicWeights.count() == src.fConicWeights.count()); 71 72 // Need to check this here in case (&src == dst) 73 bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.countPoints() > 1; 74 75 matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt); 76 77 /* 78 * Here we optimize the bounds computation, by noting if the bounds are 79 * already known, and if so, we just transform those as well and mark 80 * them as "known", rather than force the transformed path to have to 81 * recompute them. 82 * 83 * Special gotchas if the path is effectively empty (<= 1 point) or 84 * if it is non-finite. In those cases bounds need to stay empty, 85 * regardless of the matrix. 86 */ 87 if (canXformBounds) { 88 (*dst)->fBoundsIsDirty = false; 89 if (src.fIsFinite) { 90 matrix.mapRect(&(*dst)->fBounds, src.fBounds); 91 if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) { 92 (*dst)->fBounds.setEmpty(); 93 } 94 } else { 95 (*dst)->fIsFinite = false; 96 (*dst)->fBounds.setEmpty(); 97 } 98 } else { 99 (*dst)->fBoundsIsDirty = true; 100 } 101 102 (*dst)->fSegmentMask = src.fSegmentMask; 103 104 // It's an oval only if it stays a rect. 105 (*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect(); 106 107 SkDEBUGCODE((*dst)->validate();) 108 } 109 110 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) { 111 SkPathRef* ref = SkNEW(SkPathRef); 112 bool isOval; 113 uint8_t segmentMask; 114 115 int32_t packed; 116 if (!buffer->readS32(&packed)) { 117 SkDELETE(ref); 118 return NULL; 119 } 120 121 ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; 122 segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; 123 isOval = (packed >> kIsOval_SerializationShift) & 1; 124 125 int32_t verbCount, pointCount, conicCount; 126 if (!buffer->readU32(&(ref->fGenerationID)) || 127 !buffer->readS32(&verbCount) || 128 !buffer->readS32(&pointCount) || 129 !buffer->readS32(&conicCount)) { 130 SkDELETE(ref); 131 return NULL; 132 } 133 134 ref->resetToSize(verbCount, pointCount, conicCount); 135 SkASSERT(verbCount == ref->countVerbs()); 136 SkASSERT(pointCount == ref->countPoints()); 137 SkASSERT(conicCount == ref->fConicWeights.count()); 138 139 if (!buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)) || 140 !buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)) || 141 !buffer->read(ref->fConicWeights.begin(), conicCount * sizeof(SkScalar)) || 142 !buffer->read(&ref->fBounds, sizeof(SkRect))) { 143 SkDELETE(ref); 144 return NULL; 145 } 146 ref->fBoundsIsDirty = false; 147 148 // resetToSize clears fSegmentMask and fIsOval 149 ref->fSegmentMask = segmentMask; 150 ref->fIsOval = isOval; 151 return ref; 152 } 153 154 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { 155 if ((*pathRef)->unique()) { 156 SkDEBUGCODE((*pathRef)->validate();) 157 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite 158 (*pathRef)->fVerbCnt = 0; 159 (*pathRef)->fPointCnt = 0; 160 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); 161 (*pathRef)->fGenerationID = 0; 162 (*pathRef)->fConicWeights.rewind(); 163 (*pathRef)->fSegmentMask = 0; 164 (*pathRef)->fIsOval = false; 165 SkDEBUGCODE((*pathRef)->validate();) 166 } else { 167 int oldVCnt = (*pathRef)->countVerbs(); 168 int oldPCnt = (*pathRef)->countPoints(); 169 pathRef->reset(SkNEW(SkPathRef)); 170 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt); 171 } 172 } 173 174 bool SkPathRef::operator== (const SkPathRef& ref) const { 175 SkDEBUGCODE(this->validate();) 176 SkDEBUGCODE(ref.validate();) 177 178 // We explicitly check fSegmentMask as a quick-reject. We could skip it, 179 // since it is only a cache of info in the fVerbs, but its a fast way to 180 // notice a difference 181 if (fSegmentMask != ref.fSegmentMask) { 182 return false; 183 } 184 185 bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID; 186 #ifdef SK_RELEASE 187 if (genIDMatch) { 188 return true; 189 } 190 #endif 191 if (fPointCnt != ref.fPointCnt || 192 fVerbCnt != ref.fVerbCnt) { 193 SkASSERT(!genIDMatch); 194 return false; 195 } 196 if (0 == ref.fVerbCnt) { 197 SkASSERT(0 == ref.fPointCnt); 198 return true; 199 } 200 SkASSERT(this->verbsMemBegin() && ref.verbsMemBegin()); 201 if (0 != memcmp(this->verbsMemBegin(), 202 ref.verbsMemBegin(), 203 ref.fVerbCnt * sizeof(uint8_t))) { 204 SkASSERT(!genIDMatch); 205 return false; 206 } 207 SkASSERT(this->points() && ref.points()); 208 if (0 != memcmp(this->points(), 209 ref.points(), 210 ref.fPointCnt * sizeof(SkPoint))) { 211 SkASSERT(!genIDMatch); 212 return false; 213 } 214 if (fConicWeights != ref.fConicWeights) { 215 SkASSERT(!genIDMatch); 216 return false; 217 } 218 // We've done the work to determine that these are equal. If either has a zero genID, copy 219 // the other's. If both are 0 then genID() will compute the next ID. 220 if (0 == fGenerationID) { 221 fGenerationID = ref.genID(); 222 } else if (0 == ref.fGenerationID) { 223 ref.fGenerationID = this->genID(); 224 } 225 return true; 226 } 227 228 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { 229 SkDEBUGCODE(this->validate();) 230 SkDEBUGCODE(size_t beforePos = buffer->pos();) 231 232 // Call getBounds() to ensure (as a side-effect) that fBounds 233 // and fIsFinite are computed. 234 const SkRect& bounds = this->getBounds(); 235 236 int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) | 237 ((fIsOval & 1) << kIsOval_SerializationShift) | 238 (fSegmentMask << kSegmentMask_SerializationShift); 239 buffer->write32(packed); 240 241 // TODO: write gen ID here. Problem: We don't know if we're cross process or not from 242 // SkWBuffer. Until this is fixed we write 0. 243 buffer->write32(0); 244 buffer->write32(fVerbCnt); 245 buffer->write32(fPointCnt); 246 buffer->write32(fConicWeights.count()); 247 buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t)); 248 buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); 249 buffer->write(fConicWeights.begin(), fConicWeights.bytes()); 250 buffer->write(&bounds, sizeof(bounds)); 251 252 SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize()); 253 } 254 255 uint32_t SkPathRef::writeSize() const { 256 return uint32_t(5 * sizeof(uint32_t) + 257 fVerbCnt * sizeof(uint8_t) + 258 fPointCnt * sizeof(SkPoint) + 259 fConicWeights.bytes() + 260 sizeof(SkRect)); 261 } 262 263 void SkPathRef::copy(const SkPathRef& ref, 264 int additionalReserveVerbs, 265 int additionalReservePoints) { 266 SkDEBUGCODE(this->validate();) 267 this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(), 268 additionalReserveVerbs, additionalReservePoints); 269 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(uint8_t)); 270 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); 271 fConicWeights = ref.fConicWeights; 272 // We could call genID() here to force a real ID (instead of 0). However, if we're making 273 // a copy then presumably we intend to make a modification immediately afterwards. 274 fGenerationID = ref.fGenerationID; 275 fBoundsIsDirty = ref.fBoundsIsDirty; 276 if (!fBoundsIsDirty) { 277 fBounds = ref.fBounds; 278 fIsFinite = ref.fIsFinite; 279 } 280 fSegmentMask = ref.fSegmentMask; 281 fIsOval = ref.fIsOval; 282 SkDEBUGCODE(this->validate();) 283 } 284 285 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb, 286 int numVbs, 287 SkScalar** weights) { 288 // This value is just made-up for now. When count is 4, calling memset was much 289 // slower than just writing the loop. This seems odd, and hopefully in the 290 // future this will appear to have been a fluke... 291 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16; 292 293 SkDEBUGCODE(this->validate();) 294 int pCnt; 295 bool dirtyAfterEdit = true; 296 switch (verb) { 297 case SkPath::kMove_Verb: 298 pCnt = numVbs; 299 dirtyAfterEdit = false; 300 break; 301 case SkPath::kLine_Verb: 302 fSegmentMask |= SkPath::kLine_SegmentMask; 303 pCnt = numVbs; 304 break; 305 case SkPath::kQuad_Verb: 306 fSegmentMask |= SkPath::kQuad_SegmentMask; 307 pCnt = 2 * numVbs; 308 break; 309 case SkPath::kConic_Verb: 310 fSegmentMask |= SkPath::kConic_SegmentMask; 311 pCnt = 2 * numVbs; 312 break; 313 case SkPath::kCubic_Verb: 314 fSegmentMask |= SkPath::kCubic_SegmentMask; 315 pCnt = 3 * numVbs; 316 break; 317 case SkPath::kClose_Verb: 318 SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb"); 319 pCnt = 0; 320 dirtyAfterEdit = false; 321 break; 322 case SkPath::kDone_Verb: 323 SkDEBUGFAIL("growForRepeatedVerb called for kDone"); 324 // fall through 325 default: 326 SkDEBUGFAIL("default should not be reached"); 327 pCnt = 0; 328 dirtyAfterEdit = false; 329 } 330 331 size_t space = numVbs * sizeof(uint8_t) + pCnt * sizeof (SkPoint); 332 this->makeSpace(space); 333 334 SkPoint* ret = fPoints + fPointCnt; 335 uint8_t* vb = fVerbs - fVerbCnt; 336 337 // cast to unsigned, so if kMIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to 338 // be 0, the compiler will remove the test/branch entirely. 339 if ((unsigned)numVbs >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) { 340 memset(vb - numVbs, verb, numVbs); 341 } else { 342 for (int i = 0; i < numVbs; ++i) { 343 vb[~i] = verb; 344 } 345 } 346 347 fVerbCnt += numVbs; 348 fPointCnt += pCnt; 349 fFreeSpace -= space; 350 fBoundsIsDirty = true; // this also invalidates fIsFinite 351 if (dirtyAfterEdit) { 352 fIsOval = false; 353 } 354 355 if (SkPath::kConic_Verb == verb) { 356 SkASSERT(weights); 357 *weights = fConicWeights.append(numVbs); 358 } 359 360 SkDEBUGCODE(this->validate();) 361 return ret; 362 } 363 364 SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) { 365 SkDEBUGCODE(this->validate();) 366 int pCnt; 367 bool dirtyAfterEdit = true; 368 switch (verb) { 369 case SkPath::kMove_Verb: 370 pCnt = 1; 371 dirtyAfterEdit = false; 372 break; 373 case SkPath::kLine_Verb: 374 fSegmentMask |= SkPath::kLine_SegmentMask; 375 pCnt = 1; 376 break; 377 case SkPath::kQuad_Verb: 378 fSegmentMask |= SkPath::kQuad_SegmentMask; 379 pCnt = 2; 380 break; 381 case SkPath::kConic_Verb: 382 fSegmentMask |= SkPath::kConic_SegmentMask; 383 pCnt = 2; 384 break; 385 case SkPath::kCubic_Verb: 386 fSegmentMask |= SkPath::kCubic_SegmentMask; 387 pCnt = 3; 388 break; 389 case SkPath::kClose_Verb: 390 pCnt = 0; 391 dirtyAfterEdit = false; 392 break; 393 case SkPath::kDone_Verb: 394 SkDEBUGFAIL("growForVerb called for kDone"); 395 // fall through 396 default: 397 SkDEBUGFAIL("default is not reached"); 398 dirtyAfterEdit = false; 399 pCnt = 0; 400 } 401 size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint); 402 this->makeSpace(space); 403 this->fVerbs[~fVerbCnt] = verb; 404 SkPoint* ret = fPoints + fPointCnt; 405 fVerbCnt += 1; 406 fPointCnt += pCnt; 407 fFreeSpace -= space; 408 fBoundsIsDirty = true; // this also invalidates fIsFinite 409 if (dirtyAfterEdit) { 410 fIsOval = false; 411 } 412 413 if (SkPath::kConic_Verb == verb) { 414 *fConicWeights.append() = weight; 415 } 416 417 SkDEBUGCODE(this->validate();) 418 return ret; 419 } 420 421 uint32_t SkPathRef::genID() const { 422 SkASSERT(!fEditorsAttached); 423 static const uint32_t kMask = (static_cast<int64_t>(1) << SkPath::kPathRefGenIDBitCnt) - 1; 424 if (!fGenerationID) { 425 if (0 == fPointCnt && 0 == fVerbCnt) { 426 fGenerationID = kEmptyGenID; 427 } else { 428 static int32_t gPathRefGenerationID; 429 // do a loop in case our global wraps around, as we never want to return a 0 or the 430 // empty ID 431 do { 432 fGenerationID = (sk_atomic_inc(&gPathRefGenerationID) + 1) & kMask; 433 } while (fGenerationID <= kEmptyGenID); 434 } 435 } 436 return fGenerationID; 437 } 438 439 #ifdef SK_DEBUG 440 void SkPathRef::validate() const { 441 this->INHERITED::validate(); 442 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); 443 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints) >= 0); 444 SkASSERT((NULL == fPoints) == (NULL == fVerbs)); 445 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); 446 SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); 447 SkASSERT(!(NULL == fPoints && fPointCnt)); 448 SkASSERT(!(NULL == fVerbs && fVerbCnt)); 449 SkASSERT(this->currSize() == 450 fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt); 451 452 if (!fBoundsIsDirty && !fBounds.isEmpty()) { 453 bool isFinite = true; 454 for (int i = 0; i < fPointCnt; ++i) { 455 #ifdef SK_DEBUG 456 if (fPoints[i].isFinite() && 457 (fPoints[i].fX < fBounds.fLeft || fPoints[i].fX > fBounds.fRight || 458 fPoints[i].fY < fBounds.fTop || fPoints[i].fY > fBounds.fBottom)) { 459 SkDebugf("bounds: %f %f %f %f\n", 460 fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); 461 for (int j = 0; j < fPointCnt; ++j) { 462 if (i == j) { 463 SkDebugf("*"); 464 } 465 SkDebugf("%f %f\n", fPoints[j].fX, fPoints[j].fY); 466 } 467 } 468 #endif 469 470 SkASSERT(!fPoints[i].isFinite() || 471 (fPoints[i].fX >= fBounds.fLeft && fPoints[i].fX <= fBounds.fRight && 472 fPoints[i].fY >= fBounds.fTop && fPoints[i].fY <= fBounds.fBottom)); 473 if (!fPoints[i].isFinite()) { 474 isFinite = false; 475 } 476 } 477 SkASSERT(SkToBool(fIsFinite) == isFinite); 478 } 479 480 #ifdef SK_DEBUG_PATH 481 uint32_t mask = 0; 482 for (int i = 0; i < fVerbCnt; ++i) { 483 switch (fVerbs[~i]) { 484 case SkPath::kMove_Verb: 485 break; 486 case SkPath::kLine_Verb: 487 mask |= SkPath::kLine_SegmentMask; 488 break; 489 case SkPath::kQuad_Verb: 490 mask |= SkPath::kQuad_SegmentMask; 491 break; 492 case SkPath::kConic_Verb: 493 mask |= SkPath::kConic_SegmentMask; 494 break; 495 case SkPath::kCubic_Verb: 496 mask |= SkPath::kCubic_SegmentMask; 497 break; 498 case SkPath::kClose_Verb: 499 break; 500 case SkPath::kDone_Verb: 501 SkDEBUGFAIL("Done verb shouldn't be recorded."); 502 break; 503 default: 504 SkDEBUGFAIL("Unknown Verb"); 505 break; 506 } 507 } 508 SkASSERT(mask == fSegmentMask); 509 #endif // SK_DEBUG_PATH 510 } 511 #endif 512