• 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/base/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 /** Attributes for nodes in the PDF tree. */
27 class SK_API AttributeList : SkNoncopyable {
28 public:
29     AttributeList();
30     ~AttributeList();
31 
32     // Each attribute must have an owner (e.g. "Layout", "List", "Table", etc)
33     // and an attribute name (e.g. "BBox", "RowSpan", etc.) from PDF32000_2008 14.8.5,
34     // and then a value of the proper type according to the spec.
35     void appendInt(const char* owner, const char* name, int value);
36     void appendFloat(const char* owner, const char* name, float value);
37     void appendName(const char* owner, const char* attrName, const char* value);
38     void appendFloatArray(const char* owner,
39                           const char* name,
40                           const std::vector<float>& value);
41     void appendNodeIdArray(const char* owner,
42                            const char* attrName,
43                            const std::vector<int>& nodeIds);
44 
45 private:
46     friend class ::SkPDFTagTree;
47 
48     std::unique_ptr<SkPDFArray> fAttrs;
49 };
50 
51 /** A node in a PDF structure tree, giving a semantic representation
52     of the content.  Each node ID is associated with content
53     by passing the SkCanvas and node ID to SkPDF::SetNodeId() when drawing.
54     NodeIDs should be unique within each tree.
55 */
56 struct StructureElementNode {
57     SkString fTypeString;
58     std::vector<std::unique_ptr<StructureElementNode>> fChildVector;
59     int fNodeId = 0;
60     std::vector<int> fAdditionalNodeIds;
61     AttributeList fAttributes;
62     SkString fAlt;
63     SkString fLang;
64 };
65 
66 /** Optional metadata to be passed into the PDF factory function.
67 */
68 struct Metadata {
69     /** The document's title.
70     */
71     SkString fTitle;
72 
73     /** The name of the person who created the document.
74     */
75     SkString fAuthor;
76 
77     /** The subject of the document.
78     */
79     SkString fSubject;
80 
81     /** Keywords associated with the document.  Commas may be used to delineate
82         keywords within the string.
83     */
84     SkString fKeywords;
85 
86     /** If the document was converted to PDF from another format,
87         the name of the conforming product that created the
88         original document from which it was converted.
89     */
90     SkString fCreator;
91 
92     /** The product that is converting this document to PDF.
93     */
94     SkString fProducer = SkString("Skia/PDF m" SKPDF_STRING(SK_MILESTONE));
95 
96     /** The date and time the document was created.
97         The zero default value represents an unknown/unset time.
98     */
99     SkTime::DateTime fCreation = {0, 0, 0, 0, 0, 0, 0, 0};
100 
101     /** The date and time the document was most recently modified.
102         The zero default value represents an unknown/unset time.
103     */
104     SkTime::DateTime fModified = {0, 0, 0, 0, 0, 0, 0, 0};
105 
106     /** The DPI (pixels-per-inch) at which features without native PDF support
107         will be rasterized (e.g. draw image with perspective, draw text with
108         perspective, ...)  A larger DPI would create a PDF that reflects the
109         original intent with better fidelity, but it can make for larger PDF
110         files too, which would use more memory while rendering, and it would be
111         slower to be processed or sent online or to printer.
112     */
113     SkScalar fRasterDPI = SK_ScalarDefaultRasterDPI;
114 
115     /** If true, include XMP metadata, a document UUID, and sRGB output intent
116         information.  This adds length to the document and makes it
117         non-reproducable, but are necessary features for PDF/A-2b conformance
118     */
119     bool fPDFA = false;
120 
121     /** Encoding quality controls the trade-off between size and quality. By
122         default this is set to 101 percent, which corresponds to lossless
123         encoding. If this value is set to a value <= 100, and the image is
124         opaque, it will be encoded (using JPEG) with that quality setting.
125     */
126     int fEncodingQuality = 101;
127 
128     /** An optional tree of structured document tags that provide
129         a semantic representation of the content. The caller
130         should retain ownership.
131     */
132     StructureElementNode* fStructureElementTreeRoot = nullptr;
133 
134     /** Executor to handle threaded work within PDF Backend. If this is nullptr,
135         then all work will be done serially on the main thread. To have worker
136         threads assist with various tasks, set this to a valid SkExecutor
137         instance. Currently used for executing Deflate algorithm in parallel.
138 
139         If set, the PDF output will be non-reproducible in the order and
140         internal numbering of objects, but should render the same.
141 
142         Experimental.
143     */
144     SkExecutor* fExecutor = nullptr;
145 
146     /** PDF streams may be compressed to save space.
147         Use this to specify the desired compression vs time tradeoff.
148     */
149     enum class CompressionLevel : int {
150         Default = -1,
151         None = 0,
152         LowButFast = 1,
153         Average = 6,
154         HighButSlow = 9,
155     } fCompressionLevel = CompressionLevel::Default;
156 
157     /** Preferred Subsetter. Only respected if both are compiled in.
158 
159         The Sfntly subsetter is deprecated.
160 
161         Experimental.
162     */
163     enum Subsetter {
164         kHarfbuzz_Subsetter,
165         kSfntly_Subsetter,
166     } fSubsetter = kHarfbuzz_Subsetter;
167 };
168 
169 /** Associate a node ID with subsequent drawing commands in an
170     SkCanvas.  The same node ID can appear in a StructureElementNode
171     in order to associate a document's structure element tree with
172     its content.
173 
174     A node ID of zero indicates no node ID.
175 
176     @param canvas  The canvas used to draw to the PDF.
177     @param nodeId  The node ID for subsequent drawing commands.
178 */
179 SK_API void SetNodeId(SkCanvas* dst, int nodeID);
180 
181 /** Create a PDF-backed document, writing the results into a SkWStream.
182 
183     PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.
184 
185     @param stream A PDF document will be written to this stream.  The document may write
186            to the stream at anytime during its lifetime, until either close() is
187            called or the document is deleted.
188     @param metadata a PDFmetadata object.  Any fields may be left empty.
189 
190     @returns NULL if there is an error, otherwise a newly created PDF-backed SkDocument.
191 */
192 SK_API sk_sp<SkDocument> MakeDocument(SkWStream* stream, const Metadata& metadata);
193 
MakeDocument(SkWStream * stream)194 static inline sk_sp<SkDocument> MakeDocument(SkWStream* stream) {
195     return MakeDocument(stream, Metadata());
196 }
197 
198 }  // namespace SkPDF
199 
200 #undef SKPDF_STRING
201 #undef SKPDF_STRING_IMPL
202 #endif  // SkPDFDocument_DEFINED
203