| /* |
| * 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; |
| }; |