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

Unified Diff: src/core/SkStroke.cpp

Issue 1157623003: remove SK_LEGACY_STROKE_CURVES (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: work in progress Created 5 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 | « src/core/SkStroke.h ('k') | src/core/SkStrokeRec.cpp » ('j') | 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 eda26d024fae5ad12243a8a3e0df8a78b1094e44..589c98879b328841e313d953efc5121a891c252d 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -9,87 +9,48 @@
#include "SkGeometry.h"
#include "SkPath.h"
-#ifndef SK_LEGACY_STROKE_CURVES
+enum {
+ kTangent_RecursiveLimit,
+ kCubic_RecursiveLimit,
+ kConic_RecursiveLimit,
+ kQuad_RecursiveLimit
+};
- enum {
- kTangent_RecursiveLimit,
- kCubic_RecursiveLimit,
- kConic_RecursiveLimit,
- kQuad_RecursiveLimit
- };
+// quads with extreme widths (e.g. (0,1) (1,6) (0,3) width=5e7) recurse to point of failure
+// largest seen for normal cubics : 5, 26
+// largest seen for normal quads : 11
+static const int kRecursiveLimits[] = { 5*3, 26*3, 11*3, 11*3 }; // 3x limits seen in practice
- // quads with extreme widths (e.g. (0,1) (1,6) (0,3) width=5e7) recurse to point of failure
- // largest seen for normal cubics : 5, 26
- // largest seen for normal quads : 11
- static const int kRecursiveLimits[] = { 5*3, 26*3, 11*3, 11*3 }; // 3x limits seen in practice
-
- SK_COMPILE_ASSERT(0 == kTangent_RecursiveLimit, cubic_stroke_relies_on_tangent_equalling_zero);
- SK_COMPILE_ASSERT(1 == kCubic_RecursiveLimit, cubic_stroke_relies_on_cubic_equalling_one);
- SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kRecursiveLimits) == kQuad_RecursiveLimit + 1,
- recursive_limits_mismatch);
-
- #ifdef SK_DEBUG
- int gMaxRecursion[SK_ARRAY_COUNT(kRecursiveLimits)] = { 0 };
- #endif
- #ifndef DEBUG_QUAD_STROKER
- #define DEBUG_QUAD_STROKER 0
- #endif
-
- #if DEBUG_QUAD_STROKER
- /* Enable to show the decisions made in subdividing the curve -- helpful when the resulting
- stroke has more than the optimal number of quadratics and lines */
- #define STROKER_RESULT(resultType, depth, quadPts, format, ...) \
- SkDebugf("[%d] %s " format "\n", depth, __FUNCTION__, __VA_ARGS__), \
- SkDebugf(" " #resultType " t=(%g,%g)\n", quadPts->fStartT, quadPts->fEndT), \
- resultType
- #define STROKER_DEBUG_PARAMS(...) , __VA_ARGS__
- #else
- #define STROKER_RESULT(resultType, depth, quadPts, format, ...) \
- resultType
- #define STROKER_DEBUG_PARAMS(...)
- #endif
+SK_COMPILE_ASSERT(0 == kTangent_RecursiveLimit, cubic_stroke_relies_on_tangent_equalling_zero);
+SK_COMPILE_ASSERT(1 == kCubic_RecursiveLimit, cubic_stroke_relies_on_cubic_equalling_one);
+SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kRecursiveLimits) == kQuad_RecursiveLimit + 1,
+ recursive_limits_mismatch);
+#ifdef SK_DEBUG
+ int gMaxRecursion[SK_ARRAY_COUNT(kRecursiveLimits)] = { 0 };
+#endif
+#ifndef DEBUG_QUAD_STROKER
+ #define DEBUG_QUAD_STROKER 0
#endif
-#ifdef SK_LEGACY_STROKE_CURVES
-#define kMaxQuadSubdivide 5
-#define kMaxCubicSubdivide 7
+#if DEBUG_QUAD_STROKER
+ /* Enable to show the decisions made in subdividing the curve -- helpful when the resulting
+ stroke has more than the optimal number of quadratics and lines */
+ #define STROKER_RESULT(resultType, depth, quadPts, format, ...) \
+ SkDebugf("[%d] %s " format "\n", depth, __FUNCTION__, __VA_ARGS__), \
+ SkDebugf(" " #resultType " t=(%g,%g)\n", quadPts->fStartT, quadPts->fEndT), \
+ resultType
+ #define STROKER_DEBUG_PARAMS(...) , __VA_ARGS__
+#else
+ #define STROKER_RESULT(resultType, depth, quadPts, format, ...) \
+ resultType
+ #define STROKER_DEBUG_PARAMS(...)
#endif
static inline bool degenerate_vector(const SkVector& v) {
return !SkPoint::CanNormalize(v.fX, v.fY);
}
-#ifdef SK_LEGACY_STROKE_CURVES
-static inline bool normals_too_curvy(const SkVector& norm0, SkVector& norm1) {
- /* root2/2 is a 45-degree angle
- make this constant bigger for more subdivisions (but not >= 1)
- */
- static const SkScalar kFlatEnoughNormalDotProd =
- SK_ScalarSqrt2/2 + SK_Scalar1/10;
-
- SkASSERT(kFlatEnoughNormalDotProd > 0 &&
- kFlatEnoughNormalDotProd < SK_Scalar1);
-
- return SkPoint::DotProduct(norm0, norm1) <= kFlatEnoughNormalDotProd;
-}
-
-static inline bool normals_too_pinchy(const SkVector& norm0, SkVector& norm1) {
- // if the dot-product is -1, then we are definitely too pinchy. We tweak
- // that by an epsilon to ensure we have significant bits in our test
- static const int kMinSigBitsForDot = 8;
- static const SkScalar kDotEpsilon = FLT_EPSILON * (1 << kMinSigBitsForDot);
- static const SkScalar kTooPinchyNormalDotProd = kDotEpsilon - 1;
-
- // just some sanity asserts to help document the expected range
- SkASSERT(kTooPinchyNormalDotProd >= -1);
- SkASSERT(kTooPinchyNormalDotProd < SkDoubleToScalar(-0.999));
-
- SkScalar dot = SkPoint::DotProduct(norm0, norm1);
- return dot <= kTooPinchyNormalDotProd;
-}
-#endif
-
static bool set_normal_unitnormal(const SkPoint& before, const SkPoint& after,
SkScalar radius,
SkVector* normal, SkVector* unitNormal) {
@@ -113,7 +74,6 @@ static bool set_normal_unitnormal(const SkVector& vec,
}
///////////////////////////////////////////////////////////////////////////////
-#ifndef SK_LEGACY_STROKE_CURVES
struct SkQuadConstruct { // The state of the quad stroke under construction.
SkPoint fQuad[3]; // the stroked quad parallel to the original curve
@@ -154,7 +114,6 @@ struct SkQuadConstruct { // The state of the quad stroke under construction.
return true;
}
};
-#endif
class SkPathStroker {
public:
@@ -165,9 +124,7 @@ public:
void moveTo(const SkPoint&);
void lineTo(const SkPoint&);
void quadTo(const SkPoint&, const SkPoint&);
-#ifndef SK_LEGACY_STROKE_CURVES
void conicTo(const SkPoint&, const SkPoint&, SkScalar weight);
-#endif
void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&);
void close(bool isLine) { this->finishContour(true, isLine); }
@@ -183,10 +140,8 @@ private:
SkScalar fRadius;
SkScalar fInvMiterLimit;
SkScalar fResScale;
-#ifndef SK_LEGACY_STROKE_CURVES
SkScalar fInvResScale;
SkScalar fInvResScaleSquared;
-#endif
SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal;
SkPoint fFirstPt, fPrevPt; // on original path
@@ -200,7 +155,6 @@ private:
SkPath fInner, fOuter; // outer is our working answer, inner is temp
SkPath fExtra; // added as extra complete contours
-#ifndef SK_LEGACY_STROKE_CURVES
enum StrokeType {
kOuter_StrokeType = 1, // use sign-opposite values later to flip perpendicular axis
kInner_StrokeType = -1
@@ -268,7 +222,6 @@ private:
ResultType strokeCloseEnough(const SkPoint stroke[3], const SkPoint ray[2],
SkQuadConstruct* STROKER_DEBUG_PARAMS(int depth) ) const;
ResultType tangentsMeet(const SkPoint cubic[4], SkQuadConstruct* );
-#endif
void finishContour(bool close, bool isLine);
bool preJoinTo(const SkPoint&, SkVector* normal, SkVector* unitNormal,
@@ -277,16 +230,6 @@ private:
const SkVector& unitNormal);
void line_to(const SkPoint& currPt, const SkVector& normal);
-#ifdef SK_LEGACY_STROKE_CURVES
- void quad_to(const SkPoint pts[3],
- const SkVector& normalAB, const SkVector& unitNormalAB,
- SkVector* normalBC, SkVector* unitNormalBC,
- int subDivide);
- void cubic_to(const SkPoint pts[4],
- const SkVector& normalAB, const SkVector& unitNormalAB,
- SkVector* normalCD, SkVector* unitNormalCD,
- int subDivide);
-#endif
};
///////////////////////////////////////////////////////////////////////////////
@@ -392,13 +335,11 @@ SkPathStroker::SkPathStroker(const SkPath& src,
fOuter.setIsVolatile(true);
fInner.incReserve(src.countPoints());
fInner.setIsVolatile(true);
-#ifndef SK_LEGACY_STROKE_CURVES
// TODO : write a common error function used by stroking and filling
// The '4' below matches the fill scan converter's error term
fInvResScale = SkScalarInvert(resScale * 4);
fInvResScaleSquared = fInvResScale * fInvResScale;
fRecursionDepth = 0;
-#endif
}
void SkPathStroker::moveTo(const SkPoint& pt) {
@@ -427,44 +368,6 @@ void SkPathStroker::lineTo(const SkPoint& currPt) {
this->postJoinTo(currPt, normal, unitNormal);
}
-#ifdef SK_LEGACY_STROKE_CURVES
-void SkPathStroker::quad_to(const SkPoint pts[3],
- const SkVector& normalAB, const SkVector& unitNormalAB,
- SkVector* normalBC, SkVector* unitNormalBC,
- int subDivide) {
- if (!set_normal_unitnormal(pts[1], pts[2], fRadius,
- normalBC, unitNormalBC)) {
- // pts[1] nearly equals pts[2], so just draw a line to pts[2]
- this->line_to(pts[2], normalAB);
- *normalBC = normalAB;
- *unitNormalBC = unitNormalAB;
- return;
- }
-
- if (--subDivide >= 0 && normals_too_curvy(unitNormalAB, *unitNormalBC)) {
- SkPoint tmp[5];
- SkVector norm, unit;
-
- SkChopQuadAtHalf(pts, tmp);
- this->quad_to(&tmp[0], normalAB, unitNormalAB, &norm, &unit, subDivide);
- this->quad_to(&tmp[2], norm, unit, normalBC, unitNormalBC, subDivide);
- } else {
- SkVector normalB;
-
- normalB = pts[2] - pts[0];
- normalB.rotateCCW();
- SkScalar dot = SkPoint::DotProduct(unitNormalAB, *unitNormalBC);
- SkAssertResult(normalB.setLength(fRadius / SkScalarSqrt((SK_Scalar1 + dot)/2)));
-
- fOuter.quadTo( pts[1].fX + normalB.fX, pts[1].fY + normalB.fY,
- pts[2].fX + normalBC->fX, pts[2].fY + normalBC->fY);
- fInner.quadTo( pts[1].fX - normalB.fX, pts[1].fY - normalB.fY,
- pts[2].fX - normalBC->fX, pts[2].fY - normalBC->fY);
- }
-}
-#endif
-
-#ifndef SK_LEGACY_STROKE_CURVES
void SkPathStroker::setQuadEndNormal(const SkPoint quad[3], const SkVector& normalAB,
const SkVector& unitNormalAB, SkVector* normalBC, SkVector* unitNormalBC) {
if (!set_normal_unitnormal(quad[1], quad[2], fRadius, normalBC, unitNormalBC)) {
@@ -700,92 +603,6 @@ SkPathStroker::ReductionType SkPathStroker::CheckQuadLinear(const SkPoint quad[3
return kDegenerate_ReductionType;
}
-#else
-
-void SkPathStroker::cubic_to(const SkPoint pts[4],
- const SkVector& normalAB, const SkVector& unitNormalAB,
- SkVector* normalCD, SkVector* unitNormalCD,
- int subDivide) {
- SkVector ab = pts[1] - pts[0];
- SkVector cd = pts[3] - pts[2];
- SkVector normalBC, unitNormalBC;
-
- bool degenerateAB = degenerate_vector(ab);
- bool degenerateCD = degenerate_vector(cd);
-
- if (degenerateAB && degenerateCD) {
-DRAW_LINE:
- this->line_to(pts[3], normalAB);
- *normalCD = normalAB;
- *unitNormalCD = unitNormalAB;
- return;
- }
-
- if (degenerateAB) {
- ab = pts[2] - pts[0];
- degenerateAB = degenerate_vector(ab);
- }
- if (degenerateCD) {
- cd = pts[3] - pts[1];
- degenerateCD = degenerate_vector(cd);
- }
- if (degenerateAB || degenerateCD) {
- goto DRAW_LINE;
- }
- SkAssertResult(set_normal_unitnormal(cd, fRadius, normalCD, unitNormalCD));
- bool degenerateBC = !set_normal_unitnormal(pts[1], pts[2], fRadius,
- &normalBC, &unitNormalBC);
-#ifndef SK_IGNORE_CUBIC_STROKE_FIX
- if (--subDivide < 0) {
- goto DRAW_LINE;
- }
-#endif
- if (degenerateBC || normals_too_curvy(unitNormalAB, unitNormalBC) ||
- normals_too_curvy(unitNormalBC, *unitNormalCD)) {
-#ifdef SK_IGNORE_CUBIC_STROKE_FIX
- // subdivide if we can
- if (--subDivide < 0) {
- goto DRAW_LINE;
- }
-#endif
- SkPoint tmp[7];
- SkVector norm, unit, dummy, unitDummy;
-
- SkChopCubicAtHalf(pts, tmp);
- this->cubic_to(&tmp[0], normalAB, unitNormalAB, &norm, &unit,
- subDivide);
- // we use dummys since we already have a valid (and more accurate)
- // normals for CD
- this->cubic_to(&tmp[3], norm, unit, &dummy, &unitDummy, subDivide);
- } else {
- SkVector normalB, normalC;
-
- // need normals to inset/outset the off-curve pts B and C
-
- SkVector unitBC = pts[2] - pts[1];
- unitBC.normalize();
- unitBC.rotateCCW();
-
- normalB = unitNormalAB + unitBC;
- normalC = *unitNormalCD + unitBC;
-
- SkScalar dot = SkPoint::DotProduct(unitNormalAB, unitBC);
- SkAssertResult(normalB.setLength(fRadius / SkScalarSqrt((SK_Scalar1 + dot)/2)));
- dot = SkPoint::DotProduct(*unitNormalCD, unitBC);
- SkAssertResult(normalC.setLength(fRadius / SkScalarSqrt((SK_Scalar1 + dot)/2)));
-
- fOuter.cubicTo( pts[1].fX + normalB.fX, pts[1].fY + normalB.fY,
- pts[2].fX + normalC.fX, pts[2].fY + normalC.fY,
- pts[3].fX + normalCD->fX, pts[3].fY + normalCD->fY);
-
- fInner.cubicTo( pts[1].fX - normalB.fX, pts[1].fY - normalB.fY,
- pts[2].fX - normalC.fX, pts[2].fY - normalC.fY,
- pts[3].fX - normalCD->fX, pts[3].fY - normalCD->fY);
- }
-}
-#endif
-
-#ifndef SK_LEGACY_STROKE_CURVES
void SkPathStroker::conicTo(const SkPoint& pt1, const SkPoint& pt2, SkScalar weight) {
const SkConic conic(fPrevPt, pt1, pt2, weight);
SkPoint reduction;
@@ -819,10 +636,8 @@ void SkPathStroker::conicTo(const SkPoint& pt1, const SkPoint& pt2, SkScalar wei
this->setConicEndNormal(conic, normalAB, unitAB, &normalBC, &unitBC);
this->postJoinTo(pt2, normalBC, unitBC);
}
-#endif
void SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
-#ifndef SK_LEGACY_STROKE_CURVES
const SkPoint quad[3] = { fPrevPt, pt1, pt2 };
SkPoint reduction;
ReductionType reductionType = CheckQuadLinear(quad, &reduction);
@@ -853,63 +668,10 @@ void SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
this->init(kInner_StrokeType, &quadPts, 0, 1);
(void) this->quadStroke(quad, &quadPts);
this->setQuadEndNormal(quad, normalAB, unitAB, &normalBC, &unitBC);
-#else
- bool degenerateAB = SkPath::IsLineDegenerate(fPrevPt, pt1);
- bool degenerateBC = SkPath::IsLineDegenerate(pt1, pt2);
-
- if (degenerateAB | degenerateBC) {
- if (degenerateAB ^ degenerateBC) {
- this->lineTo(pt2);
- }
- return;
- }
-
- SkVector normalAB, unitAB, normalBC, unitBC;
-
- this->preJoinTo(pt1, &normalAB, &unitAB, false);
-
- {
- SkPoint pts[3], tmp[5];
- pts[0] = fPrevPt;
- pts[1] = pt1;
- pts[2] = pt2;
-
- if (SkChopQuadAtMaxCurvature(pts, tmp) == 2) {
- unitBC.setNormalize(pts[2].fX - pts[1].fX, pts[2].fY - pts[1].fY);
- unitBC.rotateCCW();
- if (normals_too_pinchy(unitAB, unitBC)) {
- normalBC = unitBC;
- normalBC.scale(fRadius);
-
- fOuter.lineTo(tmp[2].fX + normalAB.fX, tmp[2].fY + normalAB.fY);
- fOuter.lineTo(tmp[2].fX + normalBC.fX, tmp[2].fY + normalBC.fY);
- fOuter.lineTo(tmp[4].fX + normalBC.fX, tmp[4].fY + normalBC.fY);
-
- fInner.lineTo(tmp[2].fX - normalAB.fX, tmp[2].fY - normalAB.fY);
- fInner.lineTo(tmp[2].fX - normalBC.fX, tmp[2].fY - normalBC.fY);
- fInner.lineTo(tmp[4].fX - normalBC.fX, tmp[4].fY - normalBC.fY);
-
- fExtra.addCircle(tmp[2].fX, tmp[2].fY, fRadius,
- SkPath::kCW_Direction);
- } else {
- this->quad_to(&tmp[0], normalAB, unitAB, &normalBC, &unitBC,
- kMaxQuadSubdivide);
- SkVector n = normalBC;
- SkVector u = unitBC;
- this->quad_to(&tmp[2], n, u, &normalBC, &unitBC,
- kMaxQuadSubdivide);
- }
- } else {
- this->quad_to(pts, normalAB, unitAB, &normalBC, &unitBC,
- kMaxQuadSubdivide);
- }
- }
-#endif
this->postJoinTo(pt2, normalBC, unitBC);
}
-#ifndef SK_LEGACY_STROKE_CURVES
// Given a point on the curve and its derivative, scale the derivative by the radius, and
// compute the perpendicular point and its tangent.
void SkPathStroker::setRayPts(const SkPoint& tPt, SkVector* dxy, SkPoint* onPt,
@@ -1390,11 +1152,8 @@ bool SkPathStroker::quadStroke(const SkPoint quad[3], SkQuadConstruct* quadPts)
return true;
}
-#endif
-
void SkPathStroker::cubicTo(const SkPoint& pt1, const SkPoint& pt2,
const SkPoint& pt3) {
-#ifndef SK_LEGACY_STROKE_CURVES
const SkPoint cubic[4] = { fPrevPt, pt1, pt2, pt3 };
SkPoint reduction[3];
const SkPoint* tangentPt;
@@ -1441,53 +1200,6 @@ void SkPathStroker::cubicTo(const SkPoint& pt1, const SkPoint& pt2,
// emit the join even if one stroke succeeded but the last one failed
// this avoids reversing an inner stroke with a partial path followed by another moveto
this->setCubicEndNormal(cubic, normalAB, unitAB, &normalCD, &unitCD);
-#else
- bool degenerateAB = SkPath::IsLineDegenerate(fPrevPt, pt1);
- bool degenerateBC = SkPath::IsLineDegenerate(pt1, pt2);
- bool degenerateCD = SkPath::IsLineDegenerate(pt2, pt3);
-
- if (degenerateAB + degenerateBC + degenerateCD >= 2
- || (degenerateAB && SkPath::IsLineDegenerate(fPrevPt, pt2))) {
- this->lineTo(pt3);
- return;
- }
-
- SkVector normalAB, unitAB, normalCD, unitCD;
-
- // find the first tangent (which might be pt1 or pt2
- {
- const SkPoint* nextPt = &pt1;
- if (degenerateAB)
- nextPt = &pt2;
- this->preJoinTo(*nextPt, &normalAB, &unitAB, false);
- }
-
- {
- SkPoint pts[4], tmp[13];
- int i, count;
- SkVector n, u;
- SkScalar tValues[3];
-
- pts[0] = fPrevPt;
- pts[1] = pt1;
- pts[2] = pt2;
- pts[3] = pt3;
-
- count = SkChopCubicAtMaxCurvature(pts, tmp, tValues);
- n = normalAB;
- u = unitAB;
- for (i = 0; i < count; i++) {
- this->cubic_to(&tmp[i * 3], n, u, &normalCD, &unitCD,
- kMaxCubicSubdivide);
- if (i == count - 1) {
- break;
- }
- n = normalCD;
- u = unitCD;
-
- }
- }
-#endif
this->postJoinTo(pt3, normalCD, unitCD);
}
@@ -1596,10 +1308,6 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
}
}
-#ifdef SK_LEGACY_STROKE_CURVES
- SkAutoConicToQuads converter;
- const SkScalar conicTol = SK_Scalar1 / 4 / fResScale;
-#endif
SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), this->getJoin(), fResScale);
SkPath::Iter iter(src, false);
SkPath::Verb lastSegment = SkPath::kMove_Verb;
@@ -1619,21 +1327,9 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
lastSegment = SkPath::kQuad_Verb;
break;
case SkPath::kConic_Verb: {
-#ifndef SK_LEGACY_STROKE_CURVES
stroker.conicTo(pts[1], pts[2], iter.conicWeight());
lastSegment = SkPath::kConic_Verb;
break;
-#else
- // todo: if we had maxcurvature for conics, perhaps we should
- // natively extrude the conic instead of converting to quads.
- const SkPoint* quadPts =
- converter.computeQuads(pts, iter.conicWeight(), conicTol);
- for (int i = 0; i < converter.countQuads(); ++i) {
- stroker.quadTo(quadPts[1], quadPts[2]);
- quadPts += 2;
- }
- lastSegment = SkPath::kQuad_Verb;
-#endif
} break;
case SkPath::kCubic_Verb:
stroker.cubicTo(pts[1], pts[2], pts[3]);
« no previous file with comments | « src/core/SkStroke.h ('k') | src/core/SkStrokeRec.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698