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