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