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 */ getDocumentFlags()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 { RecRec93 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 { SubstituteMappingSubstituteMapping106 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