• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "SkString.h"
16 #include "SkTime.h"
17 
18 class SkCanvas;
19 class SkPixelSerializer;
20 class SkWStream;
21 
22 /** SK_ScalarDefaultDPI is 72 DPI.
23 */
24 #define SK_ScalarDefaultRasterDPI           72.0f
25 
26 /**
27  *  High-level API for creating a document-based canvas. To use..
28  *
29  *  1. Create a document, specifying a stream to store the output.
30  *  2. For each "page" of content:
31  *      a. canvas = doc->beginPage(...)
32  *      b. draw_my_content(canvas);
33  *      c. doc->endPage();
34  *  3. Close the document with doc->close().
35  */
36 class SK_API SkDocument : public SkRefCnt {
37 public:
38     /**
39      *  Create a PDF-backed document, writing the results into a SkWStream.
40      *
41      *  PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.
42      *
43      *  @param SkWStream* A PDF document will be written to this
44      *         stream.  The document may write to the stream at
45      *         anytime during its lifetime, until either close() is
46      *         called or the document is deleted.
47      *  @param dpi The DPI (pixels-per-inch) at which features without
48      *         native PDF support will be rasterized (e.g. draw image
49      *         with perspective, draw text with perspective, ...)  A
50      *         larger DPI would create a PDF that reflects the
51      *         original intent with better fidelity, but it can make
52      *         for larger PDF files too, which would use more memory
53      *         while rendering, and it would be slower to be processed
54      *         or sent online or to printer.
55      *  @returns NULL if there is an error, otherwise a newly created
56      *           PDF-backed SkDocument.
57      */
58     static SkDocument* CreatePDF(SkWStream*,
59                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
60 
61     /**
62      *  @param jpegEncoder For PDF documents, if a jpegEncoder is set,
63      *         use it to encode SkImages and SkBitmaps as [JFIF]JPEGs.
64      *         This feature is deprecated and is only supplied for
65      *         backwards compatability.
66      *
67      *         The prefered method to create PDFs with JPEG images is
68      *         to use SkImage::NewFromEncoded() and not jpegEncoder.
69      *         Chromium uses NewFromEncoded.
70      *
71      *         If the encoder is unset, or if jpegEncoder->onEncode()
72      *         returns NULL, fall back on encoding images losslessly
73      *         with Deflate.
74      */
75     static SkDocument* CreatePDF(SkWStream*,
76                                  SkScalar dpi,
77                                  SkPixelSerializer* jpegEncoder);
78 
79     /**
80      *  Create a PDF-backed document, writing the results into a file.
81      */
82     static SkDocument* CreatePDF(const char outputFilePath[],
83                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
84 
85     /**
86      *  Create a XPS-backed document, writing the results into the stream.
87      *  Returns NULL if XPS is not supported.
88      */
89     static SkDocument* CreateXPS(SkWStream* stream,
90                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
91 
92     /**
93      *  Create a XPS-backed document, writing the results into a file.
94      *  Returns NULL if XPS is not supported.
95      */
96     static SkDocument* CreateXPS(const char path[],
97                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
98     /**
99      *  Begin a new page for the document, returning the canvas that will draw
100      *  into the page. The document owns this canvas, and it will go out of
101      *  scope when endPage() or close() is called, or the document is deleted.
102      */
103     SkCanvas* beginPage(SkScalar width, SkScalar height,
104                         const SkRect* content = NULL);
105 
106     /**
107      *  Call endPage() when the content for the current page has been drawn
108      *  (into the canvas returned by beginPage()). After this call the canvas
109      *  returned by beginPage() will be out-of-scope.
110      */
111     void endPage();
112 
113     /**
114      *  Call close() when all pages have been drawn. This will close the file
115      *  or stream holding the document's contents. After close() the document
116      *  can no longer add new pages. Deleting the document will automatically
117      *  call close() if need be.
118      *  Returns true on success or false on failure.
119      */
120     bool close();
121 
122     /**
123      *  Call abort() to stop producing the document immediately.
124      *  The stream output must be ignored, and should not be trusted.
125      */
126     void abort();
127 
128     /**
129      *  Set the document's metadata, if supported by the document
130      *  type.  The creationDate and modifiedDate parameters can be
131      *  nullptr.  For example:
132      *
133      *  SkDocument* make_doc(SkWStream* output) {
134      *      std::vector<SkDocument::Attribute> info;
135      *      info.emplace_back(SkString("Title"), SkString("..."));
136      *      info.emplace_back(SkString("Author"), SkString("..."));
137      *      info.emplace_back(SkString("Subject"), SkString("..."));
138      *      info.emplace_back(SkString("Keywords"), SkString("..."));
139      *      info.emplace_back(SkString("Creator"), SkString("..."));
140      *      SkTime::DateTime now;
141      *      SkTime::GetDateTime(&now);
142      *      SkDocument* doc = SkDocument::CreatePDF(output);
143      *      doc->setMetadata(&info[0], (int)info.size(), &now, &now);
144      *      return doc;
145      *  }
146      */
147     struct Attribute {
148         SkString fKey, fValue;
AttributeAttribute149         Attribute(const SkString& k, const SkString& v) : fKey(k), fValue(v) {}
150     };
setMetadata(const SkDocument::Attribute[],int,const SkTime::DateTime *,const SkTime::DateTime *)151     virtual void setMetadata(const SkDocument::Attribute[],
152                              int /* attributeCount */,
153                              const SkTime::DateTime* /* creationDate */,
154                              const SkTime::DateTime* /* modifiedDate */) {}
155 
156 protected:
157     SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted));
158 
159     // note: subclasses must call close() in their destructor, as the base class
160     // cannot do this for them.
161     virtual ~SkDocument();
162 
163     virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
164                                   const SkRect& content) = 0;
165     virtual void onEndPage() = 0;
166     virtual bool onClose(SkWStream*) = 0;
167     virtual void onAbort() = 0;
168 
169     // Allows subclasses to write to the stream as pages are written.
getStream()170     SkWStream* getStream() { return fStream; }
171 
172     enum State {
173         kBetweenPages_State,
174         kInPage_State,
175         kClosed_State
176     };
getState()177     State getState() const { return fState; }
178 
179 private:
180     SkWStream* fStream;
181     void       (*fDoneProc)(SkWStream*, bool aborted);
182     State      fState;
183 
184     typedef SkRefCnt INHERITED;
185 };
186 
187 #endif
188