1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 The Android Open Source Project
48459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org */
88459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#ifndef SkPDFCatalog_DEFINED
118459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#define SkPDFCatalog_DEFINED
128459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
138af0b361657b0de0dd3183996976e9c557d7ae41vandebo@chromium.org#include <sys/types.h>
148af0b361657b0de0dd3183996976e9c557d7ae41vandebo@chromium.org
15421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org#include "SkPDFDocument.h"
168459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#include "SkPDFTypes.h"
178459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#include "SkRefCnt.h"
188459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#include "SkTDArray.h"
198459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
208459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org/** \class SkPDFCatalog
218459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
22f66025d59ab4c8c4439fabf6ad89ddf35a19d1fdvandebo@chromium.org    The PDF catalog manages object numbers and file offsets.  It is used
23f66025d59ab4c8c4439fabf6ad89ddf35a19d1fdvandebo@chromium.org    to create the PDF cross reference table.
248459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org*/
257d6c8f997f8fe2c222f9d6d31f984c2e7cf16cc5vandebo@chromium.orgclass SkPDFCatalog {
268459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.orgpublic:
278459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    /** Create a PDF catalog.
288459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org     */
29421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org    explicit SkPDFCatalog(SkPDFDocument::Flags flags);
30f66025d59ab4c8c4439fabf6ad89ddf35a19d1fdvandebo@chromium.org    ~SkPDFCatalog();
318459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
32f7c157610ff85f7323f5e213b62478dcc66edbecvandebo@chromium.org    /** Add the passed object to the catalog.  Refs obj.
33d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param obj         The object to add.
34d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param onFirstPage Is the object on the first page.
35f7c157610ff85f7323f5e213b62478dcc66edbecvandebo@chromium.org     *  @return The obj argument is returned.
368459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org     */
37f7c157610ff85f7323f5e213b62478dcc66edbecvandebo@chromium.org    SkPDFObject* addObject(SkPDFObject* obj, bool onFirstPage);
388459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
39d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    /** Inform the catalog of the object's position in the final stream.
40d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  The object should already have been added to the catalog.  Returns
41d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  the object's size.
42d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param obj         The object to add.
43d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param offset      The byte offset in the output stream of this object.
44d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     */
4530580f69493fd8aa86c223736b4f7564ce458760vandebo@chromium.org    size_t setFileOffset(SkPDFObject* obj, off_t offset);
46d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
478459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    /** Output the object number for the passed object.
48d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param obj         The object of interest.
49d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param stream      The writable output stream to send the output to.
508459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org     */
518459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    void emitObjectNumber(SkWStream* stream, SkPDFObject* obj);
528459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
538459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    /** Return the number of bytes that would be emitted for the passed
548459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org     *  object's object number.
55d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param obj         The object of interest
568459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org     */
578459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    size_t getObjectNumberSize(SkPDFObject* obj);
588459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
59421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org    /** Return the document flags in effect for this catalog/document.
60421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org     */
61421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org    SkPDFDocument::Flags getDocumentFlags() const { return fDocumentFlags; }
62421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org
63d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    /** Output the cross reference table for objects in the catalog.
64d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  Returns the total number of objects.
65d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param stream      The writable output stream to send the output to.
66d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *  @param firstPage   If true, include first page objects only, otherwise
67d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     *                     include all objects not on the first page.
68d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org     */
69d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    int32_t emitXrefTable(SkWStream* stream, bool firstPage);
70d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
712ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    /** Set substitute object for the passed object.
722ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     */
732ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    void setSubstitute(SkPDFObject* original, SkPDFObject* substitute);
742ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
752ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    /** Find and return any substitute object set for the passed object. If
762ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     *  there is none, return the passed object.
772ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     */
782ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    SkPDFObject* getSubstituteObject(SkPDFObject* object);
792ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
802ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    /** Set file offsets for the resources of substitute objects.
812ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     *  @param fileOffset Accumulated offset of current document.
822ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     *  @param firstPage  Indicate whether this is for the first page only.
83f5181a496d79b0dbe4d96195157b25308437cf93vandebo@chromium.org     *  @return           Total size of resources of substitute objects.
842ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     */
852ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    off_t setSubstituteResourcesOffsets(off_t fileOffset, bool firstPage);
862ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
872ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    /** Emit the resources of substitute objects.
882ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org     */
892ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    void emitSubstituteResources(SkWStream* stream, bool firstPage);
902ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
918459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.orgprivate:
928459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    struct Rec {
938459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org        Rec(SkPDFObject* object, bool onFirstPage)
948459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org            : fObject(object),
958459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org              fFileOffset(0),
968459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org              fObjNumAssigned(false),
978459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org              fOnFirstPage(onFirstPage) {
988459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org        }
998459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org        SkPDFObject* fObject;
1008459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org        off_t fFileOffset;
1018459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org        bool fObjNumAssigned;
1028459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org        bool fOnFirstPage;
1038459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    };
1048459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
1052ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    struct SubstituteMapping {
1062ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org        SubstituteMapping(SkPDFObject* original, SkPDFObject* substitute)
1072ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org            : fOriginal(original), fSubstitute(substitute) {
1082ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org        }
1092ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org        SkPDFObject* fOriginal;
1102ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org        SkPDFObject* fSubstitute;
1112ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    };
1122ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
113769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    // TODO(vandebo): Make this a hash if it's a performance problem.
1148459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    SkTDArray<struct Rec> fCatalog;
1158459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
116769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    // TODO(arthurhsu): Make this a hash if it's a performance problem.
1172ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org    SkTDArray<SubstituteMapping> fSubstituteMap;
1186addb1930013ebb2f984045141650fd7afcfa90fedisonn@google.com    SkTSet<SkPDFObject*> fSubstituteResourcesFirstPage;
1196addb1930013ebb2f984045141650fd7afcfa90fedisonn@google.com    SkTSet<SkPDFObject*> fSubstituteResourcesRemaining;
1202ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
121d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    // Number of objects on the first page.
122d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    uint32_t fFirstPageCount;
123d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    // Next object number to assign (on page > 1).
1248459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    uint32_t fNextObjNum;
125d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    // Next object number to assign on the first page.
126d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    uint32_t fNextFirstPageObjNum;
1278459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
128421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org    SkPDFDocument::Flags fDocumentFlags;
129421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org
1308459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    int findObjectIndex(SkPDFObject* obj) const;
1318459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
1328459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org    int assignObjNum(SkPDFObject* obj);
1332ef12d4bb54312091d644f0ada3639c51c9f6e5avandebo@chromium.org
1346addb1930013ebb2f984045141650fd7afcfa90fedisonn@google.com    SkTSet<SkPDFObject*>* getSubstituteList(bool firstPage);
1358459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org};
1368459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org
1378459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#endif
138