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 appendName(const char* owner, const char* attrName, const char* value); |
92 | void appendString(const char* owner, const char* attrName, const char* value); |
93 | void appendFloatArray(const char* owner, |
94 | const char* name, |
95 | const std::vector<float>& value); |
96 | // Deprecated. |
97 | void appendStringArray(const char* owner, |
98 | const char* attrName, |
99 | const std::vector<SkString>& values); |
100 | void appendNodeIdArray(const char* owner, |
101 | const char* attrName, |
102 | const std::vector<int>& nodeIds); |
103 | |
104 | private: |
105 | friend class ::SkPDFTagTree; |
106 | |
107 | std::unique_ptr<SkPDFArray> fAttrs; |
108 | }; |
109 | |
110 | /** A node in a PDF structure tree, giving a semantic representation |
111 | of the content. Each node ID is associated with content |
112 | by passing the SkCanvas and node ID to SkPDF::SetNodeId() when drawing. |
113 | NodeIDs should be unique within each tree. |
114 | */ |
115 | struct StructureElementNode { |
116 | SkString fTypeString; |
117 | std::vector<std::unique_ptr<StructureElementNode>> fChildVector; |
118 | int fNodeId = 0; |
119 | std::vector<int> fAdditionalNodeIds; |
120 | AttributeList fAttributes; |
121 | SkString fAlt; |
122 | SkString fLang; |
123 | |
124 | // Deprecated. Use fTypeString instead. |
125 | DocumentStructureType fType = DocumentStructureType::kNonStruct; |
126 | }; |
127 | |
128 | /** Optional metadata to be passed into the PDF factory function. |
129 | */ |
130 | struct Metadata { |
131 | /** The document's title. |
132 | */ |
133 | SkString fTitle; |
134 | |
135 | /** The name of the person who created the document. |
136 | */ |
137 | SkString fAuthor; |
138 | |
139 | /** The subject of the document. |
140 | */ |
141 | SkString fSubject; |
142 | |
143 | /** Keywords associated with the document. Commas may be used to delineate |
144 | keywords within the string. |
145 | */ |
146 | SkString fKeywords; |
147 | |
148 | /** If the document was converted to PDF from another format, |
149 | the name of the conforming product that created the |
150 | original document from which it was converted. |
151 | */ |
152 | SkString fCreator; |
153 | |
154 | /** The product that is converting this document to PDF. |
155 | */ |
156 | SkString fProducer = SkString("Skia/PDF m" SKPDF_STRING(SK_MILESTONE)); |
157 | |
158 | /** The date and time the document was created. |
159 | The zero default value represents an unknown/unset time. |
160 | */ |
161 | SkTime::DateTime fCreation = {0, 0, 0, 0, 0, 0, 0, 0}; |
162 | |
163 | /** The date and time the document was most recently modified. |
164 | The zero default value represents an unknown/unset time. |
165 | */ |
166 | SkTime::DateTime fModified = {0, 0, 0, 0, 0, 0, 0, 0}; |
167 | |
168 | /** The DPI (pixels-per-inch) at which features without native PDF support |
169 | will be rasterized (e.g. draw image with perspective, draw text with |
170 | perspective, ...) A larger DPI would create a PDF that reflects the |
171 | original intent with better fidelity, but it can make for larger PDF |
172 | files too, which would use more memory while rendering, and it would be |
173 | slower to be processed or sent online or to printer. |
174 | */ |
175 | SkScalar fRasterDPI = SK_ScalarDefaultRasterDPI; |
176 | |
177 | /** If true, include XMP metadata, a document UUID, and sRGB output intent |
178 | information. This adds length to the document and makes it |
179 | non-reproducable, but are necessary features for PDF/A-2b conformance |
180 | */ |
181 | bool fPDFA = false; |
182 | |
183 | /** Encoding quality controls the trade-off between size and quality. By |
184 | default this is set to 101 percent, which corresponds to lossless |
185 | encoding. If this value is set to a value <= 100, and the image is |
186 | opaque, it will be encoded (using JPEG) with that quality setting. |
187 | */ |
188 | int fEncodingQuality = 101; |
189 | |
190 | /** An optional tree of structured document tags that provide |
191 | a semantic representation of the content. The caller |
192 | should retain ownership. |
193 | */ |
194 | StructureElementNode* fStructureElementTreeRoot = nullptr; |
195 | |
196 | /** Executor to handle threaded work within PDF Backend. If this is nullptr, |
197 | then all work will be done serially on the main thread. To have worker |
198 | threads assist with various tasks, set this to a valid SkExecutor |
199 | instance. Currently used for executing Deflate algorithm in parallel. |
200 | |
201 | If set, the PDF output will be non-reproducible in the order and |
202 | internal numbering of objects, but should render the same. |
203 | |
204 | Experimental. |
205 | */ |
206 | SkExecutor* fExecutor = nullptr; |
207 | |
208 | /** Preferred Subsetter. Only respected if both are compiled in. |
209 | |
210 | The Sfntly subsetter is deprecated. |
211 | |
212 | Experimental. |
213 | */ |
214 | enum Subsetter { |
215 | kHarfbuzz_Subsetter, |
216 | kSfntly_Subsetter, |
217 | } fSubsetter = kHarfbuzz_Subsetter; |
218 | }; |
219 | |
220 | /** Associate a node ID with subsequent drawing commands in an |
221 | SkCanvas. The same node ID can appear in a StructureElementNode |
222 | in order to associate a document's structure element tree with |
223 | its content. |
224 | |
225 | A node ID of zero indicates no node ID. |
226 | |
227 | @param canvas The canvas used to draw to the PDF. |
228 | @param nodeId The node ID for subsequent drawing commands. |
229 | */ |
230 | SK_API void SetNodeId(SkCanvas* dst, int nodeID); |
231 | |
232 | /** Create a PDF-backed document, writing the results into a SkWStream. |
233 | |
234 | PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm. |
235 | |
236 | @param stream A PDF document will be written to this stream. The document may write |
237 | to the stream at anytime during its lifetime, until either close() is |
238 | called or the document is deleted. |
239 | @param metadata a PDFmetadata object. Any fields may be left empty. |
240 | |
241 | @returns NULL if there is an error, otherwise a newly created PDF-backed SkDocument. |
242 | */ |
243 | SK_API sk_sp<SkDocument> MakeDocument(SkWStream* stream, const Metadata& metadata); |
244 | |
245 | static inline sk_sp<SkDocument> MakeDocument(SkWStream* stream) { |
246 | return MakeDocument(stream, Metadata()); |
247 | } |
248 | |
249 | } // namespace SkPDF |
250 | |
251 | #undef SKPDF_STRING |
252 | #undef SKPDF_STRING_IMPL |
253 | #endif // SkPDFDocument_DEFINED |
254 | |