[PDF] Ensure that filling single line paths (with no area) does not draw anything.

Add a test to a gm to confirm the new behavior.

Fixes http://crbug.com/123072

Review URL: https://codereview.appspot.com/6137060

git-svn-id: http://skia.googlecode.com/svn/trunk@3884 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 733a612..8591728 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -262,7 +262,7 @@
 
     SkPath::FillType clipFill;
     if (clipPath) {
-        SkPDFUtils::EmitPath(*clipPath, contentStream);
+        SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream);
         clipFill = clipPath->getFillType();
     } else {
         SkPDFUtils::AppendRectangle(*clipRect, contentStream);
@@ -765,7 +765,8 @@
     if (!content.entry()) {
         return;
     }
-    SkPDFUtils::EmitPath(*pathPtr, &content.entry()->fContent);
+    SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
+                         &content.entry()->fContent);
     SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
                           &content.entry()->fContent);
 }
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index e0e18cd..35394b6 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -1378,7 +1378,7 @@
                                     &content);
         const SkPath* path = cache->findPath(glyph);
         if (path) {
-            SkPDFUtils::EmitPath(*path, &content);
+            SkPDFUtils::EmitPath(*path, paint.getStyle(), &content);
             SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(),
                                   &content);
         }
diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp
index b596a27..8cd3a90 100644
--- a/src/pdf/SkPDFUtils.cpp
+++ b/src/pdf/SkPDFUtils.cpp
@@ -7,6 +7,7 @@
  */
 
 
+#include "SkData.h"
 #include "SkGeometry.h"
 #include "SkPaint.h"
 #include "SkPath.h"
@@ -98,7 +99,23 @@
 }
 
 // static
-void SkPDFUtils::EmitPath(const SkPath& path, SkWStream* content) {
+void SkPDFUtils::EmitPath(const SkPath& path, SkPaint::Style paintStyle,
+                          SkWStream* content) {
+    // 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.
+    // Specifically: moveTo(X), lineTo(Y) and moveTo(X), lineTo(X), lineTo(Y).
+    enum SkipFillState {
+        kEmpty_SkipFillState         = 0,
+        kSingleLine_SkipFillState    = 1,
+        kNonSingleLine_SkipFillState = 2,
+    };
+    SkipFillState fillState = kEmpty_SkipFillState;
+    if (paintStyle != SkPaint::kFill_Style) {
+        fillState = kNonSingleLine_SkipFillState;
+    }
+    SkPoint lastMovePt;
+    SkDynamicMemoryWStream currentSegment;
     SkPoint args[4];
     SkPath::Iter iter(path, false);
     for (SkPath::Verb verb = iter.next(args);
@@ -107,30 +124,52 @@
         // args gets all the points, even the implicit first point.
         switch (verb) {
             case SkPath::kMove_Verb:
-                MoveTo(args[0].fX, args[0].fY, content);
+                MoveTo(args[0].fX, args[0].fY, &currentSegment);
+                lastMovePt = args[0];
+                fillState = kEmpty_SkipFillState;
                 break;
             case SkPath::kLine_Verb:
-                AppendLine(args[1].fX, args[1].fY, content);
+                AppendLine(args[1].fX, args[1].fY, &currentSegment);
+                if (fillState == kEmpty_SkipFillState) {
+                   if (args[0] != lastMovePt) {
+                       fillState = kSingleLine_SkipFillState;
+                   }
+                } else if (fillState == kSingleLine_SkipFillState) {
+                    fillState = kNonSingleLine_SkipFillState;
+                }
                 break;
             case SkPath::kQuad_Verb: {
                 SkPoint cubic[4];
                 SkConvertQuadToCubic(args, cubic);
                 AppendCubic(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY,
-                            cubic[3].fX, cubic[3].fY, content);
+                            cubic[3].fX, cubic[3].fY, &currentSegment);
+                fillState = kNonSingleLine_SkipFillState;
                 break;
             }
             case SkPath::kCubic_Verb:
                 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
-                            args[3].fX, args[3].fY, content);
+                            args[3].fX, args[3].fY, &currentSegment);
+                fillState = kNonSingleLine_SkipFillState;
                 break;
             case SkPath::kClose_Verb:
-                ClosePath(content);
+                if (fillState != kSingleLine_SkipFillState) {
+                    ClosePath(&currentSegment);
+                    SkData* data = currentSegment.copyToData();
+                    content->write(data->data(), data->size());
+                    data->unref();
+                }
+                currentSegment.reset();
                 break;
             default:
                 SkASSERT(false);
                 break;
         }
     }
+    if (currentSegment.bytesWritten() > 0) {
+        SkData* data = currentSegment.copyToData();
+        content->write(data->data(), data->size());
+        data->unref();
+    }
 }
 
 // static
diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h
index 5b9d74e..1bce614 100644
--- a/src/pdf/SkPDFUtils.h
+++ b/src/pdf/SkPDFUtils.h
@@ -10,6 +10,7 @@
 #ifndef SkPDFUtils_DEFINED
 #define SkPDFUtils_DEFINED
 
+#include "SkPaint.h"
 #include "SkPath.h"
 
 class SkMatrix;
@@ -42,7 +43,8 @@
                             SkScalar ctl2X, SkScalar ctl2Y,
                             SkScalar dstX, SkScalar dstY, SkWStream* content);
     static void AppendRectangle(const SkRect& rect, SkWStream* content);
-    static void EmitPath(const SkPath& path, SkWStream* content);
+    static void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
+                         SkWStream* content);
     static void ClosePath(SkWStream* content);
     static void PaintPath(SkPaint::Style style, SkPath::FillType fill,
                           SkWStream* content);