From d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8ca Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Thu, 24 May 2012 20:32:22 +0000 Subject: 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 --- bench/DashBench.cpp | 4 +- include/core/SkPathEffect.h | 106 ++-------------- include/effects/Sk1DPathEffect.h | 6 +- include/effects/Sk2DPathEffect.h | 2 +- include/effects/SkCornerPathEffect.h | 2 +- include/effects/SkDashPathEffect.h | 4 +- include/effects/SkDiscretePathEffect.h | 4 +- samplecode/ClockFaceView.cpp | 6 +- samplecode/SampleAll.cpp | 6 +- samplecode/SampleSlides.cpp | 8 +- samplecode/SampleTextEffects.cpp | 6 +- src/core/SkPaint.cpp | 64 +++++++--- src/core/SkPathEffect.cpp | 175 +++++++++++++++------------ src/core/SkScalerContext.cpp | 32 +++-- src/core/SkStroke.cpp | 28 +---- src/effects/Sk1DPathEffect.cpp | 8 +- src/effects/Sk2DPathEffect.cpp | 2 +- src/effects/SkCornerPathEffect.cpp | 2 +- src/effects/SkDashPathEffect.cpp | 4 +- src/effects/SkDiscretePathEffect.cpp | 4 +- src/ports/SkGlobalInitialization_default.cpp | 1 + 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 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(&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) -- cgit v1.2.3