aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-12-08 04:29:45 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-12-08 04:29:45 -0800
commit57eecc154e20b454ad2f889049670fe386f038da (patch)
treecfa01ec4f0e0b14b1e83639d0e1494d38e8f998c /src/core
parent64492c43c3faee7ab0f69b1c84e0267616f85e52 (diff)
Zero length lines may have caps, but do not need joins.
Check to see if the point is preceeded or followed by a line with a computable tangent before adding the join. R=reed@google.com BUG=566075 Review URL: https://codereview.chromium.org/1504043002
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkStroke.cpp44
1 files changed, 41 insertions, 3 deletions
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 65267d11fd..5a43075284 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -126,7 +126,7 @@ public:
SkPoint moveToPt() const { return fFirstPt; }
void moveTo(const SkPoint&);
- void lineTo(const SkPoint&);
+ void lineTo(const SkPoint&, const SkPath::Iter* iter = nullptr);
void quadTo(const SkPoint&, const SkPoint&);
void conicTo(const SkPoint&, const SkPoint&, SkScalar weight);
void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&);
@@ -187,6 +187,7 @@ private:
int fRecursionDepth; // track stack depth to abort if numerics run amok
bool fFoundTangents; // do less work until tangents meet (cubic)
+ bool fJoinCompleted; // previous join was not degenerate
void addDegenerateLine(const SkQuadConstruct* );
static ReductionType CheckConicLinear(const SkConic& , SkPoint* reduction);
@@ -273,6 +274,7 @@ bool SkPathStroker::preJoinTo(const SkPoint& currPt, SkVector* normal,
void SkPathStroker::postJoinTo(const SkPoint& currPt, const SkVector& normal,
const SkVector& unitNormal) {
+ fJoinCompleted = true;
fPrevPt = currPt;
fPrevUnitNormal = unitNormal;
fPrevNormal = normal;
@@ -359,6 +361,7 @@ void SkPathStroker::moveTo(const SkPoint& pt) {
}
fSegmentCount = 0;
fFirstPt = fPrevPt = pt;
+ fJoinCompleted = false;
}
void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) {
@@ -366,11 +369,46 @@ void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) {
fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY);
}
-void SkPathStroker::lineTo(const SkPoint& currPt) {
+static bool has_valid_tangent(const SkPath::Iter* iter) {
+ SkPath::Iter copy = *iter;
+ SkPath::Verb verb;
+ SkPoint pts[4];
+ while ((verb = copy.next(pts))) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ return false;
+ case SkPath::kLine_Verb:
+ if (pts[0] == pts[1]) {
+ continue;
+ }
+ return true;
+ case SkPath::kQuad_Verb:
+ case SkPath::kConic_Verb:
+ if (pts[0] == pts[1] && pts[0] == pts[2]) {
+ continue;
+ }
+ return true;
+ case SkPath::kCubic_Verb:
+ if (pts[0] == pts[1] && pts[0] == pts[2] && pts[0] == pts[3]) {
+ continue;
+ }
+ return true;
+ case SkPath::kClose_Verb:
+ case SkPath::kDone_Verb:
+ return false;
+ }
+ }
+ return false;
+}
+
+void SkPathStroker::lineTo(const SkPoint& currPt, const SkPath::Iter* iter) {
if (SkStrokerPriv::CapFactory(SkPaint::kButt_Cap) == fCapper
&& fPrevPt.equalsWithinTolerance(currPt, SK_ScalarNearlyZero * fInvResScale)) {
return;
}
+ if (fPrevPt == currPt && (fJoinCompleted || (iter && has_valid_tangent(iter)))) {
+ return;
+ }
SkVector normal, unitNormal;
if (!this->preJoinTo(currPt, &normal, &unitNormal, true)) {
@@ -1339,7 +1377,7 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
stroker.moveTo(pts[0]);
break;
case SkPath::kLine_Verb:
- stroker.lineTo(pts[1]);
+ stroker.lineTo(pts[1], &iter);
lastSegment = SkPath::kLine_Verb;
break;
case SkPath::kQuad_Verb: