Line data Source code
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 :
9 : #ifndef SkPDFTypes_DEFINED
10 : #define SkPDFTypes_DEFINED
11 :
12 : #include "SkRefCnt.h"
13 : #include "SkScalar.h"
14 : #include "SkTHash.h"
15 : #include "SkTypes.h"
16 :
17 : class SkData;
18 : class SkPDFObjNumMap;
19 : class SkPDFObject;
20 : class SkStreamAsset;
21 : class SkString;
22 : class SkWStream;
23 :
24 : #ifdef SK_PDF_IMAGE_STATS
25 : #include "SkAtomics.h"
26 : #endif
27 :
28 : /** \class SkPDFObject
29 :
30 : A PDF Object is the base class for primitive elements in a PDF file. A
31 : common subtype is used to ease the use of indirect object references,
32 : which are common in the PDF format.
33 :
34 : */
35 0 : class SkPDFObject : public SkRefCnt {
36 : public:
37 : /** Subclasses must implement this method to print the object to the
38 : * PDF file.
39 : * @param catalog The object catalog to use.
40 : * @param stream The writable output stream to send the output to.
41 : */
42 : virtual void emitObject(SkWStream* stream,
43 : const SkPDFObjNumMap& objNumMap) const = 0;
44 :
45 : /**
46 : * Adds all transitive dependencies of this object to the
47 : * catalog. Implementations should respect the catalog's object
48 : * substitution map.
49 : */
50 0 : virtual void addResources(SkPDFObjNumMap* catalog) const {}
51 :
52 : /**
53 : * Release all resources associated with this SkPDFObject. It is
54 : * an error to call emitObject() or addResources() after calling
55 : * drop().
56 : */
57 0 : virtual void drop() {}
58 :
59 0 : virtual ~SkPDFObject() {}
60 : private:
61 : typedef SkRefCnt INHERITED;
62 : };
63 :
64 : ////////////////////////////////////////////////////////////////////////////////
65 :
66 : /**
67 : A SkPDFUnion is a non-virtualized implementation of the
68 : non-compound, non-specialized PDF Object types: Name, String,
69 : Number, Boolean.
70 : */
71 : class SkPDFUnion {
72 : public:
73 : // Move contstructor and assignemnt operator destroy the argument
74 : // and steal their references (if needed).
75 : SkPDFUnion(SkPDFUnion&& other);
76 : SkPDFUnion& operator=(SkPDFUnion&& other);
77 :
78 : ~SkPDFUnion();
79 :
80 : /** The following nine functions are the standard way of creating
81 : SkPDFUnion objects. */
82 :
83 : static SkPDFUnion Int(int32_t);
84 :
85 0 : static SkPDFUnion Int(size_t v) { return SkPDFUnion::Int(SkToS32(v)); }
86 :
87 : static SkPDFUnion Bool(bool);
88 :
89 : static SkPDFUnion Scalar(SkScalar);
90 :
91 : static SkPDFUnion ColorComponent(uint8_t);
92 :
93 : /** These two functions do NOT take ownership of char*, and do NOT
94 : copy the string. Suitable for passing in static const
95 : strings. For example:
96 : SkPDFUnion n = SkPDFUnion::Name("Length");
97 : SkPDFUnion u = SkPDFUnion::String("Identity"); */
98 :
99 : /** SkPDFUnion::Name(const char*) assumes that the passed string
100 : is already a valid name (that is: it has no control or
101 : whitespace characters). This will not copy the name. */
102 : static SkPDFUnion Name(const char*);
103 :
104 : /** SkPDFUnion::String will encode the passed string. This will
105 : not copy the name. */
106 : static SkPDFUnion String(const char*);
107 :
108 : /** SkPDFUnion::Name(const SkString&) does not assume that the
109 : passed string is already a valid name and it will escape the
110 : string. */
111 : static SkPDFUnion Name(const SkString&);
112 :
113 : /** SkPDFUnion::String will encode the passed string. */
114 : static SkPDFUnion String(const SkString&);
115 :
116 : static SkPDFUnion Object(sk_sp<SkPDFObject>);
117 : static SkPDFUnion ObjRef(sk_sp<SkPDFObject>);
118 :
119 : /** These two non-virtual methods mirror SkPDFObject's
120 : corresponding virtuals. */
121 : void emitObject(SkWStream*, const SkPDFObjNumMap&) const;
122 : void addResources(SkPDFObjNumMap*) const;
123 :
124 : bool isName() const;
125 :
126 : private:
127 : union {
128 : int32_t fIntValue;
129 : bool fBoolValue;
130 : SkScalar fScalarValue;
131 : const char* fStaticString;
132 : char fSkString[sizeof(SkString)];
133 : SkPDFObject* fObject;
134 : };
135 : enum class Type : char {
136 : /** It is an error to call emitObject() or addResources() on an
137 : kDestroyed object. */
138 : kDestroyed = 0,
139 : kInt,
140 : kColorComponent,
141 : kBool,
142 : kScalar,
143 : kName,
144 : kString,
145 : kNameSkS,
146 : kStringSkS,
147 : kObjRef,
148 : kObject,
149 : };
150 : Type fType;
151 :
152 : SkPDFUnion(Type);
153 : // We do not now need copy constructor and copy assignment, so we
154 : // will disable this functionality.
155 : SkPDFUnion& operator=(const SkPDFUnion&) = delete;
156 : SkPDFUnion(const SkPDFUnion&) = delete;
157 : };
158 : static_assert(sizeof(SkString) == sizeof(void*), "SkString_size");
159 :
160 : ////////////////////////////////////////////////////////////////////////////////
161 :
162 : #if 0 // Enable if needed.
163 : /** This class is a SkPDFUnion with SkPDFObject virtuals attached.
164 : The only use case of this is when a non-compound PDF object is
165 : referenced indirectly. */
166 : class SkPDFAtom final : public SkPDFObject {
167 : public:
168 : void emitObject(SkWStream* stream,
169 : const SkPDFObjNumMap& objNumMap) final;
170 : void addResources(SkPDFObjNumMap* const final;
171 : SkPDFAtom(SkPDFUnion&& v) : fValue(std::move(v) {}
172 :
173 : private:
174 : const SkPDFUnion fValue;
175 : typedef SkPDFObject INHERITED;
176 : };
177 : #endif // 0
178 :
179 : ////////////////////////////////////////////////////////////////////////////////
180 :
181 : /** \class SkPDFArray
182 :
183 : An array object in a PDF.
184 : */
185 : class SkPDFArray final : public SkPDFObject {
186 : public:
187 : /** Create a PDF array. Maximum length is 8191.
188 : */
189 : SkPDFArray();
190 : ~SkPDFArray() override;
191 :
192 : // The SkPDFObject interface.
193 : void emitObject(SkWStream* stream,
194 : const SkPDFObjNumMap& objNumMap) const override;
195 : void addResources(SkPDFObjNumMap*) const override;
196 : void drop() override;
197 :
198 : /** The size of the array.
199 : */
200 : int size() const;
201 :
202 : /** Preallocate space for the given number of entries.
203 : * @param length The number of array slots to preallocate.
204 : */
205 : void reserve(int length);
206 :
207 : /** Appends a value to the end of the array.
208 : * @param value The value to add to the array.
209 : */
210 : void appendInt(int32_t);
211 : void appendColorComponent(uint8_t);
212 : void appendBool(bool);
213 : void appendScalar(SkScalar);
214 : void appendName(const char[]);
215 : void appendName(const SkString&);
216 : void appendString(const char[]);
217 : void appendString(const SkString&);
218 : void appendObject(sk_sp<SkPDFObject>);
219 : void appendObjRef(sk_sp<SkPDFObject>);
220 :
221 : private:
222 : SkTArray<SkPDFUnion> fValues;
223 : void append(SkPDFUnion&& value);
224 : SkDEBUGCODE(bool fDumped;)
225 : };
226 :
227 : /** \class SkPDFDict
228 :
229 : A dictionary object in a PDF.
230 : */
231 : class SkPDFDict : public SkPDFObject {
232 : public:
233 : /** Create a PDF dictionary.
234 : * @param type The value of the Type entry, nullptr for no type.
235 : */
236 : explicit SkPDFDict(const char type[] = nullptr);
237 :
238 : ~SkPDFDict() override;
239 :
240 : // The SkPDFObject interface.
241 : void emitObject(SkWStream* stream,
242 : const SkPDFObjNumMap& objNumMap) const override;
243 : void addResources(SkPDFObjNumMap*) const override;
244 : void drop() override;
245 :
246 : /** The size of the dictionary.
247 : */
248 : int size() const;
249 :
250 : /** Add the value to the dictionary with the given key.
251 : * @param key The text of the key for this dictionary entry.
252 : * @param value The value for this dictionary entry.
253 : */
254 : void insertObject(const char key[], sk_sp<SkPDFObject>);
255 : void insertObject(const SkString& key, sk_sp<SkPDFObject>);
256 : void insertObjRef(const char key[], sk_sp<SkPDFObject>);
257 : void insertObjRef(const SkString& key, sk_sp<SkPDFObject>);
258 :
259 : /** Add the value to the dictionary with the given key.
260 : * @param key The text of the key for this dictionary entry.
261 : * @param value The value for this dictionary entry.
262 : */
263 : void insertBool(const char key[], bool value);
264 : void insertInt(const char key[], int32_t value);
265 : void insertInt(const char key[], size_t value);
266 : void insertScalar(const char key[], SkScalar value);
267 : void insertName(const char key[], const char nameValue[]);
268 : void insertName(const char key[], const SkString& nameValue);
269 : void insertString(const char key[], const char value[]);
270 : void insertString(const char key[], const SkString& value);
271 :
272 : /** Emit the dictionary, without the "<<" and ">>".
273 : */
274 : void emitAll(SkWStream* stream,
275 : const SkPDFObjNumMap& objNumMap) const;
276 :
277 : private:
278 0 : struct Record {
279 : SkPDFUnion fKey;
280 : SkPDFUnion fValue;
281 : Record(SkPDFUnion&&, SkPDFUnion&&);
282 0 : Record(Record&&) = default;
283 : Record& operator=(Record&&) = default;
284 : Record(const Record&) = delete;
285 : Record& operator=(const Record&) = delete;
286 : };
287 : SkTArray<Record> fRecords;
288 : SkDEBUGCODE(bool fDumped;)
289 : };
290 :
291 : /** \class SkPDFSharedStream
292 :
293 : This class takes an asset and assumes that it is backed by
294 : long-lived shared data (for example, an open file
295 : descriptor). That is: no memory savings can be made by holding on
296 : to a compressed version instead.
297 : */
298 : class SkPDFSharedStream final : public SkPDFObject {
299 : public:
300 : SkPDFSharedStream(std::unique_ptr<SkStreamAsset> data);
301 : ~SkPDFSharedStream() override;
302 0 : SkPDFDict* dict() { return &fDict; }
303 : void emitObject(SkWStream*,
304 : const SkPDFObjNumMap&) const override;
305 : void addResources(SkPDFObjNumMap*) const override;
306 : void drop() override;
307 :
308 : private:
309 : std::unique_ptr<SkStreamAsset> fAsset;
310 : SkPDFDict fDict;
311 : typedef SkPDFObject INHERITED;
312 : };
313 :
314 : /** \class SkPDFStream
315 :
316 : This class takes an asset and assumes that it is the only owner of
317 : the asset's data. It immediately compresses the asset to save
318 : memory.
319 : */
320 :
321 : class SkPDFStream final : public SkPDFObject {
322 :
323 : public:
324 : /** Create a PDF stream. A Length entry is automatically added to the
325 : * stream dictionary.
326 : * @param data The data part of the stream.
327 : * @param stream The data part of the stream. */
328 : explicit SkPDFStream(sk_sp<SkData> data);
329 : explicit SkPDFStream(std::unique_ptr<SkStreamAsset> stream);
330 : ~SkPDFStream() override;
331 :
332 0 : SkPDFDict* dict() { return &fDict; }
333 :
334 : // The SkPDFObject interface.
335 : void emitObject(SkWStream* stream,
336 : const SkPDFObjNumMap& objNumMap) const override;
337 : void addResources(SkPDFObjNumMap*) const final;
338 : void drop() override;
339 :
340 : protected:
341 : /* Create a PDF stream with no data. The setData method must be called to
342 : * set the data. */
343 : SkPDFStream();
344 :
345 : /** Only call this function once. */
346 : void setData(std::unique_ptr<SkStreamAsset> stream);
347 :
348 : private:
349 : std::unique_ptr<SkStreamAsset> fCompressedData;
350 : SkPDFDict fDict;
351 :
352 : typedef SkPDFDict INHERITED;
353 : };
354 :
355 : ////////////////////////////////////////////////////////////////////////////////
356 :
357 : /** \class SkPDFObjNumMap
358 :
359 : The PDF Object Number Map manages object numbers. It is used to
360 : create the PDF cross reference table.
361 : */
362 0 : class SkPDFObjNumMap : SkNoncopyable {
363 : public:
364 : /** Add the passed object to the catalog.
365 : * @param obj The object to add.
366 : * @return True iff the object was not already added to the catalog.
367 : */
368 : bool addObject(SkPDFObject* obj);
369 :
370 : /** Add the passed object to the catalog, as well as all its dependencies.
371 : * @param obj The object to add. If nullptr, this is a noop.
372 : */
373 : void addObjectRecursively(SkPDFObject* obj);
374 :
375 : /** Get the object number for the passed object.
376 : * @param obj The object of interest.
377 : */
378 : int32_t getObjectNumber(SkPDFObject* obj) const;
379 :
380 0 : const SkTArray<sk_sp<SkPDFObject>>& objects() const { return fObjects; }
381 :
382 : private:
383 : SkTArray<sk_sp<SkPDFObject>> fObjects;
384 : SkTHashMap<SkPDFObject*, int32_t> fObjectNumbers;
385 : };
386 :
387 : ////////////////////////////////////////////////////////////////////////////////
388 :
389 : #ifdef SK_PDF_IMAGE_STATS
390 : extern SkAtomic<int> gDrawImageCalls;
391 : extern SkAtomic<int> gJpegImageObjects;
392 : extern SkAtomic<int> gRegularImageObjects;
393 : extern void SkPDFImageDumpStats();
394 : #endif // SK_PDF_IMAGE_STATS
395 :
396 : #endif
|