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                  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