revert 4046 -- GM:pathfill failed on one bot, maybe uninitialized memory somewhere?

git-svn-id: http://skia.googlecode.com/svn/trunk@4047 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-05-24 20:32:22 +00:00
parent 9797272edf
commit d3521f1a8d
21 changed files with 213 additions and 261 deletions

View File

@ -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();
}
}

View File

@ -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.
/** 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, SkStrokeRec*) = 0;
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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
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;
}
if (path == &src) {
*dst = src;
} else {
*dst = *srcPtr;
SkASSERT(path == &effectPath || path == &strokePath);
dst->swap(*(SkPath*)path);
}
}
return !rec.isHairlineStyle();
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
}
const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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());

View File

@ -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)