Chromium Code Reviews| Index: src/core/SkStroke.cpp |
| diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp |
| index df3e0f98e176ace2c66b1ea26cd3ecd2ea46cb83..bfa8a259c2f66292e7ca637f5eb05ca2fca5dd8f 100644 |
| --- a/src/core/SkStroke.cpp |
| +++ b/src/core/SkStroke.cpp |
| @@ -55,7 +55,7 @@ static bool set_normal_unitnormal(const SkPoint& before, const SkPoint& after, S |
| SkScalar radius, |
| SkVector* normal, SkVector* unitNormal) { |
| if (!unitNormal->setNormalize((after.fX - before.fX) * scale, |
| - (after.fY - before.fY) * scale)) { |
| + (after.fY - before.fY) * scale)) { |
| return false; |
| } |
| unitNormal->rotateCCW(); |
| @@ -121,7 +121,8 @@ class SkPathStroker { |
| public: |
| SkPathStroker(const SkPath& src, |
| SkScalar radius, SkScalar miterLimit, SkPaint::Cap, |
| - SkPaint::Join, SkScalar resScale); |
| + SkPaint::Join, SkScalar resScale, |
| + bool canIgnoreCenter); |
| bool hasOnlyMoveTo() const { return 0 == fSegmentCount; } |
| SkPoint moveToPt() const { return fFirstPt; } |
| @@ -157,6 +158,7 @@ private: |
| SkPoint fFirstOuterPt; |
| int fSegmentCount; |
| bool fPrevIsLine; |
| + bool fCanIgnoreCenter; |
| SkStrokerPriv::CapProc fCapper; |
| SkStrokerPriv::JoinProc fJoiner; |
| @@ -294,11 +296,19 @@ void SkPathStroker::finishContour(bool close, bool currIsLine) { |
| fFirstUnitNormal, fRadius, fInvMiterLimit, |
| fPrevIsLine, currIsLine); |
| fOuter.close(); |
| - // now add fInner as its own contour |
| - fInner.getLastPt(&pt); |
| - fOuter.moveTo(pt.fX, pt.fY); |
| - fOuter.reversePathTo(fInner); |
| - fOuter.close(); |
| + |
| + if (fCanIgnoreCenter) { |
| + if (!fOuter.getBounds().contains(fInner.getBounds())) { |
| + SkASSERT(fInner.getBounds().contains(fOuter.getBounds())); |
| + fInner.swap(fOuter); |
| + } |
| + } else { |
| + // now add fInner as its own contour |
| + fInner.getLastPt(&pt); |
| + fOuter.moveTo(pt.fX, pt.fY); |
| + fOuter.reversePathTo(fInner); |
| + fOuter.close(); |
| + } |
| } else { // add caps to start and end |
| // cap the end |
| fInner.getLastPt(&pt); |
| @@ -321,9 +331,11 @@ void SkPathStroker::finishContour(bool close, bool currIsLine) { |
| SkPathStroker::SkPathStroker(const SkPath& src, |
| SkScalar radius, SkScalar miterLimit, |
| - SkPaint::Cap cap, SkPaint::Join join, SkScalar resScale) |
| + SkPaint::Cap cap, SkPaint::Join join, SkScalar resScale, |
| + bool canIgnoreCenter) |
| : fRadius(radius) |
| - , fResScale(resScale) { |
| + , fResScale(resScale) |
| + , fCanIgnoreCenter(canIgnoreCenter) { |
| /* This is only used when join is miter_join, but we initialize it here |
| so that it is always defined, to fis valgrind warnings. |
| @@ -1339,6 +1351,11 @@ private: |
| bool fSwapWithSrc; |
| }; |
| +static bool lines_only(const SkPath& p) { |
| + return (p.getSegmentMasks() & SkPath::kLine_SegmentMask) && |
|
bsalomon
2016/08/26 01:24:25
Is this different than p.getSegmentMasks() == SkPa
robertphillips
2016/08/26 11:44:32
Haha - no! Fixed.
|
| + !(p.getSegmentMasks() & ~SkPath::kLine_SegmentMask); |
| +} |
| + |
| void SkStroke::strokePath(const SkPath& src, SkPath* dst) const { |
| SkASSERT(dst); |
| @@ -1366,7 +1383,12 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const { |
| } |
| } |
| - SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), this->getJoin(), fResScale); |
| + // We can always ignore centers for stroke and fill convex line-only paths |
| + // TODO: remove the line-only restriction |
| + bool ignoreCenter = fDoFill && lines_only(src) && src.isLastContourClosed() && src.isConvex(); |
| + |
| + SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), this->getJoin(), |
| + fResScale, ignoreCenter); |
| SkPath::Iter iter(src, false); |
| SkPath::Verb lastSegment = SkPath::kMove_Verb; |
| @@ -1420,7 +1442,7 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const { |
| DONE: |
| stroker.done(dst, lastSegment == SkPath::kLine_Verb); |
| - if (fDoFill) { |
| + if (fDoFill && !ignoreCenter) { |
| if (SkPathPriv::CheapIsFirstDirection(src, SkPathPriv::kCCW_FirstDirection)) { |
| dst->reverseAddPath(src); |
| } else { |