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

Unified Diff: src/effects/SkDashPathEffect.cpp

Issue 699623003: Crop the fast path dashed lines to the cull rect (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 1 month 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/dashing.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/SkDashPathEffect.cpp
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp
index f9a56d0ff41fe129a6af8cb15c0dded767be211c..937dd2122bd174f1d2ec4b2985f2467591c6c5cf 100644
--- a/src/effects/SkDashPathEffect.cpp
+++ b/src/effects/SkDashPathEffect.cpp
@@ -41,6 +41,114 @@ bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
fInitialDashLength, fInitialDashIndex, fIntervalLength);
}
robertphillips 2014/11/03 21:20:07 This code was adapted from src\utils\SkDashPath.cp
+static void outset_for_stroke(SkRect* rect, const SkStrokeRec& rec) {
+ SkScalar radius = SkScalarHalf(rec.getWidth());
+ if (0 == radius) {
+ radius = SK_Scalar1; // hairlines
+ }
+ if (SkPaint::kMiter_Join == rec.getJoin()) {
+ radius = SkScalarMul(radius, rec.getMiter());
+ }
+ rect->outset(radius, radius);
+}
+
+// Only handles lines for now. If returns true, dstPath is the new (smaller)
+// path. If returns false, then dstPath parameter is ignored.
+static bool cull_path(const SkPath& srcPath, const SkStrokeRec& rec,
+ const SkRect* cullRect, SkScalar intervalLength,
+ SkPath* dstPath) {
+ if (NULL == cullRect) {
+ return false;
+ }
+
+ SkPoint pts[2];
+ if (!srcPath.isLine(pts)) {
+ return false;
+ }
+
+ SkRect bounds = *cullRect;
+ outset_for_stroke(&bounds, rec);
+
+ SkScalar dx = pts[1].x() - pts[0].x();
+ SkScalar dy = pts[1].y() - pts[0].y();
+
+ if (dx && dy) {
+ return false;
+ }
+
+ if (dx) {
+ SkASSERT(dx && !dy);
+ SkScalar minX = pts[0].fX;
+ SkScalar maxX = pts[1].fX;
+
+ if (dx < 0) {
+ SkTSwap(minX, maxX);
+ }
+
+ SkASSERT(minX < maxX);
+ if (maxX < bounds.fLeft || minX > bounds.fRight) {
+ return false;
+ }
+
+ // Now we actually perform the chop, removing the excess to the left and
+ // right of the bounds (keeping our new line "in phase" with the dash,
+ // hence the (mod intervalLength).
+
+ if (minX < bounds.fLeft) {
+ minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX, intervalLength);
egdaniel 2014/11/03 22:03:31 This moding thing to get "in phase" seems off to m
+ }
+ if (maxX > bounds.fRight) {
+ maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight, intervalLength);
+ }
+
+ SkASSERT(maxX >= minX);
+ if (dx < 0) {
+ SkTSwap(minX, maxX);
+ }
+ pts[0].fX = minX;
+ pts[1].fX = maxX;
+
+ dstPath->moveTo(pts[0]);
+ dstPath->lineTo(pts[1]);
+ } else {
+ SkASSERT(dy && !dx);
+ SkScalar minY = pts[0].fY;
+ SkScalar maxY = pts[1].fY;
+
+ if (dy < 0) {
+ SkTSwap(minY, maxY);
+ }
+
+ SkASSERT(minY < maxY);
+ if (maxY < bounds.fTop || minY > bounds.fBottom) {
+ return false;
+ }
+
+ // Now we actually perform the chop, removing the excess to the top and
+ // bottom of the bounds (keeping our new line "in phase" with the dash,
+ // hence the (mod intervalLength).
+
+ if (minY < bounds.fTop) {
+ minY = bounds.fTop - SkScalarMod(bounds.fTop - minY, intervalLength);
+ }
+ if (maxY > bounds.fBottom) {
+ maxY = bounds.fBottom + SkScalarMod(maxY - bounds.fBottom, intervalLength);
+ }
+
+ SkASSERT(maxY >= minY);
+ if (dy < 0) {
+ SkTSwap(minY, maxY);
+ }
+ pts[0].fY = minY;
+ pts[1].fY = maxY;
+
+ dstPath->moveTo(pts[0]);
+ dstPath->lineTo(pts[1]);
+ }
+
+ return true;
+}
+
// Currently asPoints is more restrictive then it needs to be. In the future
// we need to:
// allow kRound_Cap capping (could allow rotations in the matrix with this)
@@ -67,9 +175,15 @@ bool SkDashPathEffect::asPoints(PointData* results,
return false;
}
+ SkPath cullPathStorage;
+ const SkPath* srcPtr = &src;
+ if (cull_path(src, rec, cullRect, fIntervalLength, &cullPathStorage)) {
+ srcPtr = &cullPathStorage;
+ }
+
SkPoint pts[2];
- if (!src.isLine(pts)) {
+ if (!srcPtr->isLine(pts)) {
return false;
}
@@ -83,7 +197,7 @@ bool SkDashPathEffect::asPoints(PointData* results,
return false;
}
- SkScalar length = SkPoint::Distance(pts[1], pts[0]);
+ SkScalar length = SkPoint::Distance(pts[1], pts[0]);
SkVector tangent = pts[1] - pts[0];
if (tangent.isZero()) {
@@ -94,9 +208,11 @@ bool SkDashPathEffect::asPoints(PointData* results,
// TODO: make this test for horizontal & vertical lines more robust
bool isXAxis = true;
- if (SK_Scalar1 == tangent.fX || -SK_Scalar1 == tangent.fX) {
+ if (SkScalarNearlyEqual(SK_Scalar1, tangent.fX) ||
+ SkScalarNearlyEqual(-SK_Scalar1, tangent.fX)) {
results->fSize.set(SkScalarHalf(fIntervals[0]), SkScalarHalf(rec.getWidth()));
- } else if (SK_Scalar1 == tangent.fY || -SK_Scalar1 == tangent.fY) {
+ } else if (SkScalarNearlyEqual(SK_Scalar1, tangent.fY) ||
+ SkScalarNearlyEqual(-SK_Scalar1, tangent.fY)) {
results->fSize.set(SkScalarHalf(rec.getWidth()), SkScalarHalf(fIntervals[0]));
isXAxis = false;
} else if (SkPaint::kRound_Cap != rec.getCap()) {
« no previous file with comments | « gm/dashing.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698