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