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