1/*
2 * Copyright 2013 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 "SkDocument.h"
9#include "SkPDFDocument.h"
10#include "SkPDFDeviceFlattener.h"
11
12class SkDocument_PDF : public SkDocument {
13public:
14    SkDocument_PDF(SkWStream* stream, void (*doneProc)(SkWStream*,bool),
15                   SkPicture::EncodeBitmap encoder,
16                   SkScalar rasterDpi)
17            : SkDocument(stream, doneProc)
18            , fEncoder(encoder)
19            , fRasterDpi(rasterDpi) {
20        fDoc = SkNEW(SkPDFDocument);
21        fCanvas = NULL;
22        fDevice = NULL;
23    }
24
25    virtual ~SkDocument_PDF() {
26        // subclasses must call close() in their destructors
27        this->close();
28    }
29
30protected:
31    virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
32                                  const SkRect& trimBox) SK_OVERRIDE {
33        SkASSERT(NULL == fCanvas);
34        SkASSERT(NULL == fDevice);
35
36        SkSize mediaBoxSize;
37        mediaBoxSize.set(width, height);
38
39        fDevice = SkNEW_ARGS(SkPDFDeviceFlattener, (mediaBoxSize, &trimBox));
40        if (fEncoder) {
41            fDevice->setDCTEncoder(fEncoder);
42        }
43        if (fRasterDpi != 0) {
44            fDevice->setRasterDpi(fRasterDpi);
45        }
46        fCanvas = SkNEW_ARGS(SkCanvas, (fDevice));
47        return fCanvas;
48    }
49
50    virtual void onEndPage() SK_OVERRIDE {
51        SkASSERT(fCanvas);
52        SkASSERT(fDevice);
53
54        fCanvas->flush();
55        fDoc->appendPage(fDevice);
56
57        fCanvas->unref();
58        fDevice->unref();
59
60        fCanvas = NULL;
61        fDevice = NULL;
62    }
63
64    virtual bool onClose(SkWStream* stream) SK_OVERRIDE {
65        SkASSERT(NULL == fCanvas);
66        SkASSERT(NULL == fDevice);
67
68        bool success = fDoc->emitPDF(stream);
69        SkDELETE(fDoc);
70        fDoc = NULL;
71        return success;
72    }
73
74    virtual void onAbort() SK_OVERRIDE {
75        SkDELETE(fDoc);
76        fDoc = NULL;
77    }
78
79private:
80    SkPDFDocument*  fDoc;
81    SkPDFDeviceFlattener* fDevice;
82    SkCanvas*       fCanvas;
83    SkPicture::EncodeBitmap fEncoder;
84    SkScalar        fRasterDpi;
85};
86
87///////////////////////////////////////////////////////////////////////////////
88
89SkDocument* SkDocument::CreatePDF(SkWStream* stream, void (*done)(SkWStream*,bool),
90                                  SkPicture::EncodeBitmap enc,
91                                  SkScalar dpi) {
92    return stream ? SkNEW_ARGS(SkDocument_PDF, (stream, done, enc, dpi)) : NULL;
93}
94
95static void delete_wstream(SkWStream* stream, bool aborted) {
96    SkDELETE(stream);
97}
98
99SkDocument* SkDocument::CreatePDF(const char path[],
100                                  SkPicture::EncodeBitmap enc,
101                                  SkScalar dpi) {
102    SkFILEWStream* stream = SkNEW_ARGS(SkFILEWStream, (path));
103    if (!stream->isValid()) {
104        SkDELETE(stream);
105        return NULL;
106    }
107    return SkNEW_ARGS(SkDocument_PDF, (stream, delete_wstream, enc, dpi));
108}
109