SkPDF: better tolerance path conversion to quadratics

BUG=chromium:691386
Change-Id: I2cb9be7dd606b2ba61ff609f9fd81a55655901f6
Reviewed-on: https://skia-review.googlesource.com/8381
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Cary Clark <caryclark@google.com>
diff --git a/gm/crbug_691386.cpp b/gm/crbug_691386.cpp
new file mode 100644
index 0000000..b08c315
--- /dev/null
+++ b/gm/crbug_691386.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkParsePath.h"
+
+DEF_SIMPLE_GM(crbug_691386, canvas, 256, 256) {
+    SkPath path;
+    if (!SkParsePath::FromSVGString("M -1 0 A 1 1 0 0 0 1 0 Z", &path)) {
+        return;
+    }
+    SkPaint p;
+    p.setStyle(SkPaint::kStroke_Style);
+    p.setStrokeWidth(0.025f);
+    canvas->scale(96.0f, 96.0f);
+    canvas->translate(1.25f, 1.25f);
+    canvas->drawPath(path, p);
+}
diff --git a/gn/gm.gni b/gn/gm.gni
index be3a482..fc3fc03 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -84,6 +84,7 @@
   "$_gm/convexpolyclip.cpp",
   "$_gm/convexpolyeffect.cpp",
   "$_gm/copyTo4444.cpp",
+  "$_gm/crbug_691386.cpp",
   "$_gm/croppedrects.cpp",
   "$_gm/cubicpaths.cpp",
   "$_gm/dashcircle.cpp",
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 6da4d3b..48c8a9d 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -781,13 +781,16 @@
     if (!content.entry()) {
         return;
     }
+    SkScalar matrixScale = matrix.mapRadius(1.0f);
+    SkScalar tolerance = matrixScale > 0.0f ? 0.25f / matrixScale : 0.25f;
     bool consumeDegeratePathSegments =
            paint.getStyle() == SkPaint::kFill_Style ||
            (paint.getStrokeCap() != SkPaint::kRound_Cap &&
             paint.getStrokeCap() != SkPaint::kSquare_Cap);
     SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
                          consumeDegeratePathSegments,
-                         &content.entry()->fContent);
+                         &content.entry()->fContent,
+                         tolerance);
     SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
                           &content.entry()->fContent);
 }
diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp
index 189bc5c..2487043 100644
--- a/src/pdf/SkPDFUtils.cpp
+++ b/src/pdf/SkPDFUtils.cpp
@@ -117,7 +117,8 @@
 
 // static
 void SkPDFUtils::EmitPath(const SkPath& path, SkPaint::Style paintStyle,
-                          bool doConsumeDegerates, SkWStream* content) {
+                          bool doConsumeDegerates, SkWStream* content,
+                          SkScalar tolerance) {
     // Filling a path with no area results in a drawing in PDF renderers but
     // Chrome expects to be able to draw some such entities with no visible
     // result, so we detect those cases and discard the drawing for them.
@@ -131,7 +132,7 @@
     {
         SkPDFUtils::AppendRectangle(rect, content);
         return;
-    }    
+    }
 
     enum SkipFillState {
         kEmpty_SkipFillState,
@@ -169,9 +170,8 @@
                 fillState = kNonSingleLine_SkipFillState;
                 break;
             case SkPath::kConic_Verb: {
-                const SkScalar tol = SK_Scalar1 / 4;
                 SkAutoConicToQuads converter;
-                const SkPoint* quads = converter.computeQuads(args, iter.conicWeight(), tol);
+                const SkPoint* quads = converter.computeQuads(args, iter.conicWeight(), tolerance);
                 for (int i = 0; i < converter.countQuads(); ++i) {
                     append_quad(&quads[i * 2], &currentSegment);
                 }
@@ -183,9 +183,7 @@
                 fillState = kNonSingleLine_SkipFillState;
                 break;
             case SkPath::kClose_Verb:
-
-                    ClosePath(&currentSegment);
-
+                ClosePath(&currentSegment);
                 currentSegment.writeToStream(content);
                 currentSegment.reset();
                 break;
diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h
index 964689f..5c9e46b 100644
--- a/src/pdf/SkPDFUtils.h
+++ b/src/pdf/SkPDFUtils.h
@@ -45,10 +45,10 @@
                  SkScalar dstX, SkScalar dstY, SkWStream* content);
 void AppendRectangle(const SkRect& rect, SkWStream* content);
 void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
-                     bool doConsumeDegerates, SkWStream* content);
+              bool doConsumeDegerates, SkWStream* content, SkScalar tolerance = 0.25f);
 inline void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
-                     SkWStream* content) {
-    SkPDFUtils::EmitPath(path, paintStyle, true, content);
+                     SkWStream* content, SkScalar tolerance = 0.25f) {
+    SkPDFUtils::EmitPath(path, paintStyle, true, content, tolerance);
 }
 void ClosePath(SkWStream* content);
 void PaintPath(SkPaint::Style style, SkPath::FillType fill,