virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
SkPath dst;
for (int i = 0; i < N; ++i) {
- SkScalar width = 0;
+ SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
- fPE->filterPath(&dst, fPath, &width);
+ fPE->filterPath(&dst, fPath, &rec);
dst.rewind();
}
}
#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 fMiterLimit; }
+ 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();
+ 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
public:
SkPathEffect() {}
- /** 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;
+ /**
+ * 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;
/**
* Compute a conservative bounds for its effect, given the src bounds.
SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner)
: INHERITED(outer, inner) {}
- // overrides
-
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
SkSumPathEffect(SkPathEffect* first, SkPathEffect* second)
: INHERITED(first, second) {}
- // overrides
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
// This class is not exported to java.
class Sk1DPathEffect : public SkPathEffect {
public:
- // override from SkPathEffect
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
protected:
/** Called at the start of each contour, returns the initial offset
*/
SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style);
- // override from SkPathEffect
- virtual bool filterPath(SkPath*, const SkPath&, SkScalar* width) SK_OVERRIDE;
+ virtual bool filterPath(SkPath*, const SkPath&, SkStrokeRec*) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath1DPathEffect)
Sk2DPathEffect(const SkMatrix& mat);
// overrides
- virtual bool filterPath(SkPath*, const SkPath&, SkScalar* width) SK_OVERRIDE;
+ virtual bool filterPath(SkPath*, const SkPath&, SkStrokeRec*) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk2DPathEffect)
// overrides for SkPathEffect
// This method is not exported to java.
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCornerPathEffect)
SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase, bool scaleToFit = false);
virtual ~SkDashPathEffect();
- // overrides for SkPathEffect
- // This method is not exported to java.
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
// overrides for SkFlattenable
// This method is not exported to java.
*/
SkDiscretePathEffect(SkScalar segLength, SkScalar deviation);
- // overrides for SkPathEffect
- // This method is not exported to java.
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width);
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect)
class InverseFillPE : public SkPathEffect {
public:
InverseFillPE() {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) SK_OVERRIDE {
*dst = src;
dst->setFillType(SkPath::kInverseWinding_FillType);
return true;
SkTDArray<SkPoint> pts;
SkPathEffect* pe = makepe(0, &pts);
- SkScalar width = -1;
+ SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
SkPath path, dstPath;
orig.getTextPath("9", 1, 0, 0, &path);
- pe->filterPath(&dstPath, path, &width);
+ pe->filterPath(&dstPath, path, &rec);
SkPaint p;
p.setAntiAlias(true);
Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
: Sk2DPathEffect(matrix), fWidth(width) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
- if (this->INHERITED::filterPath(dst, src, width)) {
- *width = fWidth;
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
+ if (this->INHERITED::filterPath(dst, src, rec)) {
+ rec->setStrokeStyle(fWidth);
return true;
}
return false;
Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
: Sk2DPathEffect(matrix), fWidth(width) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
- {
- if (this->INHERITED::filterPath(dst, src, width))
- {
- *width = fWidth;
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
+ if (this->INHERITED::filterPath(dst, src, rec)) {
+ rec->setStrokeStyle(fWidth);
return true;
}
return false;
Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
: Sk2DPathEffect(matrix), fWidth(width) {}
- virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
- if (this->INHERITED::filterPath(dst, src, width)) {
- *width = fWidth;
+ virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
+ if (this->INHERITED::filterPath(dst, src, rec)) {
+ rec->setStrokeStyle(fWidth);
return true;
}
return false;
///////////////////////////////////////////////////////////////////////////////
bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
- SkPath effectPath, strokePath;
- const SkPath* path = &src;
+ SkStrokeRec rec(*this);
- SkScalar width = this->getStrokeWidth();
+ const SkPath* srcPtr = &src;
+ SkPath 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 (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec)) {
+ srcPtr = &tmpPath;
}
- 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 (!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 (width > 0 && !path->isEmpty()) {
- SkStroke stroker(*this, width);
- stroker.strokePath(*path, &strokePath);
- path = &strokePath;
- }
-
- 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)
+ return !rec.isHairlineStyle();
}
const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
#include "SkPathEffect.h"
#include "SkPath.h"
#include "SkBuffer.h"
+#include "SkPaintDefaults.h"
+
+// must be < 0, since ==0 means hairline, and >0 means normal stroke
+#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;
+ }
+}
+
+void SkStrokeRec::setFillStyle() {
+ fWidth = kStrokeRec_FillStyleWidth;
+}
+
+#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;
///////////////////////////////////////////////////////////////////////////////
bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkScalar* width) {
+ SkStrokeRec* rec) {
// we may have failed to unflatten these, so we have to check
if (!fPE0 || !fPE1) {
return false;
SkPath tmp;
const SkPath* ptr = &src;
- if (fPE1->filterPath(&tmp, src, width)) {
+ if (fPE1->filterPath(&tmp, src, rec)) {
ptr = &tmp;
}
- return fPE0->filterPath(dst, *ptr, width);
+ return fPE0->filterPath(dst, *ptr, rec);
}
///////////////////////////////////////////////////////////////////////////////
bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkScalar* width) {
+ SkStrokeRec* rec) {
// use bit-or so that we always call both, even if the first one succeeds
- 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();
+ return fPE0->filterPath(dst, src, rec) | fPE1->filterPath(dst, src, rec);
}
///////////////////////////////////////////////////////////////////////////////
SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposePathEffect)
-//SK_DEFINE_FLATTENABLE_REGISTRAR(SkStrokePathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR(SkSumPathEffect)
path.transform(inverse, &localPath);
// now localPath is only affected by the paint settings, and not the canvas matrix
- SkScalar width = fRec.fFrameWidth;
-
+ 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);
+ }
+
if (fPathEffect) {
SkPath effectPath;
-
- if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
+ if (fPathEffect->filterPath(&effectPath, localPath, &rec)) {
localPath.swap(effectPath);
}
}
- 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);
+ if (rec.needToApply()) {
+ SkPath strokePath;
+ if (rec.applyToPath(&strokePath, localPath)) {
+ localPath.swap(strokePath);
+ }
}
// now return stuff to the caller
#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;
+ fSwapWithSrc = true;
+ } 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);
- dst->reset();
+ AutoTmpPath tmp(src, &dst);
+
if (radius <= 0) {
return;
}
#include "Sk1DPathEffect.h"
#include "SkPathMeasure.h"
-bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
+bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) {
SkPathMeasure meas(src, false);
do {
SkScalar length = meas.getLength();
}
bool SkPath1DPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkScalar* width) {
+ SkStrokeRec* rec) {
if (fAdvance > 0) {
- *width = -1;
- return this->INHERITED::filterPath(dst, src, width);
+ rec->setFillStyle();
+ return this->INHERITED::filterPath(dst, src, rec);
}
return false;
}
fMatrixIsInvertible = mat.invert(&fInverse);
}
-bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
+bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*) {
if (!fMatrixIsInvertible) {
return false;
}
}
bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkScalar* width) {
+ SkStrokeRec*) {
if (fRadius == 0) {
return false;
}
}
bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkScalar* width) {
+ SkStrokeRec* rec) {
// we do nothing if the src wants to be filled, or if our dashlength is 0
- if (*width < 0 || fInitialDashLength < 0) {
+ if (rec->isFillStyle() || fInitialDashLength < 0) {
return false;
}
}
bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
- SkScalar* width) {
- bool doFill = *width < 0;
+ SkStrokeRec* rec) {
+ bool doFill = rec->isFillStyle();
SkPathMeasure meas(src, doFill);
uint32_t seed = SkScalarRound(meas.getLength());
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)