Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | List of all members
SkOpSegment Class Reference

#include <SkOpSegment.h>

Public Member Functions

bool operator< (const SkOpSegment &rh) const
 
SkOpAngleactiveAngle (SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
 
SkOpAngleactiveAngleInner (SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
 
SkOpAngleactiveAngleOther (SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
 
bool activeOp (SkOpSpanBase *start, SkOpSpanBase *end, int xorMiMask, int xorSuMask, SkPathOp op)
 
bool activeOp (int xorMiMask, int xorSuMask, SkOpSpanBase *start, SkOpSpanBase *end, SkPathOp op, int *sumMiWinding, int *sumSuWinding)
 
bool activeWinding (SkOpSpanBase *start, SkOpSpanBase *end)
 
bool activeWinding (SkOpSpanBase *start, SkOpSpanBase *end, int *sumWinding)
 
SkOpSegmentaddConic (SkPoint pts[3], SkScalar weight, SkOpContour *parent)
 
SkOpSegmentaddCubic (SkPoint pts[4], SkOpContour *parent)
 
bool addCurveTo (const SkOpSpanBase *start, const SkOpSpanBase *end, SkPathWriter *path) const
 
SkOpAngleaddEndSpan ()
 
bool addExpanded (double newT, const SkOpSpanBase *test, bool *startOver)
 
SkOpSegmentaddLine (SkPoint pts[2], SkOpContour *parent)
 
SkOpPtTaddMissing (double t, SkOpSegment *opp, bool *allExist)
 
SkOpAngleaddStartSpan ()
 
SkOpSegmentaddQuad (SkPoint pts[3], SkOpContour *parent)
 
SkOpPtTaddT (double t)
 
SkOpPtTaddT (double t, const SkPoint &pt)
 
const SkPathOpsBoundsbounds () const
 
void bumpCount ()
 
void calcAngles ()
 
SkOpSpanBase::Collapsed collapsed (double startT, double endT) const
 
int computeSum (SkOpSpanBase *start, SkOpSpanBase *end, SkOpAngle::IncludeType includeType)
 
void clearAll ()
 
void clearOne (SkOpSpan *span)
 
bool contains (double t) const
 
SkOpContourcontour () const
 
int count () const
 
void debugAddAngle (double startT, double endT)
 
const SkOpAngledebugAngle (int id) const
 
const SkOpCoincidencedebugCoincidence () const
 
SkOpContourdebugContour (int id) const
 
int debugID () const
 
SkOpAngledebugLastAngle ()
 
const SkOpPtTdebugPtT (int id) const
 
void debugReset ()
 
const SkOpSegmentdebugSegment (int id) const
 
const SkOpSpanBasedebugSpan (int id) const
 
void debugValidate () const
 
bool done () const
 
bool done (const SkOpAngle *angle) const
 
SkDPoint dPtAtT (double mid) const
 
SkDVector dSlopeAtT (double mid) const
 
void dump () const
 
void dumpAll () const
 
void dumpAngles () const
 
void dumpCoin () const
 
void dumpPts (const char *prefix="seg") const
 
void dumpPtsInner (const char *prefix="seg") const
 
const SkOpPtTexisting (double t, const SkOpSegment *opp) const
 
SkOpSegmentfindNextOp (SkTDArray< SkOpSpanBase * > *chase, SkOpSpanBase **nextStart, SkOpSpanBase **nextEnd, bool *unsortable, bool *simple, SkPathOp op, int xorMiMask, int xorSuMask)
 
SkOpSegmentfindNextWinding (SkTDArray< SkOpSpanBase * > *chase, SkOpSpanBase **nextStart, SkOpSpanBase **nextEnd, bool *unsortable)
 
SkOpSegmentfindNextXor (SkOpSpanBase **nextStart, SkOpSpanBase **nextEnd, bool *unsortable)
 
SkOpSpanfindSortableTop (SkOpContour *)
 
SkOpGlobalStateglobalState () const
 
const SkOpSpanhead () const
 
SkOpSpanhead ()
 
void init (SkPoint pts[], SkScalar weight, SkOpContour *parent, SkPath::Verb verb)
 
SkOpSpaninsert (SkOpSpan *prev)
 
bool isClose (double t, const SkOpSegment *opp) const
 
bool isHorizontal () const
 
SkOpSegmentisSimple (SkOpSpanBase **end, int *step) const
 
bool isVertical () const
 
bool isVertical (SkOpSpanBase *start, SkOpSpanBase *end) const
 
bool isXor () const
 
void joinEnds (SkOpSegment *start)
 
const SkPointlastPt () const
 
void markAllDone ()
 
bool markAndChaseDone (SkOpSpanBase *start, SkOpSpanBase *end, SkOpSpanBase **found)
 
bool markAndChaseWinding (SkOpSpanBase *start, SkOpSpanBase *end, int winding, SkOpSpanBase **lastPtr)
 
bool markAndChaseWinding (SkOpSpanBase *start, SkOpSpanBase *end, int winding, int oppWinding, SkOpSpanBase **lastPtr)
 
bool markAngle (int maxWinding, int sumWinding, const SkOpAngle *angle, SkOpSpanBase **result)
 
bool markAngle (int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding, const SkOpAngle *angle, SkOpSpanBase **result)
 
void markDone (SkOpSpan *)
 
bool markWinding (SkOpSpan *, int winding)
 
bool markWinding (SkOpSpan *, int winding, int oppWinding)
 
bool match (const SkOpPtT *span, const SkOpSegment *parent, double t, const SkPoint &pt) const
 
bool missingCoincidence ()
 
bool moveMultiples ()
 
bool moveNearby ()
 
SkOpSegmentnext () const
 
SkOpSegmentnextChase (SkOpSpanBase **, int *step, SkOpSpan **, SkOpSpanBase **last) const
 
bool operand () const
 
bool oppXor () const
 
const SkOpSegmentprev () const
 
SkPoint ptAtT (double mid) const
 
const SkPointpts () const
 
bool ptsDisjoint (const SkOpPtT &span, const SkOpPtT &test) const
 
bool ptsDisjoint (const SkOpPtT &span, double t, const SkPoint &pt) const
 
bool ptsDisjoint (double t1, const SkPoint &pt1, double t2, const SkPoint &pt2) const
 
void rayCheck (const SkOpRayHit &base, SkOpRayDir dir, SkOpRayHit **hits, SkArenaAlloc *)
 
void release (const SkOpSpan *)
 
void resetVisited ()
 
void setContour (SkOpContour *contour)
 
void setNext (SkOpSegment *next)
 
void setPrev (SkOpSegment *prev)
 
void setUpWinding (SkOpSpanBase *start, SkOpSpanBase *end, int *maxWinding, int *sumWinding)
 
void setUpWindings (SkOpSpanBase *start, SkOpSpanBase *end, int *sumMiWinding, int *maxWinding, int *sumWinding)
 
void setUpWindings (SkOpSpanBase *start, SkOpSpanBase *end, int *sumMiWinding, int *sumSuWinding, int *maxWinding, int *sumWinding, int *oppMaxWinding, int *oppSumWinding)
 
bool sortAngles ()
 
bool spansNearby (const SkOpSpanBase *ref, const SkOpSpanBase *check, bool *found) const
 
SkOpAnglespanToAngle (SkOpSpanBase *start, SkOpSpanBase *end)
 
bool subDivide (const SkOpSpanBase *start, const SkOpSpanBase *end, SkDCurve *result) const
 
const SkOpSpanBasetail () const
 
SkOpSpanBasetail ()
 
bool testForCoincidence (const SkOpPtT *priorPtT, const SkOpPtT *ptT, const SkOpSpanBase *prior, const SkOpSpanBase *spanBase, const SkOpSegment *opp) const
 
SkOpSpanundoneSpan ()
 
int updateOppWinding (const SkOpSpanBase *start, const SkOpSpanBase *end) const
 
int updateOppWinding (const SkOpAngle *angle) const
 
int updateOppWindingReverse (const SkOpAngle *angle) const
 
int updateWinding (SkOpSpanBase *start, SkOpSpanBase *end)
 
int updateWinding (SkOpAngle *angle)
 
int updateWindingReverse (const SkOpAngle *angle)
 
SkPath::Verb verb () const
 
bool visited ()
 
SkScalar weight () const
 
SkOpSpanwindingSpanAtT (double tHit)
 
int windSum (const SkOpAngle *angle) const
 

Static Public Member Functions

static bool ComputeOneSum (const SkOpAngle *baseAngle, SkOpAngle *nextAngle, SkOpAngle::IncludeType)
 
static bool ComputeOneSumReverse (SkOpAngle *baseAngle, SkOpAngle *nextAngle, SkOpAngle::IncludeType)
 
static void ClearVisited (SkOpSpanBase *span)
 
static int OppSign (const SkOpSpanBase *start, const SkOpSpanBase *end)
 
static int SpanSign (const SkOpSpanBase *start, const SkOpSpanBase *end)
 
static bool UseInnerWinding (int outerWinding, int innerWinding)
 

Detailed Description

Definition at line 35 of file SkOpSegment.h.

Member Function Documentation

◆ activeAngle()

SkOpAngle * SkOpSegment::activeAngle ( SkOpSpanBase start,
SkOpSpanBase **  startPtr,
SkOpSpanBase **  endPtr,
bool *  done 
)

Definition at line 54 of file SkOpSegment.cpp.

55 {
56 if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done)) {
57 return result;
58 }
59 if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done)) {
60 return result;
61 }
62 return nullptr;
63}
bool done() const
SkOpAngle * activeAngleOther(SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
SkOpAngle * activeAngleInner(SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
GAsyncResult * result

◆ activeAngleInner()

SkOpAngle * SkOpSegment::activeAngleInner ( SkOpSpanBase start,
SkOpSpanBase **  startPtr,
SkOpSpanBase **  endPtr,
bool *  done 
)

Definition at line 65 of file SkOpSegment.cpp.

66 {
67 SkOpSpan* upSpan = start->upCastable();
68 if (upSpan) {
69 if (upSpan->windValue() || upSpan->oppValue()) {
70 SkOpSpanBase* next = upSpan->next();
71 if (!*endPtr) {
72 *startPtr = start;
73 *endPtr = next;
74 }
75 if (!upSpan->done()) {
76 if (upSpan->windSum() != SK_MinS32) {
77 return spanToAngle(start, next);
78 }
79 *done = false;
80 }
81 } else {
82 SkASSERT(upSpan->done());
83 }
84 }
85 SkOpSpan* downSpan = start->prev();
86 // edge leading into junction
87 if (downSpan) {
88 if (downSpan->windValue() || downSpan->oppValue()) {
89 if (!*endPtr) {
90 *startPtr = start;
91 *endPtr = downSpan;
92 }
93 if (!downSpan->done()) {
94 if (downSpan->windSum() != SK_MinS32) {
95 return spanToAngle(start, downSpan);
96 }
97 *done = false;
98 }
99 } else {
100 SkASSERT(downSpan->done());
101 }
102 }
103 return nullptr;
104}
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr int32_t SK_MinS32
Definition SkMath.h:22
SkOpAngle * spanToAngle(SkOpSpanBase *start, SkOpSpanBase *end)
SkOpSegment * next() const
const SkOpSpan * prev() const
Definition SkOpSpan.h:298
SkOpSpan * upCastable()
Definition SkOpSpan.h:393
int windSum() const
Definition SkOpSpan.h:555
SkOpSpanBase * next() const
Definition SkOpSpan.h:495
int oppValue() const
Definition SkOpSpan.h:505
bool done() const
Definition SkOpSpan.h:459
int windValue() const
Definition SkOpSpan.h:560

◆ activeAngleOther()

SkOpAngle * SkOpSegment::activeAngleOther ( SkOpSpanBase start,
SkOpSpanBase **  startPtr,
SkOpSpanBase **  endPtr,
bool *  done 
)

Definition at line 106 of file SkOpSegment.cpp.

107 {
108 SkOpPtT* oPtT = start->ptT()->next();
109 SkOpSegment* other = oPtT->segment();
110 SkOpSpanBase* oSpan = oPtT->span();
111 return other->activeAngleInner(oSpan, startPtr, endPtr, done);
112}
const SkOpSpanBase * span() const
Definition SkOpSpan.h:154
const SkOpPtT * next() const
Definition SkOpSpan.h:93
const SkOpSegment * segment() const
Definition SkOpSpan.cpp:144

◆ activeOp() [1/2]

bool SkOpSegment::activeOp ( int  xorMiMask,
int  xorSuMask,
SkOpSpanBase start,
SkOpSpanBase end,
SkPathOp  op,
int sumMiWinding,
int sumSuWinding 
)

Definition at line 129 of file SkOpSegment.cpp.

130 {
131 int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
132 this->setUpWindings(start, end, sumMiWinding, sumSuWinding,
133 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
134 bool miFrom;
135 bool miTo;
136 bool suFrom;
137 bool suTo;
138 if (operand()) {
139 miFrom = (oppMaxWinding & xorMiMask) != 0;
140 miTo = (oppSumWinding & xorMiMask) != 0;
141 suFrom = (maxWinding & xorSuMask) != 0;
142 suTo = (sumWinding & xorSuMask) != 0;
143 } else {
144 miFrom = (maxWinding & xorMiMask) != 0;
145 miTo = (sumWinding & xorMiMask) != 0;
146 suFrom = (oppMaxWinding & xorSuMask) != 0;
147 suTo = (oppSumWinding & xorSuMask) != 0;
148 }
149 bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
150#if DEBUG_ACTIVE_OP
151 SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n",
152 __FUNCTION__, debugID(), start->t(), end->t(),
153 SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result);
154#endif
155 return result;
156}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static const bool gActiveEdge[kXOR_SkPathOp+1][2][2][2][2]
bool operand() const
void setUpWindings(SkOpSpanBase *start, SkOpSpanBase *end, int *sumMiWinding, int *maxWinding, int *sumWinding)
int debugID() const
glong glong end

◆ activeOp() [2/2]

bool SkOpSegment::activeOp ( SkOpSpanBase start,
SkOpSpanBase end,
int  xorMiMask,
int  xorSuMask,
SkPathOp  op 
)

Definition at line 114 of file SkOpSegment.cpp.

115 {
116 int sumMiWinding = this->updateWinding(end, start);
117 int sumSuWinding = this->updateOppWinding(end, start);
118#if DEBUG_LIMIT_WIND_SUM
119 SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM);
120 SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM);
121#endif
122 if (this->operand()) {
123 using std::swap;
124 swap(sumMiWinding, sumSuWinding);
125 }
126 return this->activeOp(xorMiMask, xorSuMask, start, end, op, &sumMiWinding, &sumSuWinding);
127}
#define DEBUG_LIMIT_WIND_SUM
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition SkRefCnt.h:341
int updateWinding(SkOpSpanBase *start, SkOpSpanBase *end)
bool activeOp(SkOpSpanBase *start, SkOpSpanBase *end, int xorMiMask, int xorSuMask, SkPathOp op)
int updateOppWinding(const SkOpSpanBase *start, const SkOpSpanBase *end) const
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition SkVx.h:707

◆ activeWinding() [1/2]

bool SkOpSegment::activeWinding ( SkOpSpanBase start,
SkOpSpanBase end 
)

Definition at line 158 of file SkOpSegment.cpp.

158 {
159 int sumWinding = updateWinding(end, start);
160 return activeWinding(start, end, &sumWinding);
161}
bool activeWinding(SkOpSpanBase *start, SkOpSpanBase *end)

◆ activeWinding() [2/2]

bool SkOpSegment::activeWinding ( SkOpSpanBase start,
SkOpSpanBase end,
int sumWinding 
)

Definition at line 163 of file SkOpSegment.cpp.

163 {
164 int maxWinding;
165 setUpWinding(start, end, &maxWinding, sumWinding);
166 bool from = maxWinding != 0;
167 bool to = *sumWinding != 0;
168 bool result = gUnaryActiveEdge[from][to];
169 return result;
170}
static const bool gUnaryActiveEdge[2][2]
void setUpWinding(SkOpSpanBase *start, SkOpSpanBase *end, int *maxWinding, int *sumWinding)

◆ addConic()

SkOpSegment * SkOpSegment::addConic ( SkPoint  pts[3],
SkScalar  weight,
SkOpContour parent 
)
inline

Definition at line 55 of file SkOpSegment.h.

55 {
57 SkDCurve curve;
58 curve.fConic.set(pts, weight);
59 curve.setConicBounds(pts, weight, 0, 1, &fBounds);
60 return this;
61 }
void init(SkPoint pts[], SkScalar weight, SkOpContour *parent, SkPath::Verb verb)
SkScalar weight() const
const SkPoint * pts() const
@ kConic_Verb
Definition SkPath.h:1461
const SkDConic & set(const SkPoint pts[kPointCount], SkScalar weight SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))
SkDConic fConic
void setConicBounds(const SkPoint curve[3], SkScalar curveWeight, double s, double e, SkPathOpsBounds *)

◆ addCubic()

SkOpSegment * SkOpSegment::addCubic ( SkPoint  pts[4],
SkOpContour parent 
)
inline

Definition at line 63 of file SkOpSegment.h.

63 {
64 init(pts, 1, parent, SkPath::kCubic_Verb);
65 SkDCurve curve;
66 curve.fCubic.set(pts);
67 curve.setCubicBounds(pts, 1, 0, 1, &fBounds);
68 return this;
69 }
@ kCubic_Verb
Definition SkPath.h:1462
const SkDCubic & set(const SkPoint pts[kPointCount] SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))
void setCubicBounds(const SkPoint curve[4], SkScalar, double s, double e, SkPathOpsBounds *)
SkDCubic fCubic

◆ addCurveTo()

bool SkOpSegment::addCurveTo ( const SkOpSpanBase start,
const SkOpSpanBase end,
SkPathWriter path 
) const

Definition at line 172 of file SkOpSegment.cpp.

173 {
174 const SkOpSpan* spanStart = start->starter(end);
175 FAIL_IF(spanStart->alreadyAdded());
176 const_cast<SkOpSpan*>(spanStart)->markAdded();
177 SkDCurveSweep curvePart;
178 start->segment()->subDivide(start, end, &curvePart.fCurve);
179 curvePart.setCurveHullSweep(fVerb);
180 SkPath::Verb verb = curvePart.isCurve() ? fVerb : SkPath::kLine_Verb;
181 path->deferredMove(start->ptT());
182 switch (verb) {
184 FAIL_IF(!path->deferredLine(end->ptT()));
185 break;
187 path->quadTo(curvePart.fCurve.fQuad[1].asSkPoint(), end->ptT());
188 break;
190 path->conicTo(curvePart.fCurve.fConic[1].asSkPoint(), end->ptT(),
191 curvePart.fCurve.fConic.fWeight);
192 break;
194 path->cubicTo(curvePart.fCurve.fCubic[1].asSkPoint(),
195 curvePart.fCurve.fCubic[2].asSkPoint(), end->ptT());
196 break;
197 default:
198 SkASSERT(0);
199 }
200 return true;
201}
#define FAIL_IF(cond)
bool isCurve() const
void setCurveHullSweep(SkPath::Verb verb)
SkPath::Verb verb() const
const SkOpSpan * starter(const SkOpSpanBase *end) const
Definition SkOpSpan.h:347
bool alreadyAdded() const
Definition SkOpSpan.h:420
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
SkScalar fWeight
SkDQuad fQuad

◆ addEndSpan()

SkOpAngle * SkOpSegment::addEndSpan ( )
inline

Definition at line 73 of file SkOpSegment.h.

73 {
74 SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>();
75 angle->set(&fTail, fTail.prev());
76 fTail.setFromAngle(angle);
77 return angle;
78 }
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
void set(SkOpSpanBase *start, SkOpSpanBase *end)
SkArenaAlloc * allocator()
SkOpGlobalState * globalState() const
void setFromAngle(SkOpAngle *angle)
Definition SkOpSpan.h:330

◆ addExpanded()

bool SkOpSegment::addExpanded ( double  newT,
const SkOpSpanBase test,
bool *  startOver 
)

Definition at line 235 of file SkOpSegment.cpp.

235 {
236 if (this->contains(newT)) {
237 return true;
238 }
240 FAIL_IF(!between(0, newT, 1));
241 SkOpPtT* newPtT = this->addT(newT);
242 *startOver |= this->globalState()->allocatedOpSpan();
243 if (!newPtT) {
244 return false;
245 }
246 newPtT->fPt = this->ptAtT(newT);
247 SkOpPtT* oppPrev = test->ptT()->oppPrev(newPtT);
248 if (oppPrev) {
249 // const cast away to change linked list; pt/t values stays unchanged
250 SkOpSpanBase* writableTest = const_cast<SkOpSpanBase*>(test);
251 writableTest->mergeMatches(newPtT->span());
252 writableTest->ptT()->addOpp(newPtT, oppPrev);
253 writableTest->checkForCollapsedCoincidence();
254 }
255 return true;
256}
#define test(name)
static bool between(SkScalar a, SkScalar b, SkScalar c)
bool allocatedOpSpan() const
void resetAllocatedOpSpan()
SkPoint fPt
Definition SkOpSpan.h:167
void addOpp(SkOpPtT *opp, SkOpPtT *oppPrev)
Definition SkOpSpan.h:34
SkPoint ptAtT(double mid) const
SkOpPtT * addT(double t)
bool contains(double t) const
bool mergeMatches(SkOpSpanBase *opp)
Definition SkOpSpan.cpp:313
void checkForCollapsedCoincidence()
Definition SkOpSpan.cpp:288
const SkOpPtT * ptT() const
Definition SkOpSpan.h:310

◆ addLine()

SkOpSegment * SkOpSegment::addLine ( SkPoint  pts[2],
SkOpContour parent 
)
inline

Definition at line 82 of file SkOpSegment.h.

82 {
83 SkASSERT(pts[0] != pts[1]);
84 init(pts, 1, parent, SkPath::kLine_Verb);
85 fBounds.setBounds(pts, 2);
86 return this;
87 }
void setBounds(const SkPoint pts[], int count)
Definition SkRect.h:881

◆ addMissing()

SkOpPtT * SkOpSegment::addMissing ( double  t,
SkOpSegment opp,
bool *  allExist 
)

◆ addQuad()

SkOpSegment * SkOpSegment::addQuad ( SkPoint  pts[3],
SkOpContour parent 
)
inline

Definition at line 98 of file SkOpSegment.h.

98 {
99 init(pts, 1, parent, SkPath::kQuad_Verb);
100 SkDCurve curve;
101 curve.fQuad.set(pts);
102 curve.setQuadBounds(pts, 1, 0, 1, &fBounds);
103 return this;
104 }
void setQuadBounds(const SkPoint curve[3], SkScalar, double s, double e, SkPathOpsBounds *)
const SkDQuad & set(const SkPoint pts[kPointCount] SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))

◆ addStartSpan()

SkOpAngle * SkOpSegment::addStartSpan ( )
inline

Definition at line 91 of file SkOpSegment.h.

91 {
92 SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>();
93 angle->set(&fHead, fHead.next());
94 fHead.setToAngle(angle);
95 return angle;
96 }
void setToAngle(SkOpAngle *angle)
Definition SkOpSpan.h:533

◆ addT() [1/2]

SkOpPtT * SkOpSegment::addT ( double  t)

Definition at line 288 of file SkOpSegment.cpp.

288 {
289 return addT(t, this->ptAtT(t));
290}

◆ addT() [2/2]

SkOpPtT * SkOpSegment::addT ( double  t,
const SkPoint pt 
)

Definition at line 259 of file SkOpSegment.cpp.

259 {
261 SkOpSpanBase* spanBase = &fHead;
262 do {
263 SkOpPtT* result = spanBase->ptT();
264 if (t == result->fT || (!zero_or_one(t) && this->match(result, this, t, pt))) {
265 spanBase->bumpSpanAdds();
266 return result;
267 }
268 if (t < result->fT) {
269 SkOpSpan* prev = result->span()->prev();
271 // marks in global state that new op span has been allocated
272 SkOpSpan* span = this->insert(prev);
273 span->init(this, prev, t, pt);
274 this->debugValidate();
275#if DEBUG_ADD_T
276 SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t,
277 span->segment()->debugID(), span->debugID());
278#endif
279 span->bumpSpanAdds();
280 return span->ptT();
281 }
282 FAIL_WITH_NULL_IF(spanBase == &fTail);
283 } while ((spanBase = spanBase->upCast()->next()));
284 SkASSERT(0);
285 return nullptr; // we never get here, but need this to satisfy compiler
286}
#define FAIL_WITH_NULL_IF(cond, span)
bool zero_or_one(double x)
void debugValidate() const
bool match(const SkOpPtT *span, const SkOpSegment *parent, double t, const SkPoint &pt) const
const SkOpSegment * prev() const
SkOpSpan * insert(SkOpSpan *prev)
void bumpSpanAdds()
Definition SkOpSpan.h:188
int debugID() const
Definition SkOpSpan.h:224
SkOpSpan * upCast()
Definition SkOpSpan.h:383
SkOpSegment * segment() const
Definition SkOpSpan.h:318
void init(SkOpSegment *parent, SkOpSpan *prev, double t, const SkPoint &pt)
Definition SkOpSpan.cpp:398

◆ bounds()

const SkPathOpsBounds & SkOpSegment::bounds ( ) const
inline

Definition at line 109 of file SkOpSegment.h.

109 {
110 return fBounds;
111 }

◆ bumpCount()

void SkOpSegment::bumpCount ( )
inline

Definition at line 113 of file SkOpSegment.h.

113 {
114 ++fCount;
115 }

◆ calcAngles()

void SkOpSegment::calcAngles ( )

Definition at line 292 of file SkOpSegment.cpp.

292 {
293 bool activePrior = !fHead.isCanceled();
294 if (activePrior && !fHead.simple()) {
295 addStartSpan();
296 }
297 SkOpSpan* prior = &fHead;
298 SkOpSpanBase* spanBase = fHead.next();
299 while (spanBase != &fTail) {
300 if (activePrior) {
301 SkOpAngle* priorAngle = this->globalState()->allocator()->make<SkOpAngle>();
302 priorAngle->set(spanBase, prior);
303 spanBase->setFromAngle(priorAngle);
304 }
305 SkOpSpan* span = spanBase->upCast();
306 bool active = !span->isCanceled();
307 SkOpSpanBase* next = span->next();
308 if (active) {
309 SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>();
310 angle->set(span, next);
311 span->setToAngle(angle);
312 }
313 activePrior = active;
314 prior = span;
315 spanBase = next;
316 }
317 if (activePrior && !fTail.simple()) {
318 addEndSpan();
319 }
320}
SkOpAngle * addStartSpan()
Definition SkOpSegment.h:91
SkOpAngle * addEndSpan()
Definition SkOpSegment.h:73
bool simple() const
Definition SkOpSpan.h:338
bool isCanceled() const
Definition SkOpSpan.h:481

◆ clearAll()

void SkOpSegment::clearAll ( )

Definition at line 323 of file SkOpSegment.cpp.

323 {
324 SkOpSpan* span = &fHead;
325 do {
326 this->clearOne(span);
327 } while ((span = span->next()->upCastable()));
328 this->globalState()->coincidence()->release(this);
329}
void release(const SkOpSegment *)
SkOpCoincidence * coincidence()
void clearOne(SkOpSpan *span)

◆ clearOne()

void SkOpSegment::clearOne ( SkOpSpan span)

Definition at line 332 of file SkOpSegment.cpp.

332 {
333 span->setWindValue(0);
334 span->setOppValue(0);
335 this->markDone(span);
336}
void markDone(SkOpSpan *)
void setWindValue(int windValue)
Definition SkOpSpan.h:540
void setOppValue(int oppValue)
Definition SkOpSpan.h:526

◆ ClearVisited()

void SkOpSegment::ClearVisited ( SkOpSpanBase span)
static

Definition at line 1140 of file SkOpSegment.cpp.

1140 {
1141 // reset visited flag back to false
1142 do {
1143 SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
1144 while ((ptT = ptT->next()) != stopPtT) {
1145 SkOpSegment* opp = ptT->segment();
1146 opp->resetVisited();
1147 }
1148 } while (!span->final() && (span = span->upCast()->next()));
1149}
void resetVisited()
bool final() const
Definition SkOpSpan.h:271

◆ collapsed()

SkOpSpanBase::Collapsed SkOpSegment::collapsed ( double  startT,
double  endT 
) const

Definition at line 338 of file SkOpSegment.cpp.

338 {
339 const SkOpSpanBase* span = &fHead;
340 do {
343 return result;
344 }
345 } while (span->upCastable() && (span = span->upCast()->next()));
347}
Collapsed collapsed(double s, double e) const
Definition SkOpSpan.cpp:169
struct MyStruct s

◆ ComputeOneSum()

bool SkOpSegment::ComputeOneSum ( const SkOpAngle baseAngle,
SkOpAngle nextAngle,
SkOpAngle::IncludeType  includeType 
)
static

Definition at line 349 of file SkOpSegment.cpp.

350 {
351 SkOpSegment* baseSegment = baseAngle->segment();
352 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
353 int sumSuWinding;
354 bool binary = includeType >= SkOpAngle::kBinarySingle;
355 if (binary) {
356 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle);
357 if (baseSegment->operand()) {
358 using std::swap;
359 swap(sumMiWinding, sumSuWinding);
360 }
361 }
362 SkOpSegment* nextSegment = nextAngle->segment();
363 int maxWinding, sumWinding;
364 SkOpSpanBase* last = nullptr;
365 if (binary) {
366 int oppMaxWinding, oppSumWinding;
367 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding,
368 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
369 if (!nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding,
370 nextAngle, &last)) {
371 return false;
372 }
373 } else {
374 nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding,
375 &maxWinding, &sumWinding);
376 if (!nextSegment->markAngle(maxWinding, sumWinding, nextAngle, &last)) {
377 return false;
378 }
379 }
380 nextAngle->setLastMarked(last);
381 return true;
382}
SkOpSegment * segment() const
SkOpSpanBase * end() const
Definition SkOpAngle.h:73
void setLastMarked(SkOpSpanBase *marked)
Definition SkOpAngle.h:90
@ kBinarySingle
Definition SkOpAngle.h:37
SkOpSpanBase * start() const
Definition SkOpAngle.h:94
int updateWindingReverse(const SkOpAngle *angle)
int updateOppWindingReverse(const SkOpAngle *angle) const
bool markAngle(int maxWinding, int sumWinding, const SkOpAngle *angle, SkOpSpanBase **result)

◆ ComputeOneSumReverse()

bool SkOpSegment::ComputeOneSumReverse ( SkOpAngle baseAngle,
SkOpAngle nextAngle,
SkOpAngle::IncludeType  includeType 
)
static

Definition at line 384 of file SkOpSegment.cpp.

385 {
386 SkOpSegment* baseSegment = baseAngle->segment();
387 int sumMiWinding = baseSegment->updateWinding(baseAngle);
388 int sumSuWinding;
389 bool binary = includeType >= SkOpAngle::kBinarySingle;
390 if (binary) {
391 sumSuWinding = baseSegment->updateOppWinding(baseAngle);
392 if (baseSegment->operand()) {
393 using std::swap;
394 swap(sumMiWinding, sumSuWinding);
395 }
396 }
397 SkOpSegment* nextSegment = nextAngle->segment();
398 int maxWinding, sumWinding;
399 SkOpSpanBase* last = nullptr;
400 if (binary) {
401 int oppMaxWinding, oppSumWinding;
402 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding,
403 &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
404 if (!nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding,
405 nextAngle, &last)) {
406 return false;
407 }
408 } else {
409 nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding,
410 &maxWinding, &sumWinding);
411 if (!nextSegment->markAngle(maxWinding, sumWinding, nextAngle, &last)) {
412 return false;
413 }
414 }
415 nextAngle->setLastMarked(last);
416 return true;
417}

◆ computeSum()

int SkOpSegment::computeSum ( SkOpSpanBase start,
SkOpSpanBase end,
SkOpAngle::IncludeType  includeType 
)

Definition at line 420 of file SkOpSegment.cpp.

421 {
422 SkASSERT(includeType != SkOpAngle::kUnaryXor);
423 SkOpAngle* firstAngle = this->spanToAngle(end, start);
424 if (nullptr == firstAngle || nullptr == firstAngle->next()) {
425 return SK_NaN32;
426 }
427 // if all angles have a computed winding,
428 // or if no adjacent angles are orderable,
429 // or if adjacent orderable angles have no computed winding,
430 // there's nothing to do
431 // if two orderable angles are adjacent, and both are next to orderable angles,
432 // and one has winding computed, transfer to the other
433 SkOpAngle* baseAngle = nullptr;
434 bool tryReverse = false;
435 // look for counterclockwise transfers
436 SkOpAngle* angle = firstAngle->previous();
437 SkOpAngle* next = angle->next();
438 firstAngle = next;
439 do {
440 SkOpAngle* prior = angle;
441 angle = next;
442 next = angle->next();
443 SkASSERT(prior->next() == angle);
444 SkASSERT(angle->next() == next);
445 if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
446 baseAngle = nullptr;
447 continue;
448 }
449 int testWinding = angle->starter()->windSum();
450 if (SK_MinS32 != testWinding) {
451 baseAngle = angle;
452 tryReverse = true;
453 continue;
454 }
455 if (baseAngle) {
456 ComputeOneSum(baseAngle, angle, includeType);
457 baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr;
458 }
459 } while (next != firstAngle);
460 if (baseAngle && SK_MinS32 == firstAngle->starter()->windSum()) {
461 firstAngle = baseAngle;
462 tryReverse = true;
463 }
464 if (tryReverse) {
465 baseAngle = nullptr;
466 SkOpAngle* prior = firstAngle;
467 do {
468 angle = prior;
469 prior = angle->previous();
470 SkASSERT(prior->next() == angle);
471 next = angle->next();
472 if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
473 baseAngle = nullptr;
474 continue;
475 }
476 int testWinding = angle->starter()->windSum();
477 if (SK_MinS32 != testWinding) {
478 baseAngle = angle;
479 continue;
480 }
481 if (baseAngle) {
482 ComputeOneSumReverse(baseAngle, angle, includeType);
483 baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr;
484 }
485 } while (prior != firstAngle);
486 }
487 return start->starter(end)->windSum();
488}
static constexpr int32_t SK_NaN32
Definition SkMath.h:23
bool unorderable() const
Definition SkOpAngle.h:104
SkOpAngle * next() const
Definition SkOpAngle.h:82
SkOpAngle * previous() const
SkOpSpan * starter()
static bool ComputeOneSum(const SkOpAngle *baseAngle, SkOpAngle *nextAngle, SkOpAngle::IncludeType)
static bool ComputeOneSumReverse(SkOpAngle *baseAngle, SkOpAngle *nextAngle, SkOpAngle::IncludeType)

◆ contains()

bool SkOpSegment::contains ( double  t) const

Definition at line 490 of file SkOpSegment.cpp.

490 {
491 const SkOpSpanBase* spanBase = &fHead;
492 do {
493 if (spanBase->ptT()->contains(this, newT)) {
494 return true;
495 }
496 if (spanBase == &fTail) {
497 break;
498 }
499 spanBase = spanBase->upCast()->next();
500 } while (true);
501 return false;
502}
bool contains(const SkOpPtT *) const
Definition SkOpSpan.cpp:36

◆ contour()

SkOpContour * SkOpSegment::contour ( ) const
inline

Definition at line 130 of file SkOpSegment.h.

130 {
131 return fContour;
132 }

◆ count()

int SkOpSegment::count ( ) const
inline

Definition at line 134 of file SkOpSegment.h.

134 {
135 return fCount;
136 }

◆ debugAddAngle()

void SkOpSegment::debugAddAngle ( double  startT,
double  endT 
)

Definition at line 1548 of file PathOpsDebug.cpp.

1548 {
1549 SkOpPtT* startPtT = startT == 0 ? fHead.ptT() : startT == 1 ? fTail.ptT()
1550 : this->addT(startT);
1551 SkOpPtT* endPtT = endT == 0 ? fHead.ptT() : endT == 1 ? fTail.ptT()
1552 : this->addT(endT);
1553 SkOpAngle* angle = this->globalState()->allocator()->make<SkOpAngle>();
1554 SkOpSpanBase* startSpan = &fHead;
1555 while (startSpan->ptT() != startPtT) {
1556 startSpan = startSpan->upCast()->next();
1557 }
1558 SkOpSpanBase* endSpan = &fHead;
1559 while (endSpan->ptT() != endPtT) {
1560 endSpan = endSpan->upCast()->next();
1561 }
1562 angle->set(startSpan, endSpan);
1563 if (startT < endT) {
1564 startSpan->upCast()->setToAngle(angle);
1565 endSpan->setFromAngle(angle);
1566 } else {
1567 endSpan->upCast()->setToAngle(angle);
1568 startSpan->setFromAngle(angle);
1569 }
1570}

◆ debugAngle()

const SkOpAngle * SkOpSegment::debugAngle ( int  id) const

Definition at line 828 of file PathOpsDebug.cpp.

828 {
829 return this->contour()->debugAngle(id);
830}
const SkOpAngle * debugAngle(int id) const
Definition SkOpContour.h:96
SkOpContour * contour() const

◆ debugCoincidence()

const SkOpCoincidence * SkOpSegment::debugCoincidence ( ) const

Definition at line 832 of file PathOpsDebug.cpp.

832 {
833 return this->contour()->debugCoincidence();
834}
const SkOpCoincidence * debugCoincidence() const

◆ debugContour()

SkOpContour * SkOpSegment::debugContour ( int  id) const

Definition at line 836 of file PathOpsDebug.cpp.

836 {
837 return this->contour()->debugContour(id);
838}
SkOpContour * debugContour(int id) const

◆ debugID()

int SkOpSegment::debugID ( ) const
inline

Definition at line 154 of file SkOpSegment.h.

154 {
155 return SkDEBUGRELEASE(fID, -1);
156 }
#define SkDEBUGRELEASE(a, b)

◆ debugLastAngle()

SkOpAngle * SkOpSegment::debugLastAngle ( )

Definition at line 805 of file SkPathOpsDebug.cpp.

805 {
806 SkOpAngle* result = nullptr;
807 SkOpSpan* span = this->head();
808 do {
809 if (span->toAngle()) {
811 result = span->toAngle();
812 }
813 } while ((span = span->next()->upCastable()));
815 return result;
816}
const SkOpSpan * head() const
SkOpAngle * toAngle() const
Definition SkOpSpan.h:550

◆ debugPtT()

const SkOpPtT * SkOpSegment::debugPtT ( int  id) const

Definition at line 840 of file PathOpsDebug.cpp.

840 {
841 return this->contour()->debugPtT(id);
842}
const SkOpPtT * debugPtT(int id) const

◆ debugReset()

void SkOpSegment::debugReset ( )

Definition at line 1097 of file SkPathOpsDebug.cpp.

1097 {
1098 this->init(this->fPts, this->fWeight, this->contour(), this->verb());
1099}

◆ debugSegment()

const SkOpSegment * SkOpSegment::debugSegment ( int  id) const

Definition at line 844 of file PathOpsDebug.cpp.

844 {
845 return this->contour()->debugSegment(id);
846}
const SkOpSegment * debugSegment(int id) const

◆ debugSpan()

const SkOpSpanBase * SkOpSegment::debugSpan ( int  id) const

Definition at line 848 of file PathOpsDebug.cpp.

848 {
849 return this->contour()->debugSpan(id);
850}
const SkOpSpanBase * debugSpan(int id) const

◆ debugValidate()

void SkOpSegment::debugValidate ( ) const

Definition at line 2333 of file SkPathOpsDebug.cpp.

2333 {
2334#if DEBUG_COINCIDENCE_ORDER
2335 {
2336 const SkOpSpanBase* span = &fHead;
2337 do {
2338 span->debugResetCoinT();
2339 } while (!span->final() && (span = span->upCast()->next()));
2340 span = &fHead;
2341 int index = 0;
2342 do {
2343 span->debugSetCoinT(index++);
2344 } while (!span->final() && (span = span->upCast()->next()));
2345 }
2346#endif
2347#if DEBUG_COINCIDENCE
2348 if (this->globalState()->debugCheckHealth()) {
2349 return;
2350 }
2351#endif
2352#if DEBUG_VALIDATE
2353 const SkOpSpanBase* span = &fHead;
2354 double lastT = -1;
2355 const SkOpSpanBase* prev = nullptr;
2356 int count = 0;
2357 int done = 0;
2358 do {
2359 if (!span->final()) {
2360 ++count;
2361 done += span->upCast()->done() ? 1 : 0;
2362 }
2363 SkASSERT(span->segment() == this);
2364 SkASSERT(!prev || prev->upCast()->next() == span);
2365 SkASSERT(!prev || prev == span->prev());
2366 prev = span;
2367 double t = span->ptT()->fT;
2368 SkASSERT(lastT < t);
2369 lastT = t;
2370 span->debugValidate();
2371 } while (!span->final() && (span = span->upCast()->next()));
2372 SkASSERT(count == fCount);
2373 SkASSERT(done == fDoneCount);
2374 SkASSERT(count >= fDoneCount);
2375 SkASSERT(span->final());
2376 span->debugValidate();
2377#endif
2378}
double fT
Definition SkOpSpan.h:166
int count() const
void debugValidate() const
void debugResetCoinT() const
void debugSetCoinT(int) const

◆ done() [1/2]

bool SkOpSegment::done ( ) const
inline

Definition at line 200 of file SkOpSegment.h.

200 {
201 SkOPASSERT(fDoneCount <= fCount);
202 return fDoneCount == fCount;
203 }
#define SkOPASSERT(cond)

◆ done() [2/2]

bool SkOpSegment::done ( const SkOpAngle angle) const
inline

Definition at line 205 of file SkOpSegment.h.

205 {
206 return angle->start()->starter(angle->end())->done();
207 }

◆ dPtAtT()

SkDPoint SkOpSegment::dPtAtT ( double  mid) const
inline

Definition at line 209 of file SkOpSegment.h.

209 {
210 return (*CurveDPointAtT[fVerb])(fPts, fWeight, mid);
211 }
static SkDPoint(*const CurveDPointAtT[])(const SkPoint[], SkScalar, double)

◆ dSlopeAtT()

SkDVector SkOpSegment::dSlopeAtT ( double  mid) const
inline

Definition at line 213 of file SkOpSegment.h.

213 {
214 return (*CurveDSlopeAtT[fVerb])(fPts, fWeight, mid);
215 }
static SkDVector(*const CurveDSlopeAtT[])(const SkPoint[], SkScalar, double)

◆ dump()

void SkOpSegment::dump ( ) const

Definition at line 852 of file PathOpsDebug.cpp.

852 {
853 SkDebugf("%.*s", contour()->debugIndent(), " ");
854 this->dumpPts();
855 const SkOpSpanBase* span = &fHead;
856 contour()->indentDump();
857 do {
858 SkDebugf("%.*s span=%d ", contour()->debugIndent(), " ", span->debugID());
859 span->ptT()->dumpBase();
860 span->dumpBase();
861 SkDebugf("\n");
862 } while (!span->final() && (span = span->upCast()->next()));
863 contour()->outdentDump();
864}
void indentDump() const
void outdentDump() const
void dumpBase() const
void dumpPts(const char *prefix="seg") const
void dumpBase() const

◆ dumpAll()

void SkOpSegment::dumpAll ( ) const

Definition at line 866 of file PathOpsDebug.cpp.

866 {
867 SkDebugf("%.*s", contour()->debugIndent(), " ");
868 this->dumpPts();
869 const SkOpSpanBase* span = &fHead;
870 contour()->indentDump();
871 do {
872 span->dumpAll();
873 } while (!span->final() && (span = span->upCast()->next()));
874 contour()->outdentDump();
875}
void dumpAll() const

◆ dumpAngles()

void SkOpSegment::dumpAngles ( ) const

Definition at line 877 of file PathOpsDebug.cpp.

877 {
878 SkDebugf("seg=%d\n", debugID());
879 const SkOpSpanBase* span = &fHead;
880 do {
881 const SkOpAngle* fAngle = span->fromAngle();
882 const SkOpAngle* tAngle = span->final() ? nullptr : span->upCast()->toAngle();
883 if (fAngle) {
884 SkDebugf(" span=%d from=%d ", span->debugID(), fAngle->debugID());
885 fAngle->dumpTo(this, tAngle);
886 }
887 if (tAngle) {
888 SkDebugf(" span=%d to=%d ", span->debugID(), tAngle->debugID());
889 tAngle->dumpTo(this, fAngle);
890 }
891 } while (!span->final() && (span = span->upCast()->next()));
892}
int debugID() const
Definition SkOpAngle.h:45
void dumpTo(const SkOpSegment *fromSeg, const SkOpAngle *) const
SkOpAngle * fromAngle() const
Definition SkOpSpan.h:275

◆ dumpCoin()

void SkOpSegment::dumpCoin ( ) const

Definition at line 894 of file PathOpsDebug.cpp.

894 {
895 const SkOpSpan* span = &fHead;
896 do {
897 span->dumpCoin();
898 } while ((span = span->next()->upCastable()));
899}
void dumpCoin() const

◆ dumpPts()

void SkOpSegment::dumpPts ( const char *  prefix = "seg") const

Definition at line 919 of file PathOpsDebug.cpp.

919 {
920 dumpPtsInner(prefix);
921 SkDebugf("\n");
922}
void dumpPtsInner(const char *prefix="seg") const

◆ dumpPtsInner()

void SkOpSegment::dumpPtsInner ( const char *  prefix = "seg") const

Definition at line 901 of file PathOpsDebug.cpp.

901 {
902 int last = SkPathOpsVerbToPoints(fVerb);
903 SkDebugf("%s=%d {{", prefix, this->debugID());
904 if (fVerb == SkPath::kConic_Verb) {
905 SkDebugf("{");
906 }
907 int index = 0;
908 do {
909 SkDPoint::Dump(fPts[index]);
910 SkDebugf(", ");
911 } while (++index < last);
912 SkDPoint::Dump(fPts[index]);
913 SkDebugf("}}");
914 if (fVerb == SkPath::kConic_Verb) {
915 SkDebugf(", %1.9gf}", fWeight);
916 }
917}
int SkPathOpsVerbToPoints(SkPath::Verb verb)
static void Dump(const SkPoint &pt)

◆ existing()

const SkOpPtT * SkOpSegment::existing ( double  t,
const SkOpSegment opp 
) const

Definition at line 203 of file SkOpSegment.cpp.

203 {
204 const SkOpSpanBase* test = &fHead;
205 const SkOpPtT* testPtT;
206 SkPoint pt = this->ptAtT(t);
207 do {
208 testPtT = test->ptT();
209 if (testPtT->fT == t) {
210 break;
211 }
212 if (!this->match(testPtT, this, t, pt)) {
213 if (t < testPtT->fT) {
214 return nullptr;
215 }
216 continue;
217 }
218 if (!opp) {
219 return testPtT;
220 }
221 const SkOpPtT* loop = testPtT->next();
222 while (loop != testPtT) {
223 if (loop->segment() == this && loop->fT == t && loop->fPt == pt) {
224 goto foundMatch;
225 }
226 loop = loop->next();
227 }
228 return nullptr;
229 } while ((test = test->upCast()->next()));
230foundMatch:
231 return opp && !test->contains(opp) ? nullptr : testPtT;
232}

◆ findNextOp()

SkOpSegment * SkOpSegment::findNextOp ( SkTDArray< SkOpSpanBase * > *  chase,
SkOpSpanBase **  nextStart,
SkOpSpanBase **  nextEnd,
bool *  unsortable,
bool *  simple,
SkPathOp  op,
int  xorMiMask,
int  xorSuMask 
)

Definition at line 544 of file SkOpSegment.cpp.

546 {
547 SkOpSpanBase* start = *nextStart;
548 SkOpSpanBase* end = *nextEnd;
549 SkASSERT(start != end);
550 int step = start->step(end);
551 SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart
552 if ((*simple = other)) {
553 // mark the smaller of startIndex, endIndex done, and all adjacent
554 // spans with the same T value (but not 'other' spans)
555#if DEBUG_WINDING
556 SkDebugf("%s simple\n", __FUNCTION__);
557#endif
558 SkOpSpan* startSpan = start->starter(end);
559 if (startSpan->done()) {
560 return nullptr;
561 }
562 markDone(startSpan);
563 *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
564 return other;
565 }
566 SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
567 SkASSERT(endNear == end); // is this ever not end?
568 SkASSERT(endNear);
569 SkASSERT(start != endNear);
570 SkASSERT((start->t() < endNear->t()) ^ (step < 0));
571 // more than one viable candidate -- measure angles to find best
572 int calcWinding = computeSum(start, endNear, SkOpAngle::kBinaryOpp);
573 bool sortable = calcWinding != SK_NaN32;
574 if (!sortable) {
575 *unsortable = true;
576 markDone(start->starter(end));
577 return nullptr;
578 }
579 SkOpAngle* angle = this->spanToAngle(end, start);
580 if (angle->unorderable()) {
581 *unsortable = true;
582 markDone(start->starter(end));
583 return nullptr;
584 }
585#if DEBUG_SORT
586 SkDebugf("%s\n", __FUNCTION__);
587 angle->debugLoop();
588#endif
589 int sumMiWinding = updateWinding(end, start);
590 if (sumMiWinding == SK_MinS32) {
591 *unsortable = true;
592 markDone(start->starter(end));
593 return nullptr;
594 }
595 int sumSuWinding = updateOppWinding(end, start);
596 if (operand()) {
597 using std::swap;
598 swap(sumMiWinding, sumSuWinding);
599 }
600 SkOpAngle* nextAngle = angle->next();
601 const SkOpAngle* foundAngle = nullptr;
602 bool foundDone = false;
603 // iterate through the angle, and compute everyone's winding
604 SkOpSegment* nextSegment;
605 int activeCount = 0;
606 do {
607 nextSegment = nextAngle->segment();
608 bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(),
609 nextAngle->end(), op, &sumMiWinding, &sumSuWinding);
610 if (activeAngle) {
611 ++activeCount;
612 if (!foundAngle || (foundDone && activeCount & 1)) {
613 foundAngle = nextAngle;
614 foundDone = nextSegment->done(nextAngle);
615 }
616 }
617 if (nextSegment->done()) {
618 continue;
619 }
620 if (!activeAngle) {
621 (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end(), nullptr);
622 }
623 SkOpSpanBase* last = nextAngle->lastMarked();
624 if (last) {
626 *chase->append() = last;
627#if DEBUG_WINDING
628 SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__,
629 last->segment()->debugID(), last->debugID());
630 if (!last->final()) {
631 SkDebugf(" windSum=%d", last->upCast()->windSum());
632 }
633 SkDebugf("\n");
634#endif
635 }
636 } while ((nextAngle = nextAngle->next()) != angle);
637 start->segment()->markDone(start->starter(end));
638 if (!foundAngle) {
639 return nullptr;
640 }
641 *nextStart = foundAngle->start();
642 *nextEnd = foundAngle->end();
643 nextSegment = foundAngle->segment();
644#if DEBUG_WINDING
645 SkDebugf("%s from:[%d] to:[%d] start=%p end=%p\n",
646 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
647 #endif
648 return nextSegment;
649}
static int step(int x, SkScalar min, SkScalar max)
Definition BlurTest.cpp:215
SkOpSpanBase * lastMarked() const
int computeSum(SkOpSpanBase *start, SkOpSpanBase *end, SkOpAngle::IncludeType includeType)
SkOpSegment * isSimple(SkOpSpanBase **end, int *step) const
bool markAndChaseDone(SkOpSpanBase *start, SkOpSpanBase *end, SkOpSpanBase **found)
SkOpAngle * activeAngle(SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
double t() const
Definition SkOpSpan.h:375
static bool ChaseContains(const SkTDArray< SkOpSpanBase * > &, const SkOpSpanBase *)
T * append()
Definition SkTDArray.h:191

◆ findNextWinding()

SkOpSegment * SkOpSegment::findNextWinding ( SkTDArray< SkOpSpanBase * > *  chase,
SkOpSpanBase **  nextStart,
SkOpSpanBase **  nextEnd,
bool *  unsortable 
)

Definition at line 651 of file SkOpSegment.cpp.

652 {
653 SkOpSpanBase* start = *nextStart;
654 SkOpSpanBase* end = *nextEnd;
655 SkASSERT(start != end);
656 int step = start->step(end);
657 SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart
658 if (other) {
659 // mark the smaller of startIndex, endIndex done, and all adjacent
660 // spans with the same T value (but not 'other' spans)
661#if DEBUG_WINDING
662 SkDebugf("%s simple\n", __FUNCTION__);
663#endif
664 SkOpSpan* startSpan = start->starter(end);
665 if (startSpan->done()) {
666 return nullptr;
667 }
668 markDone(startSpan);
669 *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
670 return other;
671 }
672 SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
673 SkASSERT(endNear == end); // is this ever not end?
674 SkASSERT(endNear);
675 SkASSERT(start != endNear);
676 SkASSERT((start->t() < endNear->t()) ^ (step < 0));
677 // more than one viable candidate -- measure angles to find best
678 int calcWinding = computeSum(start, endNear, SkOpAngle::kUnaryWinding);
679 bool sortable = calcWinding != SK_NaN32;
680 if (!sortable) {
681 *unsortable = true;
682 markDone(start->starter(end));
683 return nullptr;
684 }
685 SkOpAngle* angle = this->spanToAngle(end, start);
686 if (angle->unorderable()) {
687 *unsortable = true;
688 markDone(start->starter(end));
689 return nullptr;
690 }
691#if DEBUG_SORT
692 SkDebugf("%s\n", __FUNCTION__);
693 angle->debugLoop();
694#endif
695 int sumWinding = updateWinding(end, start);
696 SkOpAngle* nextAngle = angle->next();
697 const SkOpAngle* foundAngle = nullptr;
698 bool foundDone = false;
699 // iterate through the angle, and compute everyone's winding
700 SkOpSegment* nextSegment;
701 int activeCount = 0;
702 do {
703 nextSegment = nextAngle->segment();
704 bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(),
705 &sumWinding);
706 if (activeAngle) {
707 ++activeCount;
708 if (!foundAngle || (foundDone && activeCount & 1)) {
709 foundAngle = nextAngle;
710 foundDone = nextSegment->done(nextAngle);
711 }
712 }
713 if (nextSegment->done()) {
714 continue;
715 }
716 if (!activeAngle) {
717 (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end(), nullptr);
718 }
719 SkOpSpanBase* last = nextAngle->lastMarked();
720 if (last) {
722 *chase->append() = last;
723#if DEBUG_WINDING
724 SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__,
725 last->segment()->debugID(), last->debugID());
726 if (!last->final()) {
727 SkDebugf(" windSum=%d", last->upCast()->windSum());
728 }
729 SkDebugf("\n");
730#endif
731 }
732 } while ((nextAngle = nextAngle->next()) != angle);
733 start->segment()->markDone(start->starter(end));
734 if (!foundAngle) {
735 return nullptr;
736 }
737 *nextStart = foundAngle->start();
738 *nextEnd = foundAngle->end();
739 nextSegment = foundAngle->segment();
740#if DEBUG_WINDING
741 SkDebugf("%s from:[%d] to:[%d] start=%p end=%p\n",
742 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
743 #endif
744 return nextSegment;
745}
@ kUnaryWinding
Definition SkOpAngle.h:35

◆ findNextXor()

SkOpSegment * SkOpSegment::findNextXor ( SkOpSpanBase **  nextStart,
SkOpSpanBase **  nextEnd,
bool *  unsortable 
)

Definition at line 747 of file SkOpSegment.cpp.

748 {
749 SkOpSpanBase* start = *nextStart;
750 SkOpSpanBase* end = *nextEnd;
751 SkASSERT(start != end);
752 int step = start->step(end);
753 SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart
754 if (other) {
755 // mark the smaller of startIndex, endIndex done, and all adjacent
756 // spans with the same T value (but not 'other' spans)
757#if DEBUG_WINDING
758 SkDebugf("%s simple\n", __FUNCTION__);
759#endif
760 SkOpSpan* startSpan = start->starter(end);
761 if (startSpan->done()) {
762 return nullptr;
763 }
764 markDone(startSpan);
765 *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
766 return other;
767 }
768 SkDEBUGCODE(SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() \
769 : (*nextStart)->prev());
770 SkASSERT(endNear == end); // is this ever not end?
771 SkASSERT(endNear);
772 SkASSERT(start != endNear);
773 SkASSERT((start->t() < endNear->t()) ^ (step < 0));
774 SkOpAngle* angle = this->spanToAngle(end, start);
775 if (!angle || angle->unorderable()) {
776 *unsortable = true;
777 markDone(start->starter(end));
778 return nullptr;
779 }
780#if DEBUG_SORT
781 SkDebugf("%s\n", __FUNCTION__);
782 angle->debugLoop();
783#endif
784 SkOpAngle* nextAngle = angle->next();
785 const SkOpAngle* foundAngle = nullptr;
786 bool foundDone = false;
787 // iterate through the angle, and compute everyone's winding
788 SkOpSegment* nextSegment;
789 int activeCount = 0;
790 do {
791 if (!nextAngle) {
792 return nullptr;
793 }
794 nextSegment = nextAngle->segment();
795 ++activeCount;
796 if (!foundAngle || (foundDone && activeCount & 1)) {
797 foundAngle = nextAngle;
798 if (!(foundDone = nextSegment->done(nextAngle))) {
799 break;
800 }
801 }
802 nextAngle = nextAngle->next();
803 } while (nextAngle != angle);
804 start->segment()->markDone(start->starter(end));
805 if (!foundAngle) {
806 return nullptr;
807 }
808 *nextStart = foundAngle->start();
809 *nextEnd = foundAngle->end();
810 nextSegment = foundAngle->segment();
811#if DEBUG_WINDING
812 SkDebugf("%s from:[%d] to:[%d] start=%p end=%p\n",
813 __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
814 #endif
815 return nextSegment;
816}
#define SkDEBUGCODE(...)
Definition SkDebug.h:23

◆ findSortableTop()

SkOpSpan * SkOpSegment::findSortableTop ( SkOpContour contourHead)

Definition at line 390 of file SkPathOpsWinding.cpp.

390 {
391 SkOpSpan* span = &fHead;
393 do {
394 next = span->next();
395 if (span->done()) {
396 continue;
397 }
398 if (span->windSum() != SK_MinS32) {
399 return span;
400 }
401 if (span->sortableTop(contourHead)) {
402 return span;
403 }
404 } while (!next->final() && (span = next->upCast()));
405 return nullptr;
406}
bool sortableTop(SkOpContour *)

◆ globalState()

SkOpGlobalState * SkOpSegment::globalState ( ) const

Definition at line 818 of file SkOpSegment.cpp.

818 {
819 return contour()->globalState();
820}
SkOpGlobalState * globalState() const

◆ head() [1/2]

SkOpSpan * SkOpSegment::head ( )
inline

Definition at line 238 of file SkOpSegment.h.

238 {
239 return &fHead;
240 }

◆ head() [2/2]

const SkOpSpan * SkOpSegment::head ( ) const
inline

Definition at line 234 of file SkOpSegment.h.

234 {
235 return &fHead;
236 }

◆ init()

void SkOpSegment::init ( SkPoint  pts[],
SkScalar  weight,
SkOpContour parent,
SkPath::Verb  verb 
)

Definition at line 822 of file SkOpSegment.cpp.

822 {
823 fContour = contour;
824 fNext = nullptr;
825 fPts = pts;
826 fWeight = weight;
827 fVerb = verb;
828 fCount = 0;
829 fDoneCount = 0;
830 fVisited = false;
831 SkOpSpan* zeroSpan = &fHead;
832 zeroSpan->init(this, nullptr, 0, fPts[0]);
833 SkOpSpanBase* oneSpan = &fTail;
834 zeroSpan->setNext(oneSpan);
835 oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]);
836 SkDEBUGCODE(fID = globalState()->nextSegmentID());
837}
void initBase(SkOpSegment *parent, SkOpSpan *prev, double t, const SkPoint &pt)
Definition SkOpSpan.cpp:243
void setNext(SkOpSpanBase *nextT)
Definition SkOpSpan.h:519

◆ insert()

SkOpSpan * SkOpSegment::insert ( SkOpSpan prev)
inline

Definition at line 244 of file SkOpSegment.h.

244 {
246 globalState->setAllocatedOpSpan();
251 SkDEBUGCODE(result->ptT()->fT = 0);
252 result->setNext(next);
253 if (next) {
255 }
256 return result;
257 }
void setPrev(SkOpSegment *prev)
void setNext(SkOpSegment *next)

◆ isClose()

bool SkOpSegment::isClose ( double  t,
const SkOpSegment opp 
) const

Definition at line 839 of file SkOpSegment.cpp.

839 {
840 SkDPoint cPt = this->dPtAtT(t);
841 SkDVector dxdy = (*CurveDSlopeAtT[this->verb()])(this->pts(), this->weight(), t);
842 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
844 (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), perp, &i);
845 int used = i.used();
846 for (int index = 0; index < used; ++index) {
847 if (cPt.roughlyEqual(i.pt(index))) {
848 return true;
849 }
850 }
851 return false;
852}
static void(*const CurveIntersectRay[])(const SkPoint[], SkScalar, const SkDLine &, SkIntersections *)
const SkDPoint & pt(int index) const
SkDPoint dPtAtT(double mid) const
bool roughlyEqual(const SkDPoint &a) const

◆ isHorizontal()

bool SkOpSegment::isHorizontal ( ) const
inline

Definition at line 261 of file SkOpSegment.h.

261 {
262 return fBounds.fTop == fBounds.fBottom;
263 }
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15

◆ isSimple()

SkOpSegment * SkOpSegment::isSimple ( SkOpSpanBase **  end,
int step 
) const
inline

Definition at line 265 of file SkOpSegment.h.

265 {
266 return nextChase(end, step, nullptr, nullptr);
267 }
SkOpSegment * nextChase(SkOpSpanBase **, int *step, SkOpSpan **, SkOpSpanBase **last) const

◆ isVertical() [1/2]

bool SkOpSegment::isVertical ( ) const
inline

Definition at line 269 of file SkOpSegment.h.

269 {
270 return fBounds.fLeft == fBounds.fRight;
271 }
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16

◆ isVertical() [2/2]

bool SkOpSegment::isVertical ( SkOpSpanBase start,
SkOpSpanBase end 
) const
inline

Definition at line 273 of file SkOpSegment.h.

273 {
274 return (*CurveIsVertical[fVerb])(fPts, fWeight, start->t(), end->t());
275 }
static bool(*const CurveIsVertical[])(const SkPoint[], SkScalar, double, double)

◆ isXor()

bool SkOpSegment::isXor ( ) const

Definition at line 854 of file SkOpSegment.cpp.

854 {
855 return fContour->isXor();
856}
bool isXor() const

◆ joinEnds()

void SkOpSegment::joinEnds ( SkOpSegment start)
inline

Definition at line 279 of file SkOpSegment.h.

279 {
280 fTail.ptT()->addOpp(start->fHead.ptT(), start->fHead.ptT());
281 }

◆ lastPt()

const SkPoint & SkOpSegment::lastPt ( ) const
inline

Definition at line 283 of file SkOpSegment.h.

283 {
284 return fPts[SkPathOpsVerbToPoints(fVerb)];
285 }

◆ markAllDone()

void SkOpSegment::markAllDone ( )

Definition at line 858 of file SkOpSegment.cpp.

858 {
859 SkOpSpan* span = this->head();
860 do {
861 this->markDone(span);
862 } while ((span = span->next()->upCastable()));
863}

◆ markAndChaseDone()

bool SkOpSegment::markAndChaseDone ( SkOpSpanBase start,
SkOpSpanBase end,
SkOpSpanBase **  found 
)

Definition at line 865 of file SkOpSegment.cpp.

865 {
866 int step = start->step(end);
867 SkOpSpan* minSpan = start->starter(end);
868 markDone(minSpan);
869 SkOpSpanBase* last = nullptr;
870 SkOpSegment* other = this;
871 SkOpSpan* priorDone = nullptr;
872 SkOpSpan* lastDone = nullptr;
873 int safetyNet = 100000;
874 while ((other = other->nextChase(&start, &step, &minSpan, &last))) {
875 if (!--safetyNet) {
876 return false;
877 }
878 if (other->done()) {
879 SkASSERT(!last);
880 break;
881 }
882 if (lastDone == minSpan || priorDone == minSpan) {
883 if (found) {
884 *found = nullptr;
885 }
886 return true;
887 }
888 other->markDone(minSpan);
889 priorDone = lastDone;
890 lastDone = minSpan;
891 }
892 if (found) {
893 *found = last;
894 }
895 return true;
896}

◆ markAndChaseWinding() [1/2]

bool SkOpSegment::markAndChaseWinding ( SkOpSpanBase start,
SkOpSpanBase end,
int  winding,
int  oppWinding,
SkOpSpanBase **  lastPtr 
)

Definition at line 923 of file SkOpSegment.cpp.

924 {
925 SkOpSpan* spanStart = start->starter(end);
926 int step = start->step(end);
927 bool success = markWinding(spanStart, winding, oppWinding);
928 SkOpSpanBase* last = nullptr;
929 SkOpSegment* other = this;
930 int safetyNet = 100000;
931 while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
932 if (!--safetyNet) {
933 return false;
934 }
935 if (spanStart->windSum() != SK_MinS32) {
936 if (this->operand() == other->operand()) {
937 if (spanStart->windSum() != winding || spanStart->oppSum() != oppWinding) {
938 this->globalState()->setWindingFailed();
939 return true; // ... but let it succeed anyway
940 }
941 } else {
942 FAIL_IF(spanStart->windSum() != oppWinding);
943 FAIL_IF(spanStart->oppSum() != winding);
944 }
945 SkASSERT(!last);
946 break;
947 }
948 if (this->operand() == other->operand()) {
949 (void) other->markWinding(spanStart, winding, oppWinding);
950 } else {
951 (void) other->markWinding(spanStart, oppWinding, winding);
952 }
953 }
954 if (lastPtr) {
955 *lastPtr = last;
956 }
957 return success;
958}
bool markWinding(SkOpSpan *, int winding)
int step(const SkOpSpanBase *end) const
Definition SkOpSpan.h:371
int oppSum() const
Definition SkOpSpan.h:500

◆ markAndChaseWinding() [2/2]

bool SkOpSegment::markAndChaseWinding ( SkOpSpanBase start,
SkOpSpanBase end,
int  winding,
SkOpSpanBase **  lastPtr 
)

Definition at line 898 of file SkOpSegment.cpp.

899 {
900 SkOpSpan* spanStart = start->starter(end);
901 int step = start->step(end);
902 bool success = markWinding(spanStart, winding);
903 SkOpSpanBase* last = nullptr;
904 SkOpSegment* other = this;
905 int safetyNet = 100000;
906 while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
907 if (!--safetyNet) {
908 return false;
909 }
910 if (spanStart->windSum() != SK_MinS32) {
911// SkASSERT(spanStart->windSum() == winding); // FIXME: is this assert too aggressive?
912 SkASSERT(!last);
913 break;
914 }
915 (void) other->markWinding(spanStart, winding);
916 }
917 if (lastPtr) {
918 *lastPtr = last;
919 }
920 return success;
921}

◆ markAngle() [1/2]

bool SkOpSegment::markAngle ( int  maxWinding,
int  sumWinding,
const SkOpAngle angle,
SkOpSpanBase **  result 
)

Definition at line 960 of file SkOpSegment.cpp.

961 {
962 SkASSERT(angle->segment() == this);
963 if (UseInnerWinding(maxWinding, sumWinding)) {
964 maxWinding = sumWinding;
965 }
966 if (!markAndChaseWinding(angle->start(), angle->end(), maxWinding, result)) {
967 return false;
968 }
969#if DEBUG_WINDING
970 SkOpSpanBase* last = *result;
971 if (last) {
972 SkDebugf("%s last seg=%d span=%d", __FUNCTION__,
973 last->segment()->debugID(), last->debugID());
974 if (!last->final()) {
975 SkDebugf(" windSum=");
977 }
978 SkDebugf("\n");
979 }
980#endif
981 return true;
982}
bool markAndChaseWinding(SkOpSpanBase *start, SkOpSpanBase *end, int winding, SkOpSpanBase **lastPtr)
static bool UseInnerWinding(int outerWinding, int innerWinding)
static void WindingPrintf(int winding)

◆ markAngle() [2/2]

bool SkOpSegment::markAngle ( int  maxWinding,
int  sumWinding,
int  oppMaxWinding,
int  oppSumWinding,
const SkOpAngle angle,
SkOpSpanBase **  result 
)

Definition at line 984 of file SkOpSegment.cpp.

985 {
986 SkASSERT(angle->segment() == this);
987 if (UseInnerWinding(maxWinding, sumWinding)) {
988 maxWinding = sumWinding;
989 }
990 if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) {
991 oppMaxWinding = oppSumWinding;
992 }
993 // caller doesn't require that this marks anything
994 if (!markAndChaseWinding(angle->start(), angle->end(), maxWinding, oppMaxWinding, result)) {
995 return false;
996 }
997#if DEBUG_WINDING
998 if (result) {
999 SkOpSpanBase* last = *result;
1000 if (last) {
1001 SkDebugf("%s last segment=%d span=%d", __FUNCTION__,
1002 last->segment()->debugID(), last->debugID());
1003 if (!last->final()) {
1004 SkDebugf(" windSum=");
1006 }
1007 SkDebugf(" \n");
1008 }
1009 }
1010#endif
1011 return true;
1012}

◆ markDone()

void SkOpSegment::markDone ( SkOpSpan span)

Definition at line 1014 of file SkOpSegment.cpp.

1014 {
1015 SkASSERT(this == span->segment());
1016 if (span->done()) {
1017 return;
1018 }
1019#if DEBUG_MARK_DONE
1020 debugShowNewWinding(__FUNCTION__, span, span->windSum(), span->oppSum());
1021#endif
1022 span->setDone(true);
1023 ++fDoneCount;
1024 debugValidate();
1025}
void setDone(bool done)
Definition SkOpSpan.h:514

◆ markWinding() [1/2]

bool SkOpSegment::markWinding ( SkOpSpan span,
int  winding 
)

Definition at line 1027 of file SkOpSegment.cpp.

1027 {
1028 SkASSERT(this == span->segment());
1029 SkASSERT(winding);
1030 if (span->done()) {
1031 return false;
1032 }
1033#if DEBUG_MARK_DONE
1034 debugShowNewWinding(__FUNCTION__, span, winding);
1035#endif
1036 span->setWindSum(winding);
1037 debugValidate();
1038 return true;
1039}
void setWindSum(int windSum)
Definition SkOpSpan.cpp:482

◆ markWinding() [2/2]

bool SkOpSegment::markWinding ( SkOpSpan span,
int  winding,
int  oppWinding 
)

Definition at line 1041 of file SkOpSegment.cpp.

1041 {
1042 SkASSERT(this == span->segment());
1043 SkASSERT(winding || oppWinding);
1044 if (span->done()) {
1045 return false;
1046 }
1047#if DEBUG_MARK_DONE
1048 debugShowNewWinding(__FUNCTION__, span, winding, oppWinding);
1049#endif
1050 span->setWindSum(winding);
1051 span->setOppSum(oppWinding);
1052 debugValidate();
1053 return true;
1054}
void setOppSum(int oppSum)
Definition SkOpSpan.cpp:472

◆ match()

bool SkOpSegment::match ( const SkOpPtT span,
const SkOpSegment parent,
double  t,
const SkPoint pt 
) const

Definition at line 1056 of file SkOpSegment.cpp.

1057 {
1058 SkASSERT(this == base->segment());
1059 if (this == testParent) {
1060 if (precisely_equal(base->fT, testT)) {
1061 return true;
1062 }
1063 }
1064 if (!SkDPoint::ApproximatelyEqual(testPt, base->fPt)) {
1065 return false;
1066 }
1067 return this != testParent || !this->ptsDisjoint(base->fT, base->fPt, testT, testPt);
1068}
bool precisely_equal(double x, double y)
bool ptsDisjoint(const SkOpPtT &span, const SkOpPtT &test) const
static bool ApproximatelyEqual(const SkPoint &a, const SkPoint &b)

◆ missingCoincidence()

bool SkOpSegment::missingCoincidence ( )

Definition at line 1161 of file SkOpSegment.cpp.

1161 {
1162 if (this->done()) {
1163 return false;
1164 }
1165 SkOpSpan* prior = nullptr;
1166 SkOpSpanBase* spanBase = &fHead;
1167 bool result = false;
1168 int safetyNet = 100000;
1169 do {
1170 SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
1171 SkOPASSERT(ptT->span() == spanBase);
1172 while ((ptT = ptT->next()) != spanStopPtT) {
1173 if (!--safetyNet) {
1174 return false;
1175 }
1176 if (ptT->deleted()) {
1177 continue;
1178 }
1179 SkOpSegment* opp = ptT->span()->segment();
1180 if (opp->done()) {
1181 continue;
1182 }
1183 // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence
1184 if (!opp->visited()) {
1185 continue;
1186 }
1187 if (spanBase == &fHead) {
1188 continue;
1189 }
1190 if (ptT->segment() == this) {
1191 continue;
1192 }
1193 SkOpSpan* span = spanBase->upCastable();
1194 // FIXME?: this assumes that if the opposite segment is coincident then no more
1195 // coincidence needs to be detected. This may not be true.
1196 if (span && span->containsCoincidence(opp)) {
1197 continue;
1198 }
1199 if (spanBase->containsCoinEnd(opp)) {
1200 continue;
1201 }
1202 SkOpPtT* priorPtT = nullptr, * priorStopPtT;
1203 // find prior span containing opp segment
1204 SkOpSegment* priorOpp = nullptr;
1205 SkOpSpan* priorTest = spanBase->prev();
1206 while (!priorOpp && priorTest) {
1207 priorStopPtT = priorPtT = priorTest->ptT();
1208 while ((priorPtT = priorPtT->next()) != priorStopPtT) {
1209 if (priorPtT->deleted()) {
1210 continue;
1211 }
1212 SkOpSegment* segment = priorPtT->span()->segment();
1213 if (segment == opp) {
1214 prior = priorTest;
1215 priorOpp = opp;
1216 break;
1217 }
1218 }
1219 priorTest = priorTest->prev();
1220 }
1221 if (!priorOpp) {
1222 continue;
1223 }
1224 if (priorPtT == ptT) {
1225 continue;
1226 }
1227 SkOpPtT* oppStart = prior->ptT();
1228 SkOpPtT* oppEnd = spanBase->ptT();
1229 bool swapped = priorPtT->fT > ptT->fT;
1230 if (swapped) {
1231 using std::swap;
1232 swap(priorPtT, ptT);
1233 swap(oppStart, oppEnd);
1234 }
1235 SkOpCoincidence* coincidences = this->globalState()->coincidence();
1236 SkOpPtT* rootPriorPtT = priorPtT->span()->ptT();
1237 SkOpPtT* rootPtT = ptT->span()->ptT();
1238 SkOpPtT* rootOppStart = oppStart->span()->ptT();
1239 SkOpPtT* rootOppEnd = oppEnd->span()->ptT();
1240 if (coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) {
1241 goto swapBack;
1242 }
1243 if (this->testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) {
1244 // mark coincidence
1245#if DEBUG_COINCIDENCE_VERBOSE
1246 SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__,
1247 rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(),
1248 rootOppEnd->debugID());
1249#endif
1250 if (!coincidences->extend(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) {
1251 coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd);
1252 }
1253#if DEBUG_COINCIDENCE
1254 SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd));
1255#endif
1256 result = true;
1257 }
1258 swapBack:
1259 if (swapped) {
1260 using std::swap;
1261 swap(priorPtT, ptT);
1262 }
1263 }
1264 } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next()));
1265 ClearVisited(&fHead);
1266 return result;
1267}
void add(SkOpPtT *coinPtTStart, SkOpPtT *coinPtTEnd, SkOpPtT *oppPtTStart, SkOpPtT *oppPtTEnd)
bool contains(const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd) const
bool extend(const SkOpPtT *coinPtTStart, const SkOpPtT *coinPtTEnd, const SkOpPtT *oppPtTStart, const SkOpPtT *oppPtTEnd)
bool deleted() const
Definition SkOpSpan.h:71
int debugID() const
Definition SkOpSpan.h:50
bool visited()
bool testForCoincidence(const SkOpPtT *priorPtT, const SkOpPtT *ptT, const SkOpSpanBase *prior, const SkOpSpanBase *spanBase, const SkOpSegment *opp) const
static void ClearVisited(SkOpSpanBase *span)
bool containsCoinEnd(const SkOpSpanBase *coin) const
Definition SkOpSpan.h:206
bool containsCoincidence(const SkOpSegment *) const
Definition SkOpSpan.cpp:387

◆ moveMultiples()

bool SkOpSegment::moveMultiples ( )

Definition at line 1271 of file SkOpSegment.cpp.

1271 {
1272 debugValidate();
1273 SkOpSpanBase* test = &fHead;
1274 do {
1275 int addCount = test->spanAddsCount();
1276// FAIL_IF(addCount < 1);
1277 if (addCount <= 1) {
1278 continue;
1279 }
1280 SkOpPtT* startPtT = test->ptT();
1281 SkOpPtT* testPtT = startPtT;
1282 int safetyHatch = 1000000;
1283 do { // iterate through all spans associated with start
1284 if (!--safetyHatch) {
1285 return false;
1286 }
1287 SkOpSpanBase* oppSpan = testPtT->span();
1288 if (oppSpan->spanAddsCount() == addCount) {
1289 continue;
1290 }
1291 if (oppSpan->deleted()) {
1292 continue;
1293 }
1294 SkOpSegment* oppSegment = oppSpan->segment();
1295 if (oppSegment == this) {
1296 continue;
1297 }
1298 // find range of spans to consider merging
1299 SkOpSpanBase* oppPrev = oppSpan;
1300 SkOpSpanBase* oppFirst = oppSpan;
1301 while ((oppPrev = oppPrev->prev())) {
1302 if (!roughly_equal(oppPrev->t(), oppSpan->t())) {
1303 break;
1304 }
1305 if (oppPrev->spanAddsCount() == addCount) {
1306 continue;
1307 }
1308 if (oppPrev->deleted()) {
1309 continue;
1310 }
1311 oppFirst = oppPrev;
1312 }
1313 SkOpSpanBase* oppNext = oppSpan;
1314 SkOpSpanBase* oppLast = oppSpan;
1315 while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) {
1316 if (!roughly_equal(oppNext->t(), oppSpan->t())) {
1317 break;
1318 }
1319 if (oppNext->spanAddsCount() == addCount) {
1320 continue;
1321 }
1322 if (oppNext->deleted()) {
1323 continue;
1324 }
1325 oppLast = oppNext;
1326 }
1327 if (oppFirst == oppLast) {
1328 continue;
1329 }
1330 SkOpSpanBase* oppTest = oppFirst;
1331 do {
1332 if (oppTest == oppSpan) {
1333 continue;
1334 }
1335 // check to see if the candidate meets specific criteria:
1336 // it contains spans of segments in test's loop but not including 'this'
1337 SkOpPtT* oppStartPtT = oppTest->ptT();
1338 SkOpPtT* oppPtT = oppStartPtT;
1339 while ((oppPtT = oppPtT->next()) != oppStartPtT) {
1340 SkOpSegment* oppPtTSegment = oppPtT->segment();
1341 if (oppPtTSegment == this) {
1342 goto tryNextSpan;
1343 }
1344 SkOpPtT* matchPtT = startPtT;
1345 do {
1346 if (matchPtT->segment() == oppPtTSegment) {
1347 goto foundMatch;
1348 }
1349 } while ((matchPtT = matchPtT->next()) != startPtT);
1350 goto tryNextSpan;
1351 foundMatch: // merge oppTest and oppSpan
1352 oppSegment->debugValidate();
1353 oppTest->mergeMatches(oppSpan);
1354 oppTest->addOpp(oppSpan);
1355 oppSegment->debugValidate();
1356 goto checkNextSpan;
1357 }
1358 tryNextSpan:
1359 ;
1360 } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()));
1361 } while ((testPtT = testPtT->next()) != startPtT);
1362checkNextSpan:
1363 ;
1364 } while ((test = test->final() ? nullptr : test->upCast()->next()));
1365 debugValidate();
1366 return true;
1367}
bool roughly_equal(double x, double y)
int spanAddsCount() const
Definition SkOpSpan.h:343
bool addOpp(SkOpSpanBase *opp)
Definition SkOpSpan.cpp:158
bool deleted() const
Definition SkOpSpan.h:261

◆ moveNearby()

bool SkOpSegment::moveNearby ( )

Definition at line 1441 of file SkOpSegment.cpp.

1441 {
1442 debugValidate();
1443 // release undeleted spans pointing to this seg that are linked to the primary span
1444 SkOpSpanBase* spanBase = &fHead;
1445 int escapeHatch = 9999; // the largest count for a regular test is 50; for a fuzzer, 500
1446 do {
1447 SkOpPtT* ptT = spanBase->ptT();
1448 const SkOpPtT* headPtT = ptT;
1449 while ((ptT = ptT->next()) != headPtT) {
1450 if (!--escapeHatch) {
1451 return false;
1452 }
1453 SkOpSpanBase* test = ptT->span();
1454 if (ptT->segment() == this && !ptT->deleted() && test != spanBase
1455 && test->ptT() == ptT) {
1456 if (test->final()) {
1457 if (spanBase == &fHead) {
1458 this->clearAll();
1459 return true;
1460 }
1461 spanBase->upCast()->release(ptT);
1462 } else if (test->prev()) {
1463 test->upCast()->release(headPtT);
1464 }
1465 break;
1466 }
1467 }
1468 spanBase = spanBase->upCast()->next();
1469 } while (!spanBase->final());
1470 // This loop looks for adjacent spans which are near by
1471 spanBase = &fHead;
1472 do { // iterate through all spans associated with start
1473 SkOpSpanBase* test = spanBase->upCast()->next();
1474 bool found;
1475 if (!this->spansNearby(spanBase, test, &found)) {
1476 return false;
1477 }
1478 if (found) {
1479 if (test->final()) {
1480 if (spanBase->prev()) {
1481 test->merge(spanBase->upCast());
1482 } else {
1483 this->clearAll();
1484 return true;
1485 }
1486 } else {
1487 spanBase->merge(test->upCast());
1488 }
1489 }
1490 spanBase = test;
1491 } while (!spanBase->final());
1492 debugValidate();
1493 return true;
1494}
bool spansNearby(const SkOpSpanBase *ref, const SkOpSpanBase *check, bool *found) const
void merge(SkOpSpan *span)
Definition SkOpSpan.cpp:259
void release(const SkOpPtT *)
Definition SkOpSpan.cpp:446

◆ next()

SkOpSegment * SkOpSegment::next ( ) const
inline

Definition at line 304 of file SkOpSegment.h.

304 {
305 return fNext;
306 }

◆ nextChase()

SkOpSegment * SkOpSegment::nextChase ( SkOpSpanBase **  startPtr,
int step,
SkOpSpan **  minPtr,
SkOpSpanBase **  last 
) const

Definition at line 1077 of file SkOpSegment.cpp.

1078 {
1079 SkOpSpanBase* origStart = *startPtr;
1080 int step = *stepPtr;
1081 SkOpSpanBase* endSpan = step > 0 ? origStart->upCast()->next() : origStart->prev();
1082 SkASSERT(endSpan);
1083 SkOpAngle* angle = step > 0 ? endSpan->fromAngle() : endSpan->upCast()->toAngle();
1084 SkOpSpanBase* foundSpan;
1085 SkOpSpanBase* otherEnd;
1086 SkOpSegment* other;
1087 if (angle == nullptr) {
1088 if (endSpan->t() != 0 && endSpan->t() != 1) {
1089 return nullptr;
1090 }
1091 SkOpPtT* otherPtT = endSpan->ptT()->next();
1092 other = otherPtT->segment();
1093 foundSpan = otherPtT->span();
1094 otherEnd = step > 0
1095 ? foundSpan->upCastable() ? foundSpan->upCast()->next() : nullptr
1096 : foundSpan->prev();
1097 } else {
1098 int loopCount = angle->loopCount();
1099 if (loopCount > 2) {
1100 return set_last(last, endSpan);
1101 }
1102 const SkOpAngle* next = angle->next();
1103 if (nullptr == next) {
1104 return nullptr;
1105 }
1106#if DEBUG_WINDING
1107 if (angle->debugSign() != next->debugSign() && !angle->segment()->contour()->isXor()
1108 && !next->segment()->contour()->isXor()) {
1109 SkDebugf("%s mismatched signs\n", __FUNCTION__);
1110 }
1111#endif
1112 other = next->segment();
1113 foundSpan = endSpan = next->start();
1114 otherEnd = next->end();
1115 }
1116 if (!otherEnd) {
1117 return nullptr;
1118 }
1119 int foundStep = foundSpan->step(otherEnd);
1120 if (*stepPtr != foundStep) {
1121 return set_last(last, endSpan);
1122 }
1123 SkASSERT(*startPtr);
1124// SkASSERT(otherEnd >= 0);
1125 SkOpSpan* origMin = step < 0 ? origStart->prev() : origStart->upCast();
1126 SkOpSpan* foundMin = foundSpan->starter(otherEnd);
1127 if (foundMin->windValue() != origMin->windValue()
1128 || foundMin->oppValue() != origMin->oppValue()) {
1129 return set_last(last, endSpan);
1130 }
1131 *startPtr = foundSpan;
1132 *stepPtr = foundStep;
1133 if (minPtr) {
1134 *minPtr = foundMin;
1135 }
1136 return other;
1137}
static SkOpSegment * set_last(SkOpSpanBase **last, SkOpSpanBase *endSpan)
int loopCount() const
int debugSign() const

◆ operand()

bool SkOpSegment::operand ( ) const

Definition at line 1496 of file SkOpSegment.cpp.

1496 {
1497 return fContour->operand();
1498}
bool operand() const

◆ operator<()

bool SkOpSegment::operator< ( const SkOpSegment rh) const
inline

Definition at line 37 of file SkOpSegment.h.

37 {
38 return fBounds.fTop < rh.fBounds.fTop;
39 }

◆ OppSign()

static int SkOpSegment::OppSign ( const SkOpSpanBase start,
const SkOpSpanBase end 
)
inlinestatic

Definition at line 311 of file SkOpSegment.h.

311 {
312 int result = start->t() < end->t() ? -start->upCast()->oppValue()
313 : end->upCast()->oppValue();
314 return result;
315 }

◆ oppXor()

bool SkOpSegment::oppXor ( ) const

Definition at line 1500 of file SkOpSegment.cpp.

1500 {
1501 return fContour->oppXor();
1502}
bool oppXor() const

◆ prev()

const SkOpSegment * SkOpSegment::prev ( ) const
inline

Definition at line 319 of file SkOpSegment.h.

319 {
320 return fPrev;
321 }

◆ ptAtT()

SkPoint SkOpSegment::ptAtT ( double  mid) const
inline

Definition at line 323 of file SkOpSegment.h.

323 {
324 return (*CurvePointAtT[fVerb])(fPts, fWeight, mid);
325 }
static SkPoint(*const CurvePointAtT[])(const SkPoint[], SkScalar, double)

◆ pts()

const SkPoint * SkOpSegment::pts ( ) const
inline

Definition at line 327 of file SkOpSegment.h.

327 {
328 return fPts;
329 }

◆ ptsDisjoint() [1/3]

bool SkOpSegment::ptsDisjoint ( const SkOpPtT span,
const SkOpPtT test 
) const
inline

Definition at line 331 of file SkOpSegment.h.

331 {
332 SkASSERT(this == span.segment());
333 SkASSERT(this == test.segment());
334 return ptsDisjoint(span.fT, span.fPt, test.fT, test.fPt);
335 }

◆ ptsDisjoint() [2/3]

bool SkOpSegment::ptsDisjoint ( const SkOpPtT span,
double  t,
const SkPoint pt 
) const
inline

Definition at line 337 of file SkOpSegment.h.

337 {
338 SkASSERT(this == span.segment());
339 return ptsDisjoint(span.fT, span.fPt, t, pt);
340 }

◆ ptsDisjoint() [3/3]

bool SkOpSegment::ptsDisjoint ( double  t1,
const SkPoint pt1,
double  t2,
const SkPoint pt2 
) const

Definition at line 1504 of file SkOpSegment.cpp.

1504 {
1505 if (fVerb == SkPath::kLine_Verb) {
1506 return false;
1507 }
1508 // quads (and cubics) can loop back to nearly a line so that an opposite curve
1509 // hits in two places with very different t values.
1510 // OPTIMIZATION: curves could be preflighted so that, for example, something like
1511 // 'controls contained by ends' could avoid this check for common curves
1512 // 'ends are extremes in x or y' is cheaper to compute and real-world common
1513 // on the other hand, the below check is relatively inexpensive
1514 double midT = (t1 + t2) / 2;
1515 SkPoint midPt = this->ptAtT(midT);
1516 double seDistSq = std::max(SkPointPriv::DistanceToSqd(pt1, pt2) * 2, FLT_EPSILON * 2);
1517 return SkPointPriv::DistanceToSqd(midPt, pt1) > seDistSq ||
1518 SkPointPriv::DistanceToSqd(midPt, pt2) > seDistSq;
1519}
static SkScalar DistanceToSqd(const SkPoint &pt, const SkPoint &a)
Definition SkPointPriv.h:48

◆ rayCheck()

void SkOpSegment::rayCheck ( const SkOpRayHit base,
SkOpRayDir  dir,
SkOpRayHit **  hits,
SkArenaAlloc allocator 
)

Definition at line 138 of file SkPathOpsWinding.cpp.

139 {
140 if (!sideways_overlap(fBounds, base.fPt, dir)) {
141 return;
142 }
143 SkScalar baseXY = pt_xy(base.fPt, dir);
144 SkScalar boundsXY = rect_side(fBounds, dir);
145 bool checkLessThan = less_than(dir);
146 if (!approximately_equal(baseXY, boundsXY) && (baseXY < boundsXY) == checkLessThan) {
147 return;
148 }
149 double tVals[3];
150 SkScalar baseYX = pt_yx(base.fPt, dir);
151 int roots = (*CurveIntercept[fVerb * 2 + xy_index(dir)])(fPts, fWeight, baseYX, tVals);
152 for (int index = 0; index < roots; ++index) {
153 double t = tVals[index];
154 if (base.fSpan->segment() == this && approximately_equal(base.fT, t)) {
155 continue;
156 }
157 SkDVector slope;
158 SkPoint pt;
159 SkDEBUGCODE(sk_bzero(&slope, sizeof(slope)));
160 bool valid = false;
161 if (approximately_zero(t)) {
162 pt = fPts[0];
163 } else if (approximately_equal(t, 1)) {
164 pt = fPts[SkPathOpsVerbToPoints(fVerb)];
165 } else {
166 SkASSERT(between(0, t, 1));
167 pt = this->ptAtT(t);
168 if (SkDPoint::ApproximatelyEqual(pt, base.fPt)) {
169 if (base.fSpan->segment() == this) {
170 continue;
171 }
172 } else {
173 SkScalar ptXY = pt_xy(pt, dir);
174 if (!approximately_equal(baseXY, ptXY) && (baseXY < ptXY) == checkLessThan) {
175 continue;
176 }
177 slope = this->dSlopeAtT(t);
178 if (fVerb == SkPath::kCubic_Verb && base.fSpan->segment() == this
179 && roughly_equal(base.fT, t)
180 && SkDPoint::RoughlyEqual(pt, base.fPt)) {
181 #if DEBUG_WINDING
182 SkDebugf("%s (rarely expect this)\n", __FUNCTION__);
183 #endif
184 continue;
185 }
186 if (fabs(pt_dydx(slope, dir) * 10000) > fabs(pt_dxdy(slope, dir))) {
187 valid = true;
188 }
189 }
190 }
191 SkOpSpan* span = this->windingSpanAtT(t);
192 if (!span) {
193 valid = false;
194 } else if (!span->windValue() && !span->oppValue()) {
195 continue;
196 }
197 SkOpRayHit* newHit = allocator->make<SkOpRayHit>();
198 newHit->fNext = *hits;
199 newHit->fPt = pt;
200 newHit->fSlope = slope;
201 newHit->fSpan = span;
202 newHit->fT = t;
203 newHit->fValid = valid;
204 *hits = newHit;
205 }
206}
static bool approximately_zero(double x)
Definition SkCubics.cpp:153
static void sk_bzero(void *buffer, size_t size)
Definition SkMalloc.h:105
static int(*const CurveIntercept[])(const SkPoint[], SkScalar, SkScalar, double *)
bool approximately_equal(double x, double y)
static int xy_index(SkOpRayDir dir)
static bool less_than(SkOpRayDir dir)
static SkScalar pt_xy(const SkPoint &pt, SkOpRayDir dir)
static double pt_dydx(const SkDVector &v, SkOpRayDir dir)
static bool sideways_overlap(const SkRect &rect, const SkPoint &pt, SkOpRayDir dir)
static SkScalar pt_yx(const SkPoint &pt, SkOpRayDir dir)
static double pt_dxdy(const SkDVector &v, SkOpRayDir dir)
static SkScalar rect_side(const SkRect &r, SkOpRayDir dir)
SkDVector dSlopeAtT(double mid) const
SkOpSpan * windingSpanAtT(double tHit)
float SkScalar
Definition extension.cpp:12
static bool RoughlyEqual(const SkPoint &a, const SkPoint &b)
SkOpRayHit * fNext

◆ release()

void SkOpSegment::release ( const SkOpSpan span)

Definition at line 504 of file SkOpSegment.cpp.

504 {
505 if (span->done()) {
506 --fDoneCount;
507 }
508 --fCount;
509 SkOPASSERT(fCount >= fDoneCount);
510}

◆ resetVisited()

void SkOpSegment::resetVisited ( )
inline

Definition at line 353 of file SkOpSegment.h.

353 {
354 fVisited = false;
355 }

◆ setContour()

void SkOpSegment::setContour ( SkOpContour contour)
inline

Definition at line 357 of file SkOpSegment.h.

357 {
358 fContour = contour;
359 }

◆ setNext()

void SkOpSegment::setNext ( SkOpSegment next)
inline

Definition at line 361 of file SkOpSegment.h.

361 {
362 fNext = next;
363 }

◆ setPrev()

void SkOpSegment::setPrev ( SkOpSegment prev)
inline

Definition at line 365 of file SkOpSegment.h.

365 {
366 fPrev = prev;
367 }

◆ setUpWinding()

void SkOpSegment::setUpWinding ( SkOpSpanBase start,
SkOpSpanBase end,
int maxWinding,
int sumWinding 
)
inline

Definition at line 369 of file SkOpSegment.h.

369 {
370 int deltaSum = SpanSign(start, end);
371 *maxWinding = *sumWinding;
372 if (*sumWinding == SK_MinS32) {
373 return;
374 }
375 *sumWinding -= deltaSum;
376 }
static int SpanSign(const SkOpSpanBase *start, const SkOpSpanBase *end)

◆ setUpWindings() [1/2]

void SkOpSegment::setUpWindings ( SkOpSpanBase start,
SkOpSpanBase end,
int sumMiWinding,
int maxWinding,
int sumWinding 
)

Definition at line 1521 of file SkOpSegment.cpp.

1522 {
1523 int deltaSum = SpanSign(start, end);
1524 *maxWinding = *sumMiWinding;
1525 *sumWinding = *sumMiWinding -= deltaSum;
1527}
static T SkTAbs(T value)
Definition SkTemplates.h:43

◆ setUpWindings() [2/2]

void SkOpSegment::setUpWindings ( SkOpSpanBase start,
SkOpSpanBase end,
int sumMiWinding,
int sumSuWinding,
int maxWinding,
int sumWinding,
int oppMaxWinding,
int oppSumWinding 
)

Definition at line 1529 of file SkOpSegment.cpp.

1531 {
1532 int deltaSum = SpanSign(start, end);
1533 int oppDeltaSum = OppSign(start, end);
1534 if (operand()) {
1535 *maxWinding = *sumSuWinding;
1536 *sumWinding = *sumSuWinding -= deltaSum;
1537 *oppMaxWinding = *sumMiWinding;
1538 *oppSumWinding = *sumMiWinding -= oppDeltaSum;
1539 } else {
1540 *maxWinding = *sumMiWinding;
1541 *sumWinding = *sumMiWinding -= deltaSum;
1542 *oppMaxWinding = *sumSuWinding;
1543 *oppSumWinding = *sumSuWinding -= oppDeltaSum;
1544 }
1547}
static int OppSign(const SkOpSpanBase *start, const SkOpSpanBase *end)

◆ sortAngles()

bool SkOpSegment::sortAngles ( )

Definition at line 1549 of file SkOpSegment.cpp.

1549 {
1550 SkOpSpanBase* span = &this->fHead;
1551 do {
1552 SkOpAngle* fromAngle = span->fromAngle();
1553 SkOpAngle* toAngle = span->final() ? nullptr : span->upCast()->toAngle();
1554 if (!fromAngle && !toAngle) {
1555 continue;
1556 }
1557#if DEBUG_ANGLE
1558 bool wroteAfterHeader = false;
1559#endif
1560 SkOpAngle* baseAngle = fromAngle;
1561 if (fromAngle && toAngle) {
1562#if DEBUG_ANGLE
1563 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), span->t(),
1564 span->debugID());
1565 wroteAfterHeader = true;
1566#endif
1567 FAIL_IF(!fromAngle->insert(toAngle));
1568 } else if (!fromAngle) {
1569 baseAngle = toAngle;
1570 }
1571 SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
1572 int safetyNet = 1000000;
1573 do {
1574 if (!--safetyNet) {
1575 return false;
1576 }
1577 SkOpSpanBase* oSpan = ptT->span();
1578 if (oSpan == span) {
1579 continue;
1580 }
1581 SkOpAngle* oAngle = oSpan->fromAngle();
1582 if (oAngle) {
1583#if DEBUG_ANGLE
1584 if (!wroteAfterHeader) {
1585 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
1586 span->t(), span->debugID());
1587 wroteAfterHeader = true;
1588 }
1589#endif
1590 if (!oAngle->loopContains(baseAngle)) {
1591 baseAngle->insert(oAngle);
1592 }
1593 }
1594 if (!oSpan->final()) {
1595 oAngle = oSpan->upCast()->toAngle();
1596 if (oAngle) {
1597#if DEBUG_ANGLE
1598 if (!wroteAfterHeader) {
1599 SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
1600 span->t(), span->debugID());
1601 wroteAfterHeader = true;
1602 }
1603#endif
1604 if (!oAngle->loopContains(baseAngle)) {
1605 baseAngle->insert(oAngle);
1606 }
1607 }
1608 }
1609 } while ((ptT = ptT->next()) != stopPtT);
1610 if (baseAngle->loopCount() == 1) {
1611 span->setFromAngle(nullptr);
1612 if (toAngle) {
1613 span->upCast()->setToAngle(nullptr);
1614 }
1615 baseAngle = nullptr;
1616 }
1617#if DEBUG_SORT
1618 SkASSERT(!baseAngle || baseAngle->loopCount() > 1);
1619#endif
1620 } while (!span->final() && (span = span->upCast()->next()));
1621 return true;
1622}
bool loopContains(const SkOpAngle *) const
bool insert(SkOpAngle *)

◆ SpanSign()

static int SkOpSegment::SpanSign ( const SkOpSpanBase start,
const SkOpSpanBase end 
)
inlinestatic

Definition at line 385 of file SkOpSegment.h.

385 {
386 int result = start->t() < end->t() ? -start->upCast()->windValue()
387 : end->upCast()->windValue();
388 return result;
389 }

◆ spansNearby()

bool SkOpSegment::spansNearby ( const SkOpSpanBase ref,
const SkOpSpanBase check,
bool *  found 
) const

Definition at line 1370 of file SkOpSegment.cpp.

1371 {
1372 const SkOpPtT* refHead = refSpan->ptT();
1373 const SkOpPtT* checkHead = checkSpan->ptT();
1374// if the first pt pair from adjacent spans are far apart, assume that all are far enough apart
1375 if (!SkDPoint::WayRoughlyEqual(refHead->fPt, checkHead->fPt)) {
1376#if DEBUG_COINCIDENCE
1377 // verify that no combination of points are close
1378 const SkOpPtT* dBugRef = refHead;
1379 do {
1380 const SkOpPtT* dBugCheck = checkHead;
1381 do {
1382 SkOPASSERT(!SkDPoint::ApproximatelyEqual(dBugRef->fPt, dBugCheck->fPt));
1383 dBugCheck = dBugCheck->next();
1384 } while (dBugCheck != checkHead);
1385 dBugRef = dBugRef->next();
1386 } while (dBugRef != refHead);
1387#endif
1388 *found = false;
1389 return true;
1390 }
1391 // check only unique points
1392 SkScalar distSqBest = SK_ScalarMax;
1393 const SkOpPtT* refBest = nullptr;
1394 const SkOpPtT* checkBest = nullptr;
1395 const SkOpPtT* ref = refHead;
1396 do {
1397 if (ref->deleted()) {
1398 continue;
1399 }
1400 while (ref->ptAlreadySeen(refHead)) {
1401 ref = ref->next();
1402 if (ref == refHead) {
1403 goto doneCheckingDistance;
1404 }
1405 }
1406 const SkOpPtT* check = checkHead;
1407 const SkOpSegment* refSeg = ref->segment();
1408 int escapeHatch = 100000; // defend against infinite loops
1409 do {
1410 if (check->deleted()) {
1411 continue;
1412 }
1413 while (check->ptAlreadySeen(checkHead)) {
1414 check = check->next();
1415 if (check == checkHead) {
1416 goto nextRef;
1417 }
1418 }
1419 SkScalar distSq = SkPointPriv::DistanceToSqd(ref->fPt, check->fPt);
1420 if (distSqBest > distSq && (refSeg != check->segment()
1421 || !refSeg->ptsDisjoint(*ref, *check))) {
1422 distSqBest = distSq;
1423 refBest = ref;
1424 checkBest = check;
1425 }
1426 if (--escapeHatch <= 0) {
1427 return false;
1428 }
1429 } while ((check = check->next()) != checkHead);
1430 nextRef:
1431 ;
1432 } while ((ref = ref->next()) != refHead);
1433doneCheckingDistance:
1434 *found = checkBest && refBest->segment()->match(refBest, checkBest->segment(), checkBest->fT,
1435 checkBest->fPt);
1436 return true;
1437}
#define check(reporter, ref, unref, make, kill)
#define SK_ScalarMax
Definition SkScalar.h:24
bool ptAlreadySeen(const SkOpPtT *head) const
Definition SkOpSpan.cpp:124
static bool WayRoughlyEqual(const SkPoint &a, const SkPoint &b)

◆ spanToAngle()

SkOpAngle * SkOpSegment::spanToAngle ( SkOpSpanBase start,
SkOpSpanBase end 
)
inline

Definition at line 391 of file SkOpSegment.h.

391 {
392 SkASSERT(start != end);
393 return start->t() < end->t() ? start->upCast()->toAngle() : start->fromAngle();
394 }

◆ subDivide()

bool SkOpSegment::subDivide ( const SkOpSpanBase start,
const SkOpSpanBase end,
SkDCurve result 
) const

Definition at line 1624 of file SkOpSegment.cpp.

1625 {
1626 SkASSERT(start != end);
1627 const SkOpPtT& startPtT = *start->ptT();
1628 const SkOpPtT& endPtT = *end->ptT();
1629 SkDEBUGCODE(edge->fVerb = fVerb);
1630 edge->fCubic[0].set(startPtT.fPt);
1631 int points = SkPathOpsVerbToPoints(fVerb);
1632 edge->fCubic[points].set(endPtT.fPt);
1633 if (fVerb == SkPath::kLine_Verb) {
1634 return false;
1635 }
1636 double startT = startPtT.fT;
1637 double endT = endPtT.fT;
1638 if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) {
1639 // don't compute midpoints if we already have them
1640 if (fVerb == SkPath::kQuad_Verb) {
1641 edge->fLine[1].set(fPts[1]);
1642 return false;
1643 }
1644 if (fVerb == SkPath::kConic_Verb) {
1645 edge->fConic[1].set(fPts[1]);
1646 edge->fConic.fWeight = fWeight;
1647 return false;
1648 }
1649 SkASSERT(fVerb == SkPath::kCubic_Verb);
1650 if (startT == 0) {
1651 edge->fCubic[1].set(fPts[1]);
1652 edge->fCubic[2].set(fPts[2]);
1653 return false;
1654 }
1655 edge->fCubic[1].set(fPts[2]);
1656 edge->fCubic[2].set(fPts[1]);
1657 return false;
1658 }
1659 if (fVerb == SkPath::kQuad_Verb) {
1660 edge->fQuad[1] = SkDQuad::SubDivide(fPts, edge->fQuad[0], edge->fQuad[2], startT, endT);
1661 } else if (fVerb == SkPath::kConic_Verb) {
1662 edge->fConic[1] = SkDConic::SubDivide(fPts, fWeight, edge->fQuad[0], edge->fQuad[2],
1663 startT, endT, &edge->fConic.fWeight);
1664 } else {
1665 SkASSERT(fVerb == SkPath::kCubic_Verb);
1666 SkDCubic::SubDivide(fPts, edge->fCubic[0], edge->fCubic[3], startT, endT, &edge->fCubic[1]);
1667 }
1668 return true;
1669}
static const int points[]
static SkDConic SubDivide(const SkPoint a[kPointCount], SkScalar weight, double t1, double t2)
static SkDCubic SubDivide(const SkPoint a[kPointCount], double t1, double t2)
static SkDQuad SubDivide(const SkPoint a[kPointCount], double t1, double t2)

◆ tail() [1/2]

SkOpSpanBase * SkOpSegment::tail ( )
inline

Definition at line 402 of file SkOpSegment.h.

402 {
403 return &fTail;
404 }

◆ tail() [2/2]

const SkOpSpanBase * SkOpSegment::tail ( ) const
inline

Definition at line 398 of file SkOpSegment.h.

398 {
399 return &fTail;
400 }

◆ testForCoincidence()

bool SkOpSegment::testForCoincidence ( const SkOpPtT priorPtT,
const SkOpPtT ptT,
const SkOpSpanBase prior,
const SkOpSpanBase spanBase,
const SkOpSegment opp 
) const

Definition at line 1671 of file SkOpSegment.cpp.

1672 {
1673 // average t, find mid pt
1674 double midT = (prior->t() + spanBase->t()) / 2;
1675 SkPoint midPt = this->ptAtT(midT);
1676 bool coincident = true;
1677 // if the mid pt is not near either end pt, project perpendicular through opp seg
1678 if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt)
1679 && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) {
1680 if (priorPtT->span() == ptT->span()) {
1681 return false;
1682 }
1683 coincident = false;
1685 SkDCurve curvePart;
1686 this->subDivide(prior, spanBase, &curvePart);
1687 SkDVector dxdy = (*CurveDDSlopeAtT[fVerb])(curvePart, 0.5f);
1688 SkDPoint partMidPt = (*CurveDDPointAtT[fVerb])(curvePart, 0.5f);
1689 SkDLine ray = {{{midPt.fX, midPt.fY}, {partMidPt.fX + dxdy.fY, partMidPt.fY - dxdy.fX}}};
1690 SkDCurve oppPart;
1691 opp->subDivide(priorPtT->span(), ptT->span(), &oppPart);
1692 (*CurveDIntersectRay[opp->verb()])(oppPart, ray, &i);
1693 // measure distance and see if it's small enough to denote coincidence
1694 for (int index = 0; index < i.used(); ++index) {
1695 if (!between(0, i[0][index], 1)) {
1696 continue;
1697 }
1698 SkDPoint oppPt = i.pt(index);
1699 if (oppPt.approximatelyDEqual(midPt)) {
1700 // the coincidence can occur at almost any angle
1701 coincident = true;
1702 }
1703 }
1704 }
1705 return coincident;
1706}
static bool coincident(const SkPoint &a, const SkPoint &b)
static SkDVector(*const CurveDDSlopeAtT[])(const SkDCurve &, double)
static void(*const CurveDIntersectRay[])(const SkDCurve &, const SkDLine &, SkIntersections *)
static SkDPoint(*const CurveDDPointAtT[])(const SkDCurve &, double)
bool subDivide(const SkOpSpanBase *start, const SkOpSpanBase *end, SkDCurve *result) const
bool approximatelyDEqual(const SkDPoint &a) const
float fX
x-axis value
float fY
y-axis value

◆ undoneSpan()

SkOpSpan * SkOpSegment::undoneSpan ( )

Definition at line 1708 of file SkOpSegment.cpp.

1708 {
1709 SkOpSpan* span = &fHead;
1711 do {
1712 next = span->next();
1713 if (!span->done()) {
1714 return span;
1715 }
1716 } while (!next->final() && (span = next->upCast()));
1717 return nullptr;
1718}

◆ updateOppWinding() [1/2]

int SkOpSegment::updateOppWinding ( const SkOpAngle angle) const

Definition at line 1731 of file SkOpSegment.cpp.

1731 {
1732 const SkOpSpanBase* startSpan = angle->start();
1733 const SkOpSpanBase* endSpan = angle->end();
1734 return updateOppWinding(endSpan, startSpan);
1735}

◆ updateOppWinding() [2/2]

int SkOpSegment::updateOppWinding ( const SkOpSpanBase start,
const SkOpSpanBase end 
) const

Definition at line 1720 of file SkOpSegment.cpp.

1720 {
1721 const SkOpSpan* lesser = start->starter(end);
1722 int oppWinding = lesser->oppSum();
1723 int oppSpanWinding = SkOpSegment::OppSign(start, end);
1724 if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding)
1725 && oppWinding != SK_MaxS32) {
1726 oppWinding -= oppSpanWinding;
1727 }
1728 return oppWinding;
1729}
static constexpr int32_t SK_MaxS32
Definition SkMath.h:21

◆ updateOppWindingReverse()

int SkOpSegment::updateOppWindingReverse ( const SkOpAngle angle) const

Definition at line 1737 of file SkOpSegment.cpp.

1737 {
1738 const SkOpSpanBase* startSpan = angle->start();
1739 const SkOpSpanBase* endSpan = angle->end();
1740 return updateOppWinding(startSpan, endSpan);
1741}

◆ updateWinding() [1/2]

int SkOpSegment::updateWinding ( SkOpAngle angle)

Definition at line 1760 of file SkOpSegment.cpp.

1760 {
1761 SkOpSpanBase* startSpan = angle->start();
1762 SkOpSpanBase* endSpan = angle->end();
1763 return updateWinding(endSpan, startSpan);
1764}

◆ updateWinding() [2/2]

int SkOpSegment::updateWinding ( SkOpSpanBase start,
SkOpSpanBase end 
)

Definition at line 1743 of file SkOpSegment.cpp.

1743 {
1744 SkOpSpan* lesser = start->starter(end);
1745 int winding = lesser->windSum();
1746 if (winding == SK_MinS32) {
1747 winding = lesser->computeWindSum();
1748 }
1749 if (winding == SK_MinS32) {
1750 return winding;
1751 }
1752 int spanWinding = SkOpSegment::SpanSign(start, end);
1753 if (winding && UseInnerWinding(winding - spanWinding, winding)
1754 && winding != SK_MaxS32) {
1755 winding -= spanWinding;
1756 }
1757 return winding;
1758}
int computeWindSum()
Definition SkOpSpan.cpp:378

◆ updateWindingReverse()

int SkOpSegment::updateWindingReverse ( const SkOpAngle angle)

Definition at line 1766 of file SkOpSegment.cpp.

1766 {
1767 SkOpSpanBase* startSpan = angle->start();
1768 SkOpSpanBase* endSpan = angle->end();
1769 return updateWinding(startSpan, endSpan);
1770}

◆ UseInnerWinding()

bool SkOpSegment::UseInnerWinding ( int  outerWinding,
int  innerWinding 
)
static

Definition at line 1775 of file SkOpSegment.cpp.

1775 {
1776 SkASSERT(outerWinding != SK_MaxS32);
1777 SkASSERT(innerWinding != SK_MaxS32);
1778 int absOut = SkTAbs(outerWinding);
1779 int absIn = SkTAbs(innerWinding);
1780 bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
1781 return result;
1782}

◆ verb()

SkPath::Verb SkOpSegment::verb ( ) const
inline

Definition at line 419 of file SkOpSegment.h.

419 {
420 return fVerb;
421 }

◆ visited()

bool SkOpSegment::visited ( )
inline

Definition at line 424 of file SkOpSegment.h.

424 {
425 if (!fVisited) {
426 fVisited = true;
427 return false;
428 }
429 return true;
430 }

◆ weight()

SkScalar SkOpSegment::weight ( ) const
inline

Definition at line 432 of file SkOpSegment.h.

432 {
433 return fWeight;
434 }

◆ windingSpanAtT()

SkOpSpan * SkOpSegment::windingSpanAtT ( double  tHit)

Definition at line 208 of file SkPathOpsWinding.cpp.

208 {
209 SkOpSpan* span = &fHead;
211 do {
212 next = span->next();
213 if (approximately_equal(tHit, next->t())) {
214 return nullptr;
215 }
216 if (tHit < next->t()) {
217 return span;
218 }
219 } while (!next->final() && (span = next->upCast()));
220 return nullptr;
221}

◆ windSum()

int SkOpSegment::windSum ( const SkOpAngle angle) const

Definition at line 1784 of file SkOpSegment.cpp.

1784 {
1785 const SkOpSpan* minSpan = angle->start()->starter(angle->end());
1786 return minSpan->windSum();
1787}

The documentation for this class was generated from the following files: