optional res-scale parameter to getFillPath
authorreed <reed@google.com>
Thu, 12 Feb 2015 21:35:52 +0000 (13:35 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 12 Feb 2015 21:35:52 +0000 (13:35 -0800)
BUG=skia:
NOTREECHECKS=True
TBR=

Review URL: https://codereview.chromium.org/911053005

include/core/SkPaint.h
include/core/SkStrokeRec.h
src/core/SkDraw.cpp
src/core/SkPaint.cpp
src/core/SkStroke.cpp
src/core/SkStroke.h
src/core/SkStrokeRec.cpp

index fef4319477ed183dc4c8772cf6bebd45e39b4610..50fe1f4c1df20399760fa26c2aedfd665a9b8ce4 100644 (file)
@@ -512,11 +512,17 @@ public:
      *  @param src  input path
      *  @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 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
      *              drawn with a hairline (width == 0)
      */
-    bool getFillPath(const SkPath& src, SkPath* dst,
-                     const SkRect* cullRect = NULL) const;
+    bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
+                     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.
         <p />
index 68fa14581d31a4ccb952172233a47dbfbd80c761..4858fce28edbc0ec44c64fba00b76ee7a0ad9087 100644 (file)
@@ -21,8 +21,8 @@ public:
     SkStrokeRec(InitStyle style);
 
     SkStrokeRec(const SkStrokeRec&);
-    SkStrokeRec(const SkPaint&, SkPaint::Style);
-    explicit SkStrokeRec(const SkPaint&);
+    SkStrokeRec(const SkPaint&, SkPaint::Style, SkScalar resScale = 1);
+    explicit SkStrokeRec(const SkPaint&, SkScalar resScale = 1);
 
     enum Style {
         kHairline_Style,
@@ -99,9 +99,9 @@ public:
     }
 
 private:
-    void init(const SkPaint& paint, SkPaint::Style style);
-
+    void init(const SkPaint&, SkPaint::Style, SkScalar resScale);
 
+    SkScalar        fResScale;
     SkScalar        fWidth;
     SkScalar        fMiterLimit;
     SkPaint::Cap    fCap;
index c42d3ef9ed6636e3895e426805d8e0b5ad52ba65..03b331108dc27226d5c761e303f4ba3bcc7d89ce 100644 (file)
@@ -1004,6 +1004,17 @@ DRAW_PATH:
     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,
                       const SkMatrix* prePathMatrix, bool pathIsMutable,
                       bool drawCoverage, SkBlitter* customBlitter) const {
@@ -1072,7 +1083,8 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
         if (this->computeConservativeLocalClipBounds(&cullRect)) {
             cullRectPtr = &cullRect;
         }
-        doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
+        doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr,
+                                    compute_res_scale_for_stroking(*fMatrix));
         pathPtr = &tmpPath;
     }
 
index 7c6c8e0109d8f71778f218aec053cf3a16fa9540..5774839ed84c9a888eadb968441c9116a07c06d7 100644 (file)
@@ -2003,9 +2003,9 @@ SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
-                          const SkRect* cullRect) const {
-    SkStrokeRec rec(*this);
+bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
+                          SkScalar resScale) const {
+    SkStrokeRec rec(*this, resScale);
 
     const SkPath* srcPtr = &src;
     SkPath tmpPath;
index f8173c0555ade651cbf15c501f7c33253fc7ce8e..db76cafe35a94925ec19a93488be6cc8e79642ce 100644 (file)
@@ -158,12 +158,12 @@ class SkPathStroker {
 public:
 #if QUAD_STROKE_APPROXIMATION
     SkPathStroker(const SkPath& src,
-                  SkScalar radius, SkScalar miterLimit, SkScalar error, SkPaint::Cap cap,
-                  SkPaint::Join join);
+                  SkScalar radius, SkScalar miterLimit, SkScalar error, SkPaint::Cap,
+                  SkPaint::Join, SkScalar resScale);
 #else
     SkPathStroker(const SkPath& src,
-                  SkScalar radius, SkScalar miterLimit, SkPaint::Cap cap,
-                  SkPaint::Join join);
+                  SkScalar radius, SkScalar miterLimit, SkPaint::Cap,
+                  SkPaint::Join, SkScalar resScale);
 #endif
 
     void moveTo(const SkPoint&);
@@ -178,12 +178,15 @@ public:
         dst->swap(fOuter);
     }
 
+    SkScalar getResScale() const { return fResScale; }
+
 private:
 #if QUAD_STROKE_APPROXIMATION
     SkScalar    fError;
 #endif
     SkScalar    fRadius;
     SkScalar    fInvMiterLimit;
+    SkScalar    fResScale;
 
     SkVector    fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal;
     SkPoint     fFirstPt, fPrevPt;  // on original path
@@ -348,13 +351,13 @@ void SkPathStroker::finishContour(bool close, bool currIsLine) {
 #if QUAD_STROKE_APPROXIMATION
 SkPathStroker::SkPathStroker(const SkPath& src,
                              SkScalar radius, SkScalar miterLimit, SkScalar error,
-                             SkPaint::Cap cap, SkPaint::Join join)
+                             SkPaint::Cap cap, SkPaint::Join join, SkScalar resScale)
 #else
 SkPathStroker::SkPathStroker(const SkPath& src,
                              SkScalar radius, SkScalar miterLimit,
-                             SkPaint::Cap cap, SkPaint::Join join)
+                             SkPaint::Cap cap, SkPaint::Join join, SkScalar resScale)
 #endif
-        : fRadius(radius) {
+        : fRadius(radius), fResScale(resScale) {
 
     /*  This is only used when join is miter_join, but we initialize it here
         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;
-    const SkScalar conicTol = SK_Scalar1 / 4;
+    const SkScalar conicTol = SK_Scalar1 / 4 / fResScale;
 
 #if QUAD_STROKE_APPROXIMATION
     SkPathStroker   stroker(src, radius, fMiterLimit, fError, this->getCap(),
-                            this->getJoin());
+                            this->getJoin(), fResScale);
 #else
-    SkPathStroker   stroker(src, radius, fMiterLimit, this->getCap(),
-                            this->getJoin());
+    SkPathStroker   stroker(src, radius, fMiterLimit, this->getCap(), this->getJoin(), fResScale);
 #endif
     SkPath::Iter    iter(src, false);
     SkPath::Verb    lastSegment = SkPath::kMove_Verb;
index cb329399a91952e67d0f097e59825d5890f8bfc6..a5446a4178fe991e06fefa296e9329c71c38097f 100644 (file)
@@ -52,6 +52,20 @@ public:
     bool    getDoFill() const { return SkToBool(fDoFill); }
     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..
      */
@@ -66,6 +80,7 @@ private:
     SkScalar    fError;
 #endif
     SkScalar    fWidth, fMiterLimit;
+    SkScalar    fResScale;
     uint8_t     fCap, fJoin;
     SkBool8     fDoFill;
 
index 95f56b76a6efadd6df3b082113d68a400f36bf97..c25a652a88e8fe4dc1aa4f3c9f7521419e583bc4 100644 (file)
@@ -12,6 +12,7 @@
 #define kStrokeRec_FillStyleWidth     (-SK_Scalar1)
 
 SkStrokeRec::SkStrokeRec(InitStyle s) {
+    fResScale       = 1;
     fWidth          = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
     fMiterLimit     = SkPaintDefaults_MiterLimit;
     fCap            = SkPaint::kDefault_Cap;
@@ -23,15 +24,17 @@ SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
     memcpy(this, &src, sizeof(src));
 }
 
-SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
-    this->init(paint, paint.getStyle());
+SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) {
+    this->init(paint, paint.getStyle(), resScale);
 }
 
-SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride) {
-    this->init(paint, styleOverride);
+SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) {
+    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) {
         case SkPaint::kFill_Style:
             fWidth = kStrokeRec_FillStyleWidth;
@@ -108,6 +111,7 @@ bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
     stroker.setMiterLimit(fMiterLimit);
     stroker.setWidth(fWidth);
     stroker.setDoFill(fStrokeAndFill);
+    stroker.setResScale(fResScale);
 #if QUAD_STROKE_APPROXIMATION
     stroker.setError(1);
 #endif