| /* |
| * 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" |
| |
| 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, |
| }; |
| |
| void addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) { |
| 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); |
| } |
| |
| // 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 SkIntersectionHelper& other, const SkPoint& pt, double newT) { |
| return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT); |
| } |
| |
| int addUnsortableT(const SkIntersectionHelper& other, bool start, const SkPoint& pt, |
| double newT) { |
| return fContour->addUnsortableT(fIndex, other.fContour, other.fIndex, start, pt, newT); |
| } |
| |
| bool advance() { |
| return ++fIndex < fLast; |
| } |
| |
| 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; |
| } |
| |
| 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: |
| SkOpContour* fContour; |
| int fIndex; |
| int fLast; |
| }; |