SkIntersectionHelper.h revision 7eaa53d8f7e48fd17d02b5e3bd91f90e9c1899ef
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright 2012 Google Inc.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * found in the LICENSE file.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkOpContour.h"
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkPath.h"
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SkIntersectionHelper {
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    enum SegmentType {
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        kHorizontalLine_Segment = -1,
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        kVerticalLine_Segment = 0,
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        kLine_Segment = SkPath::kLine_Verb,
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        kQuad_Segment = SkPath::kQuad_Verb,
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        kCubic_Segment = SkPath::kCubic_Verb,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: does it make sense to write otherIndex now if we're going to
255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // fix it up later?
26a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    void addOtherT(int index, double otherT, int otherIndex) {
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        fContour->addOtherT(fIndex, index, otherT, otherIndex);
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
31d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            bool swap) {
32d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index,
33d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                swap);
34d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
35d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
36d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Avoid collapsing t values that are close to the same since
37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // we walk ts to describe consecutive intersections. Since a pair of ts can
38d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // be nearly equal, any problems caused by this should be taken care
39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // of later.
40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // On the edge or out of range values are negative; add 2 to get end
41d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT, bool isNear) {
42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear);
43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
4651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool advance() {
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return ++fIndex < fLast;
5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
53d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    SkScalar bottom() const {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return bounds().fBottom;
5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const SkPathOpsBounds& bounds() const {
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return fContour->segments()[fIndex].bounds();
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
61d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    void init(SkOpContour* contour) {
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fContour = contour;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fIndex = 0;
645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        fLast = contour->segments().count();
655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isAdjacent(const SkIntersectionHelper& next) {
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fContour == next.fContour && fIndex + 1 == next.fIndex;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isFirstLast(const SkIntersectionHelper& next) {
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fContour == next.fContour && fIndex == 0
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                && next.fIndex == fLast - 1;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isNear(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const {
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const SkOpSegment& segment = fContour->segments()[fIndex];
78591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        double mid = (t1 + t2) / 2;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkDPoint midPtByT = segment.dPtAtT(mid);
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2);
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return midPtByT.approximatelyEqual(midPtByAvg);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SkScalar left() const {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return bounds().fLeft;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const SkPoint* pts() const {
8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return fContour->segments()[fIndex].pts();
9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkScalar right() const {
9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return bounds().fRight;
9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SegmentType segmentType() const {
9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        const SkOpSegment& segment = fContour->segments()[fIndex];
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SegmentType type = (SegmentType) segment.verb();
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (type != kLine_Segment) {
10009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return type;
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
102d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (segment.isHorizontal()) {
103d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return kHorizontalLine_Segment;
10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (segment.isVertical()) {
10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return kVerticalLine_Segment;
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return kLine_Segment;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool startAfter(const SkIntersectionHelper& after) {
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fIndex = after.fIndex;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return advance();
114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkScalar top() const {
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return bounds().fTop;
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkPath::Verb verb() const {
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fContour->segments()[fIndex].verb();
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkScalar x() const {
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return bounds().fLeft;
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool xFlipped() const {
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return x() != pts()[0].fX;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkScalar y() const {
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return bounds().fTop;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
136323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    bool yFlipped() const {
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return y() != pts()[0].fY;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkOpContour* fContour;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fIndex;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fLast;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)