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