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 175 /** 176 * Begin a new page for the document, returning the canvas that will draw 177 * into the page. The document owns this canvas, and it will go out of 178 * scope when endPage() or close() is called, or the document is deleted. 179 */ 180 SkCanvas* beginPage(SkScalar width, SkScalar height, 181 const SkRect* content = NULL); 182 183 /** 184 * Call endPage() when the content for the current page has been drawn 185 * (into the canvas returned by beginPage()). After this call the canvas 186 * returned by beginPage() will be out-of-scope. 187 */ 188 void endPage(); 189 190 /** 191 * Call close() when all pages have been drawn. This will close the file 192 * or stream holding the document's contents. After close() the document 193 * can no longer add new pages. Deleting the document will automatically 194 * call close() if need be. 195 */ 196 void close(); 197 198 /** 199 * Call abort() to stop producing the document immediately. 200 * The stream output must be ignored, and should not be trusted. 201 */ 202 void abort(); 203 204 protected: 205 SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted)); 206 207 // note: subclasses must call close() in their destructor, as the base class 208 // cannot do this for them. 209 virtual ~SkDocument(); 210 211 virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height) = 0; 212 virtual void onEndPage() = 0; 213 virtual void onClose(SkWStream*) = 0; 214 virtual void onAbort() = 0; 215 216 // Allows subclasses to write to the stream as pages are written. getStream()217 SkWStream* getStream() { return fStream; } 218 219 enum State { 220 kBetweenPages_State, 221 kInPage_State, 222 kClosed_State 223 }; getState()224 State getState() const { return fState; } 225 226 private: 227 SkWStream* fStream; 228 void (*fDoneProc)(SkWStream*, bool aborted); 229 State fState; 230 231 typedef SkRefCnt INHERITED; 232 }; 233 234 #endif 235