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#ifndef SkDocument_DEFINED
9#define SkDocument_DEFINED
10
11#include "SkBitmap.h"
12#include "SkPicture.h"
13#include "SkRect.h"
14#include "SkRefCnt.h"
15
16class SkCanvas;
17class SkWStream;
18
19/** SK_ScalarDefaultDPI is 72 DPI.
20*/
21#define SK_ScalarDefaultRasterDPI           72.0f
22
23/**
24 *  High-level API for creating a document-based canvas. To use..
25 *
26 *  1. Create a document, specifying a stream to store the output.
27 *  2. For each "page" of content:
28 *      a. canvas = doc->beginPage(...)
29 *      b. draw_my_content(canvas);
30 *      c. doc->endPage();
31 *  3. Close the document with doc->close().
32 */
33class SkDocument : public SkRefCnt {
34public:
35    SK_DECLARE_INST_COUNT(SkDocument)
36
37    /**
38     *  Create a PDF-backed document, writing the results into a file.
39     *  If there is an error trying to create the doc, returns NULL.
40     *  encoder sets the DCTEncoder for images, to encode a bitmap
41     *    as JPEG (DCT).
42     *  rasterDpi - the DPI at which features without native PDF support
43     *              will be rasterized (e.g. draw image with perspective,
44     *              draw text with perspective, ...)
45     *              A larger DPI would create a PDF that reflects the original
46     *              intent with better fidelity, but it can make for larger
47     *              PDF files too, which would use more memory while rendering,
48     *              and it would be slower to be processed or sent online or
49     *              to printer.
50     */
51    static SkDocument* CreatePDF(
52            const char filename[],
53            SkPicture::EncodeBitmap encoder = NULL,
54            SkScalar rasterDpi = SK_ScalarDefaultRasterDPI);
55
56    /**
57     *  Create a PDF-backed document, writing the results into a stream.
58     *  If there is an error trying to create the doc, returns NULL.
59     *
60     *  The document may write to the stream at anytime during its lifetime,
61     *  until either close() is called or the document is deleted. Once close()
62     *  has been called, and all of the data has been written to the stream,
63     *  if there is a Done proc provided, it will be called with the stream.
64     *  The proc can delete the stream, or whatever it needs to do.
65     *  encoder sets the DCTEncoder for images, to encode a bitmap
66     *    as JPEG (DCT).
67     *  Done - clean up method intended to allow deletion of the stream.
68     *         Its aborted parameter is true if the cleanup is due to an abort
69     *         call. It is false otherwise.
70     *  rasterDpi - the DPI at which features without native PDF support
71     *              will be rasterized (e.g. draw image with perspective,
72     *              draw text with perspective, ...)
73     *              A larger DPI would create a PDF that reflects the original
74     *              intent with better fidelity, but it can make for larger
75     *              PDF files too, which would use more memory while rendering,
76     *              and it would be slower to be processed or sent online or
77     *              to printer.     */
78    static SkDocument* CreatePDF(
79            SkWStream*, void (*Done)(SkWStream*,bool aborted) = NULL,
80            SkPicture::EncodeBitmap encoder = NULL,
81            SkScalar rasterDpi = SK_ScalarDefaultRasterDPI);
82
83    /**
84     *  Begin a new page for the document, returning the canvas that will draw
85     *  into the page. The document owns this canvas, and it will go out of
86     *  scope when endPage() or close() is called, or the document is deleted.
87     */
88    SkCanvas* beginPage(SkScalar width, SkScalar height,
89                        const SkRect* content = NULL);
90
91    /**
92     *  Call endPage() when the content for the current page has been drawn
93     *  (into the canvas returned by beginPage()). After this call the canvas
94     *  returned by beginPage() will be out-of-scope.
95     */
96    void endPage();
97
98    /**
99     *  Call close() when all pages have been drawn. This will close the file
100     *  or stream holding the document's contents. After close() the document
101     *  can no longer add new pages. Deleting the document will automatically
102     *  call close() if need be.
103     *  Returns true on success or false on failure.
104     */
105    bool close();
106
107    /**
108     *  Call abort() to stop producing the document immediately.
109     *  The stream output must be ignored, and should not be trusted.
110     */
111    void abort();
112
113protected:
114    SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted));
115    // note: subclasses must call close() in their destructor, as the base class
116    // cannot do this for them.
117    virtual ~SkDocument();
118
119    virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
120                                  const SkRect& content) = 0;
121    virtual void onEndPage() = 0;
122    virtual bool onClose(SkWStream*) = 0;
123    virtual void onAbort() = 0;
124
125    enum State {
126        kBetweenPages_State,
127        kInPage_State,
128        kClosed_State
129    };
130    State getState() const { return fState; }
131
132private:
133    SkWStream* fStream;
134    void       (*fDoneProc)(SkWStream*, bool aborted);
135    State      fState;
136
137    typedef SkRefCnt INHERITED;
138};
139
140#endif
141