SkIntersectionHelper.h revision d998bec91855b8830b01db2d2caf155ab077b91b
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 14class SkIntersectionHelper { 15public: 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, bool isNear) { 46 return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear); 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 isNear(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.approximatelyEqual(midPtByAvg); 86 } 87 88 bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const { 89 const SkOpSegment& segment = fContour->segments()[fIndex]; 90 double mid = (t1 + t2) / 2; 91 SkDPoint midPtByT = segment.dPtAtT(mid); 92 SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2); 93 return midPtByT.approximatelyPEqual(midPtByAvg); 94 } 95 96 SkScalar left() const { 97 return bounds().fLeft; 98 } 99 100 const SkPoint* pts() const { 101 return fContour->segments()[fIndex].pts(); 102 } 103 104 SkScalar right() const { 105 return bounds().fRight; 106 } 107 108 SegmentType segmentType() const { 109 const SkOpSegment& segment = fContour->segments()[fIndex]; 110 SegmentType type = (SegmentType) segment.verb(); 111 if (type != kLine_Segment) { 112 return type; 113 } 114 if (segment.isHorizontal()) { 115 return kHorizontalLine_Segment; 116 } 117 if (segment.isVertical()) { 118 return kVerticalLine_Segment; 119 } 120 return kLine_Segment; 121 } 122 123 bool startAfter(const SkIntersectionHelper& after) { 124 fIndex = after.fIndex; 125 return advance(); 126 } 127 128 SkScalar top() const { 129 return bounds().fTop; 130 } 131 132 SkPath::Verb verb() const { 133 return fContour->segments()[fIndex].verb(); 134 } 135 136 SkScalar x() const { 137 return bounds().fLeft; 138 } 139 140 bool xFlipped() const { 141 return x() != pts()[0].fX; 142 } 143 144 SkScalar y() const { 145 return bounds().fTop; 146 } 147 148 bool yFlipped() const { 149 return y() != pts()[0].fY; 150 } 151 152#ifdef SK_DEBUG 153 void dump() { 154 SkDPoint::dump(pts()[0]); 155 SkDPoint::dump(pts()[1]); 156 if (verb() >= SkPath::kQuad_Verb) { 157 SkDPoint::dump(pts()[2]); 158 } 159 if (verb() >= SkPath::kCubic_Verb) { 160 SkDPoint::dump(pts()[3]); 161 } 162 } 163#endif 164 165private: 166 SkOpContour* fContour; 167 int fIndex; 168 int fLast; 169}; 170