зеркало из https://github.com/mozilla/moz-skia.git
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:
Родитель
9797272edf
Коммит
d3521f1a8d
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !rec.isHairlineStyle();
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче