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