Home | History | Annotate | Download | only in dm
      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                  const 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     SkStreamAsset* end() {
     54         fCanvas->flush();
     55         fDocument->endPage();
     56         fDocument->close();
     57         return fWriteStream.detachAsStream();
     58     }
     59 
     60 private:
     61     SkDynamicMemoryWStream fWriteStream;
     62     SkAutoTUnref<SkDocument> fDocument;
     63     SkCanvas* fCanvas;
     64 };
     65 
     66 }  // namespace
     67 
     68 void PDFTask::draw() {
     69     SkAutoTDelete<SkStreamAsset> 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         CanvasPreflight(pdf.canvas());
     75         //TODO(mtklein): GM doesn't do this.  Why not?
     76         //pdf.canvas()->concat(fGM->getInitialTransform());
     77         fGM->draw(pdf.canvas());
     78         pdfData.reset(pdf.end());
     79     } else {
     80         SinglePagePDF pdf(fPicture->cullRect().width(), fPicture->cullRect().height());
     81         CanvasPreflight(pdf.canvas());
     82         fPicture->playback(pdf.canvas());
     83         pdfData.reset(pdf.end());
     84     }
     85 
     86     SkASSERT(pdfData.get());
     87     if (rasterize) {
     88         this->spawnChild(SkNEW_ARGS(PDFRasterizeTask,
     89                                     (*this, pdfData->duplicate(), fRasterize)));
     90     }
     91     const char* sourceType = fGM.get() ? "GM" : "SKP";
     92     this->spawnChild(SkNEW_ARGS(WriteTask,
     93                                 (*this, sourceType, pdfData->duplicate(), ".pdf")));
     94 }
     95 
     96 bool PDFTask::shouldSkip() const {
     97     if (!FLAGS_pdf) {
     98         return true;
     99     }
    100     if (fGM.get() && 0 != (fGM->getFlags() & skiagm::GM::kSkipPDF_Flag)) {
    101         return true;
    102     }
    103     return false;
    104 }
    105 
    106 }  // namespace DM
    107