Index: dm/DMPDFTask.cpp |
diff --git a/dm/DMPDFTask.cpp b/dm/DMPDFTask.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3102478c2fe5af2fb92bd568da1fed0bb413c284 |
--- /dev/null |
+++ b/dm/DMPDFTask.cpp |
@@ -0,0 +1,106 @@ |
+/* |
+ * Copyright 2014 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "DMPDFTask.h" |
+#include "DMPDFRasterizeTask.h" |
+#include "DMUtil.h" |
+#include "DMWriteTask.h" |
+#include "SkCommandLineFlags.h" |
+#include "SkDocument.h" |
+ |
+// The PDF backend is not threadsafe. If you run dm with --pdf repeatedly, you |
+// will quickly find yourself crashed. (while catchsegv out/Release/dm;; end). |
+// |
+// TODO(mtklein): re-enable by default, maybe moving to its own single thread. |
+DEFINE_bool(pdf, false, "PDF backend master switch."); |
+ |
+namespace DM { |
+ |
+PDFTask::PDFTask(const char* config, |
+ Reporter* reporter, |
+ TaskRunner* taskRunner, |
+ skiagm::GMRegistry::Factory factory, |
+ RasterizePdfProc rasterizePdfProc) |
+ : CpuTask(reporter, taskRunner) |
+ , fGM(factory(NULL)) |
+ , fName(UnderJoin(fGM->getName(), config)) |
+ , fRasterize(rasterizePdfProc) {} |
+ |
+PDFTask::PDFTask(Reporter* reporter, |
+ TaskRunner* taskRunner, |
+ const SkPicture* picture, |
+ SkString filename, |
+ RasterizePdfProc rasterizePdfProc) |
+ : CpuTask(reporter, taskRunner) |
+ , fPicture(SkRef(picture)) |
+ , fName(UnderJoin(FileToTaskName(filename).c_str(), "pdf")) |
+ , fRasterize(rasterizePdfProc) {} |
+ |
+namespace { |
+ |
+class SinglePagePDF { |
+public: |
+ SinglePagePDF(SkScalar width, SkScalar height) |
+ : fDocument(SkDocument::CreatePDF(&fWriteStream)) |
+ , fCanvas(fDocument->beginPage(width, height)) {} |
+ |
+ SkCanvas* canvas() { return fCanvas; } |
+ |
+ SkStreamAsset* end() { |
+ fCanvas->flush(); |
+ fDocument->endPage(); |
+ fDocument->close(); |
+ return fWriteStream.detachAsStream(); |
+ } |
+ |
+private: |
+ SkDynamicMemoryWStream fWriteStream; |
+ SkAutoTUnref<SkDocument> fDocument; |
+ SkCanvas* fCanvas; |
+}; |
+ |
+} // namespace |
+ |
+void PDFTask::draw() { |
+ SkAutoTDelete<SkStreamAsset> pdfData; |
+ bool rasterize = true; |
+ if (fGM.get()) { |
+ rasterize = 0 == (fGM->getFlags() & skiagm::GM::kSkipPDFRasterization_Flag); |
+ SinglePagePDF pdf(fGM->width(), fGM->height()); |
+ CanvasPreflight(pdf.canvas()); |
+ //TODO(mtklein): GM doesn't do this. Why not? |
+ //pdf.canvas()->concat(fGM->getInitialTransform()); |
+ fGM->draw(pdf.canvas()); |
+ pdfData.reset(pdf.end()); |
+ } else { |
+ SinglePagePDF pdf(fPicture->cullRect().width(), fPicture->cullRect().height()); |
+ CanvasPreflight(pdf.canvas()); |
+ fPicture->playback(pdf.canvas()); |
+ pdfData.reset(pdf.end()); |
+ } |
+ |
+ SkASSERT(pdfData.get()); |
+ if (rasterize) { |
+ this->spawnChild(SkNEW_ARGS(PDFRasterizeTask, |
+ (*this, pdfData->duplicate(), fRasterize))); |
+ } |
+ const char* sourceType = fGM.get() ? "GM" : "SKP"; |
+ this->spawnChild(SkNEW_ARGS(WriteTask, |
+ (*this, sourceType, pdfData->duplicate(), ".pdf"))); |
+} |
+ |
+bool PDFTask::shouldSkip() const { |
+ if (!FLAGS_pdf) { |
+ return true; |
+ } |
+ if (fGM.get() && 0 != (fGM->getFlags() & skiagm::GM::kSkipPDF_Flag)) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+} // namespace DM |