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