1 | // Copyright 2018 Google LLC. |
2 | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
3 | #ifndef SkPDFDocument_DEFINED |
4 | #define SkPDFDocument_DEFINED |
5 | |
6 | #include "include/core/SkDocument.h" |
7 | |
8 | #include <vector> |
9 | |
10 | #include "include/core/SkColor.h" |
11 | #include "include/core/SkMilestone.h" |
12 | #include "include/core/SkScalar.h" |
13 | #include "include/core/SkString.h" |
14 | #include "include/core/SkTime.h" |
15 | #include "include/private/SkNoncopyable.h" |
16 | |
17 | #define SKPDF_STRING(X) SKPDF_STRING_IMPL(X) |
18 | #define SKPDF_STRING_IMPL(X) #X |
19 | |
20 | class SkExecutor; |
21 | class SkPDFArray; |
22 | class SkPDFTagTree; |
23 | |
24 | namespace SkPDF { |
25 | |
26 | /** Table 333 in PDF 32000-1:2008 ยง14.8.4.2 |
27 | */ |
28 | enum class DocumentStructureType { |
29 | kDocument, //!< Document |
30 | kPart, //!< Part |
31 | kArt, //!< Article |
32 | kSect, //!< Section |
33 | kDiv, //!< Division |
34 | kBlockQuote, //!< Block quotation |
35 | kCaption, //!< Caption |
36 | kTOC, //!< Table of Contents |
37 | kTOCI, //!< Table of Contents Item |
38 | kIndex, //!< Index |
39 | kNonStruct, //!< Nonstructural element |
40 | kPrivate, //!< Private element |
41 | kH, //!< Heading |
42 | kH1, //!< Heading level 1 |
43 | kH2, //!< Heading level 2 |
44 | kH3, //!< Heading level 3 |
45 | kH4, //!< Heading level 4 |
46 | kH5, //!< Heading level 5 |
47 | kH6, //!< Heading level 6 |
48 | kP, //!< Paragraph |
49 | kL, //!< List |
50 | kLI, //!< List item |
51 | kLbl, //!< List item label |
52 | kLBody, //!< List item body |
53 | kTable, //!< Table |
54 | kTR, //!< Table row |
55 | kTH, //!< Table header cell |
56 | kTD, //!< Table data cell |
57 | kTHead, //!< Table header row group |
58 | kTBody, //!< Table body row group |
59 | , //!< table footer row group |
60 | kSpan, //!< Span |
61 | kQuote, //!< Quotation |
62 | kNote, //!< Note |
63 | kReference, //!< Reference |
64 | kBibEntry, //!< Bibliography entry |
65 | kCode, //!< Code |
66 | kLink, //!< Link |
67 | kAnnot, //!< Annotation |
68 | kRuby, //!< Ruby annotation |
69 | kRB, //!< Ruby base text |
70 | kRT, //!< Ruby annotation text |
71 | kRP, //!< Ruby punctuation |
72 | kWarichu, //!< Warichu annotation |
73 | kWT, //!< Warichu text |
74 | kWP, //!< Warichu punctuation |
75 | kFigure, //!< Figure |
76 | kFormula, //!< Formula |
77 | kForm, //!< Form control (not like an HTML FORM element) |
78 | }; |
79 | |
80 | /** Attributes for nodes in the PDF tree. */ |
81 | class SK_API AttributeList : SkNoncopyable { |
82 | public: |
83 | AttributeList(); |
84 | ~AttributeList(); |
85 | |
86 | // Each attribute must have an owner (e.g. "Layout", "List", "Table", etc) |
87 | // and an attribute name (e.g. "BBox", "RowSpan", etc.) from PDF32000_2008 14.8.5, |
88 | // and then a value of the proper type according to the spec. |
89 | void appendInt(const char* owner, const char* name, int value); |
90 | void appendFloat(const char* owner, const char* name, float value); |
91 | void appendString(const char* owner, const char* name, const char* value); |
92 | void appendFloatArray(const char* owner, |
93 | const char* name, |
94 | const std::vector<float>& value); |
95 | void appendStringArray(const char* owner, |
96 | const char* name, |
97 | const std::vector<SkString>& value); |
98 | |
99 | private: |
100 | friend class ::SkPDFTagTree; |
101 | |
102 | std::unique_ptr<SkPDFArray> fAttrs; |
103 | }; |
104 | |
105 | /** A node in a PDF structure tree, giving a semantic representation |
106 | of the content. Each node ID is associated with content |
107 | by passing the SkCanvas and node ID to SkPDF::SetNodeId() when drawing. |
108 | NodeIDs should be unique within each tree. |
109 | */ |
110 | struct StructureElementNode { |
111 | SkString fTypeString; |
112 | std::vector<std::unique_ptr<StructureElementNode>> fChildVector; |
113 | int fNodeId = 0; |
114 | std::vector<int> fAdditionalNodeIds; |
115 | AttributeList fAttributes; |
116 | SkString fAlt; |
117 | SkString fLang; |
118 | |
119 | // Deprecated. Use fChildVector instead. |
120 | StructureElementNode* fChildren = nullptr; |
121 | size_t fChildCount = 0; |
122 | |
123 | // Deprecated. Use fTypeString instead. |
124 | DocumentStructureType fType = DocumentStructureType::kNonStruct; |
125 | }; |
126 | |
127 | /** Optional metadata to be passed into the PDF factory function. |
128 | */ |
129 | struct Metadata { |
130 | /** The document's title. |
131 | */ |
132 | SkString fTitle; |
133 | |
134 | /** The name of the person who created the document. |
135 | */ |
136 | SkString fAuthor; |
137 | |
138 | /** The subject of the document. |
139 | */ |
140 | SkString fSubject; |
141 | |
142 | /** Keywords associated with the document. Commas may be used to delineate |
143 | keywords within the string. |
144 | */ |
145 | SkString fKeywords; |
146 | |
147 | /** If the document was converted to PDF from another format, |
148 | the name of the conforming product that created the |
149 | original document from which it was converted. |
150 | */ |
151 | SkString fCreator; |
152 | |
153 | /** The product that is converting this document to PDF. |
154 | */ |
155 | SkString fProducer = SkString("Skia/PDF m" SKPDF_STRING(SK_MILESTONE)); |
156 | |
157 | /** The date and time the document was created. |
158 | The zero default value represents an unknown/unset time. |
159 | */ |
160 | SkTime::DateTime fCreation = {0, 0, 0, 0, 0, 0, 0, 0}; |
161 | |
162 | /** The date and time the document was most recently modified. |
163 | The zero default value represents an unknown/unset time. |
164 | */ |
165 | SkTime::DateTime fModified = {0, 0, 0, 0, 0, 0, 0, 0}; |
166 | |
167 | /** The DPI (pixels-per-inch) at which features without native PDF support |
168 | will be rasterized (e.g. draw image with perspective, draw text with |
169 | perspective, ...) A larger DPI would create a PDF that reflects the |
170 | original intent with better fidelity, but it can make for larger PDF |
171 | files too, which would use more memory while rendering, and it would be |
172 | slower to be processed or sent online or to printer. |
173 | */ |
174 | SkScalar fRasterDPI = SK_ScalarDefaultRasterDPI; |
175 | |
176 | /** If true, include XMP metadata, a document UUID, and sRGB output intent |
177 | information. This adds length to the document and makes it |
178 | non-reproducable, but are necessary features for PDF/A-2b conformance |
179 | */ |
180 | bool fPDFA = false; |
181 | |
182 | /** Encoding quality controls the trade-off between size and quality. By |
183 | default this is set to 101 percent, which corresponds to lossless |
184 | encoding. If this value is set to a value <= 100, and the image is |
185 | opaque, it will be encoded (using JPEG) with that quality setting. |
186 | */ |
187 | int fEncodingQuality = 101; |
188 | |
189 | /** An optional tree of structured document tags that provide |
190 | a semantic representation of the content. The caller |
191 | should retain ownership. |
192 | */ |
193 | StructureElementNode* fStructureElementTreeRoot = nullptr; |
194 | |
195 | /** Executor to handle threaded work within PDF Backend. If this is nullptr, |
196 | then all work will be done serially on the main thread. To have worker |
197 | threads assist with various tasks, set this to a valid SkExecutor |
198 | instance. Currently used for executing Deflate algorithm in parallel. |
199 | |
200 | If set, the PDF output will be non-reproducible in the order and |
201 | internal numbering of objects, but should render the same. |
202 | |
203 | Experimental. |
204 | */ |
205 | SkExecutor* fExecutor = nullptr; |
206 | |
207 | /** Preferred Subsetter. Only respected if both are compiled in. |
208 | |
209 | The Sfntly subsetter is deprecated. |
210 | |
211 | Experimental. |
212 | */ |
213 | enum Subsetter { |
214 | kHarfbuzz_Subsetter, |
215 | kSfntly_Subsetter, |
216 | } fSubsetter = kHarfbuzz_Subsetter; |
217 | }; |
218 | |
219 | /** Associate a node ID with subsequent drawing commands in an |
220 | SkCanvas. The same node ID can appear in a StructureElementNode |
221 | in order to associate a document's structure element tree with |
222 | its content. |
223 | |
224 | A node ID of zero indicates no node ID. |
225 | |
226 | @param canvas The canvas used to draw to the PDF. |
227 | @param nodeId The node ID for subsequent drawing commands. |
228 | */ |
229 | SK_API void SetNodeId(SkCanvas* dst, int nodeID); |
230 | |
231 | /** Create a PDF-backed document, writing the results into a SkWStream. |
232 | |
233 | PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm. |
234 | |
235 | @param stream A PDF document will be written to this stream. The document may write |
236 | to the stream at anytime during its lifetime, until either close() is |
237 | called or the document is deleted. |
238 | @param metadata a PDFmetadata object. Any fields may be left empty. |
239 | |
240 | @returns NULL if there is an error, otherwise a newly created PDF-backed SkDocument. |
241 | */ |
242 | SK_API sk_sp<SkDocument> MakeDocument(SkWStream* stream, const Metadata& metadata); |
243 | |
244 | static inline sk_sp<SkDocument> MakeDocument(SkWStream* stream) { |
245 | return MakeDocument(stream, Metadata()); |
246 | } |
247 | |
248 | } // namespace SkPDF |
249 | |
250 | #undef SKPDF_STRING |
251 | #undef SKPDF_STRING_IMPL |
252 | #endif // SkPDFDocument_DEFINED |
253 | |