SkPathRef.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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. #include "include/private/SkPathRef.h"
  8. #include "include/core/SkPath.h"
  9. #include "include/private/SkNx.h"
  10. #include "include/private/SkOnce.h"
  11. #include "include/private/SkTo.h"
  12. #include "src/core/SkBuffer.h"
  13. #include "src/core/SkPathPriv.h"
  14. #include "src/core/SkSafeMath.h"
  15. // Conic weights must be 0 < weight <= finite
  16. static bool validate_conic_weights(const SkScalar weights[], int count) {
  17. for (int i = 0; i < count; ++i) {
  18. if (weights[i] <= 0 || !SkScalarIsFinite(weights[i])) {
  19. return false;
  20. }
  21. }
  22. return true;
  23. }
  24. //////////////////////////////////////////////////////////////////////////////
  25. SkPathRef::Editor::Editor(sk_sp<SkPathRef>* pathRef,
  26. int incReserveVerbs,
  27. int incReservePoints)
  28. {
  29. SkASSERT(incReserveVerbs >= 0);
  30. SkASSERT(incReservePoints >= 0);
  31. if ((*pathRef)->unique()) {
  32. (*pathRef)->incReserve(incReserveVerbs, incReservePoints);
  33. } else {
  34. SkPathRef* copy = new SkPathRef;
  35. copy->copy(**pathRef, incReserveVerbs, incReservePoints);
  36. pathRef->reset(copy);
  37. }
  38. fPathRef = pathRef->get();
  39. fPathRef->callGenIDChangeListeners();
  40. fPathRef->fGenerationID = 0;
  41. fPathRef->fBoundsIsDirty = true;
  42. SkDEBUGCODE(fPathRef->fEditorsAttached++;)
  43. }
  44. // Sort of like makeSpace(0) but the the additional requirement that we actively shrink the
  45. // allocations to just fit the current needs. makeSpace() will only grow, but never shrinks.
  46. //
  47. void SkPath::shrinkToFit() {
  48. const size_t kMinFreeSpaceForShrink = 8; // just made up a small number
  49. if (fPathRef->fFreeSpace <= kMinFreeSpaceForShrink) {
  50. return;
  51. }
  52. if (fPathRef->unique()) {
  53. int pointCount = fPathRef->fPointCnt;
  54. int verbCount = fPathRef->fVerbCnt;
  55. size_t ptsSize = sizeof(SkPoint) * pointCount;
  56. size_t vrbSize = sizeof(uint8_t) * verbCount;
  57. size_t minSize = ptsSize + vrbSize;
  58. void* newAlloc = sk_malloc_canfail(minSize);
  59. if (!newAlloc) {
  60. return; // couldn't allocate the smaller buffer, but that's ok
  61. }
  62. sk_careful_memcpy(newAlloc, fPathRef->fPoints, ptsSize);
  63. sk_careful_memcpy((char*)newAlloc + minSize - vrbSize, fPathRef->verbsMemBegin(), vrbSize);
  64. sk_free(fPathRef->fPoints);
  65. fPathRef->fPoints = static_cast<SkPoint*>(newAlloc);
  66. fPathRef->fVerbs = (uint8_t*)newAlloc + minSize;
  67. fPathRef->fFreeSpace = 0;
  68. fPathRef->fConicWeights.shrinkToFit();
  69. } else {
  70. sk_sp<SkPathRef> pr(new SkPathRef);
  71. pr->copy(*fPathRef, 0, 0);
  72. fPathRef = std::move(pr);
  73. }
  74. SkDEBUGCODE(fPathRef->validate();)
  75. }
  76. //////////////////////////////////////////////////////////////////////////////
  77. SkPathRef::~SkPathRef() {
  78. // Deliberately don't validate() this path ref, otherwise there's no way
  79. // to read one that's not valid and then free its memory without asserting.
  80. this->callGenIDChangeListeners();
  81. SkASSERT(fGenIDChangeListeners.empty()); // These are raw ptrs.
  82. sk_free(fPoints);
  83. SkDEBUGCODE(fPoints = nullptr;)
  84. SkDEBUGCODE(fVerbs = nullptr;)
  85. SkDEBUGCODE(fVerbCnt = 0x9999999;)
  86. SkDEBUGCODE(fPointCnt = 0xAAAAAAA;)
  87. SkDEBUGCODE(fPointCnt = 0xBBBBBBB;)
  88. SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;)
  89. SkDEBUGCODE(fEditorsAttached.store(0x7777777);)
  90. }
  91. static SkPathRef* gEmpty = nullptr;
  92. SkPathRef* SkPathRef::CreateEmpty() {
  93. static SkOnce once;
  94. once([]{
  95. gEmpty = new SkPathRef;
  96. gEmpty->computeBounds(); // Avoids races later to be the first to do this.
  97. });
  98. return SkRef(gEmpty);
  99. }
  100. static void transform_dir_and_start(const SkMatrix& matrix, bool isRRect, bool* isCCW,
  101. unsigned* start) {
  102. int inStart = *start;
  103. int rm = 0;
  104. if (isRRect) {
  105. // Degenerate rrect indices to oval indices and remember the remainder.
  106. // Ovals have one index per side whereas rrects have two.
  107. rm = inStart & 0b1;
  108. inStart /= 2;
  109. }
  110. // Is the antidiagonal non-zero (otherwise the diagonal is zero)
  111. int antiDiag;
  112. // Is the non-zero value in the top row (either kMScaleX or kMSkewX) negative
  113. int topNeg;
  114. // Are the two non-zero diagonal or antidiagonal values the same sign.
  115. int sameSign;
  116. if (matrix.get(SkMatrix::kMScaleX) != 0) {
  117. antiDiag = 0b00;
  118. if (matrix.get(SkMatrix::kMScaleX) > 0) {
  119. topNeg = 0b00;
  120. sameSign = matrix.get(SkMatrix::kMScaleY) > 0 ? 0b01 : 0b00;
  121. } else {
  122. topNeg = 0b10;
  123. sameSign = matrix.get(SkMatrix::kMScaleY) > 0 ? 0b00 : 0b01;
  124. }
  125. } else {
  126. antiDiag = 0b01;
  127. if (matrix.get(SkMatrix::kMSkewX) > 0) {
  128. topNeg = 0b00;
  129. sameSign = matrix.get(SkMatrix::kMSkewY) > 0 ? 0b01 : 0b00;
  130. } else {
  131. topNeg = 0b10;
  132. sameSign = matrix.get(SkMatrix::kMSkewY) > 0 ? 0b00 : 0b01;
  133. }
  134. }
  135. if (sameSign != antiDiag) {
  136. // This is a rotation (and maybe scale). The direction is unchanged.
  137. // Trust me on the start computation (or draw yourself some pictures)
  138. *start = (inStart + 4 - (topNeg | antiDiag)) % 4;
  139. SkASSERT(*start < 4);
  140. if (isRRect) {
  141. *start = 2 * *start + rm;
  142. }
  143. } else {
  144. // This is a mirror (and maybe scale). The direction is reversed.
  145. *isCCW = !*isCCW;
  146. // Trust me on the start computation (or draw yourself some pictures)
  147. *start = (6 + (topNeg | antiDiag) - inStart) % 4;
  148. SkASSERT(*start < 4);
  149. if (isRRect) {
  150. *start = 2 * *start + (rm ? 0 : 1);
  151. }
  152. }
  153. }
  154. void SkPathRef::CreateTransformedCopy(sk_sp<SkPathRef>* dst,
  155. const SkPathRef& src,
  156. const SkMatrix& matrix) {
  157. SkDEBUGCODE(src.validate();)
  158. if (matrix.isIdentity()) {
  159. if (dst->get() != &src) {
  160. src.ref();
  161. dst->reset(const_cast<SkPathRef*>(&src));
  162. SkDEBUGCODE((*dst)->validate();)
  163. }
  164. return;
  165. }
  166. if (!(*dst)->unique()) {
  167. dst->reset(new SkPathRef);
  168. }
  169. if (dst->get() != &src) {
  170. (*dst)->resetToSize(src.fVerbCnt, src.fPointCnt, src.fConicWeights.count());
  171. sk_careful_memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(),
  172. src.fVerbCnt * sizeof(uint8_t));
  173. (*dst)->fConicWeights = src.fConicWeights;
  174. }
  175. SkASSERT((*dst)->countPoints() == src.countPoints());
  176. SkASSERT((*dst)->countVerbs() == src.countVerbs());
  177. SkASSERT((*dst)->fConicWeights.count() == src.fConicWeights.count());
  178. // Need to check this here in case (&src == dst)
  179. bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.countPoints() > 1;
  180. matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt);
  181. /*
  182. * Here we optimize the bounds computation, by noting if the bounds are
  183. * already known, and if so, we just transform those as well and mark
  184. * them as "known", rather than force the transformed path to have to
  185. * recompute them.
  186. *
  187. * Special gotchas if the path is effectively empty (<= 1 point) or
  188. * if it is non-finite. In those cases bounds need to stay empty,
  189. * regardless of the matrix.
  190. */
  191. if (canXformBounds) {
  192. (*dst)->fBoundsIsDirty = false;
  193. if (src.fIsFinite) {
  194. matrix.mapRect(&(*dst)->fBounds, src.fBounds);
  195. if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) {
  196. (*dst)->fBounds.setEmpty();
  197. }
  198. } else {
  199. (*dst)->fIsFinite = false;
  200. (*dst)->fBounds.setEmpty();
  201. }
  202. } else {
  203. (*dst)->fBoundsIsDirty = true;
  204. }
  205. (*dst)->fSegmentMask = src.fSegmentMask;
  206. // It's an oval only if it stays a rect.
  207. bool rectStaysRect = matrix.rectStaysRect();
  208. (*dst)->fIsOval = src.fIsOval && rectStaysRect;
  209. (*dst)->fIsRRect = src.fIsRRect && rectStaysRect;
  210. if ((*dst)->fIsOval || (*dst)->fIsRRect) {
  211. unsigned start = src.fRRectOrOvalStartIdx;
  212. bool isCCW = SkToBool(src.fRRectOrOvalIsCCW);
  213. transform_dir_and_start(matrix, (*dst)->fIsRRect, &isCCW, &start);
  214. (*dst)->fRRectOrOvalIsCCW = isCCW;
  215. (*dst)->fRRectOrOvalStartIdx = start;
  216. }
  217. if (dst->get() == &src) {
  218. (*dst)->callGenIDChangeListeners();
  219. (*dst)->fGenerationID = 0;
  220. }
  221. SkDEBUGCODE((*dst)->validate();)
  222. }
  223. static bool validate_verb_sequence(const uint8_t verbs[], int vCount) {
  224. // verbs are stored backwards, but we need to visit them in logical order to determine if
  225. // they form a valid sequence.
  226. bool needsMoveTo = true;
  227. bool invalidSequence = false;
  228. for (int i = vCount - 1; i >= 0; --i) {
  229. switch (verbs[i]) {
  230. case SkPath::kMove_Verb:
  231. needsMoveTo = false;
  232. break;
  233. case SkPath::kLine_Verb:
  234. case SkPath::kQuad_Verb:
  235. case SkPath::kConic_Verb:
  236. case SkPath::kCubic_Verb:
  237. invalidSequence |= needsMoveTo;
  238. break;
  239. case SkPath::kClose_Verb:
  240. needsMoveTo = true;
  241. break;
  242. default:
  243. return false; // unknown verb
  244. }
  245. }
  246. return !invalidSequence;
  247. }
  248. // Given the verb array, deduce the required number of pts and conics,
  249. // or if an invalid verb is encountered, return false.
  250. static bool deduce_pts_conics(const uint8_t verbs[], int vCount, int* ptCountPtr,
  251. int* conicCountPtr) {
  252. // When there is at least one verb, the first is required to be kMove_Verb.
  253. if (0 < vCount && verbs[vCount-1] != SkPath::kMove_Verb) {
  254. return false;
  255. }
  256. SkSafeMath safe;
  257. int ptCount = 0;
  258. int conicCount = 0;
  259. for (int i = 0; i < vCount; ++i) {
  260. switch (verbs[i]) {
  261. case SkPath::kMove_Verb:
  262. case SkPath::kLine_Verb:
  263. ptCount = safe.addInt(ptCount, 1);
  264. break;
  265. case SkPath::kConic_Verb:
  266. conicCount += 1;
  267. // fall-through
  268. case SkPath::kQuad_Verb:
  269. ptCount = safe.addInt(ptCount, 2);
  270. break;
  271. case SkPath::kCubic_Verb:
  272. ptCount = safe.addInt(ptCount, 3);
  273. break;
  274. case SkPath::kClose_Verb:
  275. break;
  276. default:
  277. return false;
  278. }
  279. }
  280. if (!safe) {
  281. return false;
  282. }
  283. *ptCountPtr = ptCount;
  284. *conicCountPtr = conicCount;
  285. return true;
  286. }
  287. SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
  288. std::unique_ptr<SkPathRef> ref(new SkPathRef);
  289. int32_t packed;
  290. if (!buffer->readS32(&packed)) {
  291. return nullptr;
  292. }
  293. ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
  294. int32_t verbCount, pointCount, conicCount;
  295. if (!buffer->readU32(&(ref->fGenerationID)) ||
  296. !buffer->readS32(&verbCount) || (verbCount < 0) ||
  297. !buffer->readS32(&pointCount) || (pointCount < 0) ||
  298. !buffer->readS32(&conicCount) || (conicCount < 0))
  299. {
  300. return nullptr;
  301. }
  302. uint64_t pointSize64 = sk_64_mul(pointCount, sizeof(SkPoint));
  303. uint64_t conicSize64 = sk_64_mul(conicCount, sizeof(SkScalar));
  304. if (!SkTFitsIn<size_t>(pointSize64) || !SkTFitsIn<size_t>(conicSize64)) {
  305. return nullptr;
  306. }
  307. size_t verbSize = verbCount * sizeof(uint8_t);
  308. size_t pointSize = SkToSizeT(pointSize64);
  309. size_t conicSize = SkToSizeT(conicSize64);
  310. {
  311. uint64_t requiredBufferSize = sizeof(SkRect);
  312. requiredBufferSize += verbSize;
  313. requiredBufferSize += pointSize;
  314. requiredBufferSize += conicSize;
  315. if (buffer->available() < requiredBufferSize) {
  316. return nullptr;
  317. }
  318. }
  319. ref->resetToSize(verbCount, pointCount, conicCount);
  320. SkASSERT(verbCount == ref->countVerbs());
  321. SkASSERT(pointCount == ref->countPoints());
  322. SkASSERT(conicCount == ref->fConicWeights.count());
  323. if (!buffer->read(ref->verbsMemWritable(), verbSize) ||
  324. !buffer->read(ref->fPoints, pointSize) ||
  325. !buffer->read(ref->fConicWeights.begin(), conicSize) ||
  326. !buffer->read(&ref->fBounds, sizeof(SkRect))) {
  327. return nullptr;
  328. }
  329. // Check that the verbs are valid, and imply the correct number of pts and conics
  330. {
  331. int pCount, cCount;
  332. if (!validate_verb_sequence(ref->verbsMemBegin(), ref->countVerbs())) {
  333. return nullptr;
  334. }
  335. if (!deduce_pts_conics(ref->verbsMemBegin(), ref->countVerbs(), &pCount, &cCount) ||
  336. pCount != ref->countPoints() || cCount != ref->fConicWeights.count()) {
  337. return nullptr;
  338. }
  339. if (!validate_conic_weights(ref->fConicWeights.begin(), ref->fConicWeights.count())) {
  340. return nullptr;
  341. }
  342. // Check that the bounds match the serialized bounds.
  343. SkRect bounds;
  344. if (ComputePtBounds(&bounds, *ref) != SkToBool(ref->fIsFinite) || bounds != ref->fBounds) {
  345. return nullptr;
  346. }
  347. // call this after validate_verb_sequence, since it relies on valid verbs
  348. ref->fSegmentMask = ref->computeSegmentMask();
  349. }
  350. ref->fBoundsIsDirty = false;
  351. return ref.release();
  352. }
  353. void SkPathRef::Rewind(sk_sp<SkPathRef>* pathRef) {
  354. if ((*pathRef)->unique()) {
  355. SkDEBUGCODE((*pathRef)->validate();)
  356. (*pathRef)->callGenIDChangeListeners();
  357. (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite
  358. (*pathRef)->fVerbCnt = 0;
  359. (*pathRef)->fPointCnt = 0;
  360. (*pathRef)->fFreeSpace = (*pathRef)->currSize();
  361. (*pathRef)->fGenerationID = 0;
  362. (*pathRef)->fConicWeights.rewind();
  363. (*pathRef)->fSegmentMask = 0;
  364. (*pathRef)->fIsOval = false;
  365. (*pathRef)->fIsRRect = false;
  366. SkDEBUGCODE((*pathRef)->validate();)
  367. } else {
  368. int oldVCnt = (*pathRef)->countVerbs();
  369. int oldPCnt = (*pathRef)->countPoints();
  370. pathRef->reset(new SkPathRef);
  371. (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
  372. }
  373. }
  374. bool SkPathRef::operator== (const SkPathRef& ref) const {
  375. SkDEBUGCODE(this->validate();)
  376. SkDEBUGCODE(ref.validate();)
  377. // We explicitly check fSegmentMask as a quick-reject. We could skip it,
  378. // since it is only a cache of info in the fVerbs, but its a fast way to
  379. // notice a difference
  380. if (fSegmentMask != ref.fSegmentMask) {
  381. return false;
  382. }
  383. bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
  384. #ifdef SK_RELEASE
  385. if (genIDMatch) {
  386. return true;
  387. }
  388. #endif
  389. if (fPointCnt != ref.fPointCnt ||
  390. fVerbCnt != ref.fVerbCnt) {
  391. SkASSERT(!genIDMatch);
  392. return false;
  393. }
  394. if (0 == ref.fVerbCnt) {
  395. SkASSERT(0 == ref.fPointCnt);
  396. return true;
  397. }
  398. SkASSERT(this->verbsMemBegin() && ref.verbsMemBegin());
  399. if (0 != memcmp(this->verbsMemBegin(),
  400. ref.verbsMemBegin(),
  401. ref.fVerbCnt * sizeof(uint8_t))) {
  402. SkASSERT(!genIDMatch);
  403. return false;
  404. }
  405. SkASSERT(this->points() && ref.points());
  406. if (0 != memcmp(this->points(),
  407. ref.points(),
  408. ref.fPointCnt * sizeof(SkPoint))) {
  409. SkASSERT(!genIDMatch);
  410. return false;
  411. }
  412. if (fConicWeights != ref.fConicWeights) {
  413. SkASSERT(!genIDMatch);
  414. return false;
  415. }
  416. return true;
  417. }
  418. void SkPathRef::writeToBuffer(SkWBuffer* buffer) const {
  419. SkDEBUGCODE(this->validate();)
  420. SkDEBUGCODE(size_t beforePos = buffer->pos();)
  421. // Call getBounds() to ensure (as a side-effect) that fBounds
  422. // and fIsFinite are computed.
  423. const SkRect& bounds = this->getBounds();
  424. // We store fSegmentMask for older readers, but current readers can't trust it, so they
  425. // don't read it.
  426. int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
  427. (fSegmentMask << kSegmentMask_SerializationShift);
  428. buffer->write32(packed);
  429. // TODO: write gen ID here. Problem: We don't know if we're cross process or not from
  430. // SkWBuffer. Until this is fixed we write 0.
  431. buffer->write32(0);
  432. buffer->write32(fVerbCnt);
  433. buffer->write32(fPointCnt);
  434. buffer->write32(fConicWeights.count());
  435. buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t));
  436. buffer->write(fPoints, fPointCnt * sizeof(SkPoint));
  437. buffer->write(fConicWeights.begin(), fConicWeights.bytes());
  438. buffer->write(&bounds, sizeof(bounds));
  439. SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize());
  440. }
  441. uint32_t SkPathRef::writeSize() const {
  442. return uint32_t(5 * sizeof(uint32_t) +
  443. fVerbCnt * sizeof(uint8_t) +
  444. fPointCnt * sizeof(SkPoint) +
  445. fConicWeights.bytes() +
  446. sizeof(SkRect));
  447. }
  448. void SkPathRef::copy(const SkPathRef& ref,
  449. int additionalReserveVerbs,
  450. int additionalReservePoints) {
  451. SkDEBUGCODE(this->validate();)
  452. this->resetToSize(ref.fVerbCnt, ref.fPointCnt, ref.fConicWeights.count(),
  453. additionalReserveVerbs, additionalReservePoints);
  454. sk_careful_memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt*sizeof(uint8_t));
  455. sk_careful_memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint));
  456. fConicWeights = ref.fConicWeights;
  457. fBoundsIsDirty = ref.fBoundsIsDirty;
  458. if (!fBoundsIsDirty) {
  459. fBounds = ref.fBounds;
  460. fIsFinite = ref.fIsFinite;
  461. }
  462. fSegmentMask = ref.fSegmentMask;
  463. fIsOval = ref.fIsOval;
  464. fIsRRect = ref.fIsRRect;
  465. fRRectOrOvalIsCCW = ref.fRRectOrOvalIsCCW;
  466. fRRectOrOvalStartIdx = ref.fRRectOrOvalStartIdx;
  467. SkDEBUGCODE(this->validate();)
  468. }
  469. unsigned SkPathRef::computeSegmentMask() const {
  470. const uint8_t* verbs = this->verbsMemBegin();
  471. unsigned mask = 0;
  472. for (int i = this->countVerbs() - 1; i >= 0; --i) {
  473. switch (verbs[i]) {
  474. case SkPath::kLine_Verb: mask |= SkPath::kLine_SegmentMask; break;
  475. case SkPath::kQuad_Verb: mask |= SkPath::kQuad_SegmentMask; break;
  476. case SkPath::kConic_Verb: mask |= SkPath::kConic_SegmentMask; break;
  477. case SkPath::kCubic_Verb: mask |= SkPath::kCubic_SegmentMask; break;
  478. default: break;
  479. }
  480. }
  481. return mask;
  482. }
  483. void SkPathRef::interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef* out) const {
  484. const SkScalar* inValues = &ending.getPoints()->fX;
  485. SkScalar* outValues = &out->getPoints()->fX;
  486. int count = out->countPoints() * 2;
  487. for (int index = 0; index < count; ++index) {
  488. outValues[index] = outValues[index] * weight + inValues[index] * (1 - weight);
  489. }
  490. out->fBoundsIsDirty = true;
  491. out->fIsOval = false;
  492. out->fIsRRect = false;
  493. }
  494. SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
  495. int numVbs,
  496. SkScalar** weights) {
  497. // This value is just made-up for now. When count is 4, calling memset was much
  498. // slower than just writing the loop. This seems odd, and hopefully in the
  499. // future this will appear to have been a fluke...
  500. static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
  501. SkDEBUGCODE(this->validate();)
  502. int pCnt;
  503. switch (verb) {
  504. case SkPath::kMove_Verb:
  505. pCnt = numVbs;
  506. break;
  507. case SkPath::kLine_Verb:
  508. fSegmentMask |= SkPath::kLine_SegmentMask;
  509. pCnt = numVbs;
  510. break;
  511. case SkPath::kQuad_Verb:
  512. fSegmentMask |= SkPath::kQuad_SegmentMask;
  513. pCnt = 2 * numVbs;
  514. break;
  515. case SkPath::kConic_Verb:
  516. fSegmentMask |= SkPath::kConic_SegmentMask;
  517. pCnt = 2 * numVbs;
  518. break;
  519. case SkPath::kCubic_Verb:
  520. fSegmentMask |= SkPath::kCubic_SegmentMask;
  521. pCnt = 3 * numVbs;
  522. break;
  523. case SkPath::kClose_Verb:
  524. SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb");
  525. pCnt = 0;
  526. break;
  527. case SkPath::kDone_Verb:
  528. SkDEBUGFAIL("growForRepeatedVerb called for kDone");
  529. // fall through
  530. default:
  531. SkDEBUGFAIL("default should not be reached");
  532. pCnt = 0;
  533. }
  534. size_t space = numVbs * sizeof(uint8_t) + pCnt * sizeof (SkPoint);
  535. this->makeSpace(space);
  536. SkPoint* ret = fPoints + fPointCnt;
  537. uint8_t* vb = fVerbs - fVerbCnt;
  538. // cast to unsigned, so if kMIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
  539. // be 0, the compiler will remove the test/branch entirely.
  540. if ((unsigned)numVbs >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
  541. memset(vb - numVbs, verb, numVbs);
  542. } else {
  543. for (int i = 0; i < numVbs; ++i) {
  544. vb[~i] = verb;
  545. }
  546. }
  547. SkSafeMath safe;
  548. fVerbCnt = safe.addInt(fVerbCnt, numVbs);
  549. fPointCnt = safe.addInt(fPointCnt, pCnt);
  550. if (!safe) {
  551. SK_ABORT("cannot grow path");
  552. }
  553. fFreeSpace -= space;
  554. fBoundsIsDirty = true; // this also invalidates fIsFinite
  555. fIsOval = false;
  556. fIsRRect = false;
  557. if (SkPath::kConic_Verb == verb) {
  558. SkASSERT(weights);
  559. *weights = fConicWeights.append(numVbs);
  560. }
  561. SkDEBUGCODE(this->validate();)
  562. return ret;
  563. }
  564. SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
  565. SkDEBUGCODE(this->validate();)
  566. int pCnt;
  567. unsigned mask = 0;
  568. switch (verb) {
  569. case SkPath::kMove_Verb:
  570. pCnt = 1;
  571. break;
  572. case SkPath::kLine_Verb:
  573. mask = SkPath::kLine_SegmentMask;
  574. pCnt = 1;
  575. break;
  576. case SkPath::kQuad_Verb:
  577. mask = SkPath::kQuad_SegmentMask;
  578. pCnt = 2;
  579. break;
  580. case SkPath::kConic_Verb:
  581. mask = SkPath::kConic_SegmentMask;
  582. pCnt = 2;
  583. break;
  584. case SkPath::kCubic_Verb:
  585. mask = SkPath::kCubic_SegmentMask;
  586. pCnt = 3;
  587. break;
  588. case SkPath::kClose_Verb:
  589. pCnt = 0;
  590. break;
  591. case SkPath::kDone_Verb:
  592. SkDEBUGFAIL("growForVerb called for kDone");
  593. // fall through
  594. default:
  595. SkDEBUGFAIL("default is not reached");
  596. pCnt = 0;
  597. }
  598. SkSafeMath safe;
  599. int newPointCnt = safe.addInt(fPointCnt, pCnt);
  600. int newVerbCnt = safe.addInt(fVerbCnt, 1);
  601. if (!safe) {
  602. SK_ABORT("cannot grow path");
  603. }
  604. size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint);
  605. this->makeSpace(space);
  606. this->fVerbs[~fVerbCnt] = verb;
  607. SkPoint* ret = fPoints + fPointCnt;
  608. fVerbCnt = newVerbCnt;
  609. fPointCnt = newPointCnt;
  610. fSegmentMask |= mask;
  611. fFreeSpace -= space;
  612. fBoundsIsDirty = true; // this also invalidates fIsFinite
  613. fIsOval = false;
  614. fIsRRect = false;
  615. if (SkPath::kConic_Verb == verb) {
  616. *fConicWeights.append() = weight;
  617. }
  618. SkDEBUGCODE(this->validate();)
  619. return ret;
  620. }
  621. uint32_t SkPathRef::genID() const {
  622. SkASSERT(fEditorsAttached.load() == 0);
  623. static const uint32_t kMask = (static_cast<int64_t>(1) << SkPathPriv::kPathRefGenIDBitCnt) - 1;
  624. if (fGenerationID == 0) {
  625. if (fPointCnt == 0 && fVerbCnt == 0) {
  626. fGenerationID = kEmptyGenID;
  627. } else {
  628. static std::atomic<uint32_t> nextID{kEmptyGenID + 1};
  629. do {
  630. fGenerationID = nextID.fetch_add(1, std::memory_order_relaxed) & kMask;
  631. } while (fGenerationID == 0 || fGenerationID == kEmptyGenID);
  632. }
  633. }
  634. return fGenerationID;
  635. }
  636. void SkPathRef::addGenIDChangeListener(sk_sp<GenIDChangeListener> listener) {
  637. if (nullptr == listener || this == gEmpty) {
  638. return;
  639. }
  640. SkAutoMutexExclusive lock(fGenIDChangeListenersMutex);
  641. // Clean out any stale listeners before we append the new one.
  642. for (int i = 0; i < fGenIDChangeListeners.count(); ++i) {
  643. if (fGenIDChangeListeners[i]->shouldUnregisterFromPath()) {
  644. fGenIDChangeListeners[i]->unref();
  645. fGenIDChangeListeners.removeShuffle(i--); // No need to preserve the order after i.
  646. }
  647. }
  648. SkASSERT(!listener->shouldUnregisterFromPath());
  649. *fGenIDChangeListeners.append() = listener.release();
  650. }
  651. // we need to be called *before* the genID gets changed or zerod
  652. void SkPathRef::callGenIDChangeListeners() {
  653. SkAutoMutexExclusive lock(fGenIDChangeListenersMutex);
  654. for (GenIDChangeListener* listener : fGenIDChangeListeners) {
  655. if (!listener->shouldUnregisterFromPath()) {
  656. listener->onChange();
  657. }
  658. // Listeners get at most one shot, so whether these triggered or not, blow them away.
  659. listener->unref();
  660. }
  661. fGenIDChangeListeners.reset();
  662. }
  663. SkRRect SkPathRef::getRRect() const {
  664. const SkRect& bounds = this->getBounds();
  665. SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
  666. Iter iter(*this);
  667. SkPoint pts[4];
  668. uint8_t verb = iter.next(pts);
  669. SkASSERT(SkPath::kMove_Verb == verb);
  670. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  671. if (SkPath::kConic_Verb == verb) {
  672. SkVector v1_0 = pts[1] - pts[0];
  673. SkVector v2_1 = pts[2] - pts[1];
  674. SkVector dxdy;
  675. if (v1_0.fX) {
  676. SkASSERT(!v2_1.fX && !v1_0.fY);
  677. dxdy.set(SkScalarAbs(v1_0.fX), SkScalarAbs(v2_1.fY));
  678. } else if (!v1_0.fY) {
  679. SkASSERT(!v2_1.fX || !v2_1.fY);
  680. dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v2_1.fY));
  681. } else {
  682. SkASSERT(!v2_1.fY);
  683. dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v1_0.fY));
  684. }
  685. SkRRect::Corner corner =
  686. pts[1].fX == bounds.fLeft ?
  687. pts[1].fY == bounds.fTop ?
  688. SkRRect::kUpperLeft_Corner : SkRRect::kLowerLeft_Corner :
  689. pts[1].fY == bounds.fTop ?
  690. SkRRect::kUpperRight_Corner : SkRRect::kLowerRight_Corner;
  691. SkASSERT(!radii[corner].fX && !radii[corner].fY);
  692. radii[corner] = dxdy;
  693. } else {
  694. SkASSERT((verb == SkPath::kLine_Verb
  695. && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
  696. || verb == SkPath::kClose_Verb);
  697. }
  698. }
  699. SkRRect rrect;
  700. rrect.setRectRadii(bounds, radii);
  701. return rrect;
  702. }
  703. ///////////////////////////////////////////////////////////////////////////////
  704. SkPathRef::Iter::Iter() {
  705. #ifdef SK_DEBUG
  706. fPts = nullptr;
  707. fConicWeights = nullptr;
  708. #endif
  709. // need to init enough to make next() harmlessly return kDone_Verb
  710. fVerbs = nullptr;
  711. fVerbStop = nullptr;
  712. }
  713. SkPathRef::Iter::Iter(const SkPathRef& path) {
  714. this->setPathRef(path);
  715. }
  716. void SkPathRef::Iter::setPathRef(const SkPathRef& path) {
  717. fPts = path.points();
  718. fVerbs = path.verbs();
  719. fVerbStop = path.verbsMemBegin();
  720. fConicWeights = path.conicWeights();
  721. if (fConicWeights) {
  722. fConicWeights -= 1; // begin one behind
  723. }
  724. // Don't allow iteration through non-finite points.
  725. if (!path.isFinite()) {
  726. fVerbStop = fVerbs;
  727. }
  728. }
  729. uint8_t SkPathRef::Iter::next(SkPoint pts[4]) {
  730. SkASSERT(pts);
  731. SkDEBUGCODE(unsigned peekResult = this->peek();)
  732. if (fVerbs == fVerbStop) {
  733. SkASSERT(peekResult == SkPath::kDone_Verb);
  734. return (uint8_t) SkPath::kDone_Verb;
  735. }
  736. // fVerbs points one beyond next verb so decrement first.
  737. unsigned verb = *(--fVerbs);
  738. const SkPoint* srcPts = fPts;
  739. switch (verb) {
  740. case SkPath::kMove_Verb:
  741. pts[0] = srcPts[0];
  742. srcPts += 1;
  743. break;
  744. case SkPath::kLine_Verb:
  745. pts[0] = srcPts[-1];
  746. pts[1] = srcPts[0];
  747. srcPts += 1;
  748. break;
  749. case SkPath::kConic_Verb:
  750. fConicWeights += 1;
  751. // fall-through
  752. case SkPath::kQuad_Verb:
  753. pts[0] = srcPts[-1];
  754. pts[1] = srcPts[0];
  755. pts[2] = srcPts[1];
  756. srcPts += 2;
  757. break;
  758. case SkPath::kCubic_Verb:
  759. pts[0] = srcPts[-1];
  760. pts[1] = srcPts[0];
  761. pts[2] = srcPts[1];
  762. pts[3] = srcPts[2];
  763. srcPts += 3;
  764. break;
  765. case SkPath::kClose_Verb:
  766. break;
  767. case SkPath::kDone_Verb:
  768. SkASSERT(fVerbs == fVerbStop);
  769. break;
  770. }
  771. fPts = srcPts;
  772. SkASSERT(peekResult == verb);
  773. return (uint8_t) verb;
  774. }
  775. uint8_t SkPathRef::Iter::peek() const {
  776. const uint8_t* next = fVerbs;
  777. return next <= fVerbStop ? (uint8_t) SkPath::kDone_Verb : next[-1];
  778. }
  779. bool SkPathRef::isValid() const {
  780. if (static_cast<ptrdiff_t>(fFreeSpace) < 0) {
  781. return false;
  782. }
  783. if (reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints) < 0) {
  784. return false;
  785. }
  786. if ((nullptr == fPoints) != (nullptr == fVerbs)) {
  787. return false;
  788. }
  789. if (nullptr == fPoints && 0 != fFreeSpace) {
  790. return false;
  791. }
  792. if (nullptr == fPoints && fPointCnt) {
  793. return false;
  794. }
  795. if (nullptr == fVerbs && fVerbCnt) {
  796. return false;
  797. }
  798. if (this->currSize() !=
  799. fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt) {
  800. return false;
  801. }
  802. if (fIsOval || fIsRRect) {
  803. // Currently we don't allow both of these to be set, even though ovals are ro
  804. if (fIsOval == fIsRRect) {
  805. return false;
  806. }
  807. if (fIsOval) {
  808. if (fRRectOrOvalStartIdx >= 4) {
  809. return false;
  810. }
  811. } else {
  812. if (fRRectOrOvalStartIdx >= 8) {
  813. return false;
  814. }
  815. }
  816. }
  817. if (!fBoundsIsDirty && !fBounds.isEmpty()) {
  818. bool isFinite = true;
  819. Sk2s leftTop = Sk2s(fBounds.fLeft, fBounds.fTop);
  820. Sk2s rightBot = Sk2s(fBounds.fRight, fBounds.fBottom);
  821. for (int i = 0; i < fPointCnt; ++i) {
  822. Sk2s point = Sk2s(fPoints[i].fX, fPoints[i].fY);
  823. #ifdef SK_DEBUG
  824. if (fPoints[i].isFinite() &&
  825. ((point < leftTop).anyTrue() || (point > rightBot).anyTrue())) {
  826. SkDebugf("bad SkPathRef bounds: %g %g %g %g\n",
  827. fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
  828. for (int j = 0; j < fPointCnt; ++j) {
  829. if (i == j) {
  830. SkDebugf("*** bounds do not contain: ");
  831. }
  832. SkDebugf("%g %g\n", fPoints[j].fX, fPoints[j].fY);
  833. }
  834. return false;
  835. }
  836. #endif
  837. if (fPoints[i].isFinite() && (point < leftTop).anyTrue() && !(point > rightBot).anyTrue())
  838. return false;
  839. if (!fPoints[i].isFinite()) {
  840. isFinite = false;
  841. }
  842. }
  843. if (SkToBool(fIsFinite) != isFinite) {
  844. return false;
  845. }
  846. }
  847. return true;
  848. }