optional res-scale parameter to getFillPath

BUG=skia:
NOTREECHECKS=True
TBR=

Review URL: https://codereview.chromium.org/911053005
This commit is contained in:
reed 2015-02-12 13:35:52 -08:00 committed by Commit bot
parent 3a092042bc
commit 05d9044de4
7 changed files with 65 additions and 26 deletions

View File

@ -512,11 +512,17 @@ public:
* @param src input path * @param src input path
* @param dst output path (may be the same as src) * @param dst output path (may be the same as src)
* @param cullRect If not null, the dst path may be culled to this rect. * @param cullRect If not null, the dst path may be culled to this rect.
* @param resScale If > 1, increase precision, else if (0 < res < 1) reduce precision
* in favor of speed/size.
* @return true if the path should be filled, or false if it should be * @return true if the path should be filled, or false if it should be
* drawn with a hairline (width == 0) * drawn with a hairline (width == 0)
*/ */
bool getFillPath(const SkPath& src, SkPath* dst, bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
const SkRect* cullRect = NULL) const; SkScalar resScale = 1) const;
bool getFillPath(const SkPath& src, SkPath* dst) const {
return this->getFillPath(src, dst, NULL, 1);
}
/** Get the paint's shader object. /** Get the paint's shader object.
<p /> <p />

View File

@ -21,8 +21,8 @@ public:
SkStrokeRec(InitStyle style); SkStrokeRec(InitStyle style);
SkStrokeRec(const SkStrokeRec&); SkStrokeRec(const SkStrokeRec&);
SkStrokeRec(const SkPaint&, SkPaint::Style); SkStrokeRec(const SkPaint&, SkPaint::Style, SkScalar resScale = 1);
explicit SkStrokeRec(const SkPaint&); explicit SkStrokeRec(const SkPaint&, SkScalar resScale = 1);
enum Style { enum Style {
kHairline_Style, kHairline_Style,
@ -99,9 +99,9 @@ public:
} }
private: private:
void init(const SkPaint& paint, SkPaint::Style style); void init(const SkPaint&, SkPaint::Style, SkScalar resScale);
SkScalar fResScale;
SkScalar fWidth; SkScalar fWidth;
SkScalar fMiterLimit; SkScalar fMiterLimit;
SkPaint::Cap fCap; SkPaint::Cap fCap;

View File

@ -1004,6 +1004,17 @@ DRAW_PATH:
this->drawPath(path, paint, NULL, true); this->drawPath(path, paint, NULL, true);
} }
static SkScalar compute_res_scale_for_stroking(const SkMatrix& matrix) {
if (!matrix.hasPerspective()) {
SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]);
SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]);
if (SkScalarsAreFinite(sx, sy)) {
return SkTMax(sx, sy);
}
}
return 1;
}
void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
const SkMatrix* prePathMatrix, bool pathIsMutable, const SkMatrix* prePathMatrix, bool pathIsMutable,
bool drawCoverage, SkBlitter* customBlitter) const { bool drawCoverage, SkBlitter* customBlitter) const {
@ -1072,7 +1083,8 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
if (this->computeConservativeLocalClipBounds(&cullRect)) { if (this->computeConservativeLocalClipBounds(&cullRect)) {
cullRectPtr = &cullRect; cullRectPtr = &cullRect;
} }
doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr); doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr,
compute_res_scale_for_stroking(*fMatrix));
pathPtr = &tmpPath; pathPtr = &tmpPath;
} }

View File

@ -2003,9 +2003,9 @@ SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
const SkRect* cullRect) const { SkScalar resScale) const {
SkStrokeRec rec(*this); SkStrokeRec rec(*this, resScale);
const SkPath* srcPtr = &src; const SkPath* srcPtr = &src;
SkPath tmpPath; SkPath tmpPath;

View File

@ -158,12 +158,12 @@ class SkPathStroker {
public: public:
#if QUAD_STROKE_APPROXIMATION #if QUAD_STROKE_APPROXIMATION
SkPathStroker(const SkPath& src, SkPathStroker(const SkPath& src,
SkScalar radius, SkScalar miterLimit, SkScalar error, SkPaint::Cap cap, SkScalar radius, SkScalar miterLimit, SkScalar error, SkPaint::Cap,
SkPaint::Join join); SkPaint::Join, SkScalar resScale);
#else #else
SkPathStroker(const SkPath& src, SkPathStroker(const SkPath& src,
SkScalar radius, SkScalar miterLimit, SkPaint::Cap cap, SkScalar radius, SkScalar miterLimit, SkPaint::Cap,
SkPaint::Join join); SkPaint::Join, SkScalar resScale);
#endif #endif
void moveTo(const SkPoint&); void moveTo(const SkPoint&);
@ -178,12 +178,15 @@ public:
dst->swap(fOuter); dst->swap(fOuter);
} }
SkScalar getResScale() const { return fResScale; }
private: private:
#if QUAD_STROKE_APPROXIMATION #if QUAD_STROKE_APPROXIMATION
SkScalar fError; SkScalar fError;
#endif #endif
SkScalar fRadius; SkScalar fRadius;
SkScalar fInvMiterLimit; SkScalar fInvMiterLimit;
SkScalar fResScale;
SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal; SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal;
SkPoint fFirstPt, fPrevPt; // on original path SkPoint fFirstPt, fPrevPt; // on original path
@ -348,13 +351,13 @@ void SkPathStroker::finishContour(bool close, bool currIsLine) {
#if QUAD_STROKE_APPROXIMATION #if QUAD_STROKE_APPROXIMATION
SkPathStroker::SkPathStroker(const SkPath& src, SkPathStroker::SkPathStroker(const SkPath& src,
SkScalar radius, SkScalar miterLimit, SkScalar error, SkScalar radius, SkScalar miterLimit, SkScalar error,
SkPaint::Cap cap, SkPaint::Join join) SkPaint::Cap cap, SkPaint::Join join, SkScalar resScale)
#else #else
SkPathStroker::SkPathStroker(const SkPath& src, SkPathStroker::SkPathStroker(const SkPath& src,
SkScalar radius, SkScalar miterLimit, SkScalar radius, SkScalar miterLimit,
SkPaint::Cap cap, SkPaint::Join join) SkPaint::Cap cap, SkPaint::Join join, SkScalar resScale)
#endif #endif
: fRadius(radius) { : fRadius(radius), fResScale(resScale) {
/* This is only used when join is miter_join, but we initialize it here /* This is only used when join is miter_join, but we initialize it here
so that it is always defined, to fis valgrind warnings. so that it is always defined, to fis valgrind warnings.
@ -1429,14 +1432,13 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
} }
SkAutoConicToQuads converter; SkAutoConicToQuads converter;
const SkScalar conicTol = SK_Scalar1 / 4; const SkScalar conicTol = SK_Scalar1 / 4 / fResScale;
#if QUAD_STROKE_APPROXIMATION #if QUAD_STROKE_APPROXIMATION
SkPathStroker stroker(src, radius, fMiterLimit, fError, this->getCap(), SkPathStroker stroker(src, radius, fMiterLimit, fError, this->getCap(),
this->getJoin()); this->getJoin(), fResScale);
#else #else
SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), this->getJoin(), fResScale);
this->getJoin());
#endif #endif
SkPath::Iter iter(src, false); SkPath::Iter iter(src, false);
SkPath::Verb lastSegment = SkPath::kMove_Verb; SkPath::Verb lastSegment = SkPath::kMove_Verb;

View File

@ -52,6 +52,20 @@ public:
bool getDoFill() const { return SkToBool(fDoFill); } bool getDoFill() const { return SkToBool(fDoFill); }
void setDoFill(bool doFill) { fDoFill = SkToU8(doFill); } void setDoFill(bool doFill) { fDoFill = SkToU8(doFill); }
/**
* ResScale is the "intended" resolution for the output.
* Default is 1.0.
* Larger values (res > 1) indicate that the result should be more precise, since it will
* be zoomed up, and small errors will be magnified.
* Smaller values (0 < res < 1) indicate that the result can be less precise, since it will
* be zoomed down, and small errors may be invisible.
*/
SkScalar getResScale() const { return fResScale; }
void setResScale(SkScalar rs) {
SkASSERT(rs > 0 && SkScalarIsFinite(rs));
fResScale = rs;
}
/** /**
* Stroke the specified rect, winding it in the specified direction.. * Stroke the specified rect, winding it in the specified direction..
*/ */
@ -66,6 +80,7 @@ private:
SkScalar fError; SkScalar fError;
#endif #endif
SkScalar fWidth, fMiterLimit; SkScalar fWidth, fMiterLimit;
SkScalar fResScale;
uint8_t fCap, fJoin; uint8_t fCap, fJoin;
SkBool8 fDoFill; SkBool8 fDoFill;

View File

@ -12,6 +12,7 @@
#define kStrokeRec_FillStyleWidth (-SK_Scalar1) #define kStrokeRec_FillStyleWidth (-SK_Scalar1)
SkStrokeRec::SkStrokeRec(InitStyle s) { SkStrokeRec::SkStrokeRec(InitStyle s) {
fResScale = 1;
fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0; fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
fMiterLimit = SkPaintDefaults_MiterLimit; fMiterLimit = SkPaintDefaults_MiterLimit;
fCap = SkPaint::kDefault_Cap; fCap = SkPaint::kDefault_Cap;
@ -23,15 +24,17 @@ SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
memcpy(this, &src, sizeof(src)); memcpy(this, &src, sizeof(src));
} }
SkStrokeRec::SkStrokeRec(const SkPaint& paint) { SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) {
this->init(paint, paint.getStyle()); this->init(paint, paint.getStyle(), resScale);
} }
SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride) { SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) {
this->init(paint, styleOverride); this->init(paint, styleOverride, resScale);
} }
void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style) { void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) {
fResScale = resScale;
switch (style) { switch (style) {
case SkPaint::kFill_Style: case SkPaint::kFill_Style:
fWidth = kStrokeRec_FillStyleWidth; fWidth = kStrokeRec_FillStyleWidth;
@ -108,6 +111,7 @@ bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
stroker.setMiterLimit(fMiterLimit); stroker.setMiterLimit(fMiterLimit);
stroker.setWidth(fWidth); stroker.setWidth(fWidth);
stroker.setDoFill(fStrokeAndFill); stroker.setDoFill(fStrokeAndFill);
stroker.setResScale(fResScale);
#if QUAD_STROKE_APPROXIMATION #if QUAD_STROKE_APPROXIMATION
stroker.setError(1); stroker.setError(1);
#endif #endif