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