Add SkPDFDeviceFlatenner which extends SkPDFDevice to add support to flatten the path and the text when we have perspective.
prepare to deprecate SkPDFDevice constructor, and route gm and render_pdfs to use SkDocument::Create pdf interface instead. - controlled by a flag
add comments where we are supposed to flatten other features (paint, shaders, ... )

R=reed@google.com, bungeman@google.com, scroggo@google.com, vandebo@chromium.org, bsalomon@google.com

Author: edisonn@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@11751 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 3ee90fe..00fcb64 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -23,6 +23,7 @@
 #include "SkData.h"
 #include "SkDeferredCanvas.h"
 #include "SkDevice.h"
+#include "SkDocument.h"
 #include "SkDrawFilter.h"
 #include "SkForceLinking.h"
 #include "SkGPipe.h"
@@ -33,6 +34,7 @@
 #include "SkPDFRasterizer.h"
 #include "SkPicture.h"
 #include "SkRefCnt.h"
+#include "SkScalar.h"
 #include "SkStream.h"
 #include "SkTArray.h"
 #include "SkTDict.h"
@@ -75,6 +77,7 @@
 #define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
 
 extern bool gSkSuppressFontCachePurgeSpew;
+DECLARE_bool(useDocumentInsteadOfDevice);
 
 #ifdef SK_SUPPORT_PDF
     #include "SkPDFDevice.h"
@@ -627,34 +630,51 @@
         }
     }
 
-    static void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
+    static bool generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
 #ifdef SK_SUPPORT_PDF
         SkMatrix initialTransform = gm->getInitialTransform();
-        SkISize pageSize = gm->getISize();
-        SkPDFDevice* dev = NULL;
-        if (initialTransform.isIdentity()) {
-            dev = new SkPDFDevice(pageSize, pageSize, initialTransform);
+        if (FLAGS_useDocumentInsteadOfDevice) {
+            SkISize pageISize = gm->getISize();
+            SkAutoTUnref<SkDocument> pdfDoc(SkDocument::CreatePDF(&pdf, NULL, encode_to_dct_data));
+
+            if (!pdfDoc.get()) {
+                return false;
+            }
+
+            SkCanvas* canvas = NULL;
+            canvas = pdfDoc->beginPage(SkIntToScalar(pageISize.width()),
+                                       SkIntToScalar(pageISize.height()));
+            canvas->concat(initialTransform);
+
+            invokeGM(gm, canvas, true, false);
+
+            return pdfDoc->close();
         } else {
-            SkRect content = SkRect::MakeWH(SkIntToScalar(pageSize.width()),
-                                            SkIntToScalar(pageSize.height()));
-            initialTransform.mapRect(&content);
-            content.intersect(0, 0, SkIntToScalar(pageSize.width()),
-                              SkIntToScalar(pageSize.height()));
-            SkISize contentSize =
-                SkISize::Make(SkScalarRoundToInt(content.width()),
-                              SkScalarRoundToInt(content.height()));
-            dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
+            SkISize pageSize = gm->getISize();
+            SkPDFDevice* dev = NULL;
+            if (initialTransform.isIdentity()) {
+                dev = new SkPDFDevice(pageSize, pageSize, initialTransform);
+            } else {
+                SkRect content = SkRect::MakeWH(SkIntToScalar(pageSize.width()),
+                                                SkIntToScalar(pageSize.height()));
+                initialTransform.mapRect(&content);
+                content.intersect(0, 0, SkIntToScalar(pageSize.width()),
+                                  SkIntToScalar(pageSize.height()));
+                SkISize contentSize =
+                    SkISize::Make(SkScalarRoundToInt(content.width()),
+                                  SkScalarRoundToInt(content.height()));
+                dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
+            }
+            dev->setDCTEncoder(encode_to_dct_data);
+            SkAutoUnref aur(dev);
+            SkCanvas c(dev);
+            invokeGM(gm, &c, true, false);
+            SkPDFDocument doc;
+            doc.appendPage(dev);
+            doc.emitPDF(&pdf);
         }
-        dev->setDCTEncoder(encode_to_dct_data);
-        SkAutoUnref aur(dev);
-
-        SkCanvas c(dev);
-        invokeGM(gm, &c, true, false);
-
-        SkPDFDocument doc;
-        doc.appendPage(dev);
-        doc.emitPDF(&pdf);
-#endif
+#endif  // SK_SUPPORT_PDF
+        return true; // Do not report failure if pdf is not supported.
     }
 
     static void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
@@ -1048,43 +1068,46 @@
                 errors.add(write_bitmap(path, bitmapAndDigest.fBitmap));
             }
         } else if (gRec.fBackend == kPDF_Backend) {
-            generate_pdf(gm, document);
-
-            SkAutoTUnref<SkStreamAsset> documentStream(document.detachAsStream());
-            if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
-                path = make_filename(writePath, gm->shortName(), gRec.fName, "", "pdf");
-                errors.add(write_document(path, documentStream));
-            }
-
-            if (!(gm->getFlags() & GM::kSkipPDFRasterization_Flag)) {
-                for (int i = 0; i < pdfRasterizers.count(); i++) {
-                    SkBitmap pdfBitmap;
-                    SkASSERT(documentStream->rewind());
-                    bool success = (*pdfRasterizers[i]->fRasterizerFunction)(
-                            documentStream.get(), &pdfBitmap);
-                    if (!success) {
-                        gm_fprintf(stderr, "FAILED to render PDF for %s using renderer %s\n",
-                                   gm->shortName(),
-                                   pdfRasterizers[i]->fName);
-                        continue;
-                    }
-
-                    SkString configName(gRec.fName);
-                    configName.append("-");
-                    configName.append(pdfRasterizers[i]->fName);
-
-                    BitmapAndDigest bitmapAndDigest(pdfBitmap);
-                    errors.add(compare_test_results_to_stored_expectations(
-                               gm, gRec, configName.c_str(), &bitmapAndDigest));
-
-                    if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
-                        path = make_bitmap_filename(writePath, gm->shortName(), configName.c_str(),
-                                                    "", bitmapAndDigest.fDigest);
-                        errors.add(write_bitmap(path, bitmapAndDigest.fBitmap));
-                    }
-                }
+            if (!generate_pdf(gm, document)) {
+                errors.add(kGeneratePdfFailed_ErrorType);
             } else {
-                errors.add(kIntentionallySkipped_ErrorType);
+                SkAutoTUnref<SkStreamAsset> documentStream(document.detachAsStream());
+                if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
+                    path = make_filename(writePath, gm->shortName(), gRec.fName, "", "pdf");
+                    errors.add(write_document(path, documentStream));
+                }
+
+                if (!(gm->getFlags() & GM::kSkipPDFRasterization_Flag)) {
+                    for (int i = 0; i < pdfRasterizers.count(); i++) {
+                        SkBitmap pdfBitmap;
+                        SkASSERT(documentStream->rewind());
+                        bool success = (*pdfRasterizers[i]->fRasterizerFunction)(
+                                documentStream.get(), &pdfBitmap);
+                        if (!success) {
+                            gm_fprintf(stderr, "FAILED to render PDF for %s using renderer %s\n",
+                                       gm->shortName(),
+                                       pdfRasterizers[i]->fName);
+                            continue;
+                        }
+
+                        SkString configName(gRec.fName);
+                        configName.append("-");
+                        configName.append(pdfRasterizers[i]->fName);
+
+                        BitmapAndDigest bitmapAndDigest(pdfBitmap);
+                        errors.add(compare_test_results_to_stored_expectations(
+                                   gm, gRec, configName.c_str(), &bitmapAndDigest));
+
+                        if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
+                            path = make_bitmap_filename(writePath, gm->shortName(),
+                                                        configName.c_str(),
+                                                        "", bitmapAndDigest.fDigest);
+                            errors.add(write_bitmap(path, bitmapAndDigest.fBitmap));
+                        }
+                    }
+                } else {
+                    errors.add(kIntentionallySkipped_ErrorType);
+                }
             }
         } else if (gRec.fBackend == kXPS_Backend) {
             generate_xps(gm, document);
@@ -1446,6 +1469,7 @@
 // Probably define spacial names like centerx, centery, top, bottom, left, right
 // then we can write something reabable like --rotate centerx centery 90
 DEFINE_bool(forcePerspectiveMatrix, false, "Force a perspective matrix.");
+DEFINE_bool(useDocumentInsteadOfDevice, false, "Use SkDocument::CreateFoo instead of SkFooDevice.");
 
 static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
     // Filter output of warnings that JPEG is not available for the image.