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
23class SkData;
24class SkPDFArray;
25
26class SkPDFDict;
27class SkPDFDocument;
28class SkPDFObject;
29class SkPDFUnion;
30class SkStreamAsset;
31class SkString;
32class SkWStream;
33struct SkPDFObjectSerializer;
34
35struct SkPDFIndirectReference {
36 int fValue = -1;
37 explicit operator bool() { return fValue != -1; }
38};
39
40inline static bool operator==(SkPDFIndirectReference u, SkPDFIndirectReference v) {
41 return u.fValue == v.fValue;
42}
43
44inline 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*/
55class SkPDFObject {
56public:
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
68private:
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*/
81class SkPDFArray final : public SkPDFObject {
82public:
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
114private:
115 std::vector<SkPDFUnion> fValues;
116 void append(SkPDFUnion&& value);
117};
118
119static inline void SkPDFArray_Append(SkPDFArray* a, int v) { a->appendInt(v); }
120
121static inline void SkPDFArray_Append(SkPDFArray* a, SkScalar v) { a->appendScalar(v); }
122
123template <typename T, typename... Args>
124static inline void SkPDFArray_Append(SkPDFArray* a, T v, Args... args) {
125 SkPDFArray_Append(a, v);
126 SkPDFArray_Append(a, args...);
127}
128
129static inline void SkPDFArray_Append(SkPDFArray* a) {}
130
131template <typename... Args>
132static 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*/
143class SkPDFDict final : public SkPDFObject {
144public:
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
185private:
186 std::vector<std::pair<SkPDFUnion, SkPDFUnion>> fRecords;
187};
188
189static 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
199SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr<SkPDFDict> dict,
200 std::unique_ptr<SkStreamAsset> stream,
201 SkPDFDocument* doc,
202 bool deflate = kSkPDFDefaultDoDeflate);
203#endif
204