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#include "SkCanvas.h"
8#include "SkDocument.h"
9#include "SkForceLinking.h"
10#include "SkGraphics.h"
11#include "SkNullCanvas.h"
12#include "SkPicture.h"
13#include "SkStream.h"
14#include "SkTemplates.h"
15#include "PageCachingDocument.h"
16#include "ProcStats.h"
17#include "flags/SkCommandLineFlags.h"
18
19DEFINE_string2(readPath,
20               r,
21               "",
22               "(Required)  The path to a .skp Skia Picture file.");
23DEFINE_string2(writePath, w, "", "If set, write PDF output to this file.");
24DEFINE_bool(cachePages, false, "Use a PageCachingDocument.");
25DEFINE_bool(nullCanvas, true, "Render to a SkNullCanvas as a control.");
26
27__SK_FORCE_IMAGE_DECODER_LINKING;
28
29namespace {
30class NullWStream : public SkWStream {
31public:
32    NullWStream() : fBytesWritten(0) {
33    }
34    bool write(const void*, size_t size) override {
35        fBytesWritten += size;
36        return true;
37    }
38    size_t bytesWritten() const override {
39        return fBytesWritten;
40    }
41    size_t fBytesWritten;
42};
43
44SkDocument* CreatePDFDocument(SkWStream* out) {
45    if (FLAGS_cachePages) {
46        return CreatePageCachingDocument(out);
47    } else {
48        return SkDocument::CreatePDF(out);
49    }
50}
51}  // namespace
52
53int main(int argc, char** argv) {
54    SkCommandLineFlags::Parse(argc, argv);
55    if (FLAGS_readPath.isEmpty()) {
56        SkDebugf("Error: missing requires --readPath option\n");
57        return 1;
58    }
59    const char* path = FLAGS_readPath[0];
60    SkFILEStream inputStream(path);
61
62    if (!inputStream.isValid()) {
63        SkDebugf("Could not open file %s\n", path);
64        return 2;
65    }
66    SkAutoGraphics ag;
67    SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream));
68    if (NULL == picture.get()) {
69        SkDebugf("Could not read an SkPicture from %s\n", path);
70        return 3;
71    }
72
73    int width = picture->cullRect().width();
74    int height = picture->cullRect().height();
75
76    const int kLetterWidth = 612;   // 8.5 * 72
77    const int kLetterHeight = 792;  // 11 * 72
78    SkRect letterRect = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
79                                       SkIntToScalar(kLetterHeight));
80
81    int xPages = ((width - 1) / kLetterWidth) + 1;
82    int yPages = ((height - 1) / kLetterHeight) + 1;
83
84    SkAutoTDelete<SkWStream> out(SkNEW(NullWStream));
85
86    if (!FLAGS_writePath.isEmpty()) {
87        SkAutoTDelete<SkFILEWStream> fileStream(
88            SkNEW_ARGS(SkFILEWStream, (FLAGS_writePath[0])));
89        if (!fileStream->isValid()) {
90            SkDebugf("Can't open file \"%s\" for writing.", FLAGS_writePath[0]);
91            return 1;
92        }
93        out.reset(fileStream.detach());
94    }
95
96    SkCanvas* nullCanvas = SkCreateNullCanvas();
97
98    SkAutoTUnref<SkDocument> pdfDocument;
99    if (!FLAGS_nullCanvas) {
100        pdfDocument.reset(CreatePDFDocument(out.get()));
101    }
102
103    for (int y = 0; y < yPages; ++y) {
104        for (int x = 0; x < xPages; ++x) {
105            SkCanvas* canvas;
106            if (FLAGS_nullCanvas) {
107                canvas = nullCanvas;
108            } else {
109                int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
110                int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
111                canvas = pdfDocument->beginPage(w, h);
112            }
113            {
114                SkAutoCanvasRestore autoCanvasRestore(canvas, true);
115                canvas->clipRect(letterRect);
116                canvas->translate(SkIntToScalar(-kLetterWidth * x),
117                                  SkIntToScalar(-kLetterHeight * y));
118                picture->playback(canvas);
119                //canvas->drawPicture(picture);
120            }
121            canvas->flush();
122            if (!FLAGS_nullCanvas) {
123                pdfDocument->endPage();
124            }
125        }
126    }
127    if (!FLAGS_nullCanvas) {
128        pdfDocument->close();
129        pdfDocument.reset(NULL);
130    }
131    printf(SK_SIZE_T_SPECIFIER "\t%4d\n",
132           inputStream.getLength(),
133           sk_tools::getMaxResidentSetSizeMB());
134    return 0;
135}
136