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