Skip to content

Modification

gal kahana edited this page May 12, 2023 · 3 revisions

You can modify existing PDF File by using the ModifyPDF method of PDFWriter The method of writing a modified PDF file used the PDF format incremental changes feature. This way, one off writing of can still happen, even for file modifications.

To open a file for modification use ModifyPDF. Its signature is like this:

EStatusCode ModifyPDF(const string& inModifiedFile,
EPDFVersion inPDFVersion,
const string& inOptionalAlternativeOutputFile,
const LogConfiguration& inLogConfiguration,
const PDFCreationSettings& inPDFCreationSettings)

Quite similar to StartPDF, so i'll just explain the important differences. The first parameter inModifiedFile is a path to the file to be modified. You can choose to either modify it in place, or write the modified file to another file. For the first option (modify in place), pass an empty string to the third parameter (inOptionalAlternativeOutputFile). To save the modified file to a different location pass the path to the desired location as the 3rd parameter.

Once you have started a file for modification you can carry out any regular action that the library provides. For example, the following code add another page to the modified PDF:

PDFWriter pdfWriter;
pdfWriter.ModifyPDF("c:\\modifiedPDF.pdf",ePDFVersion13,"");
PDFPage* page = new PDFPage();
page->SetMediaBox(PDFRectangle(0,0,595,842));
PageContentContext* contentContext = pdfWriter.StartPageContentContext(page);
// write content to the pdf page...
pdfWriter.EndPageContentContext(contentContext);
pdfWriter.WritePageAndRelease(page);
pdfWriter.EndPDF();

As you can see, this is done exactly like adding a page to a new PDF. The only difference is in the second row which uses ModifyPDF instead of StartPDF.

Now, you may also want to modify objects in the original PDF. For example, you may want to modify an existing page, by adding comments to it. This is a little more tricky and requires some knowledge of PDF and usage of object copying.

To assist with this there are the following elements:

PDFWriter Class

PDFParser& GetModifiedFileParser();
InputFile& GetModifiedInputFile();

both of these methods should allow you to get handlers to the modified file. The parser is useful both for parsing the original objects, and also for copying object from the old document using PDFDocumentCopyingContext, which you can start by calling another method of the PDFWriter:

PDFDocumentCopyingContext* CreatePDFCopyingContextForModifiedFile();

PDFModifiedPage Class

More than most of the times you will want to modify a document by adding content to one of the pages. For example, a post production process may want to add barcodes to a PDF, or some text on top of a given page. For this there is the helper class PDFModifiedPage. An object of this class is initialized by a pdfwriter that is used in a modified file scenario, and a page index. From that point you can start using it for creating new content contexts (As you would with a regular page) and issue the regular drawing commands. When done call its WritePage method to submit the modified page.

You can find a usage example here.

The following block of code shows the essence of using this object:

PDFModifiedPage modifiedPage(&pdfWriter,0);
AbstractContentContext* contentContext = modifiedPage.StartContentContext();
AbstractContentContext::TextOptions opt(pdfWriter.GetFontForFile("fonts/arial.ttf"),14,AbstractContentContext::eGray,0);
contentContext->WriteText(75,805,"Test Text",opt);
modifiedPage.EndContentContext();
modifiedPage.WritePage();

Note specifically the usage of StartContentContext and EndContentContext for starting and ending a content context.

IndirectObjectsReferenceRegistry and ObjectsContext classes

The IndirectObjectsReferenceRegistry available through the PDFWriter ObjectsContext object, can be used to delete objects from the old PDF or modify them. use the following method to carry this out:

EStatusCode DeleteObject(ObjectIDType inObjectID);
EStatusCode MarkObjectAsUpdated(ObjectIDType inObjectID,LongFilePositionType inNewWritePosition);

To delete an object just pass its ID to DeleteObject. note that it will simply mark this object as deleted, not actually remove its code. and it's not recursive.

To modify an object just use MarkObjectAsUpdated and pass the object ID and new position in file. You probably prefer to use the ObjectsContext method StartModifiedIndirectObject:

void StartModifiedIndirectObject(ObjectIDType inObjectID);

Which is to be used instead of StartNewInDirectObject in case you want to start a new object instead of replacing an existing one. Just pass the ID of the object to replace.

For a good example on how to modify existing file to add comments check out ModifyingExistingFileContent

Clone this wiki locally