Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Unified Diff: src/core/SkStroke.cpp

Issue 2020293002: always compute a cubic normal (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gm/bug615686.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkStroke.cpp
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 20bd286316d9b33f3f705bd3c69a1cb26a5dbb48..0f02a9449a5c13b3665faf900dd5d07260b46443 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -173,7 +173,6 @@ private:
kSplit_ResultType, // the caller should split the quad stroke in two
kDegenerate_ResultType, // the caller should add a line
kQuad_ResultType, // the caller should (continue to try to) add a quad stroke
- kNormalError_ResultType, // the cubic's normal couldn't be computed -- abort
};
enum ReductionType {
@@ -207,10 +206,10 @@ private:
void conicQuadEnds(const SkConic& , SkQuadConstruct* ) const;
bool conicStroke(const SkConic& , SkQuadConstruct* );
bool cubicMidOnLine(const SkPoint cubic[4], const SkQuadConstruct* ) const;
- bool cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tPt, SkPoint* onPt,
+ void cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tPt, SkPoint* onPt,
SkPoint* tangent) const;
- bool cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* );
- bool cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct* , SkPoint* mid) const;
+ void cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* );
+ void cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct* , SkPoint* mid) const;
bool cubicStroke(const SkPoint cubic[4], SkQuadConstruct* );
void init(StrokeType strokeType, SkQuadConstruct* , SkScalar tStart, SkScalar tEnd);
ResultType intersectRay(SkQuadConstruct* , IntersectRayType STROKER_DEBUG_PARAMS(int) ) const;
@@ -786,52 +785,54 @@ void SkPathStroker::conicQuadEnds(const SkConic& conic, SkQuadConstruct* quadPts
// Given a cubic and t, return the point on curve, its perpendicular, and the perpendicular tangent.
-// Returns false if the perpendicular could not be computed (because the derivative collapsed to 0)
-bool SkPathStroker::cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tPt, SkPoint* onPt,
+void SkPathStroker::cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tPt, SkPoint* onPt,
SkPoint* tangent) const {
SkVector dxy;
+ SkPoint chopped[7];
SkEvalCubicAt(cubic, t, tPt, &dxy, nullptr);
if (dxy.fX == 0 && dxy.fY == 0) {
+ const SkPoint* cPts = cubic;
if (SkScalarNearlyZero(t)) {
dxy = cubic[2] - cubic[0];
} else if (SkScalarNearlyZero(1 - t)) {
dxy = cubic[3] - cubic[1];
} else {
- return false;
+ // If the cubic inflection falls on the cusp, subdivide the cubic
+ // to find the tangent at that point.
+ SkChopCubicAt(cubic, chopped, t);
+ dxy = chopped[3] - chopped[2];
+ if (dxy.fX == 0 && dxy.fY == 0) {
+ dxy = chopped[3] - chopped[1];
+ cPts = chopped;
+ }
}
if (dxy.fX == 0 && dxy.fY == 0) {
- dxy = cubic[3] - cubic[0];
+ dxy = cPts[3] - cPts[0];
}
}
setRayPts(*tPt, &dxy, onPt, tangent);
- return true;
}
// Given a cubic and a t range, find the start and end if they haven't been found already.
-bool SkPathStroker::cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* quadPts) {
+void SkPathStroker::cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* quadPts) {
if (!quadPts->fStartSet) {
SkPoint cubicStartPt;
- if (!this->cubicPerpRay(cubic, quadPts->fStartT, &cubicStartPt, &quadPts->fQuad[0],
- &quadPts->fTangentStart)) {
- return false;
- }
+ this->cubicPerpRay(cubic, quadPts->fStartT, &cubicStartPt, &quadPts->fQuad[0],
+ &quadPts->fTangentStart);
quadPts->fStartSet = true;
}
if (!quadPts->fEndSet) {
SkPoint cubicEndPt;
- if (!this->cubicPerpRay(cubic, quadPts->fEndT, &cubicEndPt, &quadPts->fQuad[2],
- &quadPts->fTangentEnd)) {
- return false;
- }
+ this->cubicPerpRay(cubic, quadPts->fEndT, &cubicEndPt, &quadPts->fQuad[2],
+ &quadPts->fTangentEnd);
quadPts->fEndSet = true;
}
- return true;
}
-bool SkPathStroker::cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct* quadPts,
+void SkPathStroker::cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct* quadPts,
SkPoint* mid) const {
SkPoint cubicMidPt;
- return this->cubicPerpRay(cubic, quadPts->fMidT, &cubicMidPt, mid, nullptr);
+ this->cubicPerpRay(cubic, quadPts->fMidT, &cubicMidPt, mid, nullptr);
}
// Given a quad and t, return the point on curve, its perpendicular, and the perpendicular tangent.
@@ -905,9 +906,7 @@ SkPathStroker::ResultType SkPathStroker::intersectRay(SkQuadConstruct* quadPts,
// Given a cubic and a t-range, determine if the stroke can be described by a quadratic.
SkPathStroker::ResultType SkPathStroker::tangentsMeet(const SkPoint cubic[4],
SkQuadConstruct* quadPts) {
- if (!this->cubicQuadEnds(cubic, quadPts)) {
- return kNormalError_ResultType;
- }
+ this->cubicQuadEnds(cubic, quadPts);
return this->intersectRay(quadPts, kResultType_RayType STROKER_DEBUG_PARAMS(fRecursionDepth));
}
@@ -1019,9 +1018,7 @@ SkPathStroker::ResultType SkPathStroker::strokeCloseEnough(const SkPoint stroke[
SkPathStroker::ResultType SkPathStroker::compareQuadCubic(const SkPoint cubic[4],
SkQuadConstruct* quadPts) {
// get the quadratic approximation of the stroke
- if (!this->cubicQuadEnds(cubic, quadPts)) {
- return kNormalError_ResultType;
- }
+ this->cubicQuadEnds(cubic, quadPts);
ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType
STROKER_DEBUG_PARAMS(fRecursionDepth) );
if (resultType != kQuad_ResultType) {
@@ -1029,9 +1026,7 @@ SkPathStroker::ResultType SkPathStroker::compareQuadCubic(const SkPoint cubic[4]
}
// project a ray from the curve to the stroke
SkPoint ray[2]; // points near midpoint on quad, midpoint on cubic
- if (!this->cubicPerpRay(cubic, quadPts->fMidT, &ray[1], &ray[0], nullptr)) {
- return kNormalError_ResultType;
- }
+ this->cubicPerpRay(cubic, quadPts->fMidT, &ray[1], &ray[0], nullptr);
return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts
STROKER_DEBUG_PARAMS(fRecursionDepth));
}
@@ -1087,9 +1082,7 @@ void SkPathStroker::addDegenerateLine(const SkQuadConstruct* quadPts) {
bool SkPathStroker::cubicMidOnLine(const SkPoint cubic[4], const SkQuadConstruct* quadPts) const {
SkPoint strokeMid;
- if (!cubicQuadMid(cubic, quadPts, &strokeMid)) {
- return false;
- }
+ this->cubicQuadMid(cubic, quadPts, &strokeMid);
SkScalar dist = pt_to_line(strokeMid, quadPts->fQuad[0], quadPts->fQuad[2]);
return dist < fInvResScaleSquared;
}
@@ -1098,9 +1091,6 @@ bool SkPathStroker::cubicStroke(const SkPoint cubic[4], SkQuadConstruct* quadPts
if (!fFoundTangents) {
ResultType resultType = this->tangentsMeet(cubic, quadPts);
if (kQuad_ResultType != resultType) {
- if (kNormalError_ResultType == resultType) {
- return false;
- }
if ((kDegenerate_ResultType == resultType
|| points_within_dist(quadPts->fQuad[0], quadPts->fQuad[2],
fInvResScale)) && cubicMidOnLine(cubic, quadPts)) {
@@ -1125,9 +1115,6 @@ bool SkPathStroker::cubicStroke(const SkPoint cubic[4], SkQuadConstruct* quadPts
return true;
}
}
- if (kNormalError_ResultType == resultType) {
- return false;
- }
}
if (!SkScalarIsFinite(quadPts->fQuad[2].fX) || !SkScalarIsFinite(quadPts->fQuad[2].fY)) {
return false; // just abort if projected quad isn't representable
« no previous file with comments | « gm/bug615686.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698