107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#ifndef SkOpContour_DEFINED
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define SkOpContour_DEFINED
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h"
1154359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkTDArray.h"
1254359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkTSort.h"
1307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1454359294a7c9dc54802d512a5d891a35c1663392caryclarkclass SkChunkAlloc;
15624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkenum class SkOpRayDir;
16624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkstruct SkOpRayHit;
1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkPathWriter;
1807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkOpContour {
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpContour() {
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        reset();
2354359294a7c9dc54802d512a5d891a35c1663392caryclark    }
2454359294a7c9dc54802d512a5d891a35c1663392caryclark
2554359294a7c9dc54802d512a5d891a35c1663392caryclark    ~SkOpContour() {
2654359294a7c9dc54802d512a5d891a35c1663392caryclark        if (fNext) {
2754359294a7c9dc54802d512a5d891a35c1663392caryclark            fNext->~SkOpContour();
2854359294a7c9dc54802d512a5d891a35c1663392caryclark        }
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool operator<(const SkOpContour& rh) const {
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds.fTop == rh.fBounds.fTop
3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                ? fBounds.fLeft < rh.fBounds.fLeft
3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                : fBounds.fTop < rh.fBounds.fTop;
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    void addAlignIntersections(SkOpContourHead* contourList, SkChunkAlloc* allocator) {
3827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkASSERT(fCount > 0);
3927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkOpSegment* segment = &fHead;
4027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        do {
4127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            segment->addAlignIntersections(contourList, allocator);
4227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        } while ((segment = segment->next()));
4327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    }
4427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    void addConic(SkPoint pts[3], SkScalar weight, SkChunkAlloc* allocator) {
461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        appendSegment(allocator).addConic(pts, weight, this);
471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
4954359294a7c9dc54802d512a5d891a35c1663392caryclark    void addCubic(SkPoint pts[4], SkChunkAlloc* allocator) {
5054359294a7c9dc54802d512a5d891a35c1663392caryclark        appendSegment(allocator).addCubic(pts, this);
5154359294a7c9dc54802d512a5d891a35c1663392caryclark    }
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark    SkOpSegment* addCurve(SkPath::Verb verb, const SkPoint pts[4], SkChunkAlloc* allocator);
5454359294a7c9dc54802d512a5d891a35c1663392caryclark
5554359294a7c9dc54802d512a5d891a35c1663392caryclark    void addLine(SkPoint pts[2], SkChunkAlloc* allocator) {
5654359294a7c9dc54802d512a5d891a35c1663392caryclark        appendSegment(allocator).addLine(pts, this);
57ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
58570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
5954359294a7c9dc54802d512a5d891a35c1663392caryclark    void addQuad(SkPoint pts[3], SkChunkAlloc* allocator) {
6054359294a7c9dc54802d512a5d891a35c1663392caryclark        appendSegment(allocator).addQuad(pts, this);
6107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6354359294a7c9dc54802d512a5d891a35c1663392caryclark    void align() {
6454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
6554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* segment = &fHead;
6654359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
6754359294a7c9dc54802d512a5d891a35c1663392caryclark            segment->align();
6854359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment& appendSegment(SkChunkAlloc* allocator) {
7254359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* result = fCount++
7354359294a7c9dc54802d512a5d891a35c1663392caryclark                ? SkOpTAllocator<SkOpSegment>::Allocate(allocator) : &fHead;
7454359294a7c9dc54802d512a5d891a35c1663392caryclark        result->setPrev(fTail);
7554359294a7c9dc54802d512a5d891a35c1663392caryclark        if (fTail) {
7654359294a7c9dc54802d512a5d891a35c1663392caryclark            fTail->setNext(result);
7754359294a7c9dc54802d512a5d891a35c1663392caryclark        }
7854359294a7c9dc54802d512a5d891a35c1663392caryclark        fTail = result;
7954359294a7c9dc54802d512a5d891a35c1663392caryclark        return *result;
8007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpContour* appendContour(SkChunkAlloc* allocator) {
8354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpContour* contour = SkOpTAllocator<SkOpContour>::New(allocator);
8496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        contour->setNext(nullptr);
8554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpContour* prev = this;
8654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpContour* next;
8754359294a7c9dc54802d512a5d891a35c1663392caryclark        while ((next = prev->next())) {
8854359294a7c9dc54802d512a5d891a35c1663392caryclark            prev = next;
8954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
9054359294a7c9dc54802d512a5d891a35c1663392caryclark        prev->setNext(contour);
9154359294a7c9dc54802d512a5d891a35c1663392caryclark        return contour;
9254359294a7c9dc54802d512a5d891a35c1663392caryclark    }
9354359294a7c9dc54802d512a5d891a35c1663392caryclark
9454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPathOpsBounds& bounds() const {
9554359294a7c9dc54802d512a5d891a35c1663392caryclark        return fBounds;
9654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
97dac1d17027dcaa5596885a9f333979418b35001ccaryclark
9854359294a7c9dc54802d512a5d891a35c1663392caryclark    void calcAngles(SkChunkAlloc* allocator) {
9954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
10054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* segment = &fHead;
10154359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
10254359294a7c9dc54802d512a5d891a35c1663392caryclark            segment->calcAngles(allocator);
10354359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
104dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
105dac1d17027dcaa5596885a9f333979418b35001ccaryclark
10654359294a7c9dc54802d512a5d891a35c1663392caryclark    void complete() {
10754359294a7c9dc54802d512a5d891a35c1663392caryclark        setBounds();
108dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
109dac1d17027dcaa5596885a9f333979418b35001ccaryclark
11054359294a7c9dc54802d512a5d891a35c1663392caryclark    int count() const {
11154359294a7c9dc54802d512a5d891a35c1663392caryclark        return fCount;
112ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
113dac1d17027dcaa5596885a9f333979418b35001ccaryclark
11454359294a7c9dc54802d512a5d891a35c1663392caryclark    int debugID() const {
1151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        return SkDEBUGRELEASE(fID, -1);
11654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11854359294a7c9dc54802d512a5d891a35c1663392caryclark    int debugIndent() const {
119624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        return SkDEBUGRELEASE(fDebugIndent, 0);
120ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
12107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS
12354359294a7c9dc54802d512a5d891a35c1663392caryclark    void debugShowActiveSpans() {
12454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* segment = &fHead;
12554359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
12654359294a7c9dc54802d512a5d891a35c1663392caryclark            segment->debugShowActiveSpans();
12754359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
1284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
12954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
1304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
13154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* debugAngle(int id) const {
13296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return SkDEBUGRELEASE(this->globalState()->debugAngle(id), nullptr);
13354359294a7c9dc54802d512a5d891a35c1663392caryclark    }
134570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
13526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* ) const;
13626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
13754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpContour* debugContour(int id) {
13896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return SkDEBUGRELEASE(this->globalState()->debugContour(id), nullptr);
1394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log,
14226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                                 const SkOpCoincidence* coincidence) const;
14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
14454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* debugPtT(int id) const {
14596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return SkDEBUGRELEASE(this->globalState()->debugPtT(id), nullptr);
14654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
1474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
14854359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSegment* debugSegment(int id) const {
14996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return SkDEBUGRELEASE(this->globalState()->debugSegment(id), nullptr);
150fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    }
151fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com
15254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* debugSpan(int id) const {
15396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return SkDEBUGRELEASE(this->globalState()->debugSpan(id), nullptr);
15407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpGlobalState* globalState() const {
15754359294a7c9dc54802d512a5d891a35c1663392caryclark        return fState;
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
16054359294a7c9dc54802d512a5d891a35c1663392caryclark    void debugValidate() const {
16154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
16254359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSegment* segment = &fHead;
16396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        const SkOpSegment* prior = nullptr;
16454359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
16554359294a7c9dc54802d512a5d891a35c1663392caryclark            segment->debugValidate();
16654359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(segment->prev() == prior);
16754359294a7c9dc54802d512a5d891a35c1663392caryclark            prior = segment;
16854359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
16954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(prior == fTail);
17054359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
17107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
17207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
17354359294a7c9dc54802d512a5d891a35c1663392caryclark    bool done() const {
17454359294a7c9dc54802d512a5d891a35c1663392caryclark        return fDone;
17507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
17607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
177624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dump() const;
178624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpAll() const;
17954359294a7c9dc54802d512a5d891a35c1663392caryclark    void dumpAngles() const;
180624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContours() const;
181624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursAll() const;
182624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursAngles() const;
183624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursPts() const;
184624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursPt(int segmentID) const;
185624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursSegment(int segmentID) const;
186624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursSpan(int segmentID) const;
187624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void dumpContoursSpans() const;
18854359294a7c9dc54802d512a5d891a35c1663392caryclark    void dumpPt(int ) const;
18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void dumpPts(const char* prefix = "seg") const;
19026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void dumpPtsX(const char* prefix) const;
19154359294a7c9dc54802d512a5d891a35c1663392caryclark    void dumpSegment(int ) const;
19226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void dumpSegments(const char* prefix = "seg", SkPathOp op = (SkPathOp) -1) const;
19354359294a7c9dc54802d512a5d891a35c1663392caryclark    void dumpSpan(int ) const;
19454359294a7c9dc54802d512a5d891a35c1663392caryclark    void dumpSpans() const;
19554359294a7c9dc54802d512a5d891a35c1663392caryclark
19654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& end() const {
19754359294a7c9dc54802d512a5d891a35c1663392caryclark        return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())];
19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
200d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark    bool findCollapsed() {
201d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        SkASSERT(fCount > 0);
202d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        SkOpSegment* segment = &fHead;
203d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        do {
204d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark            segment->findCollapsed();
205d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        } while ((segment = segment->next()));
206d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        return true;
207d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark    }
208d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark
209624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSpan* findSortableTop(SkOpContour* );
210624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
21154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* first() {
21254359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
21354359294a7c9dc54802d512a5d891a35c1663392caryclark        return &fHead;
214ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
215ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
21654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSegment* first() const {
21754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
21854359294a7c9dc54802d512a5d891a35c1663392caryclark        return &fHead;
219ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
220ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
221624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void indentDump() const {
222624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDEBUGCODE(fDebugIndent += 2);
22307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
22407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22554359294a7c9dc54802d512a5d891a35c1663392caryclark    void init(SkOpGlobalState* globalState, bool operand, bool isXor) {
22654359294a7c9dc54802d512a5d891a35c1663392caryclark        fState = globalState;
22754359294a7c9dc54802d512a5d891a35c1663392caryclark        fOperand = operand;
22854359294a7c9dc54802d512a5d891a35c1663392caryclark        fXor = isXor;
2291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDEBUGCODE(fID = globalState->nextContourID());
230dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
231dac1d17027dcaa5596885a9f333979418b35001ccaryclark
2325b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    int isCcw() const {
2335b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        return fCcw;
2345b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    }
2355b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
23654359294a7c9dc54802d512a5d891a35c1663392caryclark    bool isXor() const {
23754359294a7c9dc54802d512a5d891a35c1663392caryclark        return fXor;
23854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
23954359294a7c9dc54802d512a5d891a35c1663392caryclark
2405b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    void markDone() {
2415b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        SkOpSegment* segment = &fHead;
2425b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        do {
2435b5ddd73b4baf22752924bf20d097e96236c36f8caryclark            segment->markAllDone();
2445b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        } while ((segment = segment->next()));
2455b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    }
2465b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
24727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    bool missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) {
24854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
24954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* segment = &fHead;
25027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        bool result = false;
25154359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
25254359294a7c9dc54802d512a5d891a35c1663392caryclark            if (fState->angleCoincidence()) {
25326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
25426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                segment->debugCheckAngleCoin();
25526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
25627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            } else if (segment->missingCoincidence(coincidences, allocator)) {
25727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                result = true;
25827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    // FIXME: trying again loops forever in issue3651_6
25927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    // The continue below is speculative -- once there's an actual case that requires it,
26027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    // add the plumbing necessary to look for another missing coincidence in the same segment
26127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark         //       continue; // try again in case another missing coincidence is further along
26254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
26327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            segment = segment->next();
26427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        } while (segment);
26527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        return result;
26654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
26754359294a7c9dc54802d512a5d891a35c1663392caryclark
26808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    bool moveMultiples() {
26954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
27054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* segment = &fHead;
27154359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
272d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark            if (!segment->moveMultiples()) {
273d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark                return false;
274d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark            }
27554359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
27654359294a7c9dc54802d512a5d891a35c1663392caryclark        return true;
277a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    }
278a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com
27908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    void moveNearby() {
28008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        SkASSERT(fCount > 0);
28108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        SkOpSegment* segment = &fHead;
28208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        do {
28308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            segment->moveNearby();
28408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        } while ((segment = segment->next()));
28508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    }
28608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark
28754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpContour* next() {
28854359294a7c9dc54802d512a5d891a35c1663392caryclark        return fNext;
28907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
29007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
29154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpContour* next() const {
29254359294a7c9dc54802d512a5d891a35c1663392caryclark        return fNext;
293ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
294ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
2950dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    bool operand() const {
2960dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        return fOperand;
29707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
29807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
29954359294a7c9dc54802d512a5d891a35c1663392caryclark    bool oppXor() const {
30054359294a7c9dc54802d512a5d891a35c1663392caryclark        return fOppXor;
30154359294a7c9dc54802d512a5d891a35c1663392caryclark    }
30254359294a7c9dc54802d512a5d891a35c1663392caryclark
303624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void outdentDump() const {
304624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDEBUGCODE(fDebugIndent -= 2);
30554359294a7c9dc54802d512a5d891a35c1663392caryclark    }
30654359294a7c9dc54802d512a5d891a35c1663392caryclark
307624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    void rayCheck(const SkOpRayHit& base, SkOpRayDir dir, SkOpRayHit** hits, SkChunkAlloc* );
308624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
30954359294a7c9dc54802d512a5d891a35c1663392caryclark    void remove(SkOpContour* contour) {
31054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (contour == this) {
31154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(fCount == 0);
31254359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
31354359294a7c9dc54802d512a5d891a35c1663392caryclark        }
31496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkASSERT(contour->fNext == nullptr);
31554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpContour* prev = this;
31654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpContour* next;
31754359294a7c9dc54802d512a5d891a35c1663392caryclark        while ((next = prev->next()) != contour) {
31854359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(next);
31954359294a7c9dc54802d512a5d891a35c1663392caryclark            prev = next;
32054359294a7c9dc54802d512a5d891a35c1663392caryclark        }
32154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(prev);
32296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        prev->setNext(nullptr);
323ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
324dac1d17027dcaa5596885a9f333979418b35001ccaryclark
32554359294a7c9dc54802d512a5d891a35c1663392caryclark    void reset() {
32696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTail = nullptr;
32796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fNext = nullptr;
32854359294a7c9dc54802d512a5d891a35c1663392caryclark        fCount = 0;
32954359294a7c9dc54802d512a5d891a35c1663392caryclark        fDone = false;
33054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDEBUGCODE(fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin));
33154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDEBUGCODE(fFirstSorted = -1);
332624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDEBUGCODE(fDebugIndent = 0);
33354359294a7c9dc54802d512a5d891a35c1663392caryclark    }
33454359294a7c9dc54802d512a5d891a35c1663392caryclark
3355b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    void resetReverse() {
3365b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        SkOpContour* next = this;
3375b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        do {
3385b5ddd73b4baf22752924bf20d097e96236c36f8caryclark            next->fCcw = -1;
3395b5ddd73b4baf22752924bf20d097e96236c36f8caryclark            next->fReverse = false;
3405b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        } while ((next = next->next()));
3415b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    }
3425b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
3435b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    bool reversed() const {
3445b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        return fReverse;
3455b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    }
3465b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
34754359294a7c9dc54802d512a5d891a35c1663392caryclark    void setBounds() {
34854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
34954359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSegment* segment = &fHead;
35054359294a7c9dc54802d512a5d891a35c1663392caryclark        fBounds = segment->bounds();
35154359294a7c9dc54802d512a5d891a35c1663392caryclark        while ((segment = segment->next())) {
35254359294a7c9dc54802d512a5d891a35c1663392caryclark            fBounds.add(segment->bounds());
35354359294a7c9dc54802d512a5d891a35c1663392caryclark        }
35454359294a7c9dc54802d512a5d891a35c1663392caryclark    }
3550dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed
3565b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    void setCcw(int ccw) {
3575b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        fCcw = ccw;
3585b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    }
3595b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
36054359294a7c9dc54802d512a5d891a35c1663392caryclark    void setGlobalState(SkOpGlobalState* state) {
36154359294a7c9dc54802d512a5d891a35c1663392caryclark        fState = state;
36207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
36307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
36454359294a7c9dc54802d512a5d891a35c1663392caryclark    void setNext(SkOpContour* contour) {
36554359294a7c9dc54802d512a5d891a35c1663392caryclark//        SkASSERT(!fNext == !!contour);
36654359294a7c9dc54802d512a5d891a35c1663392caryclark        fNext = contour;
36707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
36807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
36907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setOperand(bool isOp) {
37007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fOperand = isOp;
37107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
37207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
37307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setOppXor(bool isOppXor) {
37407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fOppXor = isOppXor;
37507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
37607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3775b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    void setReverse() {
3785b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        fReverse = true;
3795b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    }
3805b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
38107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setXor(bool isXor) {
38207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fXor = isXor;
38307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
38554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkPath::Verb simplifyCubic(SkPoint pts[4]);
38607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
38754359294a7c9dc54802d512a5d891a35c1663392caryclark    void sortAngles() {
38854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(fCount > 0);
38954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* segment = &fHead;
39054359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
39154359294a7c9dc54802d512a5d891a35c1663392caryclark            segment->sortAngles();
39254359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
39307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
39407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
39554359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& start() const {
39654359294a7c9dc54802d512a5d891a35c1663392caryclark        return fHead.pts()[0];
3970dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
3980dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed
39954359294a7c9dc54802d512a5d891a35c1663392caryclark    void toPartialBackward(SkPathWriter* path) const {
40054359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSegment* segment = fTail;
40154359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
402ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
40354359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->prev()));
4040dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
4050dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed
40654359294a7c9dc54802d512a5d891a35c1663392caryclark    void toPartialForward(SkPathWriter* path) const {
40754359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSegment* segment = &fHead;
40854359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
409ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
41054359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((segment = segment->next()));
4110dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
4120dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed
4135b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    void toReversePath(SkPathWriter* path) const;
41454359294a7c9dc54802d512a5d891a35c1663392caryclark    void toPath(SkPathWriter* path) const;
41554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr);
4164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
41707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comprivate:
41854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpGlobalState* fState;
41954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment fHead;
42054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* fTail;
42154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpContour* fNext;
4220dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    SkPathOpsBounds fBounds;
4235b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    int fCcw;
42454359294a7c9dc54802d512a5d891a35c1663392caryclark    int fCount;
42554359294a7c9dc54802d512a5d891a35c1663392caryclark    int fFirstSorted;
42654359294a7c9dc54802d512a5d891a35c1663392caryclark    bool fDone;  // set by find top segment
42707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fOperand;  // true for the second argument to a binary operator
4285b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    bool fReverse;  // true if contour should be reverse written to path (used only by fix winding)
42954359294a7c9dc54802d512a5d891a35c1663392caryclark    bool fXor;  // set if original path had even-odd fill
43054359294a7c9dc54802d512a5d891a35c1663392caryclark    bool fOppXor;  // set if opposite path had even-odd fill
4311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(int fID);
432624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDEBUGCODE(mutable int fDebugIndent);
433624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark};
434624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
435624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkclass SkOpContourHead : public SkOpContour {
43607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
43707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
43807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
439