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