SkIntersectionHelper.h revision 7eaa53d8f7e48fd17d02b5e3bd91f90e9c1899ef
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    bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
21        return 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    bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
31            bool swap) {
32        return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index,
33                swap);
34    }
35
36    // Avoid collapsing t values that are close to the same since
37    // we walk ts to describe consecutive intersections. Since a pair of ts can
38    // be nearly equal, any problems caused by this should be taken care
39    // of later.
40    // On the edge or out of range values are negative; add 2 to get end
41    int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT, bool isNear) {
42        return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear);
43    }
44
45    int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
46        return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
47    }
48
49    bool advance() {
50        return ++fIndex < fLast;
51    }
52
53    SkScalar bottom() const {
54        return bounds().fBottom;
55    }
56
57    const SkPathOpsBounds& bounds() const {
58        return fContour->segments()[fIndex].bounds();
59    }
60
61    void init(SkOpContour* contour) {
62        fContour = contour;
63        fIndex = 0;
64        fLast = contour->segments().count();
65    }
66
67    bool isAdjacent(const SkIntersectionHelper& next) {
68        return fContour == next.fContour && fIndex + 1 == next.fIndex;
69    }
70
71    bool isFirstLast(const SkIntersectionHelper& next) {
72        return fContour == next.fContour && fIndex == 0
73                && next.fIndex == fLast - 1;
74    }
75
76    bool isNear(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const {
77        const SkOpSegment& segment = fContour->segments()[fIndex];
78        double mid = (t1 + t2) / 2;
79        SkDPoint midPtByT = segment.dPtAtT(mid);
80        SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2);
81        return midPtByT.approximatelyEqual(midPtByAvg);
82    }
83
84    SkScalar left() const {
85        return bounds().fLeft;
86    }
87
88    const SkPoint* pts() const {
89        return fContour->segments()[fIndex].pts();
90    }
91
92    SkScalar right() const {
93        return bounds().fRight;
94    }
95
96    SegmentType segmentType() const {
97        const SkOpSegment& segment = fContour->segments()[fIndex];
98        SegmentType type = (SegmentType) segment.verb();
99        if (type != kLine_Segment) {
100            return type;
101        }
102        if (segment.isHorizontal()) {
103            return kHorizontalLine_Segment;
104        }
105        if (segment.isVertical()) {
106            return kVerticalLine_Segment;
107        }
108        return kLine_Segment;
109    }
110
111    bool startAfter(const SkIntersectionHelper& after) {
112        fIndex = after.fIndex;
113        return advance();
114    }
115
116    SkScalar top() const {
117        return bounds().fTop;
118    }
119
120    SkPath::Verb verb() const {
121        return fContour->segments()[fIndex].verb();
122    }
123
124    SkScalar x() const {
125        return bounds().fLeft;
126    }
127
128    bool xFlipped() const {
129        return x() != pts()[0].fX;
130    }
131
132    SkScalar y() const {
133        return bounds().fTop;
134    }
135
136    bool yFlipped() const {
137        return y() != pts()[0].fY;
138    }
139
140private:
141    SkOpContour* fContour;
142    int fIndex;
143    int fLast;
144};
145