diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-24 21:03:11 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-24 21:03:11 +0000 |
commit | 4bbdeac58cc928dc66296bde3bd06e78070d96b7 (patch) | |
tree | 71033489f3f329bfc8c422c6e04e1df5b734cdb0 | |
parent | 82502e2e3966a9b0e48665f20154eaacd2a452b3 (diff) |
add optional cull-rect to patheffects, so they can do less work if their results
lie outside of the current clip-bounds (the cull rect).
Review URL: https://codereview.appspot.com/7206044
git-svn-id: http://skia.googlecode.com/svn/trunk@7378 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | bench/DashBench.cpp | 4 | ||||
-rw-r--r-- | include/core/SkDraw.h | 11 | ||||
-rw-r--r-- | include/core/SkPaint.h | 24 | ||||
-rw-r--r-- | include/core/SkPathEffect.h | 9 | ||||
-rw-r--r-- | include/effects/Sk1DPathEffect.h | 4 | ||||
-rw-r--r-- | include/effects/Sk2DPathEffect.h | 4 | ||||
-rw-r--r-- | include/effects/SkCornerPathEffect.h | 2 | ||||
-rw-r--r-- | include/effects/SkDashPathEffect.h | 5 | ||||
-rw-r--r-- | include/effects/SkDiscretePathEffect.h | 2 | ||||
-rw-r--r-- | samplecode/ClockFaceView.cpp | 4 | ||||
-rw-r--r-- | src/core/SkDraw.cpp | 30 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 5 | ||||
-rw-r--r-- | src/core/SkPathEffect.cpp | 14 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 2 | ||||
-rw-r--r-- | src/effects/Sk1DPathEffect.cpp | 6 | ||||
-rw-r--r-- | src/effects/Sk2DPathEffect.cpp | 6 | ||||
-rw-r--r-- | src/effects/SkCornerPathEffect.cpp | 2 | ||||
-rw-r--r-- | src/effects/SkDashPathEffect.cpp | 92 | ||||
-rw-r--r-- | src/effects/SkDiscretePathEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 4 | ||||
-rw-r--r-- | tests/DrawPathTest.cpp | 2 |
21 files changed, 181 insertions, 53 deletions
diff --git a/bench/DashBench.cpp b/bench/DashBench.cpp index f10924605c..930688f4f6 100644 --- a/bench/DashBench.cpp +++ b/bench/DashBench.cpp @@ -206,7 +206,7 @@ protected: for (int i = 0; i < N; ++i) { SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle); - fPE->filterPath(&dst, fPath, &rec); + fPE->filterPath(&dst, fPath, &rec, NULL); dst.rewind(); } } @@ -419,6 +419,6 @@ DEF_BENCH( return new GiantDashBench(p, GiantDashBench::kDiag_LineType, 0); ) // pass 2 to explicitly avoid any 1-is-the-same-as-hairline special casing // hori_2 is just too slow to enable at the moment -//DEF_BENCH( return new GiantDashBench(p, GiantDashBench::kHori_LineType, 2); ) +DEF_BENCH( return new GiantDashBench(p, GiantDashBench::kHori_LineType, 2); ) DEF_BENCH( return new GiantDashBench(p, GiantDashBench::kVert_LineType, 2); ) DEF_BENCH( return new GiantDashBench(p, GiantDashBench::kDiag_LineType, 2); ) diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h index 4ac7cf9fa0..e671d7d12c 100644 --- a/include/core/SkDraw.h +++ b/include/core/SkDraw.h @@ -104,6 +104,17 @@ private: void drawDevMask(const SkMask& mask, const SkPaint&) const; void drawBitmapAsMask(const SkBitmap&, const SkPaint&) const; + /** + * Return the current clip bounds, in local coordinates, with slop to account + * for antialiasing or hairlines (i.e. device-bounds outset by 1, and then + * run through the inverse of the matrix). + * + * If the matrix cannot be inverted, or the current clip is empty, return + * false and ignore bounds parameter. + */ + bool SK_WARN_UNUSED_RESULT + computeConservativeLocalClipBounds(SkRect* bounds) const; + public: const SkBitmap* fBitmap; // required const SkMatrix* fMatrix; // required diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index 8c4a7a4ef3..a5473d3517 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -426,16 +426,20 @@ public: */ void setStrokeJoin(Join join); - /** Applies any/all effects (patheffect, stroking) to src, returning the - result in dst. The result is that drawing src with this paint will be - the same as drawing dst with a default paint (at least from the - geometric perspective). - @param src input path - @param dst output path (may be the same as src) - @return true if the path should be filled, or false if it should be - drawn with a hairline (width == 0) - */ - bool getFillPath(const SkPath& src, SkPath* dst) const; + /** + * Applies any/all effects (patheffect, stroking) to src, returning the + * result in dst. The result is that drawing src with this paint will be + * the same as drawing dst with a default paint (at least from the + * geometric perspective). + * + * @param src input path + * @param dst output path (may be the same as src) + * @param cullRect If not null, the dst path may be culled to this rect. + * @return true if the path should be filled, or false if it should be + * drawn with a hairline (width == 0) + */ + bool getFillPath(const SkPath& src, SkPath* dst, + const SkRect* cullRect = NULL) const; /** Get the paint's shader object. <p /> diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h index f9495cdc73..7a982f40f1 100644 --- a/include/core/SkPathEffect.h +++ b/include/core/SkPathEffect.h @@ -49,7 +49,7 @@ public: * resulting stroke-rec to dst and then draw. */ virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const = 0; + SkStrokeRec*, const SkRect* cullR) const = 0; /** * Compute a conservative bounds for its effect, given the src bounds. @@ -103,7 +103,8 @@ public: * optionally return the points in 'results'. */ virtual bool asPoints(PointData* results, const SkPath& src, - const SkStrokeRec&, const SkMatrix&) const; + const SkStrokeRec&, const SkMatrix&, + const SkRect* cullR) const; protected: SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} @@ -154,7 +155,7 @@ public: : INHERITED(outer, inner) {} virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect) @@ -185,7 +186,7 @@ public: : INHERITED(first, second) {} virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect) diff --git a/include/effects/Sk1DPathEffect.h b/include/effects/Sk1DPathEffect.h index 0ceadc1bb9..4599276e7b 100644 --- a/include/effects/Sk1DPathEffect.h +++ b/include/effects/Sk1DPathEffect.h @@ -17,7 +17,7 @@ class SkPathMeasure; class SK_API Sk1DPathEffect : public SkPathEffect { public: virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; protected: /** Called at the start of each contour, returns the initial offset @@ -55,7 +55,7 @@ public: SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style); virtual bool filterPath(SkPath*, const SkPath&, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath1DPathEffect) diff --git a/include/effects/Sk2DPathEffect.h b/include/effects/Sk2DPathEffect.h index 3f774ae7b9..ed7f674f89 100644 --- a/include/effects/Sk2DPathEffect.h +++ b/include/effects/Sk2DPathEffect.h @@ -17,7 +17,7 @@ public: Sk2DPathEffect(const SkMatrix& mat); virtual bool filterPath(SkPath*, const SkPath&, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk2DPathEffect) @@ -62,7 +62,7 @@ public: : Sk2DPathEffect(matrix), fWidth(width) {} virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLine2DPathEffect) diff --git a/include/effects/SkCornerPathEffect.h b/include/effects/SkCornerPathEffect.h index ee89219f85..704b7fb8f0 100644 --- a/include/effects/SkCornerPathEffect.h +++ b/include/effects/SkCornerPathEffect.h @@ -24,7 +24,7 @@ public: virtual ~SkCornerPathEffect(); virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCornerPathEffect) diff --git a/include/effects/SkDashPathEffect.h b/include/effects/SkDashPathEffect.h index cc9ad75321..9c0775dfba 100644 --- a/include/effects/SkDashPathEffect.h +++ b/include/effects/SkDashPathEffect.h @@ -41,10 +41,11 @@ public: virtual ~SkDashPathEffect(); virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; virtual bool asPoints(PointData* results, const SkPath& src, - const SkStrokeRec&, const SkMatrix&) const SK_OVERRIDE; + const SkStrokeRec&, const SkMatrix&, + const SkRect*) const SK_OVERRIDE; virtual Factory getFactory() SK_OVERRIDE; diff --git a/include/effects/SkDiscretePathEffect.h b/include/effects/SkDiscretePathEffect.h index 029ebfd35c..999ea04810 100644 --- a/include/effects/SkDiscretePathEffect.h +++ b/include/effects/SkDiscretePathEffect.h @@ -23,7 +23,7 @@ public: SkDiscretePathEffect(SkScalar segLength, SkScalar deviation); virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE; + SkStrokeRec*, const SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect) diff --git a/samplecode/ClockFaceView.cpp b/samplecode/ClockFaceView.cpp index 9a46e8099c..a182f4df95 100644 --- a/samplecode/ClockFaceView.cpp +++ b/samplecode/ClockFaceView.cpp @@ -110,7 +110,7 @@ class InverseFillPE : public SkPathEffect { public: InverseFillPE() {} virtual bool filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const SK_OVERRIDE { + SkStrokeRec*, const SkRect*) const SK_OVERRIDE { *dst = src; dst->setFillType(SkPath::kInverseWinding_FillType); return true; @@ -198,7 +198,7 @@ protected: SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); SkPath path, dstPath; orig.getTextPath("9", 1, 0, 0, &path); - pe->filterPath(&dstPath, path, &rec); + pe->filterPath(&dstPath, path, &rec, NULL); SkPaint p; p.setAntiAlias(true); diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 45a023b06b..87f117b8e7 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -122,6 +122,23 @@ SkDraw::SkDraw(const SkDraw& src) { memcpy(this, &src, sizeof(*this)); } +bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const { + if (fRC->isEmpty()) { + return false; + } + + SkMatrix inverse; + if (!fMatrix->invert(&inverse)) { + return false; + } + + SkIRect devBounds = fRC->getBounds(); + // outset to have slop for antialasing and hairlines + devBounds.outset(1, 1); + inverse.mapRect(localBounds, SkRect::Make(devBounds)); + return true; +} + /////////////////////////////////////////////////////////////////////////////// typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); @@ -668,7 +685,10 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, path.moveTo(pts[0]); path.lineTo(pts[1]); - if (paint.getPathEffect()->asPoints(&pointData, path, rec, *fMatrix)) { + SkRect cullRect = SkRect::Make(fRC->getBounds()); + + if (paint.getPathEffect()->asPoints(&pointData, path, rec, + *fMatrix, &cullRect)) { // 'asPoints' managed to find some fast path SkPaint newP(paint); @@ -1057,7 +1077,12 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, } if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { - doFill = paint->getFillPath(*pathPtr, &tmpPath); + SkRect cullRect; + const SkRect* cullRectPtr = NULL; + if (this->computeConservativeLocalClipBounds(&cullRect)) { + cullRectPtr = &cullRect; + } + doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr); pathPtr = &tmpPath; } @@ -2765,3 +2790,4 @@ bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, return true; } + diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 8f14ba8b3b..71a68ef1c8 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -2145,13 +2145,14 @@ SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) { /////////////////////////////////////////////////////////////////////////////// -bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const { +bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, + const SkRect* cullRect) const { SkStrokeRec rec(*this); const SkPath* srcPtr = &src; SkPath tmpPath; - if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec)) { + if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) { srcPtr = &tmpPath; } diff --git a/src/core/SkPathEffect.cpp b/src/core/SkPathEffect.cpp index ebbfd6dc51..38332a4a2f 100644 --- a/src/core/SkPathEffect.cpp +++ b/src/core/SkPathEffect.cpp @@ -19,7 +19,7 @@ void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) const { } bool SkPathEffect::asPoints(PointData* results, const SkPath& src, - const SkStrokeRec&, const SkMatrix&) const { + const SkStrokeRec&, const SkMatrix&, const SkRect*) const { return false; } @@ -56,7 +56,7 @@ SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) { /////////////////////////////////////////////////////////////////////////////// bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec) const { + SkStrokeRec* rec, const SkRect* cullRect) const { // we may have failed to unflatten these, so we have to check if (!fPE0 || !fPE1) { return false; @@ -65,16 +65,18 @@ bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src, SkPath tmp; const SkPath* ptr = &src; - if (fPE1->filterPath(&tmp, src, rec)) { + if (fPE1->filterPath(&tmp, src, rec, cullRect)) { ptr = &tmp; } - return fPE0->filterPath(dst, *ptr, rec); + return fPE0->filterPath(dst, *ptr, rec, cullRect); } /////////////////////////////////////////////////////////////////////////////// bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec) const { + SkStrokeRec* rec, const SkRect* cullRect) const { // use bit-or so that we always call both, even if the first one succeeds - return fPE0->filterPath(dst, src, rec) | fPE1->filterPath(dst, src, rec); + return fPE0->filterPath(dst, src, rec, cullRect) | + fPE1->filterPath(dst, src, rec, cullRect); } + diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index c16fa76118..c35c0db444 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -638,7 +638,7 @@ void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, if (fPathEffect) { SkPath effectPath; - if (fPathEffect->filterPath(&effectPath, localPath, &rec)) { + if (fPathEffect->filterPath(&effectPath, localPath, &rec, NULL)) { localPath.swap(effectPath); } } diff --git a/src/effects/Sk1DPathEffect.cpp b/src/effects/Sk1DPathEffect.cpp index 3ef050cb88..10a68b9f84 100644 --- a/src/effects/Sk1DPathEffect.cpp +++ b/src/effects/Sk1DPathEffect.cpp @@ -12,7 +12,7 @@ #include "SkPathMeasure.h" bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const { + SkStrokeRec*, const SkRect*) const { SkPathMeasure meas(src, false); do { SkScalar length = meas.getLength(); @@ -69,10 +69,10 @@ SkPath1DPathEffect::SkPath1DPathEffect(const SkPath& path, SkScalar advance, } bool SkPath1DPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec) const { + SkStrokeRec* rec, const SkRect* cullRect) const { if (fAdvance > 0) { rec->setFillStyle(); - return this->INHERITED::filterPath(dst, src, rec); + return this->INHERITED::filterPath(dst, src, rec, cullRect); } return false; } diff --git a/src/effects/Sk2DPathEffect.cpp b/src/effects/Sk2DPathEffect.cpp index a4ebe7454f..dc15f076d6 100644 --- a/src/effects/Sk2DPathEffect.cpp +++ b/src/effects/Sk2DPathEffect.cpp @@ -17,7 +17,7 @@ Sk2DPathEffect::Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) { } bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const { + SkStrokeRec*, const SkRect*) const { if (!fMatrixIsInvertible) { return false; } @@ -80,8 +80,8 @@ Sk2DPathEffect::Sk2DPathEffect(SkFlattenableReadBuffer& buffer) { /////////////////////////////////////////////////////////////////////////////// bool SkLine2DPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec) const { - if (this->INHERITED::filterPath(dst, src, rec)) { + SkStrokeRec* rec, const SkRect* cullRect) const { + if (this->INHERITED::filterPath(dst, src, rec, cullRect)) { rec->setStrokeStyle(fWidth); return true; } diff --git a/src/effects/SkCornerPathEffect.cpp b/src/effects/SkCornerPathEffect.cpp index b63045ddf9..1cf797a249 100644 --- a/src/effects/SkCornerPathEffect.cpp +++ b/src/effects/SkCornerPathEffect.cpp @@ -31,7 +31,7 @@ static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, } bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*) const { + SkStrokeRec*, const SkRect*) const { if (0 == fRadius) { return false; } diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp index ef10ca5e8c..d1ce526073 100644 --- a/src/effects/SkDashPathEffect.cpp +++ b/src/effects/SkDashPathEffect.cpp @@ -88,10 +88,81 @@ SkDashPathEffect::~SkDashPathEffect() { sk_free(fIntervals); } +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(); + + // just do horizontal lines for now (lazy) + if (dy) { + return false; + } + + SkScalar minX = pts[0].fX; + SkScalar maxX = pts[1].fX; + + if (maxX < bounds.fLeft || minX > bounds.fRight) { + return false; + } + + if (dx < 0) { + SkTSwap(minX, maxX); + } + + // 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); + } + 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]); + return true; +} + class SpecialLineRec { public: bool init(const SkPath& src, SkPath* dst, SkStrokeRec* rec, - SkScalar pathLength, int intervalCount, SkScalar intervalLength) { if (rec->isHairlineStyle() || !src.isLine(fPts)) { return false; @@ -102,6 +173,8 @@ public: return false; } + SkScalar pathLength = SkPoint::Distance(fPts[0], fPts[1]); + fTangent = fPts[1] - fPts[0]; if (fTangent.isZero()) { return false; @@ -156,19 +229,25 @@ private: }; bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec) const { + SkStrokeRec* rec, const SkRect* cullRect) const { // we do nothing if the src wants to be filled, or if our dashlength is 0 if (rec->isFillStyle() || fInitialDashLength < 0) { return false; } - SkPathMeasure meas(src, false); const SkScalar* intervals = fIntervals; SkScalar dashCount = 0; + SkPath cullPathStorage; + const SkPath* srcPtr = &src; + if (cull_path(src, *rec, cullRect, fIntervalLength, &cullPathStorage)) { + srcPtr = &cullPathStorage; + } + SpecialLineRec lineRec; - const bool specialLine = lineRec.init(src, dst, rec, meas.getLength(), - fCount >> 1, fIntervalLength); + bool specialLine = lineRec.init(src, dst, rec, fCount >> 1, fIntervalLength); + + SkPathMeasure meas(*srcPtr, false); do { bool skipFirstSegment = meas.isClosed(); @@ -256,7 +335,8 @@ bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src, bool SkDashPathEffect::asPoints(PointData* results, const SkPath& src, const SkStrokeRec& rec, - const SkMatrix& matrix) const { + const SkMatrix& matrix, + const SkRect* cullRect) const { // width < 0 -> fill && width == 0 -> hairline so requiring width > 0 rules both out if (fInitialDashLength < 0 || 0 >= rec.getWidth()) { return false; diff --git a/src/effects/SkDiscretePathEffect.cpp b/src/effects/SkDiscretePathEffect.cpp index a936be9a50..2c95208aac 100644 --- a/src/effects/SkDiscretePathEffect.cpp +++ b/src/effects/SkDiscretePathEffect.cpp @@ -26,7 +26,7 @@ SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviatio } bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec) const { + SkStrokeRec* rec, const SkRect*) const { bool doFill = rec->isFillStyle(); SkPathMeasure meas(src, doFill); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 827fc52ba0..3e20e3b1f9 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -972,7 +972,9 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, SkStrokeRec stroke(paint); SkPathEffect* pathEffect = paint.getPathEffect(); - if (pathEffect && pathEffect->filterPath(&effectPath, *pathPtr, &stroke)) { + const SkRect* cullRect = NULL; // TODO: what is our bounds? + if (pathEffect && pathEffect->filterPath(&effectPath, *pathPtr, &stroke, + cullRect)) { pathPtr = &effectPath; } diff --git a/tests/DrawPathTest.cpp b/tests/DrawPathTest.cpp index 370559e25b..3a238db9c9 100644 --- a/tests/DrawPathTest.cpp +++ b/tests/DrawPathTest.cpp @@ -260,7 +260,7 @@ static void test_crbug_165432(skiatest::Reporter* reporter) { SkPath filteredPath; SkStrokeRec rec(paint); - REPORTER_ASSERT(reporter, !dash.filterPath(&filteredPath, path, &rec)); + REPORTER_ASSERT(reporter, !dash.filterPath(&filteredPath, path, &rec, NULL)); REPORTER_ASSERT(reporter, filteredPath.isEmpty()); } |