Home | History | Annotate | Download | only in pdf
      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      */
    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 
    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      */
    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 
    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