1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "DMPDFTask.h" 9#include "DMPDFRasterizeTask.h" 10#include "DMUtil.h" 11#include "DMWriteTask.h" 12#include "SkCommandLineFlags.h" 13#include "SkDocument.h" 14 15// The PDF backend is not threadsafe. If you run dm with --pdf repeatedly, you 16// will quickly find yourself crashed. (while catchsegv out/Release/dm;; end). 17// 18// TODO(mtklein): re-enable by default, maybe moving to its own single thread. 19DEFINE_bool(pdf, false, "PDF backend master switch."); 20 21namespace DM { 22 23PDFTask::PDFTask(const char* config, 24 Reporter* reporter, 25 TaskRunner* taskRunner, 26 skiagm::GMRegistry::Factory factory, 27 RasterizePdfProc rasterizePdfProc) 28 : CpuTask(reporter, taskRunner) 29 , fGM(factory(NULL)) 30 , fName(UnderJoin(fGM->getName(), config)) 31 , fRasterize(rasterizePdfProc) {} 32 33PDFTask::PDFTask(Reporter* reporter, 34 TaskRunner* taskRunner, 35 SkPicture* picture, 36 SkString filename, 37 RasterizePdfProc rasterizePdfProc) 38 : CpuTask(reporter, taskRunner) 39 , fPicture(SkRef(picture)) 40 , fName(UnderJoin(FileToTaskName(filename).c_str(), "pdf")) 41 , fRasterize(rasterizePdfProc) {} 42 43namespace { 44 45class SinglePagePDF { 46public: 47 SinglePagePDF(SkScalar width, SkScalar height) 48 : fDocument(SkDocument::CreatePDF(&fWriteStream)) 49 , fCanvas(fDocument->beginPage(width, height)) {} 50 51 SkCanvas* canvas() { return fCanvas; } 52 53 SkData* end() { 54 fCanvas->flush(); 55 fDocument->endPage(); 56 fDocument->close(); 57 return fWriteStream.copyToData(); 58 } 59 60private: 61 SkDynamicMemoryWStream fWriteStream; 62 SkAutoTUnref<SkDocument> fDocument; 63 SkCanvas* fCanvas; 64}; 65 66} // namespace 67 68void PDFTask::draw() { 69 SkAutoTUnref<SkData> pdfData; 70 bool rasterize = true; 71 if (fGM.get()) { 72 rasterize = 0 == (fGM->getFlags() & skiagm::GM::kSkipPDFRasterization_Flag); 73 SinglePagePDF pdf(fGM->width(), fGM->height()); 74 //TODO(mtklein): GM doesn't do this. Why not? 75 //pdf.canvas()->concat(fGM->getInitialTransform()); 76 fGM->draw(pdf.canvas()); 77 pdfData.reset(pdf.end()); 78 } else { 79 SinglePagePDF pdf(SkIntToScalar(fPicture->width()), SkIntToScalar(fPicture->height())); 80 fPicture->draw(pdf.canvas()); 81 pdfData.reset(pdf.end()); 82 } 83 84 SkASSERT(pdfData.get()); 85 if (rasterize) { 86 this->spawnChild(SkNEW_ARGS(PDFRasterizeTask, (*this, pdfData.get(), fRasterize))); 87 } 88 this->spawnChild(SkNEW_ARGS(WriteTask, (*this, pdfData.get(), ".pdf"))); 89} 90 91bool PDFTask::shouldSkip() const { 92 if (!FLAGS_pdf) { 93 return true; 94 } 95 if (fGM.get() && 0 != (fGM->getFlags() & skiagm::GM::kSkipPDF_Flag)) { 96 return true; 97 } 98 return false; 99} 100 101} // namespace DM 102