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