Skip to content

The DocumentContext Object

gal kahana edited this page Jun 10, 2013 · 8 revisions

The DocumentContext object is in charge of writing the high level objects of a PDF file. It has a similar signature as the PDFWriter, normally being the top-level implementer of these methods, and as such calling its methods and the PDFWriter methods normally generates the same results. Generally a class which is of less interest it does have a few interesting methods, explained here.
Important! Note that this class is defined in the PDFHummus Namespace.

Trailer information setting

TrailerInformation& GetTrailerInformation() provides access to the trailer information object. normally of internal purposes only it does offer one object of interest to the user, which is the Info dictionary accessible via the InfoDictionary member. The info dictionary (of class InfoDictionary) imitates the info dictionary of the PDF specifications. you can use it to set metadata information on the PDF. For example, use the following steps to set the Author name:

PDFWriter aPDFWriter;

InfoDictionary& infoDictionary = aPDFWriter.GetDocumentContext().GetTrailerInformation().InfoDictionary;

infoDictionary.Author = PDFTextString(“Roger Zelazny”);

JPG images information retrieving

you can use the JPEGImageHandler& GetJPEGImageHandler() command to retrieve a JPEGImageHandler object. this object may be used to retrieve parsed information on a JPG image. you would normally be interested in the physical size information in order to determine what size you would like the image to have. check JPG Images Support for details

Extending Document Context Level

you can extend objects in the document level by implementing an IDocumentContextExtender interface and adding it to the document context extenders list.do that use void AddDocumentContextExtender(IDocumentContextExtender* inExtender). by adding an extender, you can now hook into the DocumentContext object writing mechanism and add objects to the relevant objects dictionary, based on events. When done, use void RemoveDocumentContextExtender(IDocumentContextExtender* inExtender), to remove the extender from the list.

To implement an IDocumentContextExtender interface either derive from it or from a DocumentContextExtenderAdapter object. the benefit of using the latter object is that you can implement only what you need of the extender, as the Adapter provides null implementations to all methods.

The following section explains the methods that a user may implement to hook into DocumentContext objects writing.

IDocumentContextExtender Methods

  1. virtual EStatusCode OnPageWrite( PDFPage* inPage, DictionaryContext* inPageDictionaryContext, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext)
    Use this method to extend page object writing. The inPage Object provided is the page that is now being written. The DictionaryContext object provided by inPageDictionaryContext can be used to add values to the page dictionary object.
  2. virtual EStatusCode OnResourcesWrite( ResourcesDictionary* inResources, DictionaryContext* inPageResourcesDictionaryContext, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext)
    Use this method to extend a resources dictionary writing. This method is being called at the end of a resources dictionary writing for a page, just before the resource dictionary is being finalized. the inResources object provided represents the Resources Dictionary being written. inPageResourcesDictionaryContext provides its dictionary context for adding more keys.
  3. virtual EStatusCode OnResourceDictionaryWrite( DictionaryContext* inResourceDictionary, const string& inResourceDictionaryName, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext)
    Use this method to extend the writing of a particular resources dictionary. For example, it can be used to add more color spaces to the color space resource dictionary, provided that it is being written. The method is only called for actually written dictionaries, and not for all of them. if you want to add more resources dictionary, use the OnResourcesWrite event in addition to using this event. Note that XObject resources dictionary and ProcSet array are not causing a triggering of this event. In general you should be able to use the existing library functionality for embedding content into those two items.
  4. virtual EStatusCode OnFormXObjectWrite( ObjectIDType inFormXObjectID, ObjectIDType inFormXObjectResourcesDictionaryID, DictionaryContext* inFormDictionaryContext, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext)
    Use this method to extend form xobject dictionary writing. the inFormXObjectID and inFromXObjectResourcesDictionaryID represents the values of the form xobject object id and resources dictionary object id. The DictionaryContext object provided by inFormDictionaryContext provides the dictionary object now written, for the sake of adding keys.
  5. virtual EStatusCode OnJPEGImageXObjectWrite( ObjectIDType inImageXObjectID, DictionaryContext* inImageDictionaryContext, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, JPEGImageHandler* inJPGImageHandler)
    Allows you to extend the image XObject being written to represent a JPG image. the method can be used to add keys to the dictionary now written. access to the dictionary is provided by inImageDictionaryContext. [when using the form XObject variant, this method is still called for the image xobject that the form xobject uses]
  6. virtual EStatusCode OnTIFFImageXObjectWrite( ObjectIDType inImageXObjectID, DictionaryContext* inImageDictionaryContext, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, TIFFImageHandler* inTIFFImageHandler)
    Allows you to extend the form XObject being written to represent a TIFF image. The method can be used for adding keys to the TIFF Image form XObject by adding keysto the dictionary provided by inImageDictionaryContext.
  7. virtual EStatusCode OnCatalogWrite( CatalogInformation* inCatalogInformation, DictionaryContext* inCatalogDictionaryContext, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext)
    Add content to the catalog dictionary while it’s being written. The catalog information object (also accessible via the DocumentContext object itself) allows you to inspect the page tree as constructed by the PDFWriter library. to add keys you can use inCatalogDictionaryContext providing a dictionary context.

For events called when embedding PDFs use the following methods:

  1. virtual EStatusCode OnPDFParsingComplete( ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When embedding PDF pages, called when parsing of the input PDF is complete. This allows you to receive the PDFDocumentHandler
    which is the object handling the embedding of the PDF. most interesting method of the handler is PDFParser* GetSourceDocumentParser(), which provides you with the parser object for the input PDF, so you can read objects from it. see PDF Parsing for more details on the parser object.
  2. virtual EStatusCode OnBeforeCreateXObjectFromPage( PDFDictionary* inPageObjectDictionary, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When embedding PDF Pages as XObject forms, just before the XObject is created. providing you the PDFDocumentHandler object through inPDFDocumentHandler, and the Parsed page dictionary through inPageObjectDictionary.
  3. virtual EStatusCode OnAfterCreateXObjectFromPage( PDFFormXObject* iPageObjectResultXObject, PDFDictionary* inPageObjectDictionary, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When embedding PDF Pages as form XObjects, after the form XObject is created, provides you the PDFDocumentHandler, as well as Page dictionary, and the PDFFormXObject just created.
  4. virtual EStatusCode OnBeforeCreatePageFromPage( PDFDictionary* inPageObjectDictionary, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When embedding PDF Pages as pages, just before the page is created. providing you the PDFDocumentHandler object through inPDFDocumentHandler, and the Parsed page dictionary through inPageObjectDictionary
  5. virtual EStatusCode OnAfterCreatePageFromPage( PDFPage* iPageObjectResultPage, PDFDictionary* inPageObjectDictionary, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When embedding PDF Pages as pages, after the page is created, provides you the PDFDocumentHandler, as well as Page dictionary, and the PDFPage just created.
  6. virtual EStatusCode OnBeforeMergePageFromPage( PDFPage* inTargetPage, PDFDictionary* inPageObjectDictionary, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When merging PDF Pages content to a target page, then before a particular source page is being embedded this call is being executed. It allows you to introduce code into the page content, for instance to set a positioning matrix.
  7. virtual EStatusCode OnAfterMergePageFromPage( PDFPage* inTargetPage, PDFDictionary* inPageObjectDictionary, ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When merging PDF Pages content to a target page, then after a particular source page is being embedded this call is being executed. It allows you to plant code to restore the state of the page graphics, after the source page was embedded.
  8. virtual EStatusCode OnPDFCopyingComplete( ObjectsContext* inPDFWriterObjectContext, DocumentContext* inPDFWriterDocumentContext, PDFDocumentHandler* inPDFDocumentHandler)
    When embedding PDF Pages, fired when the PDF copying (pages or forms) is complete.

Writing Tasks

During the writing of a certain page or form you might want need to write other objects. Normally they would be objects that are referenced by this page, such as images, external graphic states or whatnot. It is then very useful to create one-time tasks that will run once this page or form writing ends. You can create them whenever you want and they will be executed once the page or form are written.

Another scenario where writing tasks are useful is when you want to write a resource object in a page or form, that is used inside the page or form.

There are three kinds of writing tasks, explained in the following passages.

IPageEndWritingTask

IPageEndWritingTask can be created and set on the document context for a particular page. They will be executed once the particular page that they are assigned to is written, immediately after. Then, the task object will be destroyed (so you don’t need to worry about cleanup).

The interface definition is here

The single method to implement is
virtual PDFHummus::EStatusCode Write(PDFPage* inPageObject, ObjectsContext* inObjectsContext, PDFHummus::DocumentContext* inDocumentContext)

it receives the page object that was written, the objects context and document context that you can use for now writing whatever it is that you want to write. Note that at this point the page is already written, so no use to modifying something in the page object input.

To activate this task use create an instance of the class of the task, and call the DocumentContext::void RegisterPageEndWritingTask(PDFPage* inPageObject,IPageEndWritingTask* inWritingTask) method.

IFormEndWritingTask

IFormEndWritingTask is use in a similar manner to IPageEndWritingTask. Instead of assigning it to a page you assign it to a form.

The interface definition is here

The single method to implement is
virtual PDFHummus::EStatusCode Write(PDFFormXObject* inFormXObject, ObjectsContext* inObjectsContext, PDFHummus::DocumentContext* inDocumentContext)

it receives the form object that was written, the objects context and document context that you can use for now writing whatever it is that you want to write. Note that at this point the form is already written, so no use to modifying something in the page object input.

To activate this task use create an instance of the class of the task, and call the DocumentContext::void RegisterFormEndWritingTask(PDFFormXObject* inFormXObject,IPageEndWritingTask* inWritingTask) method.

IResourceWritingTask

IResourceWritingTask is good for those scenarios that you need to define a resource in a certain page or a form resources dictionary, and you want it to be a direct object, and it’s of a category that is not supported by the library directly. So, for this case, simply create a resource writing task for the resource, and assign it to the particular form or page or resource dictionary (depending on what you got), and the category. This task will be executed (and then released) one the resources dictionary is written. The assigning method returns a string which is the name of the resource that you can use (so you don’t have to provide one and it’s nicely aligned with the rest of the names).

The task interface is defined here

There’s a single method to implement: virtual PDFHummus::EStatusCode Write(DictionaryContext* inResoruceCategoryContext, ObjectsContext* inObjectsContext, PDFHummus::DocumentContext* inDocumentContext)

The method receives the category dictionary together with the objects context and document context. It should write the name of the resource as key, and whatever you want as the value. The name you will receive when registering the task. Just make sure you write it as a name.

You assign a task by using one of the following methods:

std::string AddExtendedResourceMapping(PDFFormXObject* inFormXObject, const std::string& inResourceCategoryName, IResourceWritingTask* inWritingTask);

std::string AddExtendedResourceMapping(PDFPage* inPage, const std::string& inResourceCategoryName, IResourceWritingTask* inWritingTask);

std::string AddExtendedResourceMapping(ResourcesDictionary* inResourceDictionary, const std::string& inResourceCategoryName, IResourceWritingTask* inWritingTask);

The first and second methods are to be used with a form or page for their resource dictionaries writing. You can use the third method if you have the resources dictionary itself.

Clone this wiki locally