• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PDFTask(const char * config,Reporter * reporter,TaskRunner * taskRunner,skiagm::GMRegistry::Factory factory,RasterizePdfProc rasterizePdfProc)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 
PDFTask(Reporter * reporter,TaskRunner * taskRunner,const SkPicture * picture,SkString filename,RasterizePdfProc rasterizePdfProc)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:
SinglePagePDF(SkScalar width,SkScalar height)47     SinglePagePDF(SkScalar width, SkScalar height)
48         : fDocument(SkDocument::CreatePDF(&fWriteStream))
49         , fCanvas(fDocument->beginPage(width, height)) {}
50 
canvas()51     SkCanvas* canvas() { return fCanvas; }
52 
end()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 
draw()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 
shouldSkip() const96 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