blob: 5d8ebcd5903292f568d0e0f17d6f03ced924b505 [file] [log] [blame]
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkOpContour.h"
#include "SkPath.h"
class SkIntersectionHelper {
public:
enum SegmentType {
kHorizontalLine_Segment = -1,
kVerticalLine_Segment = 0,
kLine_Segment = SkPath::kLine_Verb,
kQuad_Segment = SkPath::kQuad_Verb,
kCubic_Segment = SkPath::kCubic_Verb,
};
void addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
}
// FIXME: does it make sense to write otherIndex now if we're going to
// fix it up later?
void addOtherT(int index, double otherT, int otherIndex) {
fContour->addOtherT(fIndex, index, otherT, otherIndex);
}
// Avoid collapsing t values that are close to the same since
// we walk ts to describe consecutive intersections. Since a pair of ts can
// be nearly equal, any problems caused by this should be taken care
// of later.
// On the edge or out of range values are negative; add 2 to get end
int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
}
int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
}
int addUnsortableT(const SkIntersectionHelper& other, bool start, const SkPoint& pt,
double newT) {
return fContour->addUnsortableT(fIndex, other.fContour, other.fIndex, start, pt, newT);
}
bool advance() {
return ++fIndex < fLast;
}
SkScalar bottom() const {
return bounds().fBottom;
}
const SkPathOpsBounds& bounds() const {
return fContour->segments()[fIndex].bounds();
}
void init(SkOpContour* contour) {
fContour = contour;
fIndex = 0;
fLast = contour->segments().count();
}
bool isAdjacent(const SkIntersectionHelper& next) {
return fContour == next.fContour && fIndex + 1 == next.fIndex;
}
bool isFirstLast(const SkIntersectionHelper& next) {
return fContour == next.fContour && fIndex == 0
&& next.fIndex == fLast - 1;
}
SkScalar left() const {
return bounds().fLeft;
}
const SkPoint* pts() const {
return fContour->segments()[fIndex].pts();
}
SkScalar right() const {
return bounds().fRight;
}
SegmentType segmentType() const {
const SkOpSegment& segment = fContour->segments()[fIndex];
SegmentType type = (SegmentType) segment.verb();
if (type != kLine_Segment) {
return type;
}
if (segment.isHorizontal()) {
return kHorizontalLine_Segment;
}
if (segment.isVertical()) {
return kVerticalLine_Segment;
}
return kLine_Segment;
}
bool startAfter(const SkIntersectionHelper& after) {
fIndex = after.fIndex;
return advance();
}
SkScalar top() const {
return bounds().fTop;
}
SkPath::Verb verb() const {
return fContour->segments()[fIndex].verb();
}
SkScalar x() const {
return bounds().fLeft;
}
bool xFlipped() const {
return x() != pts()[0].fX;
}
SkScalar y() const {
return bounds().fTop;
}
bool yFlipped() const {
return y() != pts()[0].fY;
}
private:
SkOpContour* fContour;
int fIndex;
int fLast;
};