#include <cpdf.h>
Inherits boost::noncopyable.
Classes | |
| class | PageTreeKidsObserver |
| class | PageTreeNodeObserver |
| class | PageTreeRootObserver |
Public Types | |
| enum | OpenMode { ReadOnly, ReadWrite, Advanced } |
| typedef unsigned | revision_t |
Public Member Functions | |
| cpdf_id_t | getId () const |
| CXref * | getCXref () const |
| configuration::ModeController * | getModeController () const |
| void | setModeController (configuration::ModeController *ctrl) |
| bool | isChanged () const |
| boost::shared_ptr< IProperty > | getIndirectProperty (const IndiRef &ref) const |
| IndiRef | addIndirectProperty (const boost::shared_ptr< IProperty > &prop, bool followRefs=false) |
| void | changeIndirectProperty (const boost::shared_ptr< IProperty > &prop) |
| void | save (bool newRevision=false) const |
| void | clone (FILE *fname) const |
| boost::shared_ptr< CDict > | getDictionary () const |
| boost::shared_ptr< const CDict > | getTrailer () const |
| void | changeTrailer (std::string &name, const boost::shared_ptr< IProperty > &value) |
| boost::shared_ptr< CPage > | insertPage (const boost::shared_ptr< CPage > &page, size_t pos) |
| void | removePage (size_t pos) |
| size_t | getPagePosition (const boost::shared_ptr< CPage > &page) const |
| unsigned int | getPageCount () const |
| boost::shared_ptr< CPage > | getPage (size_t pos) const |
| boost::shared_ptr< CPage > | getFirstPage () const |
| boost::shared_ptr< CPage > | getNextPage (const boost::shared_ptr< CPage > &page) const |
| boost::shared_ptr< CPage > | getPrevPage (const boost::shared_ptr< CPage > &page) const |
| bool | hasNextPage (const boost::shared_ptr< CPage > &page) const |
| bool | hasPrevPage (const boost::shared_ptr< CPage > &page) const |
| boost::shared_ptr< CPage > | getLastPage () const |
| OpenMode | getMode () const |
| bool | isLinearized () const |
| revision_t | getActualRevision () const |
| size_t | getRevisionSize (unsigned rev, bool includeXref=false) const |
| void | changeRevision (revision_t revisionNum) |
| size_t | getRevisionsCount () const |
| template<typename Container > | |
| void | getOutlines (Container &cont) const |
| utils::IPdfWriter * | getPdfWriter () |
| void | canChange () const |
| bool | needsCredentials () const |
| void | setCredentials (const char *ownerPasswd, const char *userPasswd) |
Static Public Member Functions | |
| static boost::shared_ptr< CPdf > | getInstance (const char *filename, OpenMode mode) |
Static Public Attributes | |
| static const cpdf_id_t | NO_PDF_ID = 0 |
Protected Types | |
| typedef std::vector< cpdf_id_t > | CPdfListContainer |
Protected Member Functions | |
| void | setPdfId () |
| void | releasePdfId () |
| void | unregisterPageObservers () |
| bool | consolidatePageTree (const boost::shared_ptr< CDict > &interNode, bool propagate=false) |
| void | consolidatePageList (const boost::shared_ptr< IProperty > &oldValue, const boost::shared_ptr< IProperty > &newValue) |
| IndiRef | registerIndirectProperty (const boost::shared_ptr< IProperty > &ip, IndiRef &ref) |
| void | registerPageTreeObservers (boost::shared_ptr< IProperty > &prop) |
| void | unregisterPageTreeObservers (boost::shared_ptr< IProperty > &prop, bool cleanup=false) |
| IndiRef | addProperty (const boost::shared_ptr< IProperty > &ip, IndiRef &indiRef, ResolvedRefStorage &storage, bool followRefs) |
| IndiRef | subsReferencies (const boost::shared_ptr< IProperty > &ip, ResolvedRefStorage &container, bool followRefs) |
Protected Attributes | |
| boost::shared_ptr < PageTreeRootObserver > | pageTreeRootObserver |
| boost::shared_ptr < PageTreeNodeObserver > | pageTreeNodeObserver |
| boost::shared_ptr < PageTreeKidsObserver > | pageTreeKidsObserver |
| ResolvedRefMapping | resolvedRefMapping |
Static Protected Attributes | |
| static CPdfListContainer | allPdfs = CPdf::CPdfListContainer() |
Private Types | |
| typedef std::map< size_t, boost::shared_ptr< CPage > > | PageList |
Private Member Functions | |
| void | initRevisionSpecific () |
| CPdf () | |
| CPdf (StreamWriter *stream, OpenMode openMode) | |
| ~CPdf () | |
| void | invalidate () |
Private Attributes | |
| cpdf_id_t | id |
| bool | change |
| IndirectMapping | indMap |
| boost::shared_ptr< CDict > | docCatalog |
| PageList | pageList |
| size_t | pageCount |
| PageTreeNodeCountCache | nodeCountCache |
| PageTreeKidsParentCache | pageTreeKidsParentCache |
| XRefWriter * | xref |
| OpenMode | mode |
| configuration::ModeController * | modeController |
| boost::weak_ptr< CPdf > | _this |
Friends | |
| class | PdfFileDeleter |
CPdf special object.
This class is responsible for pdf document maintainance. It provides wrapper on document catalog dictionary with advanced logic concerning revision handling, high level object creation and their synchronization with actual properties state and mode depending operations. Provides interface for making changes to document. In a result it provides fascade for all oparations which have document scope.
Instancing
Public constructor is not available and instances can be created on by static factory getInstance method. Also no public destructor is available because instance returned by getInstance methods is wrapped by shared_ptr smart pointer which keeps instance alive until reference to the pointer exists (this is based on reference counting scheme - see smart_ptr documentation for more information).
Open mode
Each document may be open in several modes. Each open mode brings specific handling of document manipulation. Open mode for document is set only in constructor and can't be changed during CPdf instance life cycle.
Document changes
CPdf instance contains XRefWriter typed field which maintains all changes to document content. It is not accessible outside from the class to keep full control over instance in CPdf. To enable using also xpdf code outside CPdf CXref casted supertype of XRefWriter is returned in getCXref. This instance doesn't enable any changes but enables access to most accurate indirect objects. Changes to XRefWriter can be done only by CPdf methods. Note that changes can be be done only in newest revision (
Document properties
Properties from document can be accessible from document catalog which is returned by getDictionary method. New indirect property, which may be used in some other property (by its reference) can be created by addIndirectProperty. Change of indirect property can be registered to the XRefWriter by changeIndirectProperty method. Finaly each indirect property is accessible by getIndirectProperty. All these methods are just some wrappers to XRefWriter internal field with CObject to xpdf Object conversion logic. Using them guaranties that all changes are synchronized correctly.
Pages maintainance
One of CPdf responsiblities is to keep CPage instances synchronized with current state of page tree. Page instances (CPage typed) can be obtained by getPage, getFirstPage, getLastPage, getNextPage, getPrevPage methods. All returned instances are kept in pageList to guarantee that request for page at same position returns same page instance (unless page tree is changed). CPdf uses several observers to keep this synchronization. Observer classes are inner to this class to have good access to protected and private fields. Each observer is specialized for one type of change in page tree:
insertPage and removePage enables inserting and removing new pages to the page tree. This way is prefered for making such changes. Other way (as mentioned above) is to change page tree directly using property interface. This way may lead to errors which are not recoverable (may destroy valid pdf page tree format) and so it is strongly discouraged unless you exactly know what you are doing and CPdf interface doesn't provide right way how to do it.
Pages are counted from 1 (first page) up to getPageCount return value. Note that this may not represent values used for inner page counting writen on the page. CPdf doesn't handle any kind of special document numbering.
Revision manipulation
CPdf provides interface also for document revision handling done in XRefWriter class. Actual revision number (the newest revision has the highest number and gets smaller towards the older revisions with the 0 used for the oldest one) can be obtained by getActualRevision method. Current revision can be changed by changeRevision method. As a result, just objects included until the current revisions are available. Also no changes can be done if revision is not the newest one, because PDF document doesn't support revision branching. All these operations are just delegated (after som checks) to XRefWriter.
All internal data structures which may depend on current revision are intialized and cleaned up in initRevisionSpecific method.
Note that linearized documents brings some restrictions and so no revision changing is supported by XRefWriter.
Document saving
Actual changes can be saved by save method. This works in two modes depending on given parameter. One creates new revision with changes, which means swithces to this revision whereas second approach saves changes to the end of file and doesn't change revision. Both of apporoaches have their pros and cons. Basicaly, new revision should be used if changes are ended and saving with no revision should be used if we want to temporarily store changes to prevent data lost by program crash or whatever problem.
Different way of page content storing is so called document clonig done by clone method. This method stores document content up to current revision. This enables to make snapshot of document of arbitrary revision to separate document and this document (as it has that revision as the newest one) enables making changes.
Implementation notes and limitations
This version of CPdf and all its components doesn't support linearized pdf files very well. Revision handling and all related, are not prepared for special format and objects deployed for such documents.
Each instance cotains unique identificator which is returned by getId method.
typedef std::vector<cpdf_id_t> pdfobjects::CPdf::CPdfListContainer [protected] |
Type for list of all alive pdfs.
typedef std::map<size_t, boost::shared_ptr<CPage> > pdfobjects::CPdf::PageList [private] |
Type of returned pages list.
It is association of page position with CPage instance. Elements are sorted according their position.
| typedef unsigned pdfobjects::CPdf::revision_t |
Revision type. This is used to determine which revision should or is used. It is only alias to unsigned number and 0 stands for the oldest revision and newer revisions have higher numbers.
Mode for file opening.
Possible values:
Values are placed according power of making changes. ReadOnly provides no changes, ReadWrite can change objects byt with some restrictions and Advanced have full control. If you want to add new enum value please consider this ordering.
| pdfobjects::CPdf::CPdf | ( | ) | [inline, private] |
Empty constructor.
This constructor is disabled, because we want to prevent uninitialized instances.
If you want to create instance, please use static factory method getInstance.
Referenced by getInstance().
| pdfobjects::CPdf::CPdf | ( | StreamWriter * | stream, | |
| OpenMode | openMode | |||
| ) | [private] |
Initializating constructor.
| stream | Stream with data. | |
| openMode | Mode for this file. |
Creates XRefWriter, initializes pageTreeWatchDog and finally calls initRevisionSpecific method for initialization of internal structures which depends on current revision.
References Advanced, pdfobjects::XRefWriter::easy, mode, NO_PDF_ID, pdfobjects::XRefWriter::setMode(), setPdfId(), and xref.
| pdfobjects::CPdf::~CPdf | ( | ) | [private] |
Destructor.
It is not available outside the class, because we want to keep absolute control over instance deleting. The instance is destroyed after the its last reference to the smart pointer is released.
References debug::DBG_DBG, kernelPrintDbg, releasePdfId(), and xref.
| IndiRef pdfobjects::CPdf::addIndirectProperty | ( | const boost::shared_ptr< IProperty > & | prop, | |
| bool | followRefs = false | |||
| ) |
Adds new indirect object.
| prop | Original property. | |
| followRefs | Flag for reference properties in complex type handling (default value is false). |
This method is responsible for clear indirect object creation and also safe indirect object copying between different documents (properties from different CPdf instances).
If given prop is from the same pdf, it is just deep copied and inserted as a new indirect object with the new reference (calls registerIndirectProperty with newly reserved reference).
Otherwise tries to get ResolvedRefStorage for prop's pdf (uses getId as pdf identificator). If it doesn't exist in resolvedRefMapping, new entry is created otherwise reuses ResolvedRefStorage instance associated with prop's pdf.
Then checks whether given prop is indirect object (uses hasValidRef). If yes and there already is mapping in ResolvedRefStorage and mapped reference points to non CNull object, no object is added and just mapped reference is returned. This situation may happen when object has already been added before - e. g. as a result of addition of property which refere to this one. Otherwise creates mapping in ResolvedRefStorage (calls createMapping) and delegates the rest to addProperty method.
Implementation details:
As a side effect sets change field to true
| ReadOnlyDocumentException | if mode is set to ReadOnly or we are in older revision (where no changes are allowed). |
References addProperty(), check_need_credentials, pdfobjects::createMapping(), debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, getMode(), pdfobjects::hasValidRef(), pdfobjects::isRef(), pdfobjects::isRefValid(), kernelPrintDbg, NO_PDF_ID, ReadOnly, registerIndirectProperty(), pdfobjects::XRefWriter::reserveRef(), resolvedRefMapping, pdfobjects::STATE_NEW, pdfobjects::STATE_RESOLVED, pdfobjects::STATE_RESOLVING, and xref.
Referenced by insertPage().
| IndiRef pdfobjects::CPdf::addProperty | ( | const boost::shared_ptr< IProperty > & | ip, | |
| IndiRef & | indiRef, | |||
| ResolvedRefStorage & | storage, | |||
| bool | followRefs | |||
| ) | [protected] |
Helper method for property from different pdf adding.
| ip | Property to add. | |
| indiRef | New reference for object. | |
| storage | Resolved storage which contains mapping from old indirect referencies to newly reserved ones. | |
| followRefs | Flag for reference handling. |
Makes deep copy of given ip (to prevent changes in original ip
References debug::DBG_DBG, pdfobjects::hasValidPdf(), kernelPrintDbg, registerIndirectProperty(), and subsReferencies().
Referenced by addIndirectProperty(), and subsReferencies().
| void pdfobjects::CPdf::canChange | ( | ) | const |
Throws an exception if this document can not be changed.
References check_need_credentials, getMode(), pdfobjects::utils::isLatestRevision(), pdfobjects::XRefWriter::isLinearized(), ReadOnly, and xref.
| void pdfobjects::CPdf::changeIndirectProperty | ( | const boost::shared_ptr< IProperty > & | prop | ) |
Registers change of indirect property to the xref.
| prop | Indirect property. |
Checks prop's pdf instance and if it is different than this, throws an exception. Then checks if there is mapping for prop's indiRef. If not also throws an exception.
After all checking is done, creates xpdf Object from prop and calls XRefWriter::change method. If prop is same instance as one in mapping, keeps mapping, because this means that indirect property has changed its contnet (value). Otherwise removes mapping because original property has been replaced by new property.
As a side effect sets change field to true
| CObjInvalidObject | if prop is not from same pdf or indirect mapping doesn't exist yet. | |
| ReadOnlyDocumentException | if mode is set to ReadOnly or we are in older revision (where no changes are allowed). | |
| ElementBadTypeException | if XrefWriter is in paranoid mode and paranoid check fails for new value. |
References _this, change, pdfobjects::XRefWriter::changeObject(), check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, debug::DBG_WARN, pdfobjects::IndiRef::gen, getIndirectProperty(), getMode(), indMap, pdfobjects::utils::isEncrypted(), kernelPrintDbg, pdfobjects::IndiRef::num, ReadOnly, and xref.
| void pdfobjects::CPdf::changeRevision | ( | revision_t | revisionNum | ) |
Changes revision to given one.
| revisionNum | Revision number (the oldest is 0, getRevisionCount()-1 for the newest one). |
Delegates to xref field and reinitializes all internal structures which are revision specific (calls initRevisionSpecific method).
NOTE: indirect mapping is cleared so, all indirect properties are lost and shouldn't be used anymore.
References pdfobjects::XRefWriter::changeRevision(), debug::DBG_DBG, initRevisionSpecific(), kernelPrintDbg, and xref.
| void pdfobjects::CPdf::changeTrailer | ( | std::string & | name, | |
| const boost::shared_ptr< IProperty > & | value | |||
| ) |
Changes/Adds given value associated with the given name to the trailer.
| name | Property name. | |
| value | Property value. |
If a property with the given name already exists, its value will be replaced by the given one (if it is safe to do so see XRefWriter::changeTrailer) or simply add a new one entry to the trailer.
| ReadOnlyDocumentException | if no changes can be done because actual revision is not the newest one or if pdf is in read-only mode. | |
| NotImplementedException | if document is encrypted or when trailer dictionary can't be cloned (because clone method failes). | |
| ElementBadTypeException | if the change is not allowed (either due to type safety or that given entry cannot be changed). |
References pdfobjects::XRefWriter::changeTrailer(), and xref.
| void pdfobjects::CPdf::clone | ( | FILE * | fname | ) | const |
Makes clone to file.
| fname | File handle, where to store content. |
Stores actual document state to the given file. Actual document state stands for all objects from all revistions until current one. This means that kind of fork of document is done. Be careful, because actual changes are not considered (in the most recent revision), because they are not really part of document (you have to save them as new revision at first and than clone will contain also actual changes).
Usage
save(fileName)
this should be used if we want to do fork or copy of document. This may be helpful when we want to make changes in older revision, what is not possible normaly:
cpdf->changeRevision(5); // change to 5th revision
cpdf->save("5th_revision_clone.pdf"); // creates copy of everything
// until 5th revision
Then you can open this document and make changes inside.
NOTE: this method doesn't check whether target of FILE handle is same file as one used in StreamWriter, so caller must take care about this to prevent unexpected problems (overwriting currently used data in stream).
References pdfobjects::XRefWriter::cloneRevision(), debug::DBG_DBG, debug::DBG_ERR, isLinearized(), kernelPrintDbg, and xref.
| void pdfobjects::CPdf::consolidatePageList | ( | const boost::shared_ptr< IProperty > & | oldValue, | |
| const boost::shared_ptr< IProperty > & | newValue | |||
| ) | [protected] |
Consolidates pageList after change in Page tree.
| oldValue | Old reference (CNull if no previous state). | |
| newValue | New reference (CNull if no future state). |
Removes all CPages, which are in old reference sub tree (if oldValue is not CNull - what means that new element to Kids array has been added) from pageList and invalidates them. Uses isNodeDescendant method for each page from pageList to find out if it is in sub tree.
Also calculates difference between lost pages and newly added pages (each is calculated by number of leaf nodes from oldValue resp. newValue sub tree - uses getKidsCount helper function). If oldValue or newValue is CNull 0 is used.
Tries to determine which pages have to be consolidated (those which position has changed). If newValue is CNull, we have no information about oldValue position so we can either get page information from all pages in the list or if at least one page from oldValue subtree has been removed from pageList, we can use this as starting point and just change position according calculated difference.
Page position getting is rather complex operation and may lead to whole page tree searching. This is done only if no page position is available from oldValue subtree.
This guaranties, that pages from removed subtree are not available anymore and are invalidated and also valid returned CPage instances are associated with correct position in pageList.
Implementation notes
This method should be called by obsever monitoring Kids array and Kids array elements. Some previous checking and consolidation of page tree should be done before, because this method relies on proper page tree structure.
No parameters checking is done here. Caller must be sure that:
oldValue and newValue can be CNull or CRef instances. CNull case stands for adding (if oldValue) resp. deleting (if newValue) event. If both of them are CNull no change is done by this method.
CRef stands for reference from Kids array in Intermediate node. It has to refer to page or pages dictionary.
If both values are CRef instances then oldValue has been replaced by newValue reference. This implementation assumes that both of them were on same position in the page tree - one sub tree was replaced by new one but on the same position. It is not possible that these values could be on different positions (this would cause page numbering problem).
| bool pdfobjects::CPdf::consolidatePageTree | ( | const boost::shared_ptr< CDict > & | interNode, | |
| bool | propagate = false | |||
| ) | [protected] |
Consolidates page tree.
| interNode | Intermediate node dictionary under which change has occured. | |
| propagate | Flag whether to consolidate also patent of given internode if it is needed (default is false - not to propagate). |
Recursively checks and consolidates intermediate nodes. All given nodes which are not intermediate (according getNodeType function) are ignored. In first step checks the number of page (leaf) nodes in interNode's subtree. If this number is different than Count interNode's property then sets correct value and also interNode's parent should be consolidated.
In second step, checks all childrens' Parent property to refere to this interNode. If property is missing or has wrong value (or type), sets correct value. Also consolidates all child which are intermediate nodes with recursive call of this method with false propagate flag (because it is enough to propage from this call).
Finally checks propagate flag and if it is true and also parent should be consolidated, calls method recursivelly to interNode parent (unless it is RootNode) with true propagate flag.
Implementation notes:
References _this, debug::DBG_DBG, debug::DBG_WARN, pdfobjects::CObjectFactory< Type >::getInstance(), getInstance(), pdfobjects::utils::getKidsCount(), pdfobjects::utils::getKidsFromInterNode(), pdfobjects::utils::getNodeType(), pdfobjects::utils::InterNode, pdfobjects::isInt(), pdfobjects::isRef(), kernelPrintDbg, pdfobjects::utils::LeafNode, nodeCountCache, and pdfobjects::utils::RootNode.
| revision_t pdfobjects::CPdf::getActualRevision | ( | ) | const [inline] |
Returns name of actual revision number.
Just delegate to the XRefWriter typed xref field. see XRefWriter::getActualRevision() method
References pdfobjects::XRefWriter::getActualRevision(), and xref.
| CXref* pdfobjects::CPdf::getCXref | ( | ) | const [inline] |
Returns pointer to cross reference table.
This is pointer to CXref subtype of XRefWriter type field. It contains actual state of xref table. If any of xpdf code is going to be used besides kernel, this can be safely used.
This method will return same pointer each time it is called.
References xref.
| boost::shared_ptr<CDict> pdfobjects::CPdf::getDictionary | ( | ) | const [inline] |
Returns document catalog for property access.
References docCatalog.
| boost::shared_ptr<CPage> pdfobjects::CPdf::getFirstPage | ( | ) | const [inline] |
| cpdf_id_t pdfobjects::CPdf::getId | ( | ) | const [inline] |
Returns unique identificator for this pdf.
References id.
Referenced by releasePdfId().
Returns IProperty associated with given reference.
| ref | Id and gen number of an object. |
If given reference is not found in mapping, tries to fetch object using xref. If real object is returned (this means something different than objNull), creates new property object (according Object type) and creates mapping. In objNull case, returns CNull property (according PDF specification).
References _this, check_need_credentials, pdfobjects::utils::createObjFromXpdfObj(), debug::DBG_DBG, pdfobjects::XRefWriter::fetch(), pdfobjects::IndiRef::gen, getInstance(), pdfobjects::XPdfObjectFactory::getInstance(), indMap, kernelPrintDbg, pdfobjects::IndiRef::num, and xref.
Referenced by changeIndirectProperty(), initRevisionSpecific(), and insertPage().
| boost::shared_ptr< CPdf > pdfobjects::CPdf::getInstance | ( | const char * | filename, | |
| OpenMode | mode | |||
| ) | [static] |
Factory method for CPdf instances.
| filename | File name with pdf content (if null, new document will be created). | |
| mode | Mode to open file. |
This is only way how to get instance of CPdf type. All necessary initialization is done.
| PdfOpenException | if file open fails. |
References CPdf(), debug::DBG_CRIT, debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, kernelPrintDbg, pdfedit_core_dev_init_check(), PdfFileDeleter, ReadOnly, and ReadWrite.
Referenced by consolidatePageTree(), getIndirectProperty(), getPage(), getTrailer(), and insertPage().
| boost::shared_ptr<CPage> pdfobjects::CPdf::getLastPage | ( | ) | const [inline] |
Returns last page.
Calls getPage(getPageCount()).
References getPage(), and getPageCount().
| OpenMode pdfobjects::CPdf::getMode | ( | ) | const [inline] |
Returns mode of this version.
References pdfobjects::utils::isLatestRevision(), mode, ReadOnly, and xref.
Referenced by addIndirectProperty(), canChange(), changeIndirectProperty(), pdfobjects::XRefWriter::changeObject(), pdfobjects::XRefWriter::changeTrailer(), pdfobjects::XRefWriter::createObject(), insertPage(), removePage(), pdfobjects::XRefWriter::reserveRef(), and save().
| configuration::ModeController* pdfobjects::CPdf::getModeController | ( | ) | const [inline] |
Returns actually used mode controller.
References modeController.
| boost::shared_ptr< CPage > pdfobjects::CPdf::getNextPage | ( | const boost::shared_ptr< CPage > & | page | ) | const |
Returns next page.
| page | Pointer to the page. |
Returns page which is after given one. Uses getPagePosition to get actual position of given page.
Uses getPage method.
| PageNotFoundException | if page can't be found (given page is last one or given page can't be found). |
References debug::DBG_DBG, getPage(), getPagePosition(), and kernelPrintDbg.
| void pdfobjects::CPdf::getOutlines | ( | Container & | cont | ) | const [inline] |
Returns container of outlines and the string they represent.
| cont | Output container. |
Traverses tree like structure of outlines and stores them in the order they are visited.
References check_need_credentials, debug::DBG_DBG, docCatalog, pdfobjects::utils::getAllChildrenOfPdfObject(), pdfobjects::getCDictFromDict(), kernelPrintDbg, and xref.
| boost::shared_ptr< CPage > pdfobjects::CPdf::getPage | ( | size_t | pos | ) | const |
Returns page at given position.
| pos | Position (starting from 1). |
At first tries to find page with given position in pageList. If found, returns instance from list. Otherwise, searches page tree by findPageDict helper function and if page dictionary is found, creates new CPage instance and inserts new mapping (postion to CPage instance) to pageList.
| PageNotFoundException | if pos can't be found or out of range. |
References _this, check_need_credentials, debug::DBG_DBG, debug::DBG_WARN, pdfobjects::utils::findPageDict(), getInstance(), pdfobjects::utils::getPageTreeRoot(), kernelPrintDbg, nodeCountCache, pageList, POSITION_IN_RANGE, and xref.
Referenced by getFirstPage(), getLastPage(), getNextPage(), and getPrevPage().
| unsigned int pdfobjects::CPdf::getPageCount | ( | ) | const |
Returnes total page count.
Calculates (uses getKidsCount helper function) all direct pages under page tree root node.
Note that if page tree root doesn't exists, it will return 0 rather than error (exception) announcing.
References _this, check_need_credentials, debug::DBG_DBG, pdfobjects::utils::getKidsCount(), pdfobjects::utils::getPageTreeRoot(), kernelPrintDbg, nodeCountCache, pageCount, and xref.
Referenced by getLastPage(), and insertPage().
| size_t pdfobjects::CPdf::getPagePosition | ( | const boost::shared_ptr< CPage > & | page | ) | const |
Returns absolute position of given page.
| page | Page to look for. |
Returns actual position of given page. If given page hasn't been returned by this CPdf instance or it is no longer available, exception is thrown.
NOTE: instances are same if they are stand for same instance.
| PageNotFoundException | if given page is not recognized by CPdf instance. |
References check_need_credentials, debug::DBG_DBG, kernelPrintDbg, pageList, and xref.
Referenced by getNextPage(), getPrevPage(), hasNextPage(), hasPrevPage(), and insertPage().
| utils::IPdfWriter* pdfobjects::CPdf::getPdfWriter | ( | ) | [inline] |
Returns current xref's pdf content writer. This instance can't be deallocated! It should be used only for observer registration or similar purposes.
References pdfobjects::XRefWriter::setPdfWriter(), and xref.
| boost::shared_ptr< CPage > pdfobjects::CPdf::getPrevPage | ( | const boost::shared_ptr< CPage > & | page | ) | const |
Returns previous page.
| page | Pointer to the page. |
Returns page which is before given one. Uses getPagePosition to get actual position of given page.
Uses getPage method.
| PageNotFoundException | if page can't be found (given page is last one or given page can't be found). |
References debug::DBG_DBG, getPage(), getPagePosition(), and kernelPrintDbg.
| size_t pdfobjects::CPdf::getRevisionsCount | ( | ) | const [inline] |
Returns number of available revisions.
References pdfobjects::XRefWriter::getRevisionCount(), and xref.
| size_t pdfobjects::CPdf::getRevisionSize | ( | unsigned | rev, | |
| bool | includeXref = false | |||
| ) | const [inline] |
Gets size of given revision.
| rev | Revision to examine. | |
| includeXref | Flag controling whether also xref section with trailer should be also considered. |
Delegates to XRefWriter::getRevisionCount.
References pdfobjects::XRefWriter::getRevisionSize(), and xref.
| boost::shared_ptr< const CDict > pdfobjects::CPdf::getTrailer | ( | ) | const |
Returns trailer dictionary.
Returns const Dictionary pointer to prevent doing changes to it.
References _this, getInstance(), pdfobjects::XRefWriter::getTrailerDict(), pdfobjects::CDict::setPdf(), and xref.
| bool pdfobjects::CPdf::hasNextPage | ( | const boost::shared_ptr< CPage > & | page | ) | const |
Checks for next page.
| page | Page to check. |
| PageNotFoundException | if given page doesn't come from this CPdf instance. |
References debug::DBG_DBG, getPagePosition(), kernelPrintDbg, and POSITION_IN_RANGE.
| bool pdfobjects::CPdf::hasPrevPage | ( | const boost::shared_ptr< CPage > & | page | ) | const |
Checks for previous page.
| page | Page to check. |
| PageNotFoundException | if given page doesn't come from this CPdf instance. |
References debug::DBG_DBG, getPagePosition(), kernelPrintDbg, and POSITION_IN_RANGE.
| void pdfobjects::CPdf::initRevisionSpecific | ( | ) | [private] |
Intializes revision specific stuff.
Cleans up all internal structures which may depend on the current revision. This includes indirect mapping and pageList (all pages are invalidated). After clean up is ready, initializes docCatalog field.
Finally registers pageTreeWatchDog observer. Uses registerPageTreeObserver method with Pages reference as parameter.
| ElementNotFoundException | if Root property is not found. | |
| ElementBadTypeException | if Root property is found but doesn't contain reference or reference does not point to document catalog dictionary. |
References _this, debug::DBG_DBG, debug::DBG_ERR, debug::DBG_WARN, docCatalog, getIndirectProperty(), pdfobjects::utils::getPageTreeRoot(), indMap, pdfobjects::isRef(), kernelPrintDbg, needsCredentials(), nodeCountCache, pageCount, pageList, pageTreeKidsParentCache, pageTreeRootObserver, pdfobjects::pDict, REGISTER_SHAREDPTR_OBSERVER, registerPageTreeObservers(), unregisterPageObservers(), and xref.
Referenced by changeRevision(), and setCredentials().
| boost::shared_ptr< CPage > pdfobjects::CPdf::insertPage | ( | const boost::shared_ptr< CPage > & | page, | |
| size_t | pos | |||
| ) |
Inserts given page to the document.
| page | Page used for new page creation. | |
| pos | Position where to insert new page. |
If position is greater than page count, it is added after last page. Storing to 0 position is same as if pos parameter was 1. All pages behind pos are renumbered.
Method may fail if page at position is ambiguous or given page is already stored in document. This means that it is not (or won't be) possible to get position of page reference in its parent Kids array due to multiple occurance in Kids array.
| ReadOnlyDocumentException | if mode is set to ReadOnly or we are in older revision (where no changes are allowed). | |
| AmbiguesPageTreeException | if page can't be inserted to given position because of ambiguous page tree or page is already in the tree. | |
| NoPageRootException | if no page tree root can be found. |
References _this, addIndirectProperty(), check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, pdfobjects::utils::findPageDict(), getIndirectProperty(), pdfobjects::CPageFactory::getInstance(), getInstance(), getMode(), getPageCount(), getPagePosition(), pdfobjects::utils::getPageTreeRoot(), kernelPrintDbg, nodeCountCache, pageList, pdfobjects::pArray, ReadOnly, pdfobjects::CPageAttributes::setInheritable(), and xref.
| void pdfobjects::CPdf::invalidate | ( | ) | [private] |
Helper method to cleanup all data structure before CPdf destroying. This includes invalidating all pages from pageList (those returned by getPage), unregistering all observers, clearing all cached indirect objects and cleaning up resolvedRefMapping.
Method has to be called before the object itself is deleted.
References debug::DBG_DBG, pdfobjects::deleteResolveRefStorage(), indMap, kernelPrintDbg, pageList, pageTreeKidsObserver, pageTreeNodeObserver, pageTreeRootObserver, and resolvedRefMapping.
Referenced by pdfobjects::PdfFileDeleter::operator()().
| bool pdfobjects::CPdf::isChanged | ( | ) | const [inline] |
Gets change field value.
References change.
| bool pdfobjects::CPdf::isLinearized | ( | ) | const [inline] |
Checks whether this pdf is linearized.
Delegates to XRefWriter::isLinearized.
References pdfobjects::XRefWriter::isLinearized(), and xref.
| bool pdfobjects::CPdf::needsCredentials | ( | ) | const |
Checks whether encryption credentials are required for docuement.
References pdfobjects::CXref::getNeedCredentials(), and xref.
Referenced by initRevisionSpecific().
| IndiRef pdfobjects::CPdf::registerIndirectProperty | ( | const boost::shared_ptr< IProperty > & | ip, | |
| IndiRef & | ref | |||
| ) | [protected] |
Registers definitive value of property to the xref.
| ip | Property to be used. | |
| ref | Reference for property |
Converts given property to xpdf Object and calls XRefWriter::changeObject method to register it. Reference should be in RESERVED_REF.
As a side effect sets change field to true;
References _this, change, pdfobjects::XRefWriter::changeObject(), debug::DBG_DBG, debug::DBG_INFO, debug::DBG_WARN, xpdf::freeXpdfObject(), pdfobjects::IndiRef::gen, kernelPrintDbg, pdfobjects::XRefWriter::knowsRef(), pdfobjects::IndiRef::num, and xref.
Referenced by addIndirectProperty(), and addProperty().
| void pdfobjects::CPdf::registerPageTreeObservers | ( | boost::shared_ptr< IProperty > & | prop | ) | [protected] |
Registers page tree observers.
| prop | Page tree node reference or dictionary. |
If given prop is not dictionary or reference to dictionary immediatelly returns, otherwise registers PageTreeNodeObserver to the dictionary. Then checks Kids property. If it is reference, registers same observer also to reference property and creates entry for pageTreeKidsParentCache. Finally registers PageTreeKidsObserver to Kids array (dereferenced if Kids is reference), to all its reference members and calls method recursively for such elements for whole subtree handling.
Note that this method will register observers to whole page tree if given parameter is page tree root dictionary. PageTreeRootObserver has to be registered separately.
This method should be called in the initialization and when new node is added to the tree (either intermediate node or leaf node).
References debug::DBG_DBG, debug::DBG_WARN, pdfobjects::isArray(), pdfobjects::isDict(), pdfobjects::isRef(), pageTreeKidsObserver, pageTreeKidsParentCache, pageTreeNodeObserver, REGISTER_SHAREDPTR_OBSERVER, and utilsPrintDbg.
Referenced by initRevisionSpecific().
| void pdfobjects::CPdf::releasePdfId | ( | ) | [protected] |
Releases pdf id. Should be called only from destructor context.
Currently removes id from the allPdfs static array and from all alive pdfs' resolve mappings.
References allPdfs, pdfobjects::getCPdfFromId(), getId(), id, pdfobjects::removeResolveRefMapping(), and resolvedRefMapping.
Referenced by ~CPdf().
| void pdfobjects::CPdf::removePage | ( | size_t | pos | ) |
Removes page from given position.
| pos | Position of the page. |
Removes given page from its parent Kids array. This method triggers pageList and page tree consolidation same way as it was removed manualy. As a result page count is decreased.
Method may fail if page at given position is ambigues. This means that it is not possible to get position of page reference in its parent Kids array due to multiple occurance in Kids array.
Intermediate nodes with no direct page are kept in page tree in this implementation.
| PageNotFoundException | if given page couldn't be found. | |
| ReadOnlyDocumentException | if mode is set to ReadOnly or we are in older revision (where no changes are allowed). | |
| AmbiguesPageTreeException | if page can't be inserted to given position because of ambiguous page tree. |
References _this, check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, pdfobjects::utils::findPageDict(), pdfobjects::CObjectFactory< Type >::getInstance(), getMode(), pdfobjects::utils::getPageTreeRoot(), kernelPrintDbg, nodeCountCache, pdfobjects::pArray, POSITION_IN_RANGE, ReadOnly, and xref.
| void pdfobjects::CPdf::save | ( | bool | newRevision = false |
) | const |
Saves changes to pdf file.
| newRevision | Flag for new revision creation. |
If revision is 0 (the newest one), uses XRefWriter::saveChanges method to store changes. Parameter newRevision has precisely the same meaning. For more implementation information
Method will fail if the current revision is not the most recent one.
Usage
save(true)
should be used if changes are suitable to produce new revision. This can be when we have finished work with some topic and we want to keep information that this everything is related.
save()should be used if we want to temporarily store changes to be sure that we don't lose information if some problem happens (e. g. application crashes). Next call of this function will overwrite older one.
As a side effect sets change field to false
| ReadOnlyDocumentException | if mode is set to ReadOnly or we aren't in the newest revision (where changes are enabled). |
References change, debug::DBG_DBG, debug::DBG_ERR, getMode(), pdfobjects::utils::isLatestRevision(), isLinearized(), kernelPrintDbg, ReadOnly, pdfobjects::XRefWriter::saveChanges(), and xref.
| void pdfobjects::CPdf::setCredentials | ( | const char * | ownerPasswd, | |
| const char * | userPasswd | |||
| ) |
Sets credentials for encrypted document. Delegates to CXref::setCredentials method.
References debug::DBG_INFO, initRevisionSpecific(), kernelPrintDbg, pdfobjects::CXref::setCredentials(), and xref.
| void pdfobjects::CPdf::setModeController | ( | configuration::ModeController * | ctrl | ) | [inline] |
Sets mode controller.
| ctrl | Mode controller implementator (if NULL, controller will be disabled). |
References modeController.
| void pdfobjects::CPdf::setPdfId | ( | ) | [protected] |
Sets pdf id. Should be called only from constructor context.
Currently adds id to the allPdfs static array.
References allPdfs, debug::DBG_DBG, pdfobjects::getCPdfFromId(), pdfobjects::getIdFromCPdf(), and kernelPrintDbg.
Referenced by CPdf().
| IndiRef pdfobjects::CPdf::subsReferencies | ( | const boost::shared_ptr< IProperty > & | ip, | |
| ResolvedRefStorage & | container, | |||
| bool | followRefs | |||
| ) | [protected] |
Substitues reference(s) with valid in this pdf.
| ip | Property to examine. | |
| container | Resolved storage which contains mapping from old indirect referencies to newly reserved ones. | |
| followRefs | Flag for reference handling. |
This method should be called on property from different pdf to prevent reference mismatching (reference in different pdf may have different meaning in this pdf).
Checks if given ip is reference and if it is, checks if there is existing mapping in container (searches for container element with first same as ip's reference). If there is such element, returns element::second. This guaranties two things:
If no mapping exists yet, checks followRefs parameter which controls whether referencies should be also added to the pdf. If its value is true, target property is dereferenced and addProperty method is called to add it. Given property may also be stand alone (with no pdf) and in such situation CNull property is used (because we can't get its target value and followRefs should add all indirect properties). Returned value from addProperty (reference) is used to create new mapping in container ([original, returned] mapping) and for return value.
followRefs with false value just reserves new reference and doesn't care for target property. Returned value from XRefWriter::reserveRef is also used for mapping creation and for return value.
For complex properties collects all children and calls this method recursively. If it returns with non NULL, changes child to contain new reference otherwise keeps an old one and finally returns with NULL because complex type itself didn't need reference change.
All other simple properties are ignored and returns with NULL.
References _this, addProperty(), pdfobjects::createMapping(), debug::DBG_DBG, pdfobjects::hasValidPdf(), pdfobjects::isArray(), pdfobjects::isDict(), pdfobjects::isRef(), pdfobjects::isRefValid(), pdfobjects::isStream(), kernelPrintDbg, pdfobjects::pArray, pdfobjects::pDict, pdfobjects::pRef, pdfobjects::pStream, pdfobjects::STATE_NEW, pdfobjects::STATE_RESOLVED, pdfobjects::STATE_RESOLVING, and xref.
Referenced by addProperty().
| void pdfobjects::CPdf::unregisterPageObservers | ( | ) | [protected] |
TODO
References _this, debug::DBG_DBG, debug::DBG_WARN, docCatalog, pdfobjects::utils::getPageTreeRoot(), pdfobjects::isRef(), kernelPrintDbg, pageTreeRootObserver, UNREGISTER_SHAREDPTR_OBSERVER, and unregisterPageTreeObservers().
Referenced by initRevisionSpecific().
| void pdfobjects::CPdf::unregisterPageTreeObservers | ( | boost::shared_ptr< IProperty > & | prop, | |
| bool | cleanup = false | |||
| ) | [protected] |
Unregisters page tree observers.
| prop | Page tree node reference or dictionary. | |
| cleanup | Clean up flag. |
This method is inverse to registerPageTreeObservers (with same observers but, with unregistration rather than registration). Also removes cache entry from pageTreeKidsParentCache.
This method should be called with clenaup flag set to false when node is removed from the tree and set to true when clean up for CPdf is done (e.g. when document about to be destroyed).
NOTE: If position of given node is ambiguous, unregistration is skipped, because node is still in the tree.
References _this, debug::DBG_DBG, debug::DBG_WARN, pdfobjects::utils::getNodePosition(), pdfobjects::isArray(), pdfobjects::isDict(), pdfobjects::isRef(), kernelPrintDbg, nodeCountCache, pageTreeKidsObserver, pageTreeKidsParentCache, pageTreeNodeObserver, UNREGISTER_SHAREDPTR_OBSERVER, and utilsPrintDbg.
Referenced by unregisterPageObservers().
friend class PdfFileDeleter [friend] |
Referenced by getInstance().
boost::weak_ptr<CPdf> pdfobjects::CPdf::_this [private] |
Weak reference to this instance for proper reference counting with combination to published shared_ptr.
Referenced by changeIndirectProperty(), consolidatePageTree(), getIndirectProperty(), getPage(), getPageCount(), getTrailer(), initRevisionSpecific(), insertPage(), registerIndirectProperty(), removePage(), subsReferencies(), unregisterPageObservers(), and unregisterPageTreeObservers().
CPdf::CPdfListContainer pdfobjects::CPdf::allPdfs = CPdf::CPdfListContainer() [static, protected] |
List of all aive pdfs.
Referenced by releasePdfId(), and setPdfId().
bool pdfobjects::CPdf::change [mutable, private] |
Change flag.
Value is true if and only if current changes have not been saved by save method.
Value is mutable because
Referenced by changeIndirectProperty(), isChanged(), registerIndirectProperty(), and save().
boost::shared_ptr<CDict> pdfobjects::CPdf::docCatalog [private] |
Document catalog dictionary.
It is used for document property handling. Initialization is done by initRevisionSpecific method because catalog may be specific for each revision (although this is not very often situation). Value is wrapped by shared_ptr smart pointer for instance safety.
Referenced by getDictionary(), getOutlines(), initRevisionSpecific(), and unregisterPageObservers().
cpdf_id_t pdfobjects::CPdf::id [private] |
Identificator for this pdf instance.
Referenced by getId(), and releasePdfId().
IndirectMapping pdfobjects::CPdf::indMap [mutable, private] |
Mapping between IndiRef and indirect properties.
This is essential when we want to access an indirect object from refernce. We know only the id and gen number. All indirect objects with same reference has to share value and this is guarantied by this mapping.
Referenced by changeIndirectProperty(), getIndirectProperty(), initRevisionSpecific(), and invalidate().
OpenMode pdfobjects::CPdf::mode [private] |
Mode controller instance.
This class is responsible for correct assigment of mode to properties. If not set, it's not used.
Use setModeController to set one and getModeController to get actually used one.
Referenced by getModeController(), and setModeController().
const cpdf_id_t pdfobjects::CPdf::NO_PDF_ID = 0 [static] |
Constant for pdf id of no pdf. This is used for properties which comes from no pdf. Each CPdf instance must have id different from this value.
Referenced by addIndirectProperty(), and CPdf().
PageTreeNodeCountCache pdfobjects::CPdf::nodeCountCache [mutable, private] |
Cache for page count information for intermediate nodes.
Each node which queries for its leaf pages count by getKidsCount function is cached with found value (more preciselly mapping from reference to page count is stored). So getKidsCount can use this cache next time when it is called to prevent from searching intermediate node subtree and calculating total page count again because this operation is used very often and so it would be serious performance problem.
Cached value has to be discarded each time when page count is changed under node intermediate node. This is handled in consolidatePageTree method.
Referenced by consolidatePageTree(), getPage(), getPageCount(), initRevisionSpecific(), insertPage(), removePage(), and unregisterPageTreeObservers().
size_t pdfobjects::CPdf::pageCount [mutable, private] |
Number of pages in document.
Keeps value of actual number of pages or 0 if value is invalid and getPageCount has to find out it. Whenever this is set to non 0 and change in page tree occures which can change total number of pages, it is set to 0. Value is also invalidated in initRevisionSpecific method.
This is kind of optimalization to prevent geting Root of page tree node each time when total number of pages is required.
Referenced by getPageCount(), and initRevisionSpecific().
PageList pdfobjects::CPdf::pageList [mutable, private] |
Returned pages list.
This container stores CPage instances returned by this class. Each time new page is returned, it is stored here with actual page position. This is because, page position may change from property interface from page tree. Each time this tree is changed, this list is consolidated and all page instances which are no more available on its position are invalidated (Uses CPage::invalidate method).
pageList is invalidate on each revision change (with all its pages).
It is safe to try to find page in this list at first and if not found, than searching is neccessary.
This storage behaves like CPage cache.
Referenced by getPage(), getPagePosition(), initRevisionSpecific(), insertPage(), and invalidate().
boost::shared_ptr<PageTreeKidsObserver> pdfobjects::CPdf::pageTreeKidsObserver [protected] |
Observer for Kids array in intermeadiate nodes.
This observer handles changes of Kids array members.
Referenced by invalidate(), registerPageTreeObservers(), and unregisterPageTreeObservers().
Cache for indirect Kids arrays mapping to their parents.
This cache enables to overcome problem with indirect Kids arrays in Intermediate page tree node. The problem is that members of Kids array are not able to get reference to parent (if we don't want to rely on children Parent property - which is problem, because we need to get this information in page tree consolidation when also this information is checked and corrected) unless Kids array is direct object.
Whenever Kids property from intermediate node is reference to array, mapping is created with array reference as key and current node's reference as value. This is done in registerPageTreeObservers which registers obsevers when page tree changes somehow. TODO when to discard?
Referenced by initRevisionSpecific(), registerPageTreeObservers(), and unregisterPageTreeObservers().
boost::shared_ptr<PageTreeNodeObserver> pdfobjects::CPdf::pageTreeNodeObserver [protected] |
Observer for potential intermediate nodes.
This observer handles changes of Kids array in intermediate nodes.
Referenced by invalidate(), registerPageTreeObservers(), and unregisterPageTreeObservers().
boost::shared_ptr<PageTreeRootObserver> pdfobjects::CPdf::pageTreeRootObserver [protected] |
Observer for page tree root.
This observer handles changes in page tree root.
Referenced by initRevisionSpecific(), invalidate(), and unregisterPageObservers().
Mapping for pdf's to their resolved storage. This mapping is used during new indirect property addition. Each separate document requires its own resolve storage because this storage contains translation mappings from that document the those used for current document.
Indirect objects with no PDF are associated with NO_PDF_ID id.
Referenced by addIndirectProperty(), invalidate(), and releasePdfId().
XRefWriter* pdfobjects::CPdf::xref [private] |
Cross reference table. This field holds XRefWriter implementation of XRef interface. It enables making changes to the table and also making changes to indirect objects.
This is only access point for making changes. It can be casted to XRef types which provides information about actual object values, and so original xpdf code doesn't has to be changed.
This is only part which uses xpdf Object objects as arguments.
Instance is created in constructor.
Referenced by addIndirectProperty(), canChange(), changeIndirectProperty(), changeRevision(), changeTrailer(), clone(), CPdf(), getActualRevision(), getCXref(), getIndirectProperty(), getMode(), getOutlines(), getPage(), getPageCount(), getPagePosition(), getPdfWriter(), getRevisionsCount(), getRevisionSize(), getTrailer(), initRevisionSpecific(), insertPage(), isLinearized(), needsCredentials(), registerIndirectProperty(), removePage(), save(), setCredentials(), subsReferencies(), and ~CPdf().