aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-04-29 08:28:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-29 08:28:30 -0700
commitaec251012542e971100e218bf463adbfb5d21d20 (patch)
tree16c2e84c2d59d94b75d7d2bc50fec53c0e38a898 /src/pathops
parent97fdea6c4393cf0102d7eee5790782509fb4f57b (diff)
minor fixes to cubics code and overall alignment of how bounds and tops are computed for all curve types
All but 17 extended tests work. A helper function is privately added to SkPath.h to permit a test to modify a given point in a path. BUG=skia:3588 Review URL: https://codereview.chromium.org/1107353004
Diffstat (limited to 'src/pathops')
-rw-r--r--src/pathops/SkDCubicLineIntersection.cpp6
-rw-r--r--src/pathops/SkOpContour.cpp4
-rw-r--r--src/pathops/SkOpContour.h2
-rw-r--r--src/pathops/SkOpSegment.cpp33
-rw-r--r--src/pathops/SkOpSegment.h16
-rw-r--r--src/pathops/SkPathOpsBounds.cpp51
-rw-r--r--src/pathops/SkPathOpsBounds.h23
-rw-r--r--src/pathops/SkPathOpsCommon.cpp6
-rw-r--r--src/pathops/SkPathOpsCommon.h2
-rw-r--r--src/pathops/SkPathOpsConic.cpp22
-rw-r--r--src/pathops/SkPathOpsConic.h6
-rw-r--r--src/pathops/SkPathOpsCubic.cpp89
-rw-r--r--src/pathops/SkPathOpsCubic.h6
-rw-r--r--src/pathops/SkPathOpsCurve.cpp146
-rw-r--r--src/pathops/SkPathOpsCurve.h53
-rw-r--r--src/pathops/SkPathOpsDebug.h10
-rw-r--r--src/pathops/SkPathOpsOp.cpp4
-rw-r--r--src/pathops/SkPathOpsQuad.cpp31
-rw-r--r--src/pathops/SkPathOpsQuad.h4
-rw-r--r--src/pathops/SkPathOpsRect.cpp61
-rw-r--r--src/pathops/SkPathOpsRect.h20
-rw-r--r--src/pathops/SkPathOpsSimplify.cpp4
22 files changed, 330 insertions, 269 deletions
diff --git a/src/pathops/SkDCubicLineIntersection.cpp b/src/pathops/SkDCubicLineIntersection.cpp
index f5fe01503b..f658b09f0b 100644
--- a/src/pathops/SkDCubicLineIntersection.cpp
+++ b/src/pathops/SkDCubicLineIntersection.cpp
@@ -135,7 +135,7 @@ public:
+ (fCubic[n].fX - fLine[0].fX) * adj;
}
double extremeTs[6];
- int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs);
+ int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
count = c.searchRoots(extremeTs, extrema, 0, SkDCubic::kXAxis, roots);
break;
}
@@ -171,7 +171,7 @@ public:
SkDPoint calcPt = c.ptAtT(roots[index]);
if (!approximately_equal(calcPt.fY, axisIntercept)) {
double extremeTs[6];
- int extrema = SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c[3].fY, extremeTs);
+ int extrema = SkDCubic::FindExtrema(&c[0].fY, extremeTs);
count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kYAxis, roots);
break;
}
@@ -234,7 +234,7 @@ public:
SkDPoint calcPt = c.ptAtT(roots[index]);
if (!approximately_equal(calcPt.fX, axisIntercept)) {
double extremeTs[6];
- int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs);
+ int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots);
break;
}
diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp
index ce9439ac26..107c83169b 100644
--- a/src/pathops/SkOpContour.cpp
+++ b/src/pathops/SkOpContour.cpp
@@ -69,7 +69,7 @@ void SkOpContour::toPath(SkPathWriter* path) const {
path->close();
}
-void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY,
+void SkOpContour::topSortableSegment(const SkDPoint& topLeft, SkDPoint* bestXY,
SkOpSegment** topStart) {
int segmentCount = fSortedSegments.count();
SkASSERT(segmentCount > 0);
@@ -84,7 +84,7 @@ void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY,
continue;
}
fDone = false;
- SkPoint testXY = testSegment->activeLeftTop(NULL);
+ SkDPoint testXY = testSegment->activeLeftTop(NULL);
if (*topStart) {
if (testXY.fY < topLeft.fY) {
continue;
diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h
index 3d26ae84c8..9abf38238b 100644
--- a/src/pathops/SkOpContour.h
+++ b/src/pathops/SkOpContour.h
@@ -344,7 +344,7 @@ public:
}
void toPath(SkPathWriter* path) const;
- void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart);
+ void topSortableSegment(const SkDPoint& topLeft, SkDPoint* bestXY, SkOpSegment** topStart);
SkOpSegment* undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr);
private:
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index a571609f53..ce35f846b3 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -102,9 +102,9 @@ SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta
return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable);
}
-SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) {
+SkDPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) {
SkASSERT(!done());
- SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
+ SkDPoint topPt = {SK_ScalarMax, SK_ScalarMax};
// see if either end is not done since we want smaller Y of the pair
bool lastDone = true;
SkOpSpanBase* span = &fHead;
@@ -118,10 +118,11 @@ SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) {
*firstSpan = span;
}
}
- if (fVerb != SkPath::kLine_Verb && !lastDone
- && fCubicType != SkDCubic::kSplitAtMaxCurvature_SkDCubicType) {
+ if (fVerb != SkPath::kLine_Verb && !lastDone) {
double curveTopT;
- SkPoint curveTop = (*CurveTop[fVerb])(fPts, fWeight, lastSpan->t(), span->t(),
+ SkDCurve curve;
+ this->subDivide(lastSpan, span, &curve);
+ SkDPoint curveTop = (curve.*Top[fVerb])(fPts, fWeight, lastSpan->t(), span->t(),
&curveTopT);
if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY && topPt.fX > curveTop.fX)) {
topPt = curveTop;
@@ -1092,10 +1093,7 @@ SkOpSegment* SkOpSegment::findTop(bool firstPass, SkOpSpanBase** startPtr, SkOpS
const SkOpSegment* next = angle->segment();
SkPathOpsBounds bounds;
next->subDivideBounds(angle->end(), angle->start(), &bounds);
- bool nearSame = AlmostEqualUlps(top, bounds.top());
- bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->sectorStart();
- bool lesserSector = top > bounds.fTop;
- if (lesserSector && (!nearSame || lowerSector)) {
+ if (top > bounds.fTop) {
top = bounds.fTop;
firstAngle = angle;
}
@@ -1452,7 +1450,12 @@ bool SkOpSegment::monotonicInY(const SkOpSpanBase* start, const SkOpSpanBase* en
}
SkASSERT(fVerb == SkPath::kCubic_Verb);
SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t());
- return dst.monotonicInY();
+ if (dst.monotonicInY()) {
+ return true;
+ }
+ SkDCubic whole;
+ whole.set(fPts);
+ return whole.monotonicInY();
}
bool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start,
@@ -2023,9 +2026,15 @@ bool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end,
void SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase* end,
SkPathOpsBounds* bounds) const {
- SkOpCurve edge;
+ SkDCurve edge;
+ subDivide(start, end, &edge);
+ (edge.*SetBounds[fVerb])(fPts, fWeight, start->t(), end->t(), bounds);
+}
+
+SkDPoint SkOpSegment::top(const SkOpSpanBase* start, const SkOpSpanBase* end, double* topT) const {
+ SkDCurve edge;
subDivide(start, end, &edge);
- (bounds->*SetCurveBounds[fVerb])(edge.fPts, edge.fWeight);
+ return (edge.*Top[fVerb])(fPts, fWeight, start->t(), end->t(), topT);
}
void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) {
diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h
index 1e9e1c44be..a762a66a5a 100644
--- a/src/pathops/SkOpSegment.h
+++ b/src/pathops/SkOpSegment.h
@@ -41,20 +41,24 @@ public:
bool activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end, SkPathOp op,
int* sumMiWinding, int* sumSuWinding);
- SkPoint activeLeftTop(SkOpSpanBase** firstT);
+ SkDPoint activeLeftTop(SkOpSpanBase** firstT);
bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end);
bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding);
SkOpSegment* addConic(SkPoint pts[3], SkScalar weight, SkOpContour* parent) {
init(pts, weight, parent, SkPath::kConic_Verb);
- fBounds.setConicBounds(pts, weight);
+ SkDCurve curve;
+ curve.fConic.set(pts, weight);
+ curve.setConicBounds(pts, weight, 0, 1, &fBounds);
return this;
}
SkOpSegment* addCubic(SkPoint pts[4], SkOpContour* parent) {
init(pts, 1, parent, SkPath::kCubic_Verb);
- fBounds.setCubicBounds(pts, 1);
+ SkDCurve curve;
+ curve.fCubic.set(pts);
+ curve.setCubicBounds(pts, 1, 0, 1, &fBounds);
return this;
}
@@ -88,7 +92,9 @@ public:
SkOpSegment* addQuad(SkPoint pts[3], SkOpContour* parent) {
init(pts, 1, parent, SkPath::kQuad_Verb);
- fBounds.setQuadBounds(pts, 1);
+ SkDCurve curve;
+ curve.fQuad.set(pts);
+ curve.setQuadBounds(pts, 1, 0, 1, &fBounds);
return this;
}
@@ -362,6 +368,8 @@ public:
return start->t() * (1 - mid) + end->t() * mid;
}
+ SkDPoint top(const SkOpSpanBase* start, const SkOpSpanBase* end, double* topT) const;
+
void undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end);
int updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const;
int updateOppWinding(const SkOpAngle* angle) const;
diff --git a/src/pathops/SkPathOpsBounds.cpp b/src/pathops/SkPathOpsBounds.cpp
deleted file mode 100644
index ea13e2ed2c..0000000000
--- a/src/pathops/SkPathOpsBounds.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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 "SkPathOpsBounds.h"
-#include "SkPathOpsConic.h"
-#include "SkPathOpsCubic.h"
-#include "SkPathOpsLine.h"
-#include "SkPathOpsQuad.h"
-
-void SkPathOpsBounds::setConicBounds(const SkPoint a[3], SkScalar weight) {
- SkDConic conic;
- conic.set(a, weight);
- SkDRect dRect;
- dRect.setBounds(conic);
- set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
- SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
-}
-
-void SkPathOpsBounds::setCubicBounds(const SkPoint a[4], SkScalar ) {
- SkDCubic cubic;
- cubic.set(a);
- SkDRect dRect;
- dRect.setBounds(cubic);
- set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
- SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
-}
-
-void SkPathOpsBounds::setLineBounds(const SkPoint a[2], SkScalar ) {
- setPointBounds(a[0]);
- add(a[1]);
-}
-
-void SkPathOpsBounds::setQuadBounds(const SkPoint a[3], SkScalar ) {
- SkDQuad quad;
- quad.set(a);
- SkDRect dRect;
- dRect.setBounds(quad);
- set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
- SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
-}
-
-void (SkPathOpsBounds::* const SetCurveBounds[])(const SkPoint[], SkScalar weight) = {
- NULL,
- &SkPathOpsBounds::setLineBounds,
- &SkPathOpsBounds::setQuadBounds,
- &SkPathOpsBounds::setConicBounds,
- &SkPathOpsBounds::setCubicBounds
-};
diff --git a/src/pathops/SkPathOpsBounds.h b/src/pathops/SkPathOpsBounds.h
index b65d3bea03..7b9daa3671 100644
--- a/src/pathops/SkPathOpsBounds.h
+++ b/src/pathops/SkPathOpsBounds.h
@@ -33,11 +33,11 @@ struct SkPathOpsBounds : public SkRect {
add(toAdd.fLeft, toAdd.fTop, toAdd.fRight, toAdd.fBottom);
}
- void add(const SkPoint& pt) {
- if (pt.fX < fLeft) fLeft = pt.fX;
- if (pt.fY < fTop) fTop = pt.fY;
- if (pt.fX > fRight) fRight = pt.fX;
- if (pt.fY > fBottom) fBottom = pt.fY;
+ void add(const SkDPoint& pt) {
+ if (pt.fX < fLeft) fLeft = SkDoubleToScalar(pt.fX);
+ if (pt.fY < fTop) fTop = SkDoubleToScalar(pt.fY);
+ if (pt.fX > fRight) fRight = SkDoubleToScalar(pt.fX);
+ if (pt.fY > fBottom) fBottom = SkDoubleToScalar(pt.fY);
}
bool almostContains(const SkPoint& pt) {
@@ -55,19 +55,12 @@ struct SkPathOpsBounds : public SkRect {
|| (fLeft == fRight && fTop == fBottom);
}
- void setConicBounds(const SkPoint a[3], SkScalar weight);
- void setCubicBounds(const SkPoint a[4], SkScalar );
- void setLineBounds(const SkPoint a[2], SkScalar );
- void setQuadBounds(const SkPoint a[3], SkScalar );
-
- void setPointBounds(const SkPoint& pt) {
- fLeft = fRight = pt.fX;
- fTop = fBottom = pt.fY;
+ void setPointBounds(const SkDPoint& pt) {
+ fLeft = fRight = SkDoubleToScalar(pt.fX);
+ fTop = fBottom = SkDoubleToScalar(pt.fY);
}
typedef SkRect INHERITED;
};
-extern void (SkPathOpsBounds::* const SetCurveBounds[])(const SkPoint[], SkScalar weight);
-
#endif
diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp
index 3496179e65..05b370a1df 100644
--- a/src/pathops/SkPathOpsCommon.cpp
+++ b/src/pathops/SkPathOpsCommon.cpp
@@ -205,13 +205,13 @@ void DebugShowActiveSpans(SkTDArray<SkOpContour* >& contourList) {
#endif
static SkOpSegment* findTopSegment(const SkTDArray<SkOpContour* >& contourList,
- bool firstPass, SkOpSpanBase** start, SkOpSpanBase** end, SkPoint* topLeft,
+ bool firstPass, SkOpSpanBase** start, SkOpSpanBase** end, SkDPoint* topLeft,
bool* unsortable, bool* done, SkChunkAlloc* allocator) {
SkOpSegment* result;
const SkOpSegment* lastTopStart = NULL;
SkOpSpanBase* lastStart = NULL, * lastEnd = NULL;
do {
- SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
+ SkDPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
int contourCount = contourList.count();
SkOpSegment* topStart = NULL;
*done = true;
@@ -300,7 +300,7 @@ struct SortableTop2 { // error if local in pre-C++11
SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour* >& contourList, bool firstPass,
SkOpAngle::IncludeType angleIncludeType, bool* firstContour, SkOpSpanBase** startPtr,
- SkOpSpanBase** endPtr, SkPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical,
+ SkOpSpanBase** endPtr, SkDPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical,
SkChunkAlloc* allocator) {
SkOpSegment* current = findTopSegment(contourList, firstPass, startPtr, endPtr, topLeft,
unsortable, done, allocator);
diff --git a/src/pathops/SkPathOpsCommon.h b/src/pathops/SkPathOpsCommon.h
index 1bf17919ad..82eb5da215 100644
--- a/src/pathops/SkPathOpsCommon.h
+++ b/src/pathops/SkPathOpsCommon.h
@@ -19,7 +19,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr,
SkOpSpanBase** endPtr);
SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour*>& , bool firstPass,
SkOpAngle::IncludeType , bool* firstContour, SkOpSpanBase** index,
- SkOpSpanBase** endIndex, SkPoint* topLeft, bool* unsortable,
+ SkOpSpanBase** endIndex, SkDPoint* topLeft, bool* unsortable,
bool* done, bool* onlyVertical, SkChunkAlloc* );
SkOpSegment* FindUndone(SkTDArray<SkOpContour*>& contourList, SkOpSpanBase** startPtr,
SkOpSpanBase** endPtr);
diff --git a/src/pathops/SkPathOpsConic.cpp b/src/pathops/SkPathOpsConic.cpp
index 869a406dce..b9b0cda0d4 100644
--- a/src/pathops/SkPathOpsConic.cpp
+++ b/src/pathops/SkPathOpsConic.cpp
@@ -111,25 +111,3 @@ SkDPoint SkDConic::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, do
*weight = chopped.fWeight;
return chopped[1];
}
-
-SkDPoint SkDConic::top(double startT, double endT, double* topT) const {
- SkDConic sub = subDivide(startT, endT);
- SkDPoint topPt = sub[0];
- *topT = startT;
- if (topPt.fY > sub[2].fY || (topPt.fY == sub[2].fY && topPt.fX > sub[2].fX)) {
- *topT = endT;
- topPt = sub[2];
- }
- if (!between(sub[0].fY, sub[1].fY, sub[2].fY)) {
- double extremeT;
- if (FindExtrema(&sub[0].fY, sub.fWeight, &extremeT)) {
- extremeT = startT + (endT - startT) * extremeT;
- SkDPoint test = ptAtT(extremeT);
- if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) {
- *topT = extremeT;
- topPt = test;
- }
- }
- }
- return topPt;
-}
diff --git a/src/pathops/SkPathOpsConic.h b/src/pathops/SkPathOpsConic.h
index 8251901554..bc73049c46 100644
--- a/src/pathops/SkPathOpsConic.h
+++ b/src/pathops/SkPathOpsConic.h
@@ -72,6 +72,10 @@ struct SkDConic {
return fPts.isLinear(startIndex, endIndex);
}
+ bool monotonicInX() const {
+ return fPts.monotonicInX();
+ }
+
bool monotonicInY() const {
return fPts.monotonicInY();
}
@@ -109,8 +113,6 @@ struct SkDConic {
return conic.subDivide(a, c, t1, t2, newWeight);
}
- SkDPoint top(double startT, double endT, double* topT) const;
-
// utilities callable by the user from the debugger when the implementation code is linked in
void dump() const;
void dumpID(int id) const;
diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
index 63f828fb22..777298b297 100644
--- a/src/pathops/SkPathOpsCubic.cpp
+++ b/src/pathops/SkPathOpsCubic.cpp
@@ -75,7 +75,7 @@ double SkDCubic::calcPrecision() const {
return (width > height ? width : height) / gPrecisionUnit;
}
-bool SkDCubic::clockwise(bool* swap) const {
+bool SkDCubic::clockwise(const SkDCubic& whole, bool* swap) const {
SkDPoint lastPt = fPts[kPointLast];
SkDPoint firstPt = fPts[0];
double sum = 0;
@@ -105,34 +105,15 @@ bool SkDCubic::clockwise(bool* swap) const {
lastPt = firstPt;
firstPt = idx == 1 ? fPts[furthest] : fPts[kPointLast];
}
- *swap = sum > 0 && !this->monotonicInY();
+ *swap = sum > 0 && !this->monotonicInY() && !whole.monotonicInY();
return sum <= 0;
}
bool SkDCubic::Clockwise(const SkPoint* pts, double startT, double endT, bool* swap) {
SkDCubic cubic;
cubic.set(pts);
-#if 0
- bool flip = startT > endT;
- double inflectionTs[2];
- int inflections = cubic.findInflections(inflectionTs);
- for (int index = 0; index < inflections; ++index) {
- double inflectionT = inflectionTs[index];
- if (between(startT, inflectionT, endT)) {
- if (flip) {
- if (!roughly_equal(inflectionT, endT)) {
- startT = inflectionT;
- }
- } else {
- if (!roughly_equal(inflectionT, startT)) {
- endT = inflectionT;
- }
- }
- }
- }
-#endif
SkDCubic part = cubic.subDivide(startT, endT);
- return part.clockwise(swap);
+ return part.clockwise(cubic, swap);
}
void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) {
@@ -301,9 +282,14 @@ bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t, CubicType*
return false;
}
+bool SkDCubic::monotonicInX() const {
+ return precisely_between(fPts[0].fX, fPts[1].fX, fPts[3].fX)
+ && precisely_between(fPts[0].fX, fPts[2].fX, fPts[3].fX);
+}
+
bool SkDCubic::monotonicInY() const {
- return between(fPts[0].fY, fPts[1].fY, fPts[3].fY)
- && between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
+ return precisely_between(fPts[0].fY, fPts[1].fY, fPts[3].fY)
+ && precisely_between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
}
void SkDCubic::otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const {
@@ -343,6 +329,28 @@ int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) {
double s[3];
int realRoots = RootsReal(A, B, C, D, s);
int foundRoots = SkDQuad::AddValidTs(s, realRoots, t);
+ for (int index = 0; index < realRoots; ++index) {
+ double tValue = s[index];
+ if (!approximately_one_or_less(tValue) && between(1, tValue, 1.00005)) {
+ for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
+ if (approximately_equal(t[idx2], 1)) {
+ goto nextRoot;
+ }
+ }
+ SkASSERT(foundRoots < 3);
+ t[foundRoots++] = 1;
+ } else if (!approximately_zero_or_more(tValue) && between(-0.00005, tValue, 0)) {
+ for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
+ if (approximately_equal(t[idx2], 0)) {
+ goto nextRoot;
+ }
+ }
+ SkASSERT(foundRoots < 3);
+ t[foundRoots++] = 0;
+ }
+nextRoot:
+ ;
+ }
return foundRoots;
}
@@ -487,10 +495,14 @@ static void formulate_F1DotF2(const double src[], double coeff[4]) {
C = 3(b - a)
Solve for t, keeping only those that fit between 0 < t < 1
*/
-int SkDCubic::FindExtrema(double a, double b, double c, double d, double tValues[2]) {
+int SkDCubic::FindExtrema(const double src[], double tValues[2]) {
// we divide A,B,C by 3 to simplify
- double A = d - a + 3*(b - c);
- double B = 2*(a - b - b + c);
+ double a = src[0];
+ double b = src[2];
+ double c = src[4];
+ double d = src[6];
+ double A = d - a + 3 * (b - c);
+ double B = 2 * (a - b - b + c);
double C = b - a;
return SkDQuad::RootsValidT(A, B, C, tValues);
@@ -519,29 +531,6 @@ int SkDCubic::findMaxCurvature(double tValues[]) const {
return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues);
}
-SkDPoint SkDCubic::top(double startT, double endT, double* topT) const {
- SkDCubic sub = subDivide(startT, endT);
- SkDPoint topPt = sub[0];
- *topT = startT;
- if (topPt.fY > sub[3].fY || (topPt.fY == sub[3].fY && topPt.fX > sub[3].fX)) {
- *topT = endT;
- topPt = sub[3];
- }
- double extremeTs[2];
- if (!sub.monotonicInY()) {
- int roots = FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, sub[3].fY, extremeTs);
- for (int index = 0; index < roots; ++index) {
- double t = startT + (endT - startT) * extremeTs[index];
- SkDPoint mid = ptAtT(t);
- if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) {
- *topT = t;
- topPt = mid;
- }
- }
- }
- return topPt;
-}
-
SkDPoint SkDCubic::ptAtT(double t) const {
if (0 == t) {
return fPts[0];
diff --git a/src/pathops/SkPathOpsCubic.h b/src/pathops/SkPathOpsCubic.h
index 269073ca69..f9d291056e 100644
--- a/src/pathops/SkPathOpsCubic.h
+++ b/src/pathops/SkPathOpsCubic.h
@@ -57,7 +57,7 @@ struct SkDCubic {
double binarySearch(double min, double max, double axisIntercept, SearchAxis xAxis) const;
double calcPrecision() const;
SkDCubicPair chopAt(double t) const;
- bool clockwise(bool* swap) const;
+ bool clockwise(const SkDCubic& whole, bool* swap) const;
static bool Clockwise(const SkPoint* pts, double startT, double endT, bool* swap);
static void Coefficients(const double* cubic, double* A, double* B, double* C, double* D);
static bool ComplexBreak(const SkPoint pts[4], SkScalar* t, CubicType* cubicType);
@@ -72,7 +72,7 @@ struct SkDCubic {
void dumpInner() const;
SkDVector dxdyAtT(double t) const;
bool endsAreExtremaInXOrY() const;
- static int FindExtrema(double a, double b, double c, double d, double tValue[2]);
+ static int FindExtrema(const double src[], double tValue[2]);
int findInflections(double tValues[2]) const;
static int FindInflections(const SkPoint a[kPointCount], double tValues[2]) {
@@ -87,6 +87,7 @@ struct SkDCubic {
bool hullIntersects(const SkDQuad& c2, bool* isLinear) const;
bool hullIntersects(const SkDPoint* pts, int ptCount, bool* isLinear) const;
bool isLinear(int startIndex, int endIndex) const;
+ bool monotonicInX() const;
bool monotonicInY() const;
void otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const;
SkDPoint ptAtT(double t) const;
@@ -121,7 +122,6 @@ struct SkDCubic {
cubic.subDivide(a, d, t1, t2, p);
}
- SkDPoint top(double startT, double endT, double* topT) const;
SkDQuad toQuad() const;
static const int gPrecisionUnit;
diff --git a/src/pathops/SkPathOpsCurve.cpp b/src/pathops/SkPathOpsCurve.cpp
new file mode 100644
index 0000000000..651e64a908
--- /dev/null
+++ b/src/pathops/SkPathOpsCurve.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkPathOpsBounds.h"
+#include "SkPathOpsRect.h"
+#include "SkPathOpsCurve.h"
+
+SkDPoint SkDCurve::conicTop(const SkPoint curve[3], SkScalar curveWeight,
+ double startT, double endT, double* topT) {
+ SkDPoint topPt = fConic[0];
+ *topT = startT;
+ if (topPt.fY > fConic[2].fY || (topPt.fY == fConic[2].fY && topPt.fX > fConic[2].fX)) {
+ *topT = endT;
+ topPt = fConic[2];
+ }
+ if (!fConic.monotonicInY()) {
+ double extremeT;
+ if (SkDConic::FindExtrema(&fConic.fPts.fPts[0].fY, fConic.fWeight, &extremeT)) {
+ SkDConic dCurve;
+ dCurve.set(curve, curveWeight);
+ extremeT = startT + (endT - startT) * extremeT;
+ SkDPoint test = dCurve.ptAtT(extremeT);
+ if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) {
+ *topT = extremeT;
+ topPt = test;
+ }
+ }
+ }
+ return topPt;
+}
+
+SkDPoint SkDCurve::cubicTop(const SkPoint curve[4], SkScalar ,
+ double startT, double endT, double* topT) {
+ SkDPoint topPt = fCubic[0];
+ *topT = startT;
+ if (topPt.fY > fCubic[3].fY || (topPt.fY == fCubic[3].fY && topPt.fX > fCubic[3].fX)) {
+ *topT = endT;
+ topPt = fCubic[3];
+ }
+ double extremeTs[2];
+ if (!fCubic.monotonicInY()) {
+ int roots = SkDCubic::FindExtrema(&fCubic.fPts[0].fY, extremeTs);
+ SkDCubic dCurve;
+ dCurve.set(curve);
+ for (int index = 0; index < roots; ++index) {
+ double t = startT + (endT - startT) * extremeTs[index];
+ SkDPoint mid = dCurve.ptAtT(t);
+ if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) {
+ *topT = t;
+ topPt = mid;
+ }
+ }
+ }
+ return topPt;
+}
+
+SkDPoint SkDCurve::lineTop(const SkPoint[2], SkScalar , double startT, double endT, double* topT) {
+ SkDPoint topPt = fLine[0];
+ *topT = startT;
+ if (topPt.fY > fLine[1].fY || (topPt.fY == fLine[1].fY && topPt.fX > fLine[1].fX)) {
+ *topT = endT;
+ topPt = fLine[1];
+ }
+ return topPt;
+}
+
+SkDPoint SkDCurve::quadTop(const SkPoint curve[3], SkScalar ,
+ double startT, double endT, double* topT) {
+ SkDPoint topPt = fQuad[0];
+ *topT = startT;
+ if (topPt.fY > fQuad[2].fY || (topPt.fY == fQuad[2].fY && topPt.fX > fQuad[2].fX)) {
+ *topT = endT;
+ topPt = fQuad[2];
+ }
+ if (!fQuad.monotonicInY()) {
+ double extremeT;
+ if (SkDQuad::FindExtrema(&fQuad.fPts[0].fY, &extremeT)) {
+ SkDQuad dCurve;
+ dCurve.set(curve);
+ extremeT = startT + (endT - startT) * extremeT;
+ SkDPoint test = dCurve.ptAtT(extremeT);
+ if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) {
+ *topT = extremeT;
+ topPt = test;
+ }
+ }
+ }
+ return topPt;
+}
+
+SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar curveWeight,
+ double tStart, double tEnd, double* topT) = {
+ NULL,
+ &SkDCurve::lineTop,
+ &SkDCurve::quadTop,
+ &SkDCurve::conicTop,
+ &SkDCurve::cubicTop
+};
+
+void SkDCurve::setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) {
+ SkDConic dCurve;
+ dCurve.set(curve, curveWeight);
+ SkDRect dRect;
+ dRect.setBounds(dCurve, fConic, tStart, tEnd);
+ bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
+ SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
+}
+
+void SkDCurve::setCubicBounds(const SkPoint curve[4], SkScalar ,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) {
+ SkDCubic dCurve;
+ dCurve.set(curve);
+ SkDRect dRect;
+ dRect.setBounds(dCurve, fCubic, tStart, tEnd);
+ bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
+ SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
+}
+
+void SkDCurve::setLineBounds(const SkPoint[2], SkScalar ,
+ double , double , SkPathOpsBounds* bounds) {
+ bounds->setPointBounds(fLine[0]);
+ bounds->add(fLine[1]);
+}
+
+void SkDCurve::setQuadBounds(const SkPoint curve[3], SkScalar ,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) {
+ SkDQuad dCurve;
+ dCurve.set(curve);
+ SkDRect dRect;
+ dRect.setBounds(dCurve, fQuad, tStart, tEnd);
+ bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
+ SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
+}
+
+void (SkDCurve::* const SetBounds[])(const SkPoint curve[], SkScalar curveWeight,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) = {
+ NULL,
+ &SkDCurve::setLineBounds,
+ &SkDCurve::setQuadBounds,
+ &SkDCurve::setConicBounds,
+ &SkDCurve::setCubicBounds
+};
diff --git a/src/pathops/SkPathOpsCurve.h b/src/pathops/SkPathOpsCurve.h
index 69af91cf34..bfbc515719 100644
--- a/src/pathops/SkPathOpsCurve.h
+++ b/src/pathops/SkPathOpsCurve.h
@@ -16,6 +16,8 @@
#include "SkPath.h"
#endif
+struct SkPathOpsBounds;
+
struct SkOpCurve {
SkPoint fPts[4];
SkScalar fWeight;
@@ -43,6 +45,7 @@ struct SkOpCurve {
SkDEBUGCODE(fWeight = 1);
SkDEBUGCODE(fVerb = SkPath::kCubic_Verb);
}
+
};
struct SkDCurve {
@@ -64,9 +67,29 @@ struct SkDCurve {
return fCubic[n];
}
+ SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight,
+ double s, double e, double* topT);
+ SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT);
void dumpID(int ) const;
+ SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT);
+ SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT);
+
+ void setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
+ double s, double e, SkPathOpsBounds* );
+ void setCubicBounds(const SkPoint curve[4], SkScalar ,
+ double s, double e, SkPathOpsBounds* );
+ void setLineBounds(const SkPoint[2], SkScalar , double , double , SkPathOpsBounds* );
+ void setQuadBounds(const SkPoint curve[3], SkScalar ,
+ double s, double e, SkPathOpsBounds*);
};
+
+extern void (SkDCurve::* const SetBounds[])(const SkPoint curve[], SkScalar cWeight,
+ double tStart, double tEnd, SkPathOpsBounds* );
+
+extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight,
+ double tStart, double tEnd, double* topT);
+
static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) {
SkDLine line;
line.set(a);
@@ -179,36 +202,6 @@ static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) =
fcubic_dxdy_at_t
};
-static SkPoint quad_top(const SkPoint a[3], SkScalar , double startT, double endT, double* topT) {
- SkDQuad quad;
- quad.set(a);
- SkDPoint topPt = quad.top(startT, endT, topT);
- return topPt.asSkPoint();
-}
-
-static SkPoint conic_top(const SkPoint a[3], SkScalar weight, double startT, double endT,
- double* topT) {
- SkDConic conic;
- conic.set(a, weight);
- SkDPoint topPt = conic.top(startT, endT, topT);
- return topPt.asSkPoint();
-}
-
-static SkPoint cubic_top(const SkPoint a[4], SkScalar , double startT, double endT, double* topT) {
- SkDCubic cubic;
- cubic.set(a);
- SkDPoint topPt = cubic.top(startT, endT, topT);
- return topPt.asSkPoint();
-}
-
-static SkPoint (* const CurveTop[])(const SkPoint[], SkScalar , double , double , double* ) = {
- NULL,
- NULL,
- quad_top,
- conic_top,
- cubic_top
-};
-
static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) {
SkDLine line;
line.set(a);
diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h
index 8473d66c70..0624ad687a 100644
--- a/src/pathops/SkPathOpsDebug.h
+++ b/src/pathops/SkPathOpsDebug.h
@@ -37,8 +37,6 @@
#if FORCE_RELEASE
-#define DEBUG_CUBIC_SWAP_TOP 0
-
#define DEBUG_ACTIVE_OP 0
#define DEBUG_ACTIVE_SPANS 0
#define DEBUG_ADD_INTERSECTING_TS 0
@@ -47,23 +45,21 @@
#define DEBUG_ASSEMBLE 0
#define DEBUG_CUBIC_BINARY_SEARCH 0
#define DEBUG_CUBIC_SPLIT 0
-#define DEBUG_DUMP_SEGMENTS DEBUG_CUBIC_SWAP_TOP
+#define DEBUG_DUMP_SEGMENTS 0 // 1
#define DEBUG_FLOW 0
#define DEBUG_LIMIT_WIND_SUM 0
#define DEBUG_MARK_DONE 0
#define DEBUG_PATH_CONSTRUCTION 0
#define DEBUG_PERP 0
-#define DEBUG_SHOW_TEST_NAME DEBUG_CUBIC_SWAP_TOP
+#define DEBUG_SHOW_TEST_NAME 0 // 1
#define DEBUG_SORT 0
-#define DEBUG_SWAP_TOP DEBUG_CUBIC_SWAP_TOP
+#define DEBUG_SWAP_TOP 0 // 1
#define DEBUG_T_SECT 0
#define DEBUG_T_SECT_DUMP 0
#define DEBUG_VALIDATE 0
#define DEBUG_WINDING 0
#define DEBUG_WINDING_AT_T 0
-#undef DEBUG_CUBIC_SWAP_TOP
-
#else
#define DEBUG_ACTIVE_OP 1
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index 4e3ec4aad3..1105af5d70 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -104,8 +104,8 @@ static bool bridgeOp(SkTDArray<SkOpContour* >& contourList, const SkPathOp op,
bool unsortable = false;
bool topUnsortable = false;
bool firstPass = true;
- SkPoint lastTopLeft;
- SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
+ SkDPoint lastTopLeft;
+ SkDPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
do {
SkOpSpanBase* start = NULL;
SkOpSpanBase* end = NULL;
diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp
index 397a3ce98a..66f191bb0e 100644
--- a/src/pathops/SkPathOpsQuad.cpp
+++ b/src/pathops/SkPathOpsQuad.cpp
@@ -240,6 +240,10 @@ static double interp_quad_coords(const double* src, double t) {
return abc;
}
+bool SkDQuad::monotonicInX() const {
+ return between(fPts[0].fX, fPts[1].fX, fPts[2].fX);
+}
+
bool SkDQuad::monotonicInY() const {
return between(fPts[0].fY, fPts[1].fY, fPts[2].fY);
}
@@ -323,28 +327,6 @@ SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, dou
return b;
}
-SkDPoint SkDQuad::top(double startT, double endT, double* topT) const {
- SkDQuad sub = subDivide(startT, endT);
- SkDPoint topPt = sub[0];
- *topT = startT;
- if (topPt.fY > sub[2].fY || (topPt.fY == sub[2].fY && topPt.fX > sub[2].fX)) {
- *topT = endT;
- topPt = sub[2];
- }
- if (!between(sub[0].fY, sub[1].fY, sub[2].fY)) {
- double extremeT;
- if (FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, &extremeT)) {
- extremeT = startT + (endT - startT) * extremeT;
- SkDPoint test = ptAtT(extremeT);
- if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) {
- *topT = extremeT;
- topPt = test;
- }
- }
- }
- return topPt;
-}
-
/* classic one t subdivision */
static void interp_quad_coords(const double* src, double* dst, double t) {
double ab = SkDInterp(src[0], src[2], t);
@@ -397,10 +379,13 @@ static int valid_unit_divide(double numer, double denom, double* ratio)
B = 2(b - a)
Solve for t, only if it fits between 0 < t < 1
*/
-int SkDQuad::FindExtrema(double a, double b, double c, double tValue[1]) {
+int SkDQuad::FindExtrema(const double src[], double tValue[1]) {
/* At + B == 0
t = -B / A
*/
+ double a = src[0];
+ double b = src[2];
+ double c = src[4];
return valid_unit_divide(a - b, a - b - b + c, tValue);
}
diff --git a/src/pathops/SkPathOpsQuad.h b/src/pathops/SkPathOpsQuad.h
index b201860f98..de4ce4baa3 100644
--- a/src/pathops/SkPathOpsQuad.h
+++ b/src/pathops/SkPathOpsQuad.h
@@ -62,11 +62,12 @@ struct SkDQuad {
SkDQuadPair chopAt(double t) const;
static bool Clockwise(const SkOpCurve& edge, bool* swap);
SkDVector dxdyAtT(double t) const;
- static int FindExtrema(double a, double b, double c, double tValue[1]);
+ static int FindExtrema(const double src[], double tValue[1]);
bool hullIntersects(const SkDQuad& , bool* isLinear) const;
bool hullIntersects(const SkDConic& , bool* isLinear) const;
bool hullIntersects(const SkDCubic& , bool* isLinear) const;
bool isLinear(int startIndex, int endIndex) const;
+ bool monotonicInX() const;
bool monotonicInY() const;
double nearestT(const SkDPoint&) const;
void otherPts(int oddMan, const SkDPoint* endPt[2]) const;
@@ -89,7 +90,6 @@ struct SkDQuad {
}
SkDConic toConic() const;
SkDCubic toCubic() const;
- SkDPoint top(double startT, double endT, double* topT) const;
// utilities callable by the user from the debugger when the implementation code is linked in
void dump() const;
diff --git a/src/pathops/SkPathOpsRect.cpp b/src/pathops/SkPathOpsRect.cpp
index 540db16a0e..8c01153532 100644
--- a/src/pathops/SkPathOpsRect.cpp
+++ b/src/pathops/SkPathOpsRect.cpp
@@ -10,54 +10,53 @@
#include "SkPathOpsQuad.h"
#include "SkPathOpsRect.h"
-void SkDRect::setBounds(const SkDQuad& quad) {
- set(quad[0]);
- add(quad[2]);
+void SkDRect::setBounds(const SkDQuad& curve, const SkDQuad& sub, double startT, double endT) {
+ set(sub[0]);
+ add(sub[2]);
double tValues[2];
int roots = 0;
- if (!between(quad[0].fX, quad[1].fX, quad[2].fX)) {
- roots = SkDQuad::FindExtrema(quad[0].fX, quad[1].fX, quad[2].fX, tValues);
+ if (!sub.monotonicInX()) {
+ roots = SkDQuad::FindExtrema(&sub[0].fX, tValues);
}
- if (!between(quad[0].fY, quad[1].fY, quad[2].fY)) {
- roots += SkDQuad::FindExtrema(quad[0].fY, quad[1].fY, quad[2].fY, &tValues[roots]);
+ if (!sub.monotonicInY()) {
+ roots += SkDQuad::FindExtrema(&sub[0].fY, &tValues[roots]);
}
- for (int x = 0; x < roots; ++x) {
- add(quad.ptAtT(tValues[x]));
+ for (int index = 0; index < roots; ++index) {
+ double t = startT + (endT - startT) * tValues[index];
+ add(curve.ptAtT(t));
}
}
-void SkDRect::setBounds(const SkDConic& conic) {
- set(conic[0]);
- add(conic[2]);
+void SkDRect::setBounds(const SkDConic& curve, const SkDConic& sub, double startT, double endT) {
+ set(sub[0]);
+ add(sub[2]);
double tValues[2];
int roots = 0;
- if (!between(conic[0].fX, conic[1].fX, conic[2].fX)) {
- roots = SkDConic::FindExtrema(&conic[0].fX, conic.fWeight, tValues);
+ if (!sub.monotonicInX()) {
+ roots = SkDConic::FindExtrema(&sub[0].fX, sub.fWeight, tValues);
}
- if (!between(conic[0].fY, conic[1].fY, conic[2].fY)) {
- roots += SkDConic::FindExtrema(&conic[0].fY, conic.fWeight, &tValues[roots]);
+ if (!sub.monotonicInY()) {
+ roots += SkDConic::FindExtrema(&sub[0].fY, sub.fWeight, &tValues[roots]);
}
- for (int x = 0; x < roots; ++x) {
- add(conic.ptAtT(tValues[x]));
+ for (int index = 0; index < roots; ++index) {
+ double t = startT + (endT - startT) * tValues[index];
+ add(curve.ptAtT(t));
}
}
-static bool is_bounded_by_end_points(double a, double b, double c, double d) {
- return between(a, b, d) && between(a, c, d);
-}
-
-void SkDRect::setBounds(const SkDCubic& c) {
- set(c[0]);
- add(c[3]);
+void SkDRect::setBounds(const SkDCubic& curve, const SkDCubic& sub, double startT, double endT) {
+ set(sub[0]);
+ add(sub[3]);
double tValues[4];
int roots = 0;
- if (!is_bounded_by_end_points(c[0].fX, c[1].fX, c[2].fX, c[3].fX)) {
- roots = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, tValues);
+ if (!sub.monotonicInX()) {
+ roots = SkDCubic::FindExtrema(&sub[0].fX, tValues);
}
- if (!is_bounded_by_end_points(c[0].fY, c[1].fY, c[2].fY, c[3].fY)) {
- roots += SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c[3].fY, &tValues[roots]);
+ if (!sub.monotonicInY()) {
+ roots += SkDCubic::FindExtrema(&sub[0].fY, &tValues[roots]);
}
- for (int x = 0; x < roots; ++x) {
- add(c.ptAtT(tValues[x]));
+ for (int index = 0; index < roots; ++index) {
+ double t = startT + (endT - startT) * tValues[index];
+ add(curve.ptAtT(t));
}
}
diff --git a/src/pathops/SkPathOpsRect.h b/src/pathops/SkPathOpsRect.h
index f783d96b99..7fec70a32a 100644
--- a/src/pathops/SkPathOpsRect.h
+++ b/src/pathops/SkPathOpsRect.h
@@ -48,9 +48,23 @@ struct SkDRect {
return fBottom - fTop;
}
- void setBounds(const SkDConic&);
- void setBounds(const SkDCubic&);
- void setBounds(const SkDQuad&);
+ void setBounds(const SkDConic& curve) {
+ setBounds(curve, curve, 0, 1);
+ }
+
+ void setBounds(const SkDConic& curve, const SkDConic& sub, double tStart, double tEnd);
+
+ void setBounds(const SkDCubic& curve) {
+ setBounds(curve, curve, 0, 1);
+ }
+
+ void setBounds(const SkDCubic& curve, const SkDCubic& sub, double tStart, double tEnd);
+
+ void setBounds(const SkDQuad& curve) {
+ setBounds(curve, curve, 0, 1);
+ }
+
+ void setBounds(const SkDQuad& curve, const SkDQuad& sub, double tStart, double tEnd);
};
#endif
diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp
index b4f8e22142..14c6837c1b 100644
--- a/src/pathops/SkPathOpsSimplify.cpp
+++ b/src/pathops/SkPathOpsSimplify.cpp
@@ -16,8 +16,8 @@ static bool bridgeWinding(SkTDArray<SkOpContour* >& contourList, SkPathWriter* s
bool unsortable = false;
bool topUnsortable = false;
bool firstPass = true;
- SkPoint lastTopLeft;
- SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
+ SkDPoint lastTopLeft;
+ SkDPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
do {
SkOpSpanBase* start = NULL;
SkOpSpanBase* end = NULL;