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