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 "SkPixelSerializer.h" 14 #include "SkRect.h" 15 #include "SkRefCnt.h" 16 #include "SkString.h" 17 #include "SkTime.h" 18 19 class SkCanvas; 20 class SkWStream; 21 22 #ifdef SK_BUILD_FOR_WIN 23 struct IXpsOMObjectFactory; 24 #endif 25 26 /** SK_ScalarDefaultDPI is 72 DPI. 27 */ 28 #define SK_ScalarDefaultRasterDPI 72.0f 29 30 /** 31 * High-level API for creating a document-based canvas. To use.. 32 * 33 * 1. Create a document, specifying a stream to store the output. 34 * 2. For each "page" of content: 35 * a. canvas = doc->beginPage(...) 36 * b. draw_my_content(canvas); 37 * c. doc->endPage(); 38 * 3. Close the document with doc->close(). 39 */ 40 class SK_API SkDocument : public SkRefCnt { 41 public: 42 struct OptionalTimestamp { 43 SkTime::DateTime fDateTime; 44 bool fEnabled; OptionalTimestampOptionalTimestamp45 OptionalTimestamp() : fEnabled(false) {} 46 }; 47 48 /** 49 * Optional metadata to be passed into the PDF factory function. 50 */ 51 struct PDFMetadata { 52 /** 53 * The document's title. 54 */ 55 SkString fTitle; 56 /** 57 * The name of the person who created the document. 58 */ 59 SkString fAuthor; 60 /** 61 * The subject of the document. 62 */ 63 SkString fSubject; 64 /** 65 * Keywords associated with the document. Commas may be used 66 * to delineate keywords within the string. 67 */ 68 SkString fKeywords; 69 /** 70 * If the document was converted to PDF from another format, 71 * the name of the conforming product that created the 72 * original document from which it was converted. 73 */ 74 SkString fCreator; 75 /** 76 * The product that is converting this document to PDF. 77 * 78 * Leave fProducer empty to get the default, correct value. 79 */ 80 SkString fProducer; 81 /** 82 * The date and time the document was created. 83 */ 84 OptionalTimestamp fCreation; 85 /** 86 * The date and time the document was most recently modified. 87 */ 88 OptionalTimestamp fModified; 89 }; 90 91 /** 92 * Create a PDF-backed document, writing the results into a 93 * SkWStream. 94 * 95 * PDF pages are sized in point units. 1 pt == 1/72 inch == 96 * 127/360 mm. 97 * 98 * @param stream A PDF document will be written to this 99 * stream. The document may write to the stream at 100 * anytime during its lifetime, until either close() is 101 * called or the document is deleted. 102 * @param dpi The DPI (pixels-per-inch) at which features without 103 * native PDF support will be rasterized (e.g. draw image 104 * with perspective, draw text with perspective, ...) A 105 * larger DPI would create a PDF that reflects the 106 * original intent with better fidelity, but it can make 107 * for larger PDF files too, which would use more memory 108 * while rendering, and it would be slower to be processed 109 * or sent online or to printer. 110 * @param metadata a PDFmetadata object. Any fields may be left 111 * empty. 112 * @param jpegEncoder For PDF documents, if a jpegEncoder is set, 113 * use it to encode SkImages and SkBitmaps as [JFIF]JPEGs. 114 * This feature is deprecated and is only supplied for 115 * backwards compatability. 116 * The prefered method to create PDFs with JPEG images is 117 * to use SkImage::NewFromEncoded() and not jpegEncoder. 118 * Chromium uses NewFromEncoded. 119 * If the encoder is unset, or if jpegEncoder->onEncode() 120 * returns NULL, fall back on encoding images losslessly 121 * with Deflate. 122 * @param pdfa Iff true, include XMP metadata, a document UUID, 123 * and sRGB output intent information. This adds length 124 * to the document and makes it non-reproducable, but are 125 * necessary features for PDF/A-2b conformance 126 * 127 * @returns NULL if there is an error, otherwise a newly created 128 * PDF-backed SkDocument. 129 */ 130 static sk_sp<SkDocument> MakePDF(SkWStream* stream, 131 SkScalar dpi, 132 const SkDocument::PDFMetadata& metadata, 133 sk_sp<SkPixelSerializer> jpegEncoder, 134 bool pdfa); 135 136 static sk_sp<SkDocument> MakePDF(SkWStream* stream, 137 SkScalar dpi = SK_ScalarDefaultRasterDPI) { 138 return SkDocument::MakePDF(stream, dpi, SkDocument::PDFMetadata(), 139 nullptr, false); 140 } 141 142 /** 143 * Create a PDF-backed document, writing the results into a file. 144 */ 145 static sk_sp<SkDocument> MakePDF(const char outputFilePath[], 146 SkScalar dpi = SK_ScalarDefaultRasterDPI); 147 148 #ifdef SK_BUILD_FOR_WIN 149 /** 150 * Create a XPS-backed document, writing the results into the stream. 151 * 152 * @param stream A XPS document will be written to this stream. The 153 * document may write to the stream at anytime during its 154 * lifetime, until either close() or abort() are called or 155 * the document is deleted. 156 * @param xpsFactory A pointer to a COM XPS factory. Must be non-null. 157 * The document will take a ref to the factory. See 158 * dm/DMSrcSink.cpp for an example. 159 * @param dpi The DPI (pixels-per-inch) at which features without 160 * native XPS support will be rasterized (e.g. draw image 161 * with perspective, draw text with perspective, ...) A 162 * larger DPI would create a XPS that reflects the 163 * original intent with better fidelity, but it can make 164 * for larger XPS files too, which would use more memory 165 * while rendering, and it would be slower to be processed 166 * or sent online or to printer. 167 * 168 * @returns nullptr if XPS is not supported. 169 */ 170 static sk_sp<SkDocument> MakeXPS(SkWStream* stream, 171 IXpsOMObjectFactory* xpsFactory, 172 SkScalar dpi = SK_ScalarDefaultRasterDPI); 173 #endif 174 // DEPRECATED; TODO(halcanary): remove this function after Chromium switches to new API. MakeXPS(SkWStream *)175 static sk_sp<SkDocument> MakeXPS(SkWStream*) { return nullptr; } 176 177 /** 178 * Begin a new page for the document, returning the canvas that will draw 179 * into the page. The document owns this canvas, and it will go out of 180 * scope when endPage() or close() is called, or the document is deleted. 181 */ 182 SkCanvas* beginPage(SkScalar width, SkScalar height, 183 const SkRect* content = NULL); 184 185 /** 186 * Call endPage() when the content for the current page has been drawn 187 * (into the canvas returned by beginPage()). After this call the canvas 188 * returned by beginPage() will be out-of-scope. 189 */ 190 void endPage(); 191 192 /** 193 * Call close() when all pages have been drawn. This will close the file 194 * or stream holding the document's contents. After close() the document 195 * can no longer add new pages. Deleting the document will automatically 196 * call close() if need be. 197 */ 198 void close(); 199 200 /** 201 * Call abort() to stop producing the document immediately. 202 * The stream output must be ignored, and should not be trusted. 203 */ 204 void abort(); 205 206 protected: 207 SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted)); 208 209 // note: subclasses must call close() in their destructor, as the base class 210 // cannot do this for them. 211 virtual ~SkDocument(); 212 213 virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height, 214 const SkRect& content) = 0; 215 virtual void onEndPage() = 0; 216 virtual void onClose(SkWStream*) = 0; 217 virtual void onAbort() = 0; 218 219 // Allows subclasses to write to the stream as pages are written. getStream()220 SkWStream* getStream() { return fStream; } 221 222 enum State { 223 kBetweenPages_State, 224 kInPage_State, 225 kClosed_State 226 }; getState()227 State getState() const { return fState; } 228 229 private: 230 SkWStream* fStream; 231 void (*fDoneProc)(SkWStream*, bool aborted); 232 State fState; 233 234 typedef SkRefCnt INHERITED; 235 }; 236 237 #endif 238