/* * Copyright 2010 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkPDFCatalog_DEFINED #define SkPDFCatalog_DEFINED #include <sys/types.h> #include "SkPDFDocument.h" #include "SkPDFTypes.h" #include "SkRefCnt.h" #include "SkTDArray.h" /** \class SkPDFCatalog The PDF catalog manages object numbers and file offsets. It is used to create the PDF cross reference table. */ class SkPDFCatalog { public: /** Create a PDF catalog. */ explicit SkPDFCatalog(SkPDFDocument::Flags flags); ~SkPDFCatalog(); /** Add the passed object to the catalog. Refs obj. * @param obj The object to add. * @param onFirstPage Is the object on the first page. * @return The obj argument is returned. */ SkPDFObject* addObject(SkPDFObject* obj, bool onFirstPage); /** Inform the catalog of the object's position in the final stream. * The object should already have been added to the catalog. Returns * the object's size. * @param obj The object to add. * @param offset The byte offset in the output stream of this object. */ size_t setFileOffset(SkPDFObject* obj, off_t offset); /** Output the object number for the passed object. * @param obj The object of interest. * @param stream The writable output stream to send the output to. */ void emitObjectNumber(SkWStream* stream, SkPDFObject* obj); /** Return the number of bytes that would be emitted for the passed * object's object number. * @param obj The object of interest */ size_t getObjectNumberSize(SkPDFObject* obj); /** Return the document flags in effect for this catalog/document. */ SkPDFDocument::Flags getDocumentFlags() const { return fDocumentFlags; } /** Output the cross reference table for objects in the catalog. * Returns the total number of objects. * @param stream The writable output stream to send the output to. * @param firstPage If true, include first page objects only, otherwise * include all objects not on the first page. */ int32_t emitXrefTable(SkWStream* stream, bool firstPage); /** Set substitute object for the passed object. */ void setSubstitute(SkPDFObject* original, SkPDFObject* substitute); /** Find and return any substitute object set for the passed object. If * there is none, return the passed object. */ SkPDFObject* getSubstituteObject(SkPDFObject* object); /** Set file offsets for the resources of substitute objects. * @param fileOffset Accumulated offset of current document. * @param firstPage Indicate whether this is for the first page only. * @return Total size of resources of substitute objects. */ off_t setSubstituteResourcesOffsets(off_t fileOffset, bool firstPage); /** Emit the resources of substitute objects. */ void emitSubstituteResources(SkWStream* stream, bool firstPage); private: struct Rec { Rec(SkPDFObject* object, bool onFirstPage) : fObject(object), fFileOffset(0), fObjNumAssigned(false), fOnFirstPage(onFirstPage) { } SkPDFObject* fObject; off_t fFileOffset; bool fObjNumAssigned; bool fOnFirstPage; }; struct SubstituteMapping { SubstituteMapping(SkPDFObject* original, SkPDFObject* substitute) : fOriginal(original), fSubstitute(substitute) { } SkPDFObject* fOriginal; SkPDFObject* fSubstitute; }; // TODO(vandebo): Make this a hash if it's a performance problem. SkTDArray<struct Rec> fCatalog; // TODO(arthurhsu): Make this a hash if it's a performance problem. SkTDArray<SubstituteMapping> fSubstituteMap; SkTDArray<SkPDFObject*> fSubstituteResourcesFirstPage; SkTDArray<SkPDFObject*> fSubstituteResourcesRemaining; // Number of objects on the first page. uint32_t fFirstPageCount; // Next object number to assign (on page > 1). uint32_t fNextObjNum; // Next object number to assign on the first page. uint32_t fNextFirstPageObjNum; SkPDFDocument::Flags fDocumentFlags; int findObjectIndex(SkPDFObject* obj) const; int assignObjNum(SkPDFObject* obj); SkTDArray<SkPDFObject*>* getSubstituteList(bool firstPage); }; #endif