180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2010 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkPDFCatalog_DEFINED
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPDFCatalog_DEFINED
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <sys/types.h>
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPDFDocument.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPDFTypes.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRefCnt.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h"
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** \class SkPDFCatalog
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    The PDF catalog manages object numbers and file offsets.  It is used
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    to create the PDF cross reference table.
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkPDFCatalog {
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Create a PDF catalog.
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    explicit SkPDFCatalog(SkPDFDocument::Flags flags);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkPDFCatalog();
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Add the passed object to the catalog.  Refs obj.
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param obj         The object to add.
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param onFirstPage Is the object on the first page.
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @return The obj argument is returned.
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPDFObject* addObject(SkPDFObject* obj, bool onFirstPage);
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Inform the catalog of the object's position in the final stream.
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  The object should already have been added to the catalog.  Returns
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  the object's size.
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param obj         The object to add.
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param offset      The byte offset in the output stream of this object.
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t setFileOffset(SkPDFObject* obj, off_t offset);
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Output the object number for the passed object.
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param obj         The object of interest.
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param stream      The writable output stream to send the output to.
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void emitObjectNumber(SkWStream* stream, SkPDFObject* obj);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Return the number of bytes that would be emitted for the passed
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  object's object number.
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param obj         The object of interest
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t getObjectNumberSize(SkPDFObject* obj);
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Return the document flags in effect for this catalog/document.
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPDFDocument::Flags getDocumentFlags() const { return fDocumentFlags; }
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Output the cross reference table for objects in the catalog.
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Returns the total number of objects.
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param stream      The writable output stream to send the output to.
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param firstPage   If true, include first page objects only, otherwise
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *                     include all objects not on the first page.
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int32_t emitXrefTable(SkWStream* stream, bool firstPage);
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Set substitute object for the passed object.
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void setSubstitute(SkPDFObject* original, SkPDFObject* substitute);
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Find and return any substitute object set for the passed object. If
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  there is none, return the passed object.
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPDFObject* getSubstituteObject(SkPDFObject* object);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Set file offsets for the resources of substitute objects.
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param fileOffset Accumulated offset of current document.
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @param firstPage  Indicate whether this is for the first page only.
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  @return           Total size of resources of substitute objects.
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    off_t setSubstituteResourcesOffsets(off_t fileOffset, bool firstPage);
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Emit the resources of substitute objects.
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void emitSubstituteResources(SkWStream* stream, bool firstPage);
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Rec {
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Rec(SkPDFObject* object, bool onFirstPage)
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            : fObject(object),
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              fFileOffset(0),
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              fObjNumAssigned(false),
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              fOnFirstPage(onFirstPage) {
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPDFObject* fObject;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        off_t fFileOffset;
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool fObjNumAssigned;
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool fOnFirstPage;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct SubstituteMapping {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SubstituteMapping(SkPDFObject* original, SkPDFObject* substitute)
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            : fOriginal(original), fSubstitute(substitute) {
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPDFObject* fOriginal;
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPDFObject* fSubstitute;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO(vandebo): Make this a hash if it's a performance problem.
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<struct Rec> fCatalog;
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO(arthurhsu): Make this a hash if it's a performance problem.
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<SubstituteMapping> fSubstituteMap;
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkTSet<SkPDFObject*> fSubstituteResourcesFirstPage;
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkTSet<SkPDFObject*> fSubstituteResourcesRemaining;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Number of objects on the first page.
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t fFirstPageCount;
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Next object number to assign (on page > 1).
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t fNextObjNum;
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Next object number to assign on the first page.
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t fNextFirstPageObjNum;
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPDFDocument::Flags fDocumentFlags;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int findObjectIndex(SkPDFObject* obj) const;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int assignObjNum(SkPDFObject* obj);
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkTSet<SkPDFObject*>* getSubstituteList(bool firstPage);
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
138