| /* | |
| * Copyright 2012 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkOpContour.h" | |
| #include "SkPath.h" | |
| #ifdef SK_DEBUG | |
| #include "SkPathOpsPoint.h" | |
| #endif | |
| class SkIntersectionHelper { | |
| public: | |
| enum SegmentType { | |
| kHorizontalLine_Segment = -1, | |
| kVerticalLine_Segment = 0, | |
| kLine_Segment = SkPath::kLine_Verb, | |
| kQuad_Segment = SkPath::kQuad_Verb, | |
| kCubic_Segment = SkPath::kCubic_Verb, | |
| }; | |
| bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) { | |
| return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap); | |
| } | |
| // FIXME: does it make sense to write otherIndex now if we're going to | |
| // fix it up later? | |
| void addOtherT(int index, double otherT, int otherIndex) { | |
| fContour->addOtherT(fIndex, index, otherT, otherIndex); | |
| } | |
| bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index, | |
| bool swap) { | |
| return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index, | |
| swap); | |
| } | |
| // Avoid collapsing t values that are close to the same since | |
| // we walk ts to describe consecutive intersections. Since a pair of ts can | |
| // be nearly equal, any problems caused by this should be taken care | |
| // of later. | |
| // On the edge or out of range values are negative; add 2 to get end | |
| int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) { | |
| return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT); | |
| } | |
| int addSelfT(const SkPoint& pt, double newT) { | |
| return fContour->addSelfT(fIndex, pt, newT); | |
| } | |
| bool advance() { | |
| return ++fIndex < fLast; | |
| } | |
| void alignTPt(SkIntersectionHelper& other, bool swap, int index, | |
| SkIntersections* ts, SkPoint* point) { | |
| fContour->alignTPt(fIndex, other.fContour, other.fIndex, swap, index, ts, point); | |
| } | |
| SkScalar bottom() const { | |
| return bounds().fBottom; | |
| } | |
| const SkPathOpsBounds& bounds() const { | |
| return fContour->segments()[fIndex].bounds(); | |
| } | |
| void init(SkOpContour* contour) { | |
| fContour = contour; | |
| fIndex = 0; | |
| fLast = contour->segments().count(); | |
| } | |
| bool isAdjacent(const SkIntersectionHelper& next) { | |
| return fContour == next.fContour && fIndex + 1 == next.fIndex; | |
| } | |
| bool isFirstLast(const SkIntersectionHelper& next) { | |
| return fContour == next.fContour && fIndex == 0 | |
| && next.fIndex == fLast - 1; | |
| } | |
| bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const { | |
| const SkOpSegment& segment = fContour->segments()[fIndex]; | |
| double mid = (t1 + t2) / 2; | |
| SkDPoint midPtByT = segment.dPtAtT(mid); | |
| SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2); | |
| return midPtByT.approximatelyPEqual(midPtByAvg); | |
| } | |
| SkScalar left() const { | |
| return bounds().fLeft; | |
| } | |
| const SkPoint* pts() const { | |
| return fContour->segments()[fIndex].pts(); | |
| } | |
| SkScalar right() const { | |
| return bounds().fRight; | |
| } | |
| SegmentType segmentType() const { | |
| const SkOpSegment& segment = fContour->segments()[fIndex]; | |
| SegmentType type = (SegmentType) segment.verb(); | |
| if (type != kLine_Segment) { | |
| return type; | |
| } | |
| if (segment.isHorizontal()) { | |
| return kHorizontalLine_Segment; | |
| } | |
| if (segment.isVertical()) { | |
| return kVerticalLine_Segment; | |
| } | |
| return kLine_Segment; | |
| } | |
| bool startAfter(const SkIntersectionHelper& after) { | |
| fIndex = after.fIndex; | |
| return advance(); | |
| } | |
| SkScalar top() const { | |
| return bounds().fTop; | |
| } | |
| SkPath::Verb verb() const { | |
| return fContour->segments()[fIndex].verb(); | |
| } | |
| SkScalar x() const { | |
| return bounds().fLeft; | |
| } | |
| bool xFlipped() const { | |
| return x() != pts()[0].fX; | |
| } | |
| SkScalar y() const { | |
| return bounds().fTop; | |
| } | |
| bool yFlipped() const { | |
| return y() != pts()[0].fY; | |
| } | |
| private: | |
| // utility callable by the user from the debugger when the implementation code is linked in | |
| void dump() const; | |
| SkOpContour* fContour; | |
| int fIndex; | |
| int fLast; | |
| }; |