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)