blob: 1a4b1f044145e70054cc125033284b4c47dd56dd [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000020 bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
21 return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
caryclark@google.com07393ca2013-04-08 11:47:37 +000022 }
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
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000030 bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
caryclark@google.com570863f2013-09-16 15:55:01 +000031 bool swap) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000032 return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index,
33 swap);
caryclark@google.com570863f2013-09-16 15:55:01 +000034 }
35
caryclark@google.com07393ca2013-04-08 11:47:37 +000036 // 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
caryclark@google.com570863f2013-09-16 15:55:01 +000041 int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT, bool isNear) {
42 return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear);
caryclark@google.com07393ca2013-04-08 11:47:37 +000043 }
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
caryclark@google.com07393ca2013-04-08 11:47:37 +000049 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
caryclark@google.com570863f2013-09-16 15:55:01 +000076 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);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000081 return midPtByT.approximatelyEqual(midPtByAvg);
caryclark@google.com570863f2013-09-16 15:55:01 +000082 }
83
caryclark@google.com07393ca2013-04-08 11:47:37 +000084 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};