1
2/*
3 * Copyright 2010 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkPDFTypes_DEFINED
11#define SkPDFTypes_DEFINED
12
13#include "SkRefCnt.h"
14#include "SkScalar.h"
15#include "SkString.h"
16#include "SkTDArray.h"
17#include "SkTSet.h"
18#include "SkTypes.h"
19
20class SkPDFCatalog;
21class SkWStream;
22
23/** \class SkPDFObject
24
25    A PDF Object is the base class for primitive elements in a PDF file.  A
26    common subtype is used to ease the use of indirect object references,
27    which are common in the PDF format.
28*/
29class SkPDFObject : public SkRefCnt {
30public:
31    SK_DECLARE_INST_COUNT(SkPDFObject)
32
33    /** Return the size (number of bytes) of this object in the final output
34     *  file. Compound objects or objects that are computationally intensive
35     *  to output should override this method.
36     *  @param catalog  The object catalog to use.
37     *  @param indirect If true, output an object identifier with the object.
38     */
39    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
40
41    /** For non-primitive objects (i.e. objects defined outside this file),
42     *  this method will add to newResourceObjects any objects that this method
43     *  depends on, but not already in knownResourceObjects. This operates
44     *  recursively so if this object depends on another object and that object
45     *  depends on two more, all three objects will be added.
46     *
47     *  @param knownResourceObjects  The set of resources to be ignored.
48     *  @param newResourceObjects  The set to append dependant resources to.
49     */
50    virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
51                              SkTSet<SkPDFObject*>* newResourceObjects);
52
53    /** Emit this object unless the catalog has a substitute object, in which
54     *  case emit that.
55     *  @see emitObject
56     */
57    void emit(SkWStream* stream, SkPDFCatalog* catalog, bool indirect);
58
59    /** Helper function to output an indirect object.
60     *  @param catalog The object catalog to use.
61     *  @param stream  The writable output stream to send the output to.
62     */
63    void emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog);
64
65    /** Helper function to find the size of an indirect object.
66     *  @param catalog The object catalog to use.
67     */
68    size_t getIndirectOutputSize(SkPDFCatalog* catalog);
69
70    /** Static helper function to add a resource to a list.  The list takes
71     *  a reference.
72     * @param resource  The resource to add.
73     * @param list      The list to add the resource to.
74     */
75    static void AddResourceHelper(SkPDFObject* resource,
76                                  SkTDArray<SkPDFObject*>* list);
77
78    /** Static helper function to copy and reference the resources (and all
79     *   their subresources) into a new list.
80     * @param resources The resource list.
81     * @param newResourceObjects All the resource objects (recursively) used on
82     *                         the page are added to this array.  This gives
83     *                         the caller a chance to deduplicate resources
84     *                         across pages.
85     * @param knownResourceObjects  The set of resources to be ignored.
86     */
87    static void GetResourcesHelper(
88            const SkTDArray<SkPDFObject*>* resources,
89            const SkTSet<SkPDFObject*>& knownResourceObjects,
90            SkTSet<SkPDFObject*>* newResourceObjects);
91
92protected:
93    /** Subclasses must implement this method to print the object to the
94     *  PDF file.
95     *  @param catalog  The object catalog to use.
96     *  @param indirect If true, output an object identifier with the object.
97     *  @param stream   The writable output stream to send the output to.
98     */
99    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
100                            bool indirect) = 0;
101
102        typedef SkRefCnt INHERITED;
103};
104
105/** \class SkPDFObjRef
106
107    An indirect reference to a PDF object.
108*/
109class SkPDFObjRef : public SkPDFObject {
110public:
111    SK_DECLARE_INST_COUNT(SkPDFObjRef)
112
113    /** Create a reference to an existing SkPDFObject.
114     *  @param obj The object to reference.
115     */
116    explicit SkPDFObjRef(SkPDFObject* obj);
117    virtual ~SkPDFObjRef();
118
119    // The SkPDFObject interface.
120    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
121                            bool indirect);
122    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
123
124private:
125    SkAutoTUnref<SkPDFObject> fObj;
126
127    typedef SkPDFObject INHERITED;
128};
129
130/** \class SkPDFInt
131
132    An integer object in a PDF.
133*/
134class SkPDFInt : public SkPDFObject {
135public:
136    SK_DECLARE_INST_COUNT(SkPDFInt)
137
138    /** Create a PDF integer (usually for indirect reference purposes).
139     *  @param value An integer value between 2^31 - 1 and -2^31.
140     */
141    explicit SkPDFInt(int32_t value);
142    virtual ~SkPDFInt();
143
144    // The SkPDFObject interface.
145    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
146                            bool indirect);
147
148private:
149    int32_t fValue;
150
151    typedef SkPDFObject INHERITED;
152};
153
154/** \class SkPDFBool
155
156    An boolean value in a PDF.
157*/
158class SkPDFBool : public SkPDFObject {
159public:
160    SK_DECLARE_INST_COUNT(SkPDFBool)
161
162    /** Create a PDF boolean.
163     *  @param value true or false.
164     */
165    explicit SkPDFBool(bool value);
166    virtual ~SkPDFBool();
167
168    // The SkPDFObject interface.
169    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
170                            bool indirect);
171    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
172
173private:
174    bool fValue;
175
176    typedef SkPDFObject INHERITED;
177};
178
179/** \class SkPDFScalar
180
181    A real number object in a PDF.
182*/
183class SkPDFScalar : public SkPDFObject {
184public:
185    SK_DECLARE_INST_COUNT(SkPDFScalar)
186
187    /** Create a PDF real number.
188     *  @param value A real value.
189     */
190    explicit SkPDFScalar(SkScalar value);
191    virtual ~SkPDFScalar();
192
193    static void Append(SkScalar value, SkWStream* stream);
194
195    // The SkPDFObject interface.
196    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
197                            bool indirect);
198
199private:
200    SkScalar fValue;
201
202    typedef SkPDFObject INHERITED;
203};
204
205/** \class SkPDFString
206
207    A string object in a PDF.
208*/
209class SkPDFString : public SkPDFObject {
210public:
211    SK_DECLARE_INST_COUNT(SkPDFString)
212
213    /** Create a PDF string. Maximum length (in bytes) is 65,535.
214     *  @param value A string value.
215     */
216    explicit SkPDFString(const char value[]);
217    explicit SkPDFString(const SkString& value);
218
219    /** Create a PDF string. Maximum length (in bytes) is 65,535.
220     *  @param value     A string value.
221     *  @param len       The length of value.
222     *  @param wideChars Indicates if the top byte in value is significant and
223     *                   should be encoded (true) or not (false).
224     */
225    SkPDFString(const uint16_t* value, size_t len, bool wideChars);
226    virtual ~SkPDFString();
227
228    // The SkPDFObject interface.
229    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
230                            bool indirect);
231    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
232
233    static SkString FormatString(const char* input, size_t len);
234    static SkString FormatString(const uint16_t* input, size_t len,
235                                 bool wideChars);
236private:
237    static const size_t kMaxLen = 65535;
238
239    const SkString fValue;
240
241    static SkString DoFormatString(const void* input, size_t len,
242                                 bool wideInput, bool wideOutput);
243
244    typedef SkPDFObject INHERITED;
245};
246
247/** \class SkPDFName
248
249    A name object in a PDF.
250*/
251class SkPDFName : public SkPDFObject {
252public:
253    SK_DECLARE_INST_COUNT(SkPDFName)
254
255    /** Create a PDF name object. Maximum length is 127 bytes.
256     *  @param value The name.
257     */
258    explicit SkPDFName(const char name[]);
259    explicit SkPDFName(const SkString& name);
260    virtual ~SkPDFName();
261
262    bool operator==(const SkPDFName& b) const;
263
264    // The SkPDFObject interface.
265    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
266                            bool indirect);
267    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
268
269private:
270    static const size_t kMaxLen = 127;
271
272    const SkString fValue;
273
274    static SkString FormatName(const SkString& input);
275
276    typedef SkPDFObject INHERITED;
277};
278
279/** \class SkPDFArray
280
281    An array object in a PDF.
282*/
283class SkPDFArray : public SkPDFObject {
284public:
285    SK_DECLARE_INST_COUNT(SkPDFArray)
286
287    /** Create a PDF array. Maximum length is 8191.
288     */
289    SkPDFArray();
290    virtual ~SkPDFArray();
291
292    // The SkPDFObject interface.
293    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
294                            bool indirect);
295    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
296
297    /** The size of the array.
298     */
299    int size() { return fValue.count(); }
300
301    /** Preallocate space for the given number of entries.
302     *  @param length The number of array slots to preallocate.
303     */
304    void reserve(int length);
305
306    /** Returns the object at the given offset in the array.
307     *  @param index The index into the array to retrieve.
308     */
309    SkPDFObject* getAt(int index) { return fValue[index]; }
310
311    /** Set the object at the given offset in the array. Ref's value.
312     *  @param index The index into the array to set.
313     *  @param value The value to add to the array.
314     *  @return The value argument is returned.
315     */
316    SkPDFObject* setAt(int index, SkPDFObject* value);
317
318    /** Append the object to the end of the array and increments its ref count.
319     *  @param value The value to add to the array.
320     *  @return The value argument is returned.
321     */
322    SkPDFObject* append(SkPDFObject* value);
323
324    /** Creates a SkPDFInt object and appends it to the array.
325     *  @param value The value to add to the array.
326     */
327    void appendInt(int32_t value);
328
329    /** Creates a SkPDFScalar object and appends it to the array.
330     *  @param value The value to add to the array.
331     */
332    void appendScalar(SkScalar value);
333
334    /** Creates a SkPDFName object and appends it to the array.
335     *  @param value The value to add to the array.
336     */
337    void appendName(const char name[]);
338
339private:
340    static const int kMaxLen = 8191;
341    SkTDArray<SkPDFObject*> fValue;
342
343    typedef SkPDFObject INHERITED;
344};
345
346/** \class SkPDFDict
347
348    A dictionary object in a PDF.
349*/
350class SkPDFDict : public SkPDFObject {
351public:
352    SK_DECLARE_INST_COUNT(SkPDFDict)
353
354    /** Create a PDF dictionary. Maximum number of entries is 4095.
355     */
356    SkPDFDict();
357
358    /** Create a PDF dictionary with a Type entry.
359     *  @param type   The value of the Type entry.
360     */
361    explicit SkPDFDict(const char type[]);
362
363    virtual ~SkPDFDict();
364
365    // The SkPDFObject interface.
366    virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog,
367                            bool indirect);
368    virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
369
370    /** The size of the dictionary.
371     */
372    int size() { return fValue.count(); }
373
374    /** Add the value to the dictionary with the given key.  Refs value.
375     *  @param key   The key for this dictionary entry.
376     *  @param value The value for this dictionary entry.
377     *  @return The value argument is returned.
378     */
379    SkPDFObject* insert(SkPDFName* key, SkPDFObject* value);
380
381    /** Add the value to the dictionary with the given key.  Refs value.  The
382     *  method will create the SkPDFName object.
383     *  @param key   The text of the key for this dictionary entry.
384     *  @param value The value for this dictionary entry.
385     *  @return The value argument is returned.
386     */
387    SkPDFObject* insert(const char key[], SkPDFObject* value);
388
389    /** Add the int to the dictionary with the given key.
390     *  @param key   The text of the key for this dictionary entry.
391     *  @param value The int value for this dictionary entry.
392     */
393    void insertInt(const char key[], int32_t value);
394
395    /**
396     *  Calls insertInt() but asserts in debug builds that the value can be represented
397     *  by an int32_t.
398     */
399    void insertInt(const char key[], size_t value) {
400        this->insertInt(key, SkToS32(value));
401    }
402
403    /** Add the scalar to the dictionary with the given key.
404     *  @param key   The text of the key for this dictionary entry.
405     *  @param value The scalar value for this dictionary entry.
406     */
407    void insertScalar(const char key[], SkScalar value);
408
409    /** Add the name to the dictionary with the given key.
410     *  @param key   The text of the key for this dictionary entry.
411     *  @param name  The name for this dictionary entry.
412     */
413    void insertName(const char key[], const char name[]);
414
415    /** Add the name to the dictionary with the given key.
416     *  @param key   The text of the key for this dictionary entry.
417     *  @param name  The name for this dictionary entry.
418     */
419    void insertName(const char key[], const SkString& name) {
420        this->insertName(key, name.c_str());
421    }
422
423    /** Remove all entries from the dictionary.
424     */
425    void clear();
426
427private:
428    struct Rec {
429      SkPDFName* key;
430      SkPDFObject* value;
431    };
432
433public:
434    class Iter {
435    public:
436        explicit Iter(const SkPDFDict& dict);
437        SkPDFName* next(SkPDFObject** value);
438
439    private:
440        const Rec* fIter;
441        const Rec* fStop;
442    };
443
444private:
445    static const int kMaxLen = 4095;
446
447    SkTDArray<struct Rec> fValue;
448
449    typedef SkPDFObject INHERITED;
450};
451
452#endif
453