• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 class SkPDFCatalog;
21 class 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 */
29 class SkPDFObject : public SkRefCnt {
30 public:
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 
92 protected:
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 */
109 class SkPDFObjRef : public SkPDFObject {
110 public:
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 
124 private:
125     SkAutoTUnref<SkPDFObject> fObj;
126 
127     typedef SkPDFObject INHERITED;
128 };
129 
130 /** \class SkPDFInt
131 
132     An integer object in a PDF.
133 */
134 class SkPDFInt : public SkPDFObject {
135 public:
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 
148 private:
149     int32_t fValue;
150 
151     typedef SkPDFObject INHERITED;
152 };
153 
154 /** \class SkPDFBool
155 
156     An boolean value in a PDF.
157 */
158 class SkPDFBool : public SkPDFObject {
159 public:
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 
173 private:
174     bool fValue;
175 
176     typedef SkPDFObject INHERITED;
177 };
178 
179 /** \class SkPDFScalar
180 
181     A real number object in a PDF.
182 */
183 class SkPDFScalar : public SkPDFObject {
184 public:
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 
199 private:
200     SkScalar fValue;
201 
202     typedef SkPDFObject INHERITED;
203 };
204 
205 /** \class SkPDFString
206 
207     A string object in a PDF.
208 */
209 class SkPDFString : public SkPDFObject {
210 public:
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);
236 private:
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 */
251 class SkPDFName : public SkPDFObject {
252 public:
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 
269 private:
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 */
283 class SkPDFArray : public SkPDFObject {
284 public:
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      */
size()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      */
getAt(int index)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 
339 private:
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 */
350 class SkPDFDict : public SkPDFObject {
351 public:
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      */
size()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      */
insertInt(const char key[],size_t value)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      */
insertName(const char key[],const SkString & name)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 
427 private:
428     struct Rec {
429       SkPDFName* key;
430       SkPDFObject* value;
431     };
432 
433 public:
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 
444 private:
445     static const int kMaxLen = 4095;
446 
447     SkTDArray<struct Rec> fValue;
448 
449     typedef SkPDFObject INHERITED;
450 };
451 
452 #endif
453