Inverse fill support in PDF

BUG= https://code.google.com/p/skia/issues/detail?id=241 (partial fix)
R=edisonn@google.com, vandebo@chromium.org, reed@google.com

Author: richardlin@chromium.org

Review URL: https://chromiumcodereview.appspot.com/19519017

git-svn-id: http://skia.googlecode.com/svn/trunk@10476 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/inversepaths.cpp b/gm/inversepaths.cpp
new file mode 100644
index 0000000..dc2b636
--- /dev/null
+++ b/gm/inversepaths.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2013 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 "SkCanvas.h"
+#include "SkPath.h"
+
+namespace skiagm {
+
+static SkPath generate_square(SkScalar cx, SkScalar cy, SkScalar w) {
+    SkRect rect = SkRect::MakeXYWH(cx - w / 2, cy - w / 2, w, w);
+    SkPath path;
+    path.addRect(rect);
+    return path;
+}
+
+static SkPath generate_rect_line(SkScalar cx, SkScalar cy, SkScalar l) {
+    SkRect rect = SkRect::MakeXYWH(cx - l / 2, cy, l, 0);
+    SkPath path;
+    path.addRect(rect);
+    return path;
+}
+
+static SkPath generate_circle(SkScalar cx, SkScalar cy, SkScalar d) {
+    SkPath path;
+    path.addCircle(cx, cy, d/2, SkPath::kCW_Direction);
+    return path;
+}
+
+static SkPath generate_line(SkScalar cx, SkScalar cy, SkScalar l) {
+    SkPath path;
+    path.moveTo(cx - l / 2, cy);
+    path.lineTo(cx + l / 2, cy);
+    return path;
+}
+
+SkPaint::Style styles[] = {
+        SkPaint::kStroke_Style,
+        SkPaint::kStrokeAndFill_Style,
+        SkPaint::kFill_Style
+};
+SkScalar pathSizes[] = {
+        40,
+        10,
+        0
+};
+SkScalar strokeWidths[] = {
+        10,
+        0
+};
+SkPath ((*paths[])(SkScalar, SkScalar, SkScalar)) = {
+        generate_square,
+        generate_rect_line,
+        generate_circle,
+        generate_line
+};
+
+const SkScalar slideWidth = 90, slideHeight = 90;
+const SkScalar slideBoundary = 5;
+
+
+class InversePathsGM : public GM {
+public:
+    InversePathsGM() {
+
+    }
+
+protected:
+    virtual SkString onShortName() {
+        return SkString("inverse_paths");
+    }
+
+    virtual SkISize onISize() {
+        return make_isize(800, 900);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) {
+        SkScalar cx = slideWidth / 2 + slideBoundary;
+        SkScalar cy = slideHeight / 2 + slideBoundary;
+        SkScalar dx = slideWidth + 2 * slideBoundary;
+        SkScalar dy = slideHeight + 2 * slideBoundary;
+
+        SkRect clipRect = SkRect::MakeLTRB(slideBoundary, slideBoundary,
+                                           slideBoundary + slideWidth,
+                                           slideBoundary + slideHeight);
+        SkPaint clipPaint;
+        clipPaint.setStyle(SkPaint::kStroke_Style);
+        clipPaint.setStrokeWidth(SkIntToScalar(2));
+
+        SkPaint outlinePaint;
+        outlinePaint.setColor(0x40000000);
+        outlinePaint.setStyle(SkPaint::kStroke_Style);
+        outlinePaint.setStrokeWidth(SkIntToScalar(0));
+
+        for (size_t styleIndex = 0; styleIndex < SK_ARRAY_COUNT(styles);
+                styleIndex++) {
+            for (size_t sizeIndex = 0; sizeIndex < SK_ARRAY_COUNT(pathSizes);
+                    sizeIndex++) {
+                SkScalar size = pathSizes[sizeIndex];
+
+                canvas->save();
+
+                for (size_t widthIndex = 0;
+                        widthIndex < SK_ARRAY_COUNT(strokeWidths);
+                        widthIndex++) {
+                    SkPaint paint;
+                    paint.setColor(0xff007000);
+                    paint.setStrokeWidth(strokeWidths[widthIndex]);
+                    paint.setStyle(styles[styleIndex]);
+
+                    for (size_t pathIndex = 0;
+                            pathIndex < SK_ARRAY_COUNT(paths);
+                            pathIndex++) {
+                        canvas->drawRect(clipRect, clipPaint);
+
+                        canvas->save();
+                        canvas->clipRect(clipRect);
+
+                        SkPath path = paths[pathIndex](cx, cy, size);
+                        path.setFillType(SkPath::kInverseWinding_FillType);
+                        canvas->drawPath(path, paint);
+
+                        path.setFillType(SkPath::kWinding_FillType);
+                        canvas->drawPath(path, outlinePaint);
+
+                        canvas->restore();
+                        canvas->translate(dx, 0);
+                    }
+                }
+
+                canvas->restore();
+                canvas->translate(0, dy);
+            }
+        }
+    }
+
+private:
+    typedef GM INHERITED;
+};
+
+DEF_GM( return new InversePathsGM; )
+}