30 while (!chase.
empty()) {
39 *startPtr = last->start();
40 *endPtr = last->end();
62 int sumMiWinding, sumSuWinding;
79 swap(sumMiWinding, sumSuWinding);
84 while ((angle = angle->
next()) != firstAngle) {
88 int maxWinding = 0, sumWinding = 0, oppMaxWinding = 0, oppSumWinding = 0;
91 &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
93 if (!segment->
done(angle)) {
101 if (!segment->
markAngle(maxWinding, sumWinding, oppMaxWinding,
102 oppSumWinding, angle,
nullptr)) {
123 const int xorMask,
const int xorOpMask,
SkPathWriter* writer) {
124 bool unsortable =
false;
125 bool lastSimple =
false;
139 if (!unsortable && current->
done()) {
147 &unsortable, &simple, op, xorMask, xorOpMask);
149 if (!unsortable && writer->
hasMove()
158 }
else if (lastSimple) {
166 SkDebugf(
"%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
168 end->pt().fX,
end->pt().fY);
176 }
while (!writer->
isClosed() && (!unsortable || !
start->starter(
end)->done()));
179 if (!spanStart->
done()) {
192 if (last && !last->
chased()) {
198 if (!last->
final()) {
231 {{
false,
false }, {
true,
false }},
232 {{
false,
false }, {
false,
true }},
233 {{
false,
true }, {
true,
true }},
234 {{
false,
true }, {
true,
false }},
235 {{
false,
true }, {
false,
false }},
238#if DEBUG_T_SECT_LOOP_COUNT
244void ReportPathOpsDebugging() {
245 debugWorstState.debugLoopReport();
248extern void (*gVerboseFinalize)();
258 if (SkPathOpsDebug::gDumpOp) {
269 result->setFillType(fillType);
290 if (!
two.isEmpty()) {
308 const SkPath* minuend = &one;
312 swap(minuend, subtrahend);
316 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
323 const int xorMask =
builder.xorMask();
324 builder.addOperand(*subtrahend);
328#if DEBUG_DUMP_SEGMENTS
332 const int xorOpMask =
builder.xorMask();
336 result->setFillType(fillType);
346 }
while ((current = current->
next()));
352 globalState.debugAddToGlobalCoinDicts();
363 result->setFillType(fillType);
365 if (!
bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper)) {
370#if DEBUG_T_SECT_LOOP_COUNT
371 static SkMutex& debugWorstLoop = *(
new SkMutex);
374 if (!gVerboseFinalize) {
375 gVerboseFinalize = &ReportPathOpsDebugging;
377 debugWorstState.debugDoYourWorst(&globalState);
385 if (SkPathOpsDebug::gVerifyOp) {
387 ReportOpFail(one,
two, op);
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static float next(float f)
bool AddIntersectTs(SkOpContour *test, SkOpContour *next, SkOpCoincidence *coincidence)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr int32_t SK_MinS32
bool SortContourList(SkOpContourHead **contourList, bool evenOdd, bool oppEvenOdd)
const SkOpAngle * AngleWinding(SkOpSpanBase *start, SkOpSpanBase *end, int *windingPtr, bool *sortablePtr)
bool HandleCoincidence(SkOpContourHead *contourList, SkOpCoincidence *coincidence)
SkOpSpan * FindSortableTop(SkOpContourHead *)
#define SkDEBUGPARAMS(...)
bool OpDebug(const SkPath &one, const SkPath &two, SkPathOp op, SkPath *result SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char *testName))
static const bool gOutInverse[kReverseDifference_SkPathOp+1][2][2]
bool Op(const SkPath &one, const SkPath &two, SkPathOp op, SkPath *result)
static bool findChaseOp(SkTDArray< SkOpSpanBase * > &chase, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, SkOpSegment **result)
static bool bridgeOp(SkOpContourHead *contourList, const SkPathOp op, const int xorMask, const int xorOpMask, SkPathWriter *writer)
static const SkPathOp gOpInverse[kReverseDifference_SkPathOp+1][2][2]
@ kReverseDifference_SkPathOp
subtract the first path from the op path
@ kDifference_SkPathOp
subtract the op path from the first path
@ kIntersect_SkPathOp
intersect the two paths
@ kUnion_SkPathOp
union (inclusive-or) the two paths
@ kXOR_SkPathOp
exclusive-or the two paths
bool SK_API Simplify(const SkPath &path, SkPath *result)
void swap(sk_sp< T > &a, sk_sp< T > &b)
SkOpSegment * segment() const
SkOpSpanBase * end() const
SkOpSpanBase * start() const
void dumpSegments(const char *prefix="seg", SkPathOp op=(SkPathOp) -1) const
void setPhase(SkOpPhase phase)
const SkOpSpanBase * span() const
SkPath::Verb verb() const
SkOpSegment * findNextOp(SkTDArray< SkOpSpanBase * > *chase, SkOpSpanBase **nextStart, SkOpSpanBase **nextEnd, bool *unsortable, bool *simple, SkPathOp op, int xorMiMask, int xorSuMask)
bool activeWinding(SkOpSpanBase *start, SkOpSpanBase *end)
int updateWindingReverse(const SkOpAngle *angle)
bool markAndChaseDone(SkOpSpanBase *start, SkOpSpanBase *end, SkOpSpanBase **found)
void setUpWindings(SkOpSpanBase *start, SkOpSpanBase *end, int *sumMiWinding, int *maxWinding, int *sumWinding)
SkOpGlobalState * globalState() const
bool addCurveTo(const SkOpSpanBase *start, const SkOpSpanBase *end, SkPathWriter *path) const
SkOpAngle * activeAngle(SkOpSpanBase *start, SkOpSpanBase **startPtr, SkOpSpanBase **endPtr, bool *done)
bool activeOp(SkOpSpanBase *start, SkOpSpanBase *end, int xorMiMask, int xorSuMask, SkPathOp op)
int updateOppWindingReverse(const SkOpAngle *angle) const
bool markAngle(int maxWinding, int sumWinding, const SkOpAngle *angle, SkOpSpanBase **result)
void markDone(SkOpSpan *)
void setChased(bool chased)
SkOpSegment * segment() const
const SkOpPtT * ptT() const
SkOpSpanBase * next() const
static void ShowActiveSpans(SkOpContourHead *contourList)
static bool ChaseContains(const SkTDArray< SkOpSpanBase * > &, const SkOpSpanBase *)
bool isInverseFillType() const
void toggleInverseFillType()
bool isRect(SkRect *rect, bool *isClosed=nullptr, SkPathDirection *direction=nullptr) const
bool intersect(const SkRect &r)