xref: /aosp_15_r20/external/skia/src/pdf/SkPDFTypes.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2010 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkPDFTypes_DEFINED
9 #define SkPDFTypes_DEFINED
10 
11 #include "include/core/SkScalar.h"
12 #include "include/core/SkTypes.h"
13 #include "src/pdf/SkPDFUnion.h"
14 
15 #include <cstddef>
16 #include <cstdint>
17 #include <memory>
18 #include <utility>
19 #include <vector>
20 
21 class SkPDFDocument;
22 class SkStreamAsset;
23 class SkString;
24 class SkWStream;
25 
26 struct SkPDFIndirectReference {
27     int fValue = -1;
28     explicit operator bool() const { return fValue != -1; }
29 
30     bool operator==(SkPDFIndirectReference v) const {
31         return fValue == v.fValue;
32     }
33 
34     bool operator!=(SkPDFIndirectReference v) const {
35         return fValue != v.fValue;
36     }
37 };
38 
39 /** \class SkPDFObject
40 
41     A PDF Object is the base class for primitive elements in a PDF file.  A
42     common subtype is used to ease the use of indirect object references,
43     which are common in the PDF format.
44 
45 */
46 class SkPDFObject {
47 public:
48     SkPDFObject() = default;
49 
50     /** Subclasses must implement this method to print the object to the
51      *  PDF file.
52      *  @param catalog  The object catalog to use.
53      *  @param stream   The writable output stream to send the output to.
54      */
55     virtual void emitObject(SkWStream* stream) const = 0;
56 
57     virtual ~SkPDFObject() = default;
58 
59 private:
60     SkPDFObject(SkPDFObject&&) = delete;
61     SkPDFObject(const SkPDFObject&) = delete;
62     SkPDFObject& operator=(SkPDFObject&&) = delete;
63     SkPDFObject& operator=(const SkPDFObject&) = delete;
64 };
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 
68 /** \class SkPDFArray
69 
70     An array object in a PDF.
71 */
72 class SkPDFArray final : public SkPDFObject {
73 public:
74     /** Create a PDF array. Maximum length is 8191.
75      */
76     SkPDFArray();
77     ~SkPDFArray() override;
78 
79     // The SkPDFObject interface.
80     void emitObject(SkWStream* stream) const override;
81 
82     /** The size of the array.
83      */
84     size_t size() const;
85 
86     /** Preallocate space for the given number of entries.
87      *  @param length The number of array slots to preallocate.
88      */
89     void reserve(int length);
90 
91     /** Appends a value to the end of the array.
92      *  @param value The value to add to the array.
93      */
94     void appendInt(int32_t);
95     void appendColorComponent(uint8_t);
96     void appendBool(bool);
97     void appendScalar(SkScalar);
98     void appendName(const char[]);
99     void appendName(SkString);
100     void appendByteString(const char[]);
101     void appendTextString(const char[]);
102     void appendByteString(SkString);
103     void appendTextString(SkString);
104     void appendObject(std::unique_ptr<SkPDFObject>&&);
105     void appendRef(SkPDFIndirectReference);
106 
107 private:
108     std::vector<SkPDFUnion> fValues;
109     void append(SkPDFUnion&& value);
110 };
111 
SkPDFArray_Append(SkPDFArray * a,int v)112 static inline void SkPDFArray_Append(SkPDFArray* a, int v) { a->appendInt(v); }
113 
SkPDFArray_Append(SkPDFArray * a,SkScalar v)114 static inline void SkPDFArray_Append(SkPDFArray* a, SkScalar v) { a->appendScalar(v); }
115 
116 template <typename T, typename... Args>
SkPDFArray_Append(SkPDFArray * a,T v,Args...args)117 static inline void SkPDFArray_Append(SkPDFArray* a, T v, Args... args) {
118     SkPDFArray_Append(a, v);
119     SkPDFArray_Append(a, args...);
120 }
121 
SkPDFArray_Append(SkPDFArray * a)122 static inline void SkPDFArray_Append(SkPDFArray* a) {}
123 
124 template <typename... Args>
SkPDFMakeArray(Args...args)125 static inline std::unique_ptr<SkPDFArray> SkPDFMakeArray(Args... args) {
126     std::unique_ptr<SkPDFArray> ret(new SkPDFArray());
127     ret->reserve(sizeof...(Args));
128     SkPDFArray_Append(ret.get(), args...);
129     return ret;
130 }
131 
132 /** \class SkPDFDict
133 
134     A dictionary object in a PDF.
135 */
136 class SkPDFDict final : public SkPDFObject {
137 public:
138     /** Create a PDF dictionary.
139      *  @param type   The value of the Type entry, nullptr for no type.
140      */
141     explicit SkPDFDict(const char type[] = nullptr);
142 
143     ~SkPDFDict() override;
144 
145     // The SkPDFObject interface.
146     void emitObject(SkWStream* stream) const override;
147 
148     /** The size of the dictionary.
149      */
150     size_t size() const;
151 
152     /** Preallocate space for n key-value pairs */
153     void reserve(int n);
154 
155     /** Add the value to the dictionary with the given key.
156      *  @param key   The text of the key for this dictionary entry.
157      *  @param value The value for this dictionary entry.
158      */
159     void insertObject(const char key[], std::unique_ptr<SkPDFObject>&&);
160     void insertObject(SkString, std::unique_ptr<SkPDFObject>&&);
161     void insertRef(const char key[], SkPDFIndirectReference);
162     void insertRef(SkString, SkPDFIndirectReference);
163 
164     /** Add the value to the dictionary with the given key.
165      *  @param key   The text of the key for this dictionary entry.
166      *  @param value The value for this dictionary entry.
167      */
168     void insertBool(const char key[], bool value);
169     void insertInt(const char key[], int32_t value);
170     void insertInt(const char key[], size_t value);
171     void insertScalar(const char key[], SkScalar value);
172     void insertColorComponentF(const char key[], SkScalar value);
173     void insertName(const char key[], const char nameValue[]);
174     void insertName(const char key[], SkString nameValue);
175     void insertByteString(const char key[], const char value[]);
176     void insertTextString(const char key[], const char value[]);
177     void insertByteString(const char key[], SkString value);
178     void insertTextString(const char key[], SkString value);
179     void insertUnion(const char key[], SkPDFUnion&&);
180 
181 private:
182     std::vector<std::pair<SkPDFUnion, SkPDFUnion>> fRecords;
183 };
184 
185 static inline std::unique_ptr<SkPDFDict> SkPDFMakeDict(const char* type = nullptr) {
186     return std::make_unique<SkPDFDict>(type);
187 }
188 
189 enum class SkPDFSteamCompressionEnabled : bool {
190     No = false,
191     Yes = true,
192     Default =
193 #ifdef SK_PDF_LESS_COMPRESSION
194         No,
195 #else
196         Yes,
197 #endif
198 };
199 
200 // Exposed for unit testing.
201 void SkPDFWriteTextString(SkWStream* wStream, const char* cin, size_t len);
202 void SkPDFWriteByteString(SkWStream* wStream, const char* cin, size_t len);
203 
204 SkPDFIndirectReference SkPDFStreamOut(
205     std::unique_ptr<SkPDFDict> dict,
206     std::unique_ptr<SkStreamAsset> stream,
207     SkPDFDocument* doc,
208     SkPDFSteamCompressionEnabled compress = SkPDFSteamCompressionEnabled::Default);
209 #endif
210