Skip to content

Using Form XObjects

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

Form XObjects are reusable graphic objects. A Form XObjects has a content stream (much like a page) which defines a certain graphic. The form can be placed in one or more other content streams by using the “Do” operator. This way the content is defined once and use multiple times. This can help with making files shorter.

The library allows you to create Form XObjects and use them.

To define a Form XObject you do the following:
1. Create a PDFFormXObject object
2. Get its content context
3. Using PDF drawing operators create some graphics on the form
4. Finalize the form
5. Register the form in another content object (page or another form XObject) by assigning a name to the Form XObject object ID
6. In the content of the other object, use the operator “Do” with the assigned name to show the Form graphics. you can use Matrix transformation to set the position, rotation etc. of the Form.

Now, for a step by step explanation:

Creating a Form XObject

The following code defines a form XObject that draw a red rectangle:

PDFFormXObject* xobjectForm = pdfWriter.StartFormXObject(PDFRectangle(0,0,200,100));
ObjectIDType formObjectID = xobjectForm->GetObjectID();
XObjectContentContext* xobjectContentContext = xobjectForm->GetContentContext();
xobjectContentContext->q();
xobjectContentContext->k(0,100,100,0);
xobjectContentContext->re(0,0,200,100);
xobjectContentContext->f();
xobjectContentContext->Q();
pdfWriter.EndFormXObjectAndRelease(xobjectForm);

The first line starts a Form XObject. it’s width is 200 and height 100.
The second line saves the form XObject ID. This is to be used later with the page(s) that will be showing that form).
To start drawing the form content, the content context is acquired by calling:
xobjectForm->GetContentContext()
with the content context, the user can now place drawing command, which are exactly the same as in the case of a page content context. you can look at AbstractContentContext to see which PDF commands are supported.
When the content writing is done, use the EndFormXObjectAndRelease method of PDFWriter to finalize the Form XObject footer and release the Form XObject object.

Using a Form XObject

Using a form XObject in a page requires two things – that you register it in the resources dictionary of the page, with a particular name, and then using the Do operator with that name:

string formXObjectName = page->GetResourcesDictionary().AddFormXObjectMapping(formObjectID);
pageContentContext->q();
pageContentContext->cm(1,0,0,1,200,600);
pageContentContext->Do(formXObjectName);
pageContentContext->Q();

the code sample assumes that you are already familiar with page content writing. You can read about it in Adding Content to PDF Pages.
The first line of the code gets the resources dictionary of the page. A resources dictionary of a page is a simple map between objects in the PDF file and names. It normally contains mapping for things like Form XObjects, Image XObject, Fonts etc. Once a certain mapping for an object exist in the dictionary you can use the name in the content stream. The library represents for Resources dictionary (both for pages and XObject Forms in ResourcesDictionary) In our example a Form XObject mapping is added according to the form object ID saves from the previous segment of code. The return value is a name, which is later used with the “Do” command, that simply draws that form XObject on the page. The matrix applied prior to using the “Do” operator will cause the form graphics to appear in X=200 and Y=600.

The cool things about a form, of course, is that you can use it multiple times in the same page. Also it is possible to use it in multiple pages, even using different names. What maintains the identity of the particular form is the mapping of the name to the particular XObject Form object ID.

Important! When writing a form XObject, note that a form xobject content context cannot be paused, as it is possible with a page context. Therefore, if you wish to use other objects in the form content you will either have to define them before the form or use forward referencing. You can read about forward referencing in Forward Referencing.

For a complete example of how to use reusable form XObject see FormXObjectTest

Clone this wiki locally