aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/DashBench.cpp4
-rw-r--r--include/core/SkPathEffect.h106
-rw-r--r--include/effects/Sk1DPathEffect.h6
-rw-r--r--include/effects/Sk2DPathEffect.h2
-rw-r--r--include/effects/SkCornerPathEffect.h2
-rw-r--r--include/effects/SkDashPathEffect.h4
-rw-r--r--include/effects/SkDiscretePathEffect.h4
-rw-r--r--samplecode/ClockFaceView.cpp6
-rw-r--r--samplecode/SampleAll.cpp6
-rw-r--r--samplecode/SampleSlides.cpp8
-rw-r--r--samplecode/SampleTextEffects.cpp6
-rw-r--r--src/core/SkPaint.cpp64
-rw-r--r--src/core/SkPathEffect.cpp175
-rw-r--r--src/core/SkScalerContext.cpp32
-rw-r--r--src/core/SkStroke.cpp28
-rw-r--r--src/effects/Sk1DPathEffect.cpp8
-rw-r--r--src/effects/Sk2DPathEffect.cpp2
-rw-r--r--src/effects/SkCornerPathEffect.cpp2
-rw-r--r--src/effects/SkDashPathEffect.cpp4
-rw-r--r--src/effects/SkDiscretePathEffect.cpp4
-rw-r--r--src/ports/SkGlobalInitialization_default.cpp1
21 files changed, 213 insertions, 261 deletions
diff --git a/bench/DashBench.cpp b/bench/DashBench.cpp
index 215581603e..e9969c47ce 100644
--- a/bench/DashBench.cpp
+++ b/bench/DashBench.cpp
@@ -204,9 +204,9 @@ protected:
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
SkPath dst;
for (int i = 0; i < N; ++i) {
- SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
+ SkScalar width = 0;
- fPE->filterPath(&dst, fPath, &rec);
+ fPE->filterPath(&dst, fPath, &width);
dst.rewind();
}
}
diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h
index edf749b44c..c4a60d23fe 100644
--- a/include/core/SkPathEffect.h
+++ b/include/core/SkPathEffect.h
@@ -11,85 +11,9 @@
#define SkPathEffect_DEFINED
#include "SkFlattenable.h"
-#include "SkPaint.h"
class SkPath;
-class SkStrokeRec {
-public:
- enum InitStyle {
- kHairline_InitStyle,
- kFill_InitStyle
- };
- SkStrokeRec(InitStyle style);
-
- SkStrokeRec(const SkStrokeRec&);
- explicit SkStrokeRec(const SkPaint&);
-
- enum Style {
- kHairline_Style,
- kFill_Style,
- kStroke_Style,
- kStrokeAndFill_Style
- };
-
- Style getStyle() const;
- SkScalar getWidth() const { return fWidth; }
- SkScalar getMiter() const { return fWidth; }
- SkPaint::Cap getCap() const { return fCap; }
- SkPaint::Join getJoin() const { return fJoin; }
-
- bool isHairlineStyle() const {
- return kHairline_Style == this->getStyle();
- }
-
- bool isFillStyle() const {
- return kFill_Style == this->getStyle();
- }
-
- void setFillStyle() { fWidth = -SK_Scalar1; }
- void setHairlineStyle() { fWidth = 0; }
-
- void setStrokeStyle(SkScalar width, bool strokeAndFill = false) {
- fWidth = width;
- fStrokeAndFill = strokeAndFill;
- }
-
- void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
- fCap = cap;
- fJoin = join;
- fMiterLimit = miterLimit;
- }
-
- /**
- * Returns true if this specifes any thick stroking, i.e. applyToPath()
- * will return true.
- */
- bool needToApply() const {
- Style style = this->getStyle();
- return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
- }
-
- /**
- * Apply these stroke parameters to the src path, returning the result
- * in dst.
- *
- * If there was no change (i.e. style == hairline or fill) this returns
- * false and dst is unchanged. Otherwise returns true and the result is
- * stored in dst.
- *
- * src and dst may be the same path.
- */
- bool applyToPath(SkPath* dst, const SkPath& src) const;
-
-private:
- SkScalar fWidth;
- SkScalar fMiterLimit;
- SkPaint::Cap fCap;
- SkPaint::Join fJoin;
- bool fStrokeAndFill;
-};
-
/** \class SkPathEffect
SkPathEffect is the base class for objects in the SkPaint that affect
@@ -102,22 +26,13 @@ class SK_API SkPathEffect : public SkFlattenable {
public:
SkPathEffect() {}
- /**
- * Given a src path (input) and a stroke-rec (input and output), apply
- * this effect to the src path, returning the new path in dst, and return
- * true. If this effect cannot be applied, return false and ignore dst
- * and stroke-rec.
- *
- * The stroke-rec specifies the initial request for stroking (if any).
- * The effect can treat this as input only, or it can choose to change
- * the rec as well. For example, the effect can decide to change the
- * stroke's width or join, or the effect can change the rec from stroke
- * to fill (or fill to stroke) in addition to returning a new (dst) path.
- *
- * If this method returns true, the caller will apply (as needed) the
- * resulting stroke-rec to dst and then draw.
- */
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) = 0;
+ /** Given a src path and a width value, return true if the patheffect
+ has produced a new path (dst) and a new width value. If false is returned,
+ ignore dst and width.
+ On input, width >= 0 means the src should be stroked
+ On output, width >= 0 means the dst should be stroked
+ */
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) = 0;
/**
* Compute a conservative bounds for its effect, given the src bounds.
@@ -173,7 +88,9 @@ public:
SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner)
: INHERITED(outer, inner) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
+ // overrides
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
@@ -203,7 +120,8 @@ public:
SkSumPathEffect(SkPathEffect* first, SkPathEffect* second)
: INHERITED(first, second) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
+ // overrides
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
diff --git a/include/effects/Sk1DPathEffect.h b/include/effects/Sk1DPathEffect.h
index eafac36b89..25b6ff32d8 100644
--- a/include/effects/Sk1DPathEffect.h
+++ b/include/effects/Sk1DPathEffect.h
@@ -18,7 +18,8 @@ class SkPathMeasure;
// This class is not exported to java.
class Sk1DPathEffect : public SkPathEffect {
public:
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
+ // override from SkPathEffect
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
protected:
/** Called at the start of each contour, returns the initial offset
@@ -55,7 +56,8 @@ public:
*/
SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style);
- virtual bool filterPath(SkPath*, const SkPath&, SkStrokeRec*) SK_OVERRIDE;
+ // override from SkPathEffect
+ virtual bool filterPath(SkPath*, const SkPath&, SkScalar* width) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath1DPathEffect)
diff --git a/include/effects/Sk2DPathEffect.h b/include/effects/Sk2DPathEffect.h
index 724fb8f3a1..30bbe1ab16 100644
--- a/include/effects/Sk2DPathEffect.h
+++ b/include/effects/Sk2DPathEffect.h
@@ -19,7 +19,7 @@ public:
Sk2DPathEffect(const SkMatrix& mat);
// overrides
- virtual bool filterPath(SkPath*, const SkPath&, SkStrokeRec*) SK_OVERRIDE;
+ virtual bool filterPath(SkPath*, const SkPath&, SkScalar* width) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk2DPathEffect)
diff --git a/include/effects/SkCornerPathEffect.h b/include/effects/SkCornerPathEffect.h
index 02fe6d9b9f..01dae7e6f3 100644
--- a/include/effects/SkCornerPathEffect.h
+++ b/include/effects/SkCornerPathEffect.h
@@ -27,7 +27,7 @@ public:
// overrides for SkPathEffect
// This method is not exported to java.
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCornerPathEffect)
diff --git a/include/effects/SkDashPathEffect.h b/include/effects/SkDashPathEffect.h
index 87580aa37d..0c9e53cc31 100644
--- a/include/effects/SkDashPathEffect.h
+++ b/include/effects/SkDashPathEffect.h
@@ -41,7 +41,9 @@ public:
SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase, bool scaleToFit = false);
virtual ~SkDashPathEffect();
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
+ // overrides for SkPathEffect
+ // This method is not exported to java.
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
// overrides for SkFlattenable
// This method is not exported to java.
diff --git a/include/effects/SkDiscretePathEffect.h b/include/effects/SkDiscretePathEffect.h
index 29fd3c5242..30d07d3c21 100644
--- a/include/effects/SkDiscretePathEffect.h
+++ b/include/effects/SkDiscretePathEffect.h
@@ -24,7 +24,9 @@ public:
*/
SkDiscretePathEffect(SkScalar segLength, SkScalar deviation);
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
+ // overrides for SkPathEffect
+ // This method is not exported to java.
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect)
diff --git a/samplecode/ClockFaceView.cpp b/samplecode/ClockFaceView.cpp
index 7d4da1051b..85559929b1 100644
--- a/samplecode/ClockFaceView.cpp
+++ b/samplecode/ClockFaceView.cpp
@@ -108,7 +108,7 @@ private:
class InverseFillPE : public SkPathEffect {
public:
InverseFillPE() {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE {
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
*dst = src;
dst->setFillType(SkPath::kInverseWinding_FillType);
return true;
@@ -197,10 +197,10 @@ protected:
SkTDArray<SkPoint> pts;
SkPathEffect* pe = makepe(0, &pts);
- SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
+ SkScalar width = -1;
SkPath path, dstPath;
orig.getTextPath("9", 1, 0, 0, &path);
- pe->filterPath(&dstPath, path, &rec);
+ pe->filterPath(&dstPath, path, &width);
SkPaint p;
p.setAntiAlias(true);
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index 4ab3b0e453..ea35ff1ea9 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -210,9 +210,9 @@ public:
Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
: Sk2DPathEffect(matrix), fWidth(width) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
- if (this->INHERITED::filterPath(dst, src, rec)) {
- rec->setStrokeStyle(fWidth);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
+ if (this->INHERITED::filterPath(dst, src, width)) {
+ *width = fWidth;
return true;
}
return false;
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index f800f43f51..49a4ee5945 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -602,9 +602,11 @@ public:
Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
: Sk2DPathEffect(matrix), fWidth(width) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
- if (this->INHERITED::filterPath(dst, src, rec)) {
- rec->setStrokeStyle(fWidth);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
+ {
+ if (this->INHERITED::filterPath(dst, src, width))
+ {
+ *width = fWidth;
return true;
}
return false;
diff --git a/samplecode/SampleTextEffects.cpp b/samplecode/SampleTextEffects.cpp
index 215154894e..4a1e202877 100644
--- a/samplecode/SampleTextEffects.cpp
+++ b/samplecode/SampleTextEffects.cpp
@@ -181,9 +181,9 @@ public:
Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
: Sk2DPathEffect(matrix), fWidth(width) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
- if (this->INHERITED::filterPath(dst, src, rec)) {
- rec->setStrokeStyle(fWidth);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
+ if (this->INHERITED::filterPath(dst, src, width)) {
+ *width = fWidth;
return true;
}
return false;
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 8a4071f34d..1b74fa1e44 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1987,27 +1987,61 @@ SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
///////////////////////////////////////////////////////////////////////////////
bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
- SkStrokeRec rec(*this);
+ SkPath effectPath, strokePath;
+ const SkPath* path = &src;
- const SkPath* srcPtr = &src;
- SkPath tmpPath;
+ SkScalar width = this->getStrokeWidth();
- if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec)) {
- srcPtr = &tmpPath;
+ switch (this->getStyle()) {
+ case SkPaint::kFill_Style:
+ width = -1; // mark it as no-stroke
+ break;
+ case SkPaint::kStrokeAndFill_Style:
+ if (width == 0) {
+ width = -1; // mark it as no-stroke
+ }
+ break;
+ case SkPaint::kStroke_Style:
+ break;
+ default:
+ SkDEBUGFAIL("unknown paint style");
}
- if (!rec.applyToPath(dst, *srcPtr)) {
- if (srcPtr == &tmpPath) {
- // If path's were copy-on-write, this trick would not be needed.
- // As it is, we want to save making a deep-copy from tmpPath -> dst
- // since we know we're just going to delete tmpPath when we return,
- // so the swap saves that copy.
- dst->swap(tmpPath);
- } else {
- *dst = *srcPtr;
+ if (this->getPathEffect()) {
+ // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
+ if (this->getStyle() == SkPaint::kStrokeAndFill_Style) {
+ width = -1; // mark it as no-stroke
+ }
+
+ if (this->getPathEffect()->filterPath(&effectPath, src, &width)) {
+ path = &effectPath;
}
+
+ // restore the width if we earlier had to lie, and if we're still set to no-stroke
+ // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
+ // and we want to respect that (i.e. don't overwrite their setting for width)
+ if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) {
+ width = this->getStrokeWidth();
+ if (width == 0) {
+ width = -1;
+ }
+ }
+ }
+
+ if (width > 0 && !path->isEmpty()) {
+ SkStroke stroker(*this, width);
+ stroker.strokePath(*path, &strokePath);
+ path = &strokePath;
}
- return !rec.isHairlineStyle();
+
+ if (path == &src) {
+ *dst = src;
+ } else {
+ SkASSERT(path == &effectPath || path == &strokePath);
+ dst->swap(*(SkPath*)path);
+ }
+
+ return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
}
const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
diff --git a/src/core/SkPathEffect.cpp b/src/core/SkPathEffect.cpp
index 9be694392a..dcce6d6b56 100644
--- a/src/core/SkPathEffect.cpp
+++ b/src/core/SkPathEffect.cpp
@@ -10,78 +10,6 @@
#include "SkPathEffect.h"
#include "SkPath.h"
#include "SkBuffer.h"
-#include "SkPaintDefaults.h"
-
-#define kStrokeRec_FillStyleWidth (-SK_Scalar1)
-
-SkStrokeRec::SkStrokeRec(InitStyle s) {
- fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
- fMiterLimit = SkPaintDefaults_MiterLimit;
- fCap = SkPaint::kDefault_Cap;
- fJoin = SkPaint::kDefault_Join;
- fStrokeAndFill = false;
-}
-
-SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
- memcpy(this, &src, sizeof(src));
-}
-
-SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
- switch (paint.getStyle()) {
- case SkPaint::kFill_Style:
- fWidth = kStrokeRec_FillStyleWidth;
- fStrokeAndFill = false;
- break;
- case SkPaint::kStroke_Style:
- fWidth = paint.getStrokeWidth();
- fStrokeAndFill = false;
- break;
- case SkPaint::kStrokeAndFill_Style:
- fWidth = paint.getStrokeWidth();
- fStrokeAndFill = true;
- break;
- default:
- SkASSERT(!"unknown paint style");
- // fall back on just fill
- fWidth = kStrokeRec_FillStyleWidth;
- fStrokeAndFill = false;
- break;
- }
-
- // copy these from the paint, regardless of our "style"
- fMiterLimit = paint.getStrokeMiter();
- fCap = paint.getStrokeCap();
- fJoin = paint.getStrokeJoin();
-}
-
-SkStrokeRec::Style SkStrokeRec::getStyle() const {
- if (fWidth < 0) {
- return kFill_Style;
- } else if (0 == fWidth) {
- return kHairline_Style;
- } else {
- return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
- }
-}
-
-#include "SkStroke.h"
-
-bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
- if (fWidth <= 0) { // hairline or fill
- return false;
- }
-
- SkStroke stroker;
- stroker.setCap(fCap);
- stroker.setJoin(fJoin);
- stroker.setMiterLimit(fMiterLimit);
- stroker.setWidth(fWidth);
- stroker.setDoFill(fStrokeAndFill);
- stroker.strokePath(src, dst);
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) {
*dst = src;
@@ -120,7 +48,7 @@ SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) {
///////////////////////////////////////////////////////////////////////////////
bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkStrokeRec* rec) {
+ SkScalar* width) {
// we may have failed to unflatten these, so we have to check
if (!fPE0 || !fPE1) {
return false;
@@ -129,22 +57,115 @@ 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, width)) {
ptr = &tmp;
}
- return fPE0->filterPath(dst, *ptr, rec);
+ return fPE0->filterPath(dst, *ptr, width);
}
///////////////////////////////////////////////////////////////////////////////
bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkStrokeRec* rec) {
+ SkScalar* width) {
// 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, width) | fPE1->filterPath(dst, src, width);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkStroke.h"
+
+/** \class SkStrokePathEffect
+
+ SkStrokePathEffect simulates stroking inside a patheffect, allowing the
+ caller to have explicit control of when to stroke a path. Typically this is
+ used if the caller wants to stroke before another patheffect is applied
+ (using SkComposePathEffect or SkSumPathEffect).
+ */
+class SkStrokePathEffect : public SkPathEffect {
+public:
+ SkStrokePathEffect(const SkPaint&);
+ SkStrokePathEffect(SkScalar width, SkPaint::Style, SkPaint::Join,
+ SkPaint::Cap, SkScalar miterLimit = -1);
+
+ // overrides
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkStrokePathEffect)
+
+protected:
+ SkStrokePathEffect(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkScalar fWidth, fMiter;
+ uint8_t fStyle, fJoin, fCap;
+
+ typedef SkPathEffect INHERITED;
+
+ // illegal
+ SkStrokePathEffect(const SkStrokePathEffect&);
+ SkStrokePathEffect& operator=(const SkStrokePathEffect&);
+};
+
+SkStrokePathEffect::SkStrokePathEffect(const SkPaint& paint)
+ : fWidth(paint.getStrokeWidth()), fMiter(paint.getStrokeMiter()),
+ fStyle(SkToU8(paint.getStyle())), fJoin(SkToU8(paint.getStrokeJoin())),
+ fCap(SkToU8(paint.getStrokeCap())) {
+}
+
+SkStrokePathEffect::SkStrokePathEffect(SkScalar width, SkPaint::Style style,
+ SkPaint::Join join, SkPaint::Cap cap, SkScalar miter)
+ : fWidth(width), fMiter(miter), fStyle(SkToU8(style)),
+ fJoin(SkToU8(join)), fCap(SkToU8(cap)) {
+ if (miter < 0) { // signal they want the default
+ fMiter = SkIntToScalar(4);
+ }
+}
+
+bool SkStrokePathEffect::filterPath(SkPath* dst, const SkPath& src,
+ SkScalar* width) {
+ if (fWidth < 0 || fStyle == SkPaint::kFill_Style) {
+ return false;
+ }
+
+ if (fStyle == SkPaint::kStroke_Style && fWidth == 0) { // hairline
+ *width = 0;
+ return true;
+ }
+
+ SkStroke stroke;
+
+ stroke.setWidth(fWidth);
+ stroke.setMiterLimit(fMiter);
+ stroke.setJoin((SkPaint::Join)fJoin);
+ stroke.setCap((SkPaint::Cap)fCap);
+ stroke.setDoFill(fStyle == SkPaint::kStrokeAndFill_Style);
+
+ stroke.strokePath(src, dst);
+ return true;
+}
+
+void SkStrokePathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ buffer.writeScalar(fWidth);
+ buffer.writeScalar(fMiter);
+ buffer.write8(fStyle);
+ buffer.write8(fJoin);
+ buffer.write8(fCap);
+}
+
+SkStrokePathEffect::SkStrokePathEffect(SkFlattenableReadBuffer& buffer) {
+ fWidth = buffer.readScalar();
+ fMiter = buffer.readScalar();
+ fStyle = buffer.readU8();
+ fJoin = buffer.readU8();
+ fCap = buffer.readU8();
}
///////////////////////////////////////////////////////////////////////////////
SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposePathEffect)
+//SK_DEFINE_FLATTENABLE_REGISTRAR(SkStrokePathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR(SkSumPathEffect)
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index d47c314834..50dbfc52b1 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -625,30 +625,26 @@ void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
path.transform(inverse, &localPath);
// now localPath is only affected by the paint settings, and not the canvas matrix
- SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
-
- if (fRec.fFrameWidth > 0) {
- rec.setStrokeStyle(fRec.fFrameWidth,
- SkToBool(fRec.fFlags & kFrameAndFill_Flag));
- // glyphs are always closed contours, so cap type is ignored,
- // so we just pass something.
- rec.setStrokeParams(SkPaint::kButt_Cap,
- (SkPaint::Join)fRec.fStrokeJoin,
- fRec.fMiterLimit);
- }
-
+ SkScalar width = fRec.fFrameWidth;
+
if (fPathEffect) {
SkPath effectPath;
- if (fPathEffect->filterPath(&effectPath, localPath, &rec)) {
+
+ if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
localPath.swap(effectPath);
}
}
- if (rec.needToApply()) {
- SkPath strokePath;
- if (rec.applyToPath(&strokePath, localPath)) {
- localPath.swap(strokePath);
- }
+ if (width > 0) {
+ SkStroke stroker;
+ SkPath outline;
+
+ stroker.setWidth(width);
+ stroker.setMiterLimit(fRec.fMiterLimit);
+ stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
+ stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
+ stroker.strokePath(localPath, &outline);
+ localPath.swap(outline);
}
// now return stuff to the caller
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 0d3885f0ea..fd7dccc6c7 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -563,38 +563,12 @@ void SkStroke::setJoin(SkPaint::Join join) {
#define APPLY_PROC(proc, pts, count)
#endif
-// If src==dst, then we use a tmp path to record the stroke, and then swap
-// its contents with src when we're done.
-class AutoTmpPath {
-public:
- AutoTmpPath(const SkPath& src, SkPath** dst) : fSrc(src) {
- if (&src == *dst) {
- *dst = &fTmpDst;
- } else {
- (*dst)->reset();
- fSwapWithSrc = false;
- }
- }
-
- ~AutoTmpPath() {
- if (fSwapWithSrc) {
- fTmpDst.swap(*const_cast<SkPath*>(&fSrc));
- }
- }
-
-private:
- SkPath fTmpDst;
- const SkPath& fSrc;
- bool fSwapWithSrc;
-};
-
void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
SkASSERT(&src != NULL && dst != NULL);
SkScalar radius = SkScalarHalf(fWidth);
- AutoTmpPath tmp(src, &dst);
-
+ dst->reset();
if (radius <= 0) {
return;
}
diff --git a/src/effects/Sk1DPathEffect.cpp b/src/effects/Sk1DPathEffect.cpp
index 10a9a8434b..09e8d135b6 100644
--- a/src/effects/Sk1DPathEffect.cpp
+++ b/src/effects/Sk1DPathEffect.cpp
@@ -10,7 +10,7 @@
#include "Sk1DPathEffect.h"
#include "SkPathMeasure.h"
-bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) {
+bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
SkPathMeasure meas(src, false);
do {
SkScalar length = meas.getLength();
@@ -67,10 +67,10 @@ SkPath1DPathEffect::SkPath1DPathEffect(const SkPath& path, SkScalar advance,
}
bool SkPath1DPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkStrokeRec* rec) {
+ SkScalar* width) {
if (fAdvance > 0) {
- rec->setFillStyle();
- return this->INHERITED::filterPath(dst, src, rec);
+ *width = -1;
+ return this->INHERITED::filterPath(dst, src, width);
}
return false;
}
diff --git a/src/effects/Sk2DPathEffect.cpp b/src/effects/Sk2DPathEffect.cpp
index 3f8c998651..8693157f16 100644
--- a/src/effects/Sk2DPathEffect.cpp
+++ b/src/effects/Sk2DPathEffect.cpp
@@ -31,7 +31,7 @@ Sk2DPathEffect::Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) {
fMatrixIsInvertible = mat.invert(&fInverse);
}
-bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) {
+bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
if (!fMatrixIsInvertible) {
return false;
}
diff --git a/src/effects/SkCornerPathEffect.cpp b/src/effects/SkCornerPathEffect.cpp
index 749384d579..474623175b 100644
--- a/src/effects/SkCornerPathEffect.cpp
+++ b/src/effects/SkCornerPathEffect.cpp
@@ -36,7 +36,7 @@ static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius,
}
bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkStrokeRec*) {
+ SkScalar* width) {
if (fRadius == 0) {
return false;
}
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp
index 13c19afab4..0cc97b6b15 100644
--- a/src/effects/SkDashPathEffect.cpp
+++ b/src/effects/SkDashPathEffect.cpp
@@ -81,9 +81,9 @@ SkDashPathEffect::~SkDashPathEffect() {
}
bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkStrokeRec* rec) {
+ SkScalar* width) {
// we do nothing if the src wants to be filled, or if our dashlength is 0
- if (rec->isFillStyle() || fInitialDashLength < 0) {
+ if (*width < 0 || fInitialDashLength < 0) {
return false;
}
diff --git a/src/effects/SkDiscretePathEffect.cpp b/src/effects/SkDiscretePathEffect.cpp
index 0536e5646d..06b9d19c68 100644
--- a/src/effects/SkDiscretePathEffect.cpp
+++ b/src/effects/SkDiscretePathEffect.cpp
@@ -26,8 +26,8 @@ SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviatio
}
bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkStrokeRec* rec) {
- bool doFill = rec->isFillStyle();
+ SkScalar* width) {
+ bool doFill = *width < 0;
SkPathMeasure meas(src, doFill);
uint32_t seed = SkScalarRound(meas.getLength());
diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp
index 81f88311a4..8995d3b1fd 100644
--- a/src/ports/SkGlobalInitialization_default.cpp
+++ b/src/ports/SkGlobalInitialization_default.cpp
@@ -68,6 +68,7 @@ void SkFlattenable::InitializeFlattenables() {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPixelXorXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRectShape)
+// SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStrokePathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShape)