aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2016-08-26 05:30:19 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-26 05:30:19 -0700
commitad2344693c70f13d5e4216df8458b4d907395bde (patch)
tree6e4ce1773716748290645e5e18eeb91b723bb5c3 /src
parentcc319b95a58ae15e88c3c028b8726e7cab9121ff (diff)
Ignore fill when stroke & filling convex line-only paths
This seems to work well for miter and bevel joins with the resulting stroke and fill path remaining convex. There seems to be an issue with round joins where the outer generated shell is usually not convex. Without this CL the resulting stroke & filled paths are always concave. Perf-wise (on Windows): convex-lineonly-paths-stroke-and-fill bench (in ms) w/o w/CL %decrease 8888 2.88 2.01 30.2 gpu 4.4 1.38 68.6 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2275243003 Review-Url: https://codereview.chromium.org/2275243003
Diffstat (limited to 'src')
-rw-r--r--src/core/SkStroke.cpp40
1 files changed, 29 insertions, 11 deletions
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index df3e0f98e1..8ff7910bdc 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.
@@ -1366,7 +1378,13 @@ 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 && (src.getSegmentMasks() == SkPath::kLine_SegmentMask) &&
+ 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 +1438,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 {