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. 19 DEFINE_bool(pdf, false, "PDF backend master switch."); 20 21 namespace DM { 22 23 PDFTask::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 33 PDFTask::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 43 namespace { 44 45 class SinglePagePDF { 46 public: 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 60 private: 61 SkDynamicMemoryWStream fWriteStream; 62 SkAutoTUnref<SkDocument> fDocument; 63 SkCanvas* fCanvas; 64 }; 65 66 } // namespace 67 68 void 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 91 bool 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