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