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 SkPDFCatalog_DEFINED
     11 #define SkPDFCatalog_DEFINED
     12 
     13 #include <sys/types.h>
     14 
     15 #include "SkPDFDocument.h"
     16 #include "SkPDFTypes.h"
     17 #include "SkRefCnt.h"
     18 #include "SkTDArray.h"
     19 
     20 /** \class SkPDFCatalog
     21 
     22     The PDF catalog manages object numbers and file offsets.  It is used
     23     to create the PDF cross reference table.
     24 */
     25 class SkPDFCatalog {
     26 public:
     27     /** Create a PDF catalog.
     28      */
     29     explicit SkPDFCatalog(SkPDFDocument::Flags flags);
     30     ~SkPDFCatalog();
     31 
     32     /** Add the passed object to the catalog.  Refs obj.
     33      *  @param obj         The object to add.
     34      *  @param onFirstPage Is the object on the first page.
     35      *  @return The obj argument is returned.
     36      */
     37     SkPDFObject* addObject(SkPDFObject* obj, bool onFirstPage);
     38 
     39     /** Inform the catalog of the object's position in the final stream.
     40      *  The object should already have been added to the catalog.  Returns
     41      *  the object's size.
     42      *  @param obj         The object to add.
     43      *  @param offset      The byte offset in the output stream of this object.
     44      */
     45     size_t setFileOffset(SkPDFObject* obj, off_t offset);
     46 
     47     /** Output the object number for the passed object.
     48      *  @param obj         The object of interest.
     49      *  @param stream      The writable output stream to send the output to.
     50      */
     51     void emitObjectNumber(SkWStream* stream, SkPDFObject* obj);
     52 
     53     /** Return the number of bytes that would be emitted for the passed
     54      *  object's object number.
     55      *  @param obj         The object of interest
     56      */
     57     size_t getObjectNumberSize(SkPDFObject* obj);
     58 
     59     /** Return the document flags in effect for this catalog/document.
     60      */
     61     SkPDFDocument::Flags getDocumentFlags() const { return fDocumentFlags; }
     62 
     63     /** Output the cross reference table for objects in the catalog.
     64      *  Returns the total number of objects.
     65      *  @param stream      The writable output stream to send the output to.
     66      *  @param firstPage   If true, include first page objects only, otherwise
     67      *                     include all objects not on the first page.
     68      */
     69     int32_t emitXrefTable(SkWStream* stream, bool firstPage);
     70 
     71     /** Set substitute object for the passed object.
     72      */
     73     void setSubstitute(SkPDFObject* original, SkPDFObject* substitute);
     74 
     75     /** Find and return any substitute object set for the passed object. If
     76      *  there is none, return the passed object.
     77      */
     78     SkPDFObject* getSubstituteObject(SkPDFObject* object);
     79 
     80     /** Set file offsets for the resources of substitute objects.
     81      *  @param fileOffset Accumulated offset of current document.
     82      *  @param firstPage  Indicate whether this is for the first page only.
     83      *  @return           Total size of resources of substitute objects.
     84      */
     85     off_t setSubstituteResourcesOffsets(off_t fileOffset, bool firstPage);
     86 
     87     /** Emit the resources of substitute objects.
     88      */
     89     void emitSubstituteResources(SkWStream* stream, bool firstPage);
     90 
     91 private:
     92     struct Rec {
     93         Rec(SkPDFObject* object, bool onFirstPage)
     94             : fObject(object),
     95               fFileOffset(0),
     96               fObjNumAssigned(false),
     97               fOnFirstPage(onFirstPage) {
     98         }
     99         SkPDFObject* fObject;
    100         off_t fFileOffset;
    101         bool fObjNumAssigned;
    102         bool fOnFirstPage;
    103     };
    104 
    105     struct SubstituteMapping {
    106         SubstituteMapping(SkPDFObject* original, SkPDFObject* substitute)
    107             : fOriginal(original), fSubstitute(substitute) {
    108         }
    109         SkPDFObject* fOriginal;
    110         SkPDFObject* fSubstitute;
    111     };
    112 
    113     // TODO(vandebo): Make this a hash if it's a performance problem.
    114     SkTDArray<struct Rec> fCatalog;
    115 
    116     // TODO(arthurhsu): Make this a hash if it's a performance problem.
    117     SkTDArray<SubstituteMapping> fSubstituteMap;
    118     SkTSet<SkPDFObject*> fSubstituteResourcesFirstPage;
    119     SkTSet<SkPDFObject*> fSubstituteResourcesRemaining;
    120 
    121     // Number of objects on the first page.
    122     uint32_t fFirstPageCount;
    123     // Next object number to assign (on page > 1).
    124     uint32_t fNextObjNum;
    125     // Next object number to assign on the first page.
    126     uint32_t fNextFirstPageObjNum;
    127 
    128     SkPDFDocument::Flags fDocumentFlags;
    129 
    130     int findObjectIndex(SkPDFObject* obj) const;
    131 
    132     int assignObjNum(SkPDFObject* obj);
    133 
    134     SkTSet<SkPDFObject*>* getSubstituteList(bool firstPage);
    135 };
    136 
    137 #endif
    138