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