SkIntersectionHelper.h revision 570863f2e22b8ea7d7c504bd15e4f766af097df2
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#include "SkOpContour.h"
8#include "SkPath.h"
9
10class SkIntersectionHelper {
11public:
12    enum SegmentType {
13        kHorizontalLine_Segment = -1,
14        kVerticalLine_Segment = 0,
15        kLine_Segment = SkPath::kLine_Verb,
16        kQuad_Segment = SkPath::kQuad_Verb,
17        kCubic_Segment = SkPath::kCubic_Verb,
18    };
19
20    void addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
21        fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
22    }
23
24    // FIXME: does it make sense to write otherIndex now if we're going to
25    // fix it up later?
26    void addOtherT(int index, double otherT, int otherIndex) {
27        fContour->addOtherT(fIndex, index, otherT, otherIndex);
28    }
29
30    void addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
31            bool swap) {
32        fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index, swap);
33    }
34
35    // Avoid collapsing t values that are close to the same since
36    // we walk ts to describe consecutive intersections. Since a pair of ts can
37    // be nearly equal, any problems caused by this should be taken care
38    // of later.
39    // On the edge or out of range values are negative; add 2 to get end
40    int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT, bool isNear) {
41        return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear);
42    }
43
44    int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
45        return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
46    }
47
48    bool advance() {
49        return ++fIndex < fLast;
50    }
51
52    SkScalar bottom() const {
53        return bounds().fBottom;
54    }
55
56    const SkPathOpsBounds& bounds() const {
57        return fContour->segments()[fIndex].bounds();
58    }
59
60    void init(SkOpContour* contour) {
61        fContour = contour;
62        fIndex = 0;
63        fLast = contour->segments().count();
64    }
65
66    bool isAdjacent(const SkIntersectionHelper& next) {
67        return fContour == next.fContour && fIndex + 1 == next.fIndex;
68    }
69
70    bool isFirstLast(const SkIntersectionHelper& next) {
71        return fContour == next.fContour && fIndex == 0
72                && next.fIndex == fLast - 1;
73    }
74
75    bool isNear(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const {
76        const SkOpSegment& segment = fContour->segments()[fIndex];
77        double mid = (t1 + t2) / 2;
78        SkDPoint midPtByT = segment.dPtAtT(mid);
79        SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2);
80        return midPtByT.approximatelyEqualHalf(midPtByAvg);
81    }
82
83    SkScalar left() const {
84        return bounds().fLeft;
85    }
86
87    const SkPoint* pts() const {
88        return fContour->segments()[fIndex].pts();
89    }
90
91    SkScalar right() const {
92        return bounds().fRight;
93    }
94
95    SegmentType segmentType() const {
96        const SkOpSegment& segment = fContour->segments()[fIndex];
97        SegmentType type = (SegmentType) segment.verb();
98        if (type != kLine_Segment) {
99            return type;
100        }
101        if (segment.isHorizontal()) {
102            return kHorizontalLine_Segment;
103        }
104        if (segment.isVertical()) {
105            return kVerticalLine_Segment;
106        }
107        return kLine_Segment;
108    }
109
110    bool startAfter(const SkIntersectionHelper& after) {
111        fIndex = after.fIndex;
112        return advance();
113    }
114
115    SkScalar top() const {
116        return bounds().fTop;
117    }
118
119    SkPath::Verb verb() const {
120        return fContour->segments()[fIndex].verb();
121    }
122
123    SkScalar x() const {
124        return bounds().fLeft;
125    }
126
127    bool xFlipped() const {
128        return x() != pts()[0].fX;
129    }
130
131    SkScalar y() const {
132        return bounds().fTop;
133    }
134
135    bool yFlipped() const {
136        return y() != pts()[0].fY;
137    }
138
139private:
140    SkOpContour* fContour;
141    int fIndex;
142    int fLast;
143};
144