| Index: src/pathops/SkOpContour.h
|
| ===================================================================
|
| --- src/pathops/SkOpContour.h (revision 0)
|
| +++ src/pathops/SkOpContour.h (revision 0)
|
| @@ -0,0 +1,253 @@
|
| +/*
|
| + * Copyright 2013 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +#ifndef SkOpContour_DEFINED
|
| +#define SkOpContour_DEFINED
|
| +
|
| +#include "SkOpSegment.h"
|
| +#include "SkTArray.h"
|
| +
|
| +class SkIntersections;
|
| +class SkOpContour;
|
| +class SkPathWriter;
|
| +
|
| +struct SkCoincidence {
|
| + SkOpContour* fContours[2];
|
| + int fSegments[2];
|
| + double fTs[2][2];
|
| + SkPoint fPts[2];
|
| +};
|
| +
|
| +class SkOpContour {
|
| +public:
|
| + SkOpContour() {
|
| + reset();
|
| +#if DEBUG_DUMP
|
| + fID = ++gContourID;
|
| +#endif
|
| + }
|
| +
|
| + bool operator<(const SkOpContour& rh) const {
|
| + return fBounds.fTop == rh.fBounds.fTop
|
| + ? fBounds.fLeft < rh.fBounds.fLeft
|
| + : fBounds.fTop < rh.fBounds.fTop;
|
| + }
|
| +
|
| + void addCoincident(int index, SkOpContour* other, int otherIndex,
|
| + const SkIntersections& ts, bool swap);
|
| + void addCoincidentPoints();
|
| +
|
| + void addCross(const SkOpContour* crosser) {
|
| +#ifdef DEBUG_CROSS
|
| + for (int index = 0; index < fCrosses.count(); ++index) {
|
| + SkASSERT(fCrosses[index] != crosser);
|
| + }
|
| +#endif
|
| + *fCrosses.append() = crosser;
|
| + }
|
| +
|
| + void addCubic(const SkPoint pts[4]) {
|
| + fSegments.push_back().addCubic(pts, fOperand, fXor);
|
| + fContainsCurves = fContainsCubics = true;
|
| + }
|
| +
|
| + int addLine(const SkPoint pts[2]) {
|
| + fSegments.push_back().addLine(pts, fOperand, fXor);
|
| + return fSegments.count();
|
| + }
|
| +
|
| + void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
|
| + fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
|
| + }
|
| +
|
| + int addQuad(const SkPoint pts[3]) {
|
| + fSegments.push_back().addQuad(pts, fOperand, fXor);
|
| + fContainsCurves = true;
|
| + return fSegments.count();
|
| + }
|
| +
|
| + int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
|
| + setContainsIntercepts();
|
| + return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT);
|
| + }
|
| +
|
| + int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
|
| + setContainsIntercepts();
|
| + return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, newT);
|
| + }
|
| +
|
| + int addUnsortableT(int segIndex, SkOpContour* other, int otherIndex, bool start,
|
| + const SkPoint& pt, double newT) {
|
| + return fSegments[segIndex].addUnsortableT(&other->fSegments[otherIndex], start, pt, newT);
|
| + }
|
| +
|
| + const SkPathOpsBounds& bounds() const {
|
| + return fBounds;
|
| + }
|
| +
|
| + void calcCoincidentWinding();
|
| +
|
| + void complete() {
|
| + setBounds();
|
| + fContainsIntercepts = false;
|
| + }
|
| +
|
| + bool containsCubics() const {
|
| + return fContainsCubics;
|
| + }
|
| +
|
| + bool crosses(const SkOpContour* crosser) const {
|
| + for (int index = 0; index < fCrosses.count(); ++index) {
|
| + if (fCrosses[index] == crosser) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool done() const {
|
| + return fDone;
|
| + }
|
| +
|
| + const SkPoint& end() const {
|
| + const SkOpSegment& segment = fSegments.back();
|
| + return segment.pts()[segment.verb()];
|
| + }
|
| +
|
| + void findTooCloseToCall() {
|
| + int segmentCount = fSegments.count();
|
| + for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
|
| + fSegments[sIndex].findTooCloseToCall();
|
| + }
|
| + }
|
| +
|
| + void fixOtherTIndex() {
|
| + int segmentCount = fSegments.count();
|
| + for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
|
| + fSegments[sIndex].fixOtherTIndex();
|
| + }
|
| + }
|
| +
|
| + SkOpSegment* nonVerticalSegment(int& start, int& end);
|
| +
|
| + bool operand() const {
|
| + return fOperand;
|
| + }
|
| +
|
| + void reset() {
|
| + fSegments.reset();
|
| + fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
|
| + fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false;
|
| + }
|
| +
|
| + void resolveCoincidence(SkTDArray<SkOpContour*>& contourList);
|
| +
|
| + SkTArray<SkOpSegment>& segments() {
|
| + return fSegments;
|
| + }
|
| +
|
| + void setContainsIntercepts() {
|
| + fContainsIntercepts = true;
|
| + }
|
| +
|
| + void setOperand(bool isOp) {
|
| + fOperand = isOp;
|
| + }
|
| +
|
| + void setOppXor(bool isOppXor) {
|
| + fOppXor = isOppXor;
|
| + int segmentCount = fSegments.count();
|
| + for (int test = 0; test < segmentCount; ++test) {
|
| + fSegments[test].setOppXor(isOppXor);
|
| + }
|
| + }
|
| +
|
| + void setXor(bool isXor) {
|
| + fXor = isXor;
|
| + }
|
| +
|
| + void sortSegments();
|
| +
|
| + const SkPoint& start() const {
|
| + return fSegments.front().pts()[0];
|
| + }
|
| +
|
| + void toPath(SkPathWriter& path) const;
|
| +
|
| + void toPartialBackward(SkPathWriter& path) const {
|
| + int segmentCount = fSegments.count();
|
| + for (int test = segmentCount - 1; test >= 0; --test) {
|
| + fSegments[test].addCurveTo(1, 0, path, true);
|
| + }
|
| + }
|
| +
|
| + void toPartialForward(SkPathWriter& path) const {
|
| + int segmentCount = fSegments.count();
|
| + for (int test = 0; test < segmentCount; ++test) {
|
| + fSegments[test].addCurveTo(0, 1, path, true);
|
| + }
|
| + }
|
| +
|
| + void topSortableSegment(const SkPoint& topLeft, SkPoint& bestXY, SkOpSegment*& topStart);
|
| + SkOpSegment* undoneSegment(int& start, int& end);
|
| +
|
| + int updateSegment(int index, const SkPoint* pts) {
|
| + SkOpSegment& segment = fSegments[index];
|
| + segment.updatePts(pts);
|
| + return segment.verb() + 1;
|
| + }
|
| +
|
| +#if DEBUG_TEST
|
| + SkTArray<SkOpSegment>& debugSegments() {
|
| + return fSegments;
|
| + }
|
| +#endif
|
| +
|
| +#if DEBUG_DUMP
|
| + void dump();
|
| +#endif
|
| +
|
| +#if DEBUG_ACTIVE_SPANS
|
| + void debugShowActiveSpans() {
|
| + for (int index = 0; index < fSegments.count(); ++index) {
|
| + fSegments[index].debugShowActiveSpans();
|
| + }
|
| + }
|
| +
|
| + void validateActiveSpans() {
|
| + for (int index = 0; index < fSegments.count(); ++index) {
|
| + fSegments[index].validateActiveSpans();
|
| + }
|
| + }
|
| +#endif
|
| +
|
| +#if DEBUG_SHOW_WINDING
|
| + int debugShowWindingValues(int totalSegments, int ofInterest);
|
| + static void debugShowWindingValues(SkTDArray<SkOpContour*>& contourList);
|
| +#endif
|
| +
|
| +private:
|
| + void setBounds();
|
| +
|
| + SkTArray<SkOpSegment> fSegments;
|
| + SkTDArray<SkOpSegment*> fSortedSegments;
|
| + int fFirstSorted;
|
| + SkTDArray<SkCoincidence> fCoincidences;
|
| + SkTDArray<const SkOpContour*> fCrosses;
|
| + SkPathOpsBounds fBounds;
|
| + bool fContainsIntercepts; // FIXME: is this used by anybody?
|
| + bool fContainsCubics;
|
| + bool fContainsCurves;
|
| + bool fDone;
|
| + bool fOperand; // true for the second argument to a binary operator
|
| + bool fXor;
|
| + bool fOppXor;
|
| +#if DEBUG_DUMP
|
| + int fID;
|
| +#endif
|
| +};
|
| +
|
| +#endif
|
|
|