SkIntersectionHelper.h revision d998bec91855b8830b01db2d2caf155ab077b91b
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright 2012 Google Inc. 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use of this source code is governed by a BSD-style license that can be 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * found in the LICENSE file. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#include "SkOpContour.h" 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "SkPath.h" 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef SK_DEBUG 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "SkPathOpsPoint.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtclass SkIntersectionHelper { 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpublic: 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum SegmentType { 17b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt kHorizontalLine_Segment = -1, 18cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kVerticalLine_Segment = 0, 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kLine_Segment = SkPath::kLine_Verb, 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kQuad_Segment = SkPath::kQuad_Verb, 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kCubic_Segment = SkPath::kCubic_Verb, 221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt }; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) { 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap); 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // FIXME: does it make sense to write otherIndex now if we're going to 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // fix it up later? 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void addOtherT(int index, double otherT, int otherIndex) { 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fContour->addOtherT(fIndex, index, otherT, otherIndex); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index, 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool swap) { 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index, 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt swap); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Avoid collapsing t values that are close to the same since 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // we walk ts to describe consecutive intersections. Since a pair of ts can 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // be nearly equal, any problems caused by this should be taken care 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // of later. 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // On the edge or out of range values are negative; add 2 to get end 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT, bool isNear) { 4668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear); 4768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 4868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 4968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) { 5068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT); 5168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 5268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 5368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt bool advance() { 5468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return ++fIndex < fLast; 5568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 5668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 5768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt SkScalar bottom() const { 5868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return bounds().fBottom; 5968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 6068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 6168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt const SkPathOpsBounds& bounds() const { 6268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return fContour->segments()[fIndex].bounds(); 6368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 6468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 6568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt void init(SkOpContour* contour) { 6668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt fContour = contour; 6768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt fIndex = 0; 6868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt fLast = contour->segments().count(); 6968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 7068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 7168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt bool isAdjacent(const SkIntersectionHelper& next) { 7268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return fContour == next.fContour && fIndex + 1 == next.fIndex; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool isFirstLast(const SkIntersectionHelper& next) { 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return fContour == next.fContour && fIndex == 0 77cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt && next.fIndex == fLast - 1; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool isNear(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const SkOpSegment& segment = fContour->segments()[fIndex]; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt double mid = (t1 + t2) / 2; 83b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt SkDPoint midPtByT = segment.dPtAtT(mid); 84b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2); 85b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return midPtByT.approximatelyEqual(midPtByAvg); 86b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 87b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 88b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const { 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const SkOpSegment& segment = fContour->segments()[fIndex]; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt double mid = (t1 + t2) / 2; 91c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt SkDPoint midPtByT = segment.dPtAtT(mid); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return midPtByT.approximatelyPEqual(midPtByAvg); 94c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 95c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt SkScalar left() const { 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return bounds().fLeft; 98c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 100c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt const SkPoint* pts() const { 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return fContour->segments()[fIndex].pts(); 102c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 10304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt SkScalar right() const { 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return bounds().fRight; 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 107c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 108c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt SegmentType segmentType() const { 109c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt const SkOpSegment& segment = fContour->segments()[fIndex]; 11004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt SegmentType type = (SegmentType) segment.verb(); 11104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (type != kLine_Segment) { 11204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return type; 11304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 11404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (segment.isHorizontal()) { 11504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return kHorizontalLine_Segment; 11604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 11704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (segment.isVertical()) { 11804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return kVerticalLine_Segment; 11904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 120c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt return kLine_Segment; 12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bool startAfter(const SkIntersectionHelper& after) { 12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt fIndex = after.fIndex; 12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return advance(); 12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt SkScalar top() const { 12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return bounds().fTop; 13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt SkPath::Verb verb() const { 1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return fContour->segments()[fIndex].verb(); 1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt SkScalar x() const { 1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return bounds().fLeft; 1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bool xFlipped() const { 1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return x() != pts()[0].fX; 1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt SkScalar y() const { 14568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return bounds().fTop; 14668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 14768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 14868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt bool yFlipped() const { 14968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return y() != pts()[0].fY; 1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 151c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 152c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#ifdef SK_DEBUG 153c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt void dump() { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SkDPoint::dump(pts()[0]); 15534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt SkDPoint::dump(pts()[1]); 15634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (verb() >= SkPath::kQuad_Verb) { 15734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt SkDPoint::dump(pts()[2]); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (verb() >= SkPath::kCubic_Verb) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SkDPoint::dump(pts()[3]); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtprivate: 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SkOpContour* fContour; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int fIndex; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int fLast; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt