Skip to main content

Code samples

Here you’ll find some samples to get you started with the PDF Toolbox SDK.

Annotations

Add annotations to PDF

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
// Create output document
using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);

// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page and add annotations
Page outPage = CopyAndAddAnnotations(outDoc, inDoc.Pages[0], copyOptions);

// Add the page to the output document's page list
outDoc.Pages.Add(outPage);

// Copy the remaining pages and add to the output document's page list
PageList inPages = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList outPages = PageList.Copy(outDoc, inPages, copyOptions);
outDoc.Pages.AddRange(outPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static Page CopyAndAddAnnotations(Document outDoc, Page inPage, PageCopyOptions copyOptions)
{
// Copy page to output document
Page outPage = Page.Copy(outDoc, inPage, copyOptions);

// Make a RGB color space
ColorSpace rgb = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);

// Get the page size for positioning annotations
Size pageSize = outPage.Size;

// Get the output page's list of annotations for adding annotations
AnnotationList annotations = outPage.Annotations;

// Create a sticky note and add to output page's annotations
Paint green = Paint.Create(outDoc, rgb, new double[] { 0, 1, 0 }, null);
Point stickyNoteTopLeft = new Point() { X = 10, Y = pageSize.Height - 10 };
StickyNote stickyNote = StickyNote.Create(outDoc, stickyNoteTopLeft, "Hello world!", green);
annotations.Add(stickyNote);

// Create an ellipse and add to output page's annotations
Paint blue = Paint.Create(outDoc, rgb, new double[] { 0, 0, 1 }, null);
Paint yellow = Paint.Create(outDoc, rgb, new double[] { 1, 1, 0 }, null);
Rectangle ellipseBox = new Rectangle() { Left = 10, Bottom = pageSize.Height - 60, Right = 70, Top = pageSize.Height - 20 };
EllipseAnnotation ellipse = EllipseAnnotation.Create(outDoc, ellipseBox, new Stroke(blue, 1.5), yellow);
annotations.Add(ellipse);

// Create a free text and add to output page's annotations
Paint yellowTransp = Paint.Create(outDoc, rgb, new double[] { 1, 1, 0 }, new Transparency(0.5));
Rectangle freeTextBox = new Rectangle() { Left = 10, Bottom = pageSize.Height - 170, Right = 120, Top = pageSize.Height - 70 };
FreeText freeText = FreeText.Create(outDoc, freeTextBox, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellowTransp);
annotations.Add(freeText);

// A highlight and a web-link to be fitted on existing page content elements
Highlight highlight = null;
WebLink webLink = null;
// Extract content elements from the input page
ContentExtractor extractor = new ContentExtractor(inPage.Content);
foreach (ContentElement element in extractor)
{
// Take the first text element
if (highlight == null && element is TextElement textElement)
{
// Get the quadrilaterals of this text element
QuadrilateralList quadrilaterals = new QuadrilateralList();
foreach (TextFragment fragment in textElement.Text)
quadrilaterals.Add(fragment.Transform.TransformRectangle(fragment.BoundingBox));

// Create a highlight and add to output page's annotations
highlight = Highlight.CreateFromQuadrilaterals(outDoc, quadrilaterals, yellow);
annotations.Add(highlight);
}

// Take the first image element
if (webLink == null && element is ImageElement)
{
// Get the quadrilateral of this image
QuadrilateralList quadrilaterals = new QuadrilateralList();
quadrilaterals.Add(element.Transform.TransformRectangle(element.BoundingBox));

// Create a web-link and add to the output page's links
webLink = WebLink.CreateFromQuadrilaterals(outDoc, quadrilaterals, "https://www.pdf-tools.com");
Paint red = Paint.Create(outDoc, rgb, new double[] { 1, 0, 0 }, null);
webLink.BorderStyle = new Stroke(red, 1.5);
outPage.Links.Add(webLink);
}

// Exit loop if highlight and webLink have been created
if (highlight != null && webLink != null)
break;
}

// return the finished page
return outPage;
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
// Create file stream
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page and add annotations
Page outPage = copyAndAddAnnotations(outDoc, inDoc.getPages().get(0), copyOptions);

// Add the page to the output document's page list
outDoc.getPages().add(outPage);

// Copy the remaining pages and add to the output document's page list
PageList inPages = inDoc.getPages().subList(1, inDoc.getPages().size());
PageList outPages = PageList.copy(outDoc, inPages, copyOptions);
outDoc.getPages().addAll(outPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static Page copyAndAddAnnotations(Document outDoc, Page inPage, PageCopyOptions copyOptions) throws ConformanceException, CorruptException, IOException, UnsupportedFeatureException {
// Copy page to output document
Page outPage = Page.copy(outDoc, inPage, copyOptions);

// Make a RGB color space
ColorSpace rgb = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);

// Get the page size for positioning annotations
Size pageSize = outPage.getSize();

// Get the output page's list of annotations for adding annotations
AnnotationList annotations = outPage.getAnnotations();

// Create a sticky note and add to output page's annotations
Paint green = Paint.create(outDoc, rgb, new double[] { 0, 1, 0 }, null);
Point stickyNoteTopLeft = new Point(10, pageSize.height - 10 );
StickyNote stickyNote = StickyNote.create(outDoc, stickyNoteTopLeft, "Hello world!", green);
annotations.add(stickyNote);

// Create an ellipse and add to output page's annotations
Paint blue = Paint.create(outDoc, rgb, new double[] { 0, 0, 1 }, null);
Paint yellow = Paint.create(outDoc, rgb, new double[] { 1, 1, 0 }, null);
Rectangle ellipseBox = new Rectangle(10, pageSize.height - 60, 70, pageSize.height - 20);
EllipseAnnotation ellipse = EllipseAnnotation.create(outDoc, ellipseBox, new Stroke(blue, 1.5), yellow);
annotations.add(ellipse);

// Create a free text and add to output page's annotations
Paint yellowTransp = Paint.create(outDoc, rgb, new double[] { 1, 1, 0 }, new Transparency(0.5));
Rectangle freeTextBox = new Rectangle(10, pageSize.height - 170, 120, pageSize.height - 70);
FreeText freeText = FreeText.create(outDoc, freeTextBox, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellowTransp);
annotations.add(freeText);

// A highlight and a web-link to be fitted on existing page content elements
Highlight highlight = null;
WebLink webLink = null;
// Extract content elements from the input page
ContentExtractor extractor = new ContentExtractor(inPage.getContent());
for (ContentElement element : extractor) {
// Take the first text element
if (highlight == null && element instanceof TextElement) {
TextElement textElement = (TextElement)element;
// Get the quadrilaterals of this text element
QuadrilateralList quadrilaterals = new QuadrilateralList();
for (TextFragment fragment : textElement.getText())
quadrilaterals.add(fragment.getTransform().transformRectangle(fragment.getBoundingBox()));

// Create a highlight and add to output page's annotations
highlight = Highlight.createFromQuadrilaterals(outDoc, quadrilaterals, yellow);
annotations.add(highlight);
}

// Take the first image element
if (webLink == null && element instanceof ImageElement) {
// Get the quadrilateral of this image
QuadrilateralList quadrilaterals = new QuadrilateralList();
quadrilaterals.add(element.getTransform().transformRectangle(element.getBoundingBox()));

// Create a web-link and add to the output page's links
webLink = WebLink.createFromQuadrilaterals(outDoc, quadrilaterals, "https://www.pdf-tools.com");
Paint red = Paint.create(outDoc, rgb, new double[] { 1, 0, 0 }, null);
webLink.setBorderStyle(new Stroke(red, 1.5));
outPage.getLinks().add(webLink);
}

// Exit loop if highlight and webLink have been created
if (highlight != null && webLink != null)
break;
}

// return the finished page
return outPage;
}

Annotations and Form Fields

Add Form Field

Download code sample
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Copy all form fields
FieldNodeMap inFormFields = inDoc.FormFields;
FieldNodeMap outFormFields = outDoc.FormFields;
foreach (KeyValuePair<string, FieldNode> inPair in inFormFields)
{
FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inPair.Value);
outFormFields.Add(inPair.Key, outFormFieldNode);
}

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions
{
FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
UnsignedSignatures = CopyStrategy.Remove,
};

// Copy first page
Page inPage = inDoc.Pages[0];
Page outPage = Page.Copy(outDoc, inPage, copyOptions);

// Add different types of form fields to the output page
AddCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle { Left = 50, Bottom = 300, Right = 70, Top = 320 });
AddComboBox(outDoc, "Combo Box ID", new string[] { "item 1", "item 2" }, "item 1", outPage, new Rectangle { Left = 50, Bottom = 260, Right = 210, Top = 280 });
AddListBox(outDoc, "List Box ID", new string[] { "item 1", "item 2", "item 3" }, new string[] { "item 1", "item 3" }, outPage, new Rectangle { Left = 50, Bottom = 160, Right = 210, Top = 240 });
AddRadioButtonGroup(outDoc, "Radio Button ID", new string[] { "A", "B", "C" }, 0, outPage, new Rectangle { Left = 50, Bottom = 120, Right = 210, Top = 140 });
AddGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle { Left = 50, Bottom = 80, Right = 210, Top = 100 });

// Add page to output document
outDoc.Pages.Add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddCheckBox(Document doc, string id, bool isChecked, Page page, Rectangle rectangle)
{
// Create a check box
CheckBox checkBox = CheckBox.Create(doc);

// Add the check box to the document
doc.FormFields.Add(id, checkBox);

// Set the check box's state
checkBox.Checked = isChecked;

// Create a widget and add it to the page's widgets
page.Widgets.Add(checkBox.AddNewWidget(rectangle));
}
private static void AddComboBox(Document doc, string id, string[] itemNames, string value, Page page, Rectangle rectangle)
{
// Create a combo box
ComboBox comboBox = ComboBox.Create(doc);

// Add the combo box to the document
doc.FormFields.Add(id, comboBox);

// Loop over all given item names
foreach (string itemName in itemNames)
{
// Create a new choice item
ChoiceItem item = comboBox.AddNewItem(itemName);

// Check whether this is the chosen item name
if (value.Equals(itemName))
comboBox.ChosenItem = item;
}
if (comboBox.ChosenItem == null && !string.IsNullOrEmpty(value))
{
// If no item has been chosen then assume we want to set the editable item
comboBox.CanEdit = true;
comboBox.EditableItemName = value;
}

// Create a widget and add it to the page's widgets
page.Widgets.Add(comboBox.AddNewWidget(rectangle));
}
private static void AddListBox(Document doc, string id, string[] itemNames, string[] chosenNames, Page page, Rectangle rectangle)
{
// Create a list box
ListBox listBox = ListBox.Create(doc);

// Add the list box to the document
doc.FormFields.Add(id, listBox);

// Allow multiple selections
listBox.AllowMultiSelect = true;
ChoiceItemList chosenItems = listBox.ChosenItems;

// Loop over all given item names
foreach (string itemName in itemNames)
{
// Create a new choice item
ChoiceItem item = listBox.AddNewItem(itemName);

// Check whether to add to the chosen items
if (chosenNames.Contains(itemName))
chosenItems.Add(item);
}

// Create a widget and add it to the page's widgets
page.Widgets.Add(listBox.AddNewWidget(rectangle));
}
private static void AddRadioButtonGroup(Document doc, string id, string[] buttonNames, int chosen, Page page, Rectangle rectangle)
{
// Create a radio button group
RadioButtonGroup group = RadioButtonGroup.Create(doc);

// Get the page's widgets
WidgetList widgets = page.Widgets;

// Add the radio button group to the document
doc.FormFields.Add(id, group);

// We partition the given rectangle horizontally into sub-rectangles, one for each button
// Compute the width of the sub-rectangles
double buttonWidth = (rectangle.Right - rectangle.Left) / buttonNames.Length;

// Loop over all button names
for (int i = 0; i < buttonNames.Length; i++)
{
// Compute the sub-rectangle for this button
Rectangle buttonRectangle = new Rectangle()
{
Left = rectangle.Left + i * buttonWidth,
Bottom = rectangle.Bottom,
Right = rectangle.Left + (i + 1) * buttonWidth,
Top = rectangle.Top
};

// Create the button and an associated widget
RadioButton button = group.AddNewButton(buttonNames[i]);
Widget widget = button.AddNewWidget(buttonRectangle);

// Check if this is the chosen button
if (i == chosen)
group.ChosenButton = button;

// Add the widget to the page's widgets
widgets.Add(widget);
}
}
private static void AddGeneralTextField(Document doc, string id, string value, Page page, Rectangle rectangle)
{
// Create a general text field
GeneralTextField field = GeneralTextField.Create(doc);

// Add the field to the document
doc.FormFields.Add(id, field);

// Set the text value
field.Text = value;

// Create a widget and add it to the page's widgets
page.Widgets.Add(field.AddNewWidget(rectangle));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Copy all form fields
FieldNodeMap inFormFields = inDoc.getFormFields();
FieldNodeMap outFormFields = outDoc.getFormFields();
for (Entry<String, FieldNode> entry : inFormFields.entrySet())
outFormFields.put(entry.getKey(), FieldNode.copy(outDoc, entry.getValue()));

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();
copyOptions.setFormFields(FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS);
copyOptions.setUnsignedSignatures(CopyStrategy.REMOVE);

// Copy first page
Page inPage = inDoc.getPages().get(0);
Page outPage = Page.copy(outDoc, inPage, copyOptions);

// Add different types of form fields to the output page
addCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle(50, 300, 70, 320));
addComboBox(outDoc, "Combo Box ID", new String[] { "item 1", "item 2" }, "item 1", outPage,
new Rectangle(50, 260, 210, 280));
addListBox(outDoc, "List Box ID", new String[] { "item 1", "item 2", "item 3" },
new String[] { "item 1", "item 3" }, outPage, new Rectangle(50, 160, 210, 240));
addRadioButtonGroup(outDoc, "Radio Button ID", new String[] { "A", "B", "C" }, 0, outPage,
new Rectangle(50, 120, 210, 140));
addGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle(50, 80, 210, 100));

// Add page to output document
outDoc.getPages().add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addCheckBox(Document doc, String id, boolean isChecked, Page page, Rectangle rectangle)
throws PdfToolboxException {
// Create a check box
CheckBox checkBox = CheckBox.create(doc);

// Add the check box to the document
doc.getFormFields().put(id, checkBox);

// Set the check box's state
checkBox.setChecked(isChecked);

// Create a widget and add it to the page's widgets
page.getWidgets().add(checkBox.addNewWidget(rectangle));
}
private static void addListBox(Document doc, String id, String[] itemNames, String[] chosenNames, Page page,
Rectangle rectangle) throws PdfToolboxException {
List<String> chosenNamesList = Arrays.asList(chosenNames);

// Create a list box
ListBox listBox = ListBox.create(doc);

// Add the list box to the document
doc.getFormFields().put(id, listBox);

// Allow multiple selections
listBox.setAllowMultiSelect(true);

// Get the list of chosen items
ChoiceItemList chosenItems = listBox.getChosenItems();

// Loop over all given item names
for (String itemName : itemNames) {
ChoiceItem item = listBox.addNewItem(itemName);
// Check whether to add to the chosen items
if (chosenNamesList.contains(itemName))
chosenItems.add(item);
}

// Create a widget and add it to the page's widgets
page.getWidgets().add(listBox.addNewWidget(rectangle));
}
private static void addComboBox(Document doc, String id, String[] itemNames, String value, Page page,
Rectangle rectangle) throws PdfToolboxException {
// Create a combo box
ComboBox comboBox = ComboBox.create(doc);

// Add the combo box to the document
doc.getFormFields().put(id, comboBox);

// Loop over all given item names
for (String itemName : itemNames) {
ChoiceItem item = comboBox.addNewItem(itemName);
// Check whether to add to the chosen items
if (value.equals(itemName))
comboBox.setChosenItem(item);
}
if (comboBox.getChosenItem() == null && !(value == null || value.isEmpty())) {
// If no item has been chosen then assume we want to set the editable item
comboBox.setCanEdit(true);
comboBox.setEditableItemName(value);
}

// Create a widget and add it to the page's widgets
page.getWidgets().add(comboBox.addNewWidget(rectangle));
}
private static void addRadioButtonGroup(Document doc, String id, String[] buttonNames, int chosen, Page page,
Rectangle rectangle) throws PdfToolboxException {
// Create a radio button group
RadioButtonGroup group = RadioButtonGroup.create(doc);

// Add the radio button group to the document
doc.getFormFields().put(id, group);

// We partition the given rectangle horizontally into sub-rectangles, one for
// each button
// Compute the width of the sub-rectangles
double buttonWidth = (rectangle.right - rectangle.left) / buttonNames.length;

// Get the page's widgets
WidgetList widgets = page.getWidgets();

// Loop over all button names
for (int i = 0; i < buttonNames.length; i++) {
// Compute the sub-rectangle for this button
Rectangle buttonRectangle = new Rectangle(rectangle.left + i * buttonWidth, rectangle.bottom,
rectangle.left + (i + 1) * buttonWidth, rectangle.top);

// Create the button and an associated widget
RadioButton button = group.addNewButton(buttonNames[i]);
Widget widget = button.addNewWidget(buttonRectangle);

// Check if this is the chosen button
if (i == chosen)
group.setChosenButton(button);

// Add the widget to the page's widgets
widgets.add(widget);
}
}
private static void addGeneralTextField(Document doc, String id, String value, Page page, Rectangle rectangle)
throws PdfToolboxException {
// Create a general text field
GeneralTextField field = GeneralTextField.create(doc);

// Add the field to the document
doc.getFormFields().put(id, field);

// Set the check box's state
field.setText(value);

// Create a widget and add it to the page's widgets
page.getWidgets().add(field.addNewWidget(rectangle));
}

Fill Form Fields

Download code sample
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// Objects that need releasing or closing
TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
TPtxPdf_Metadata* pInMetadata = NULL;
TPtxPdf_Metadata* pOutMetadata = NULL;
TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
TPtxPdf_FileReferenceList* pInFileRefList = NULL;
TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
TPtxPdf_FileReference* pInFileRef = NULL;
TPtxPdf_FileReference* pOutFileRef = NULL;

iReturnValue = 0;

// Output intent
pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
if (pInOutputIntent != NULL)
{
pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
_T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
_T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Metadata
pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
if (pInMetadata != NULL)
{
pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
_T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Viewer settings
pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
if (pInViewerSettings != NULL)
{
pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
_T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
_T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
Ptx_GetLastError());

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}
Ptx_Release(pInFileRefList);
pInFileRefList = NULL;
Ptx_Release(pOutFileRefList);
pOutFileRefList = NULL;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}

cleanup:
if (pInOutputIntent != NULL)
Ptx_Release(pInOutputIntent);
if (pOutOutputIntent != NULL)
Ptx_Release(pOutOutputIntent);
if (pInMetadata != NULL)
Ptx_Release(pInMetadata);
if (pOutMetadata != NULL)
Ptx_Release(pOutMetadata);
if (pInViewerSettings != NULL)
Ptx_Release(pInViewerSettings);
if (pOutViewerSettings != NULL)
Ptx_Release(pOutViewerSettings);
if (pInFileRefList != NULL)
Ptx_Release(pInFileRefList);
if (pOutFileRefList != NULL)
Ptx_Release(pOutFileRefList);
if (pInFileRef != NULL)
Ptx_Release(pInFileRef);
if (pOutFileRef != NULL)
Ptx_Release(pOutFileRef);
return iReturnValue;
}
int copyFields(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// Objects that need releasing or closing
TPtxPdfForms_FieldNodeMap* pInFields = NULL;
TPtxPdfForms_FieldNodeMap* pOutFields = NULL;
TCHAR* szFieldKey = NULL;
TPtxPdfForms_FieldNode* pInFieldNode = NULL;
TPtxPdfForms_FieldNode* pOutFieldNode = NULL;

iReturnValue = 0;

pInFields = PtxPdf_Document_GetFormFields(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFields,
_T("Failed to get form fields of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

pOutFields = PtxPdf_Document_GetFormFields(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFields,
_T("Failed to get form fields of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

for (int iField = PtxPdfForms_FieldNodeMap_GetBegin(pInFields);
iField != PtxPdfForms_FieldNodeMap_GetEnd(pInFields);
iField = PtxPdfForms_FieldNodeMap_GetNext(pInFields, iField))
{
if (iField == 0)
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Get key
size_t nKey = PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, 0);
GOTO_CLEANUP_IF_ZERO(nKey, _T("Failed to get form field key\n"));
szFieldKey = (TCHAR*)malloc(nKey * sizeof(TCHAR*));
GOTO_CLEANUP_IF_NULL(szFieldKey, _T("Failed to allocate memory for field key\n"));
if (PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, nKey) != nKey)
{
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field key. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
// Get input field node
pInFieldNode = PtxPdfForms_FieldNodeMap_GetValue(pInFields, iField);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFieldNode, _T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Copy field node to output document
pOutFieldNode = PtxPdfForms_FieldNode_Copy(pOutDoc, pInFieldNode);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFieldNode, _T("Failed to copy form field. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Add copied field node to output fields
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_FieldNodeMap_Set(pOutFields, szFieldKey, pOutFieldNode),
_T("Failed to add form field \"%s\". %s (ErrorCode: 0x%08x)\n"), szFieldKey,
szErrorBuff, Ptx_GetLastError());
// Clean up for next iteration
free(szFieldKey);
szFieldKey = NULL;
Ptx_Release(pOutFieldNode);
pOutFieldNode = NULL;
Ptx_Release(pInFieldNode);
pInFieldNode = NULL;
}

cleanup:
if (pOutFieldNode != NULL)
Ptx_Release(pOutFieldNode);
if (pInFieldNode != NULL)
Ptx_Release(pInFieldNode);
if (szFieldKey != NULL)
free(szFieldKey);
if (pOutFields != NULL)
Ptx_Release(pOutFields);
if (pInFields != NULL)
Ptx_Release(pInFields);
return iReturnValue;
}
int fillFormField(TPtxPdfForms_Field* pField, const TCHAR* szValue)
{
// Objects that need releasing or closing
TPtxPdfForms_RadioButtonList* pButtonList = NULL;
TPtxPdfForms_RadioButton* pButton = NULL;
TPtxPdfForms_ChoiceItemList* pChoiceItemList = NULL;
TPtxPdfForms_ChoiceItem* pItem = NULL;
TCHAR* szName = NULL;

// Other variables
TPtxPdfForms_FieldType iType = 0;
TPtxPdfForms_CheckBox* pCheckBox = NULL;
TPtxPdfForms_RadioButtonGroup* pRadioButtonGroup = NULL;

iReturnValue = 0;
iType = PtxPdfForms_Field_GetType(pField);

if (iType == ePtxPdfForms_FieldType_GeneralTextField || iType == ePtxPdfForms_FieldType_CombTextField)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_TextField_SetText((TPtxPdfForms_TextField*)pField, szValue),
_T("Failed to set text field value. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else if (iType == ePtxPdfForms_FieldType_CheckBox)
{
pCheckBox = (TPtxPdfForms_CheckBox*)pField;
if (_tcscmp(szValue, _T("on")) == 0)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, TRUE),
_T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, FALSE),
_T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
}
else if (iType == ePtxPdfForms_FieldType_RadioButtonGroup)
{
pRadioButtonGroup = (TPtxPdfForms_RadioButtonGroup*)pField;
pButtonList = PtxPdfForms_RadioButtonGroup_GetButtons(pRadioButtonGroup);
for (int iButton = 0; iButton < PtxPdfForms_RadioButtonList_GetCount(pButtonList); iButton++)
{
pButton = PtxPdfForms_RadioButtonList_Get(pButtonList, iButton);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pButton, _T("Failed to get radio button. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError())
size_t nName = PtxPdfForms_RadioButton_GetExportName(pButton, szName, 0);
GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get radio button name\n"));
szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for radio button name\n"));
if (PtxPdfForms_RadioButton_GetExportName(pButton, szName, nName) != nName)
{
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get radio button name. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
}
if (_tcscmp(szValue, szName) == 0)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_RadioButtonGroup_SetChosenButton(pRadioButtonGroup, pButton),
_T("Failed to set radio button. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
}
free(szName);
szName = NULL;
Ptx_Release(pButton);
pButton = NULL;
}
}
else if (iType == ePtxPdfForms_FieldType_ComboBox || iType == ePtxPdfForms_FieldType_ListBox)
{
pChoiceItemList = PtxPdfForms_ChoiceField_GetItems((TPtxPdfForms_ChoiceField*)pField);
for (int iItem = 0; iItem < PtxPdfForms_ChoiceItemList_GetCount(pChoiceItemList); iItem++)
{
pItem = PtxPdfForms_ChoiceItemList_Get(pChoiceItemList, iItem);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pItem,
_T("Failed to get item from choice field. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
size_t nName = PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, 0);
GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get choice item name\n"));
szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for choice item name\n"));
if (PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, nName) != nName)
{
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get choice item name. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
}
if (_tcscmp(szValue, szName) == 0)
{
break;
}
free(szName);
szName = NULL;
Ptx_Release(pItem);
pItem = NULL;
}
if (pItem != NULL)
{
free(szName);
szName = NULL;
if (iType == ePtxPdfForms_FieldType_ComboBox)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_ComboBox_SetChosenItem((TPtxPdfForms_ComboBox*)pField, pItem),
_T("Failed to set choice item for combo box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else // iType == ePtxPdfForms_FieldType_ListBox
{
Ptx_Release(pChoiceItemList);
pChoiceItemList = PtxPdfForms_ListBox_GetChosenItems((TPtxPdfForms_ListBox*)pField);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pChoiceItemList, _T("Failed to get list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_ChoiceItemList_Clear(pChoiceItemList),
_T("Failed to clear list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_ChoiceItemList_Add(pChoiceItemList, pItem),
_T("Failed to add item to list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
}
}
}

cleanup:
if (szName != NULL)
free(szName);
if (pItem == NULL)
Ptx_Release(pItem);
if (pChoiceItemList == NULL)
Ptx_Release(pChoiceItemList);
if (pButton != NULL)
Ptx_Release(pButton);
if (pButtonList != NULL)
Ptx_Release(pButton);

return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

FieldNodeMap outFields = outDoc.FormFields;

// Copy all form fields
FieldNodeMap inFields = inDoc.FormFields;
foreach (var inPair in inFields)
{
FieldNode inFieldNode = inPair.Value;
FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inFieldNode);
outFields.Add(inPair.Key, outFormFieldNode);
}

// Find the given field, exception thrown if not found
var selectedNode = outFields.Lookup(fieldIdentifier);
if (selectedNode is Field selectedField)
FillFormField(selectedField, fieldValue);

// Configure copying options for updating existing widgets and removing signature fields
PageCopyOptions copyOptions = new PageCopyOptions
{
FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
UnsignedSignatures = CopyStrategy.Remove,
};

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
static void FillFormField(Field formField, string value)
{
// Apply the value, depending on the field type
if (formField is TextField textField)
{
// Set the text
textField.Text = value;
}
else if (formField is CheckBox checkBox)
{
// Check or un-check
checkBox.Checked = "on".Equals(value, StringComparison.CurrentCultureIgnoreCase);
}
else if (formField is RadioButtonGroup group)
{
// Search the buttons for given name
foreach (var button in group.Buttons)
{
if (value.Equals(button.ExportName))
{
// Found: Select this button
group.ChosenButton = button;
break;
}
}
}
else if (formField is ComboBox comboBox)
{
// Search for the given item
foreach (var item in comboBox.Items)
{
if (value.Equals(item.DisplayName))
{
// Found: Select this item.
comboBox.ChosenItem = item;
break;
}
}
}
else if (formField is ListBox listBox)
{
// Search for the given item
foreach (var item in listBox.Items)
{
if (value.Equals(item.DisplayName))
{
// Found: Set this item as the only selected item
var itemList = listBox.ChosenItems;
itemList.Clear();
itemList.Add(item);
break;
}
}
}
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Copy all form fields
FieldNodeMap inFormFields = inDoc.getFormFields();
FieldNodeMap outFormFields = outDoc.getFormFields();
for (Entry<String, FieldNode> entry : inFormFields.entrySet())
outFormFields.put(entry.getKey(), FieldNode.copy(outDoc, entry.getValue()));

// Find the given field, exception thrown if not found
Field selectedField = (Field) outFormFields.lookup(fieldIdentifier);
fillFormField(selectedField, fieldValue);

// Configure copying options for updating existing widgets and removing signature fields
PageCopyOptions copyOptions = new PageCopyOptions();
copyOptions.setFormFields(FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS);
copyOptions.setUnsignedSignatures(CopyStrategy.REMOVE);

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void fillFormField(Field formField, String value) throws PdfToolboxException {
// Apply the value, depending on the field type
if (formField instanceof TextField) {
// Set the text
TextField textField = (TextField) formField;
textField.setText(value);
} else if (formField instanceof CheckBox) {
// Check or un-check
CheckBox checkBox = (CheckBox) formField;
checkBox.setChecked(value.equalsIgnoreCase("on"));
} else if (formField instanceof RadioButtonGroup) {
// Search the buttons for given name
RadioButtonGroup group = (RadioButtonGroup) formField;
for (RadioButton button : group.getButtons()) {
if (value.equals(button.getExportName())) {
// Found: Select this button
group.setChosenButton(button);
break;
}
}
} else if (formField instanceof ComboBox) {
// Search for the given item
ComboBox comboBox = (ComboBox) formField;
for (ChoiceItem item : comboBox.getItems()) {
if (value.equals(item.getDisplayName())) {
// Found: Select this item
comboBox.setChosenItem(item);
break;
}
}
} else if (formField instanceof ListBox) {
// Search for the given item
ListBox listBox = (ListBox) formField;
for (ChoiceItem item : listBox.getItems()) {
if (value.equals(item.getDisplayName())) {
// Found: Set this item as the only selected item
ChoiceItemList itemList = listBox.getChosenItems();
itemList.clear();
itemList.add(item);
break;
}
}
}
}

Content Addition

Add barcode to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create file stream
pFontStream = _tfopen(szFontPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pFontStream, _T("Failed to open font file."));
PtxSysCreateFILEStreamDescriptor(&fontDescriptor, pFontStream, 0);

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());
pFont = PtxPdfContent_Font_Create(pOutDoc, &fontDescriptor, TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get page lists of input and output document
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy first page
pInPage = PtxPdf_PageList_Get(pInPageList, 0);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Add barcode image to copied page
if (addBarcode(pOutDoc, pOutPage, szBarcode, pFont, 50) != 0)
goto cleanup;

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Get remaining pages from input
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
_T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy remaining pages to output
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
_T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Add the copied pages to the output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addBarcode(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szBarcode, TPtxPdfContent_Font* pFont,
double dFontSize)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdfContent_Text* pBarcodeText = NULL;
TPtxPdfContent_TextGenerator* pTextGenerator = NULL;

pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create text object
pBarcodeText = PtxPdfContent_Text_Create(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pBarcodeText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create text generator
pTextGenerator = PtxPdfContent_TextGenerator_New(pBarcodeText, pFont, dFontSize, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Calculate position
TPtxGeomReal_Size size;
PtxPdf_Page_GetSize(pOutPage, &size);
TPtxGeomReal_Point position;
double dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szBarcode);
GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
double dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontAscent, _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
double dFontDescent = PtxPdfContent_Font_GetDescent(pFont);
GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontDescent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
position.dX = size.dWidth - (dTextWidth + dBorder);
position.dY = size.dHeight - (dFontSize * (dFontAscent + dFontDescent) + dBorder);

// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
_T("Failed to move to position %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
// Add given barcode string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szBarcode),
_T("Failed to add barcode string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Close text generator
if (pTextGenerator != NULL)
PtxPdfContent_TextGenerator_Close(pTextGenerator);

// Paint the positioned barcode text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pBarcodeText),
_T("Failed to paint the positioned barcode text. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

cleanup:
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);

return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create file stream
using (Stream fontStream = new FileStream(fontPath, FileMode.Open, FileAccess.Read))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Create embedded font in output document
Font font = Font.Create(outDoc, fontStream, true);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add barcode, and append to output document
Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
AddBarcode(outDoc, outPage, barcode, font, 50);
outDoc.Pages.Add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddBarcode(Document outputDoc, Page outPage, string barcode,
Font font, double fontSize)
{
// Create content generator
using ContentGenerator gen = new ContentGenerator(outPage.Content, false);

// Create text object
Text barcodeText = Text.Create(outputDoc);

// Create text generator
using (TextGenerator textGenerator = new TextGenerator(barcodeText, font, fontSize, null))
{
// Calculate position
Point position = new Point
{
X = outPage.Size.Width - (textGenerator.GetWidth(barcode) + Border),
Y = outPage.Size.Height - (fontSize * (font.Ascent + font.Descent) + Border)
};

// Move to position
textGenerator.MoveTo(position);
// Add given barcode string
textGenerator.ShowLine(barcode);
}
// Paint the positioned barcode text
gen.PaintText(barcodeText);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
// Create file stream
FileStream fontStream = new FileStream(fontPath, FileStream.Mode.READ_ONLY);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Create embedded font in output document
Font font = Font.create(outDoc, fontStream, true);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add barcode, and append to output document
Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
addBarcode(outDoc, outPage, barcode, font, 50);
outDoc.getPages().add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addBarcode(Document outputDoc, Page outPage, String barcode, Font font, double fontSize) throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text barcodeText = Text.create(outputDoc);

// Create a text generator
TextGenerator textgenerator = new TextGenerator(barcodeText, font, fontSize, null);

// Calculate position
Point position = new Point(outPage.getSize().width - (textgenerator.getWidth(barcode) + Border),
outPage.getSize().height - (fontSize * (font.getAscent() + font.getDescent()) + Border));

// Move to position
textgenerator.moveTo(position);
// Add given barcode string
textgenerator.showLine(barcode);
// Close text generator
textgenerator.close();

// Paint the positioned barcode text
generator.paintText(barcodeText);
}
}

Add Data Matrix to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Create embedded font in output document
pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get page lists of input and output document
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy first page
pInPage = PtxPdf_PageList_Get(pInPageList, 0);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Add datamatrix image to copied page
if (addDataMatrix(pOutDoc, pOutPage, szDatamatrixPath) != 0)
goto cleanup;

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Get remaining pages from input
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
_T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy remaining pages to output
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
_T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Add the copied pages to the output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addDataMatrix(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szDataMatrixPath)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxSys_StreamDescriptor datamatrixDescriptor;
FILE* pDatamatrixStream = NULL;
TPtxPdfContent_Image* pDatamatrix = NULL;

pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Import data matrix
pDatamatrixStream = _tfopen(szDataMatrixPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pDatamatrixStream, _T("Failed to open data matrix file \"%s\".\n"), szDataMatrixPath);
PtxSysCreateFILEStreamDescriptor(&datamatrixDescriptor, pDatamatrixStream, 0);

// Create image object for data matrix
pDatamatrix = PtxPdfContent_Image_Create(pOutDoc, &datamatrixDescriptor);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pDatamatrix, _T("Failed to create image object. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Data matrix size
double dDatamatrixSize = 85.0;

// Calculate Rectangle for data matrix
TPtxGeomReal_Size size;
PtxPdf_Page_GetSize(pOutPage, &size);
TPtxGeomReal_Rectangle rect;
rect.dLeft = dBorder;
rect.dBottom = size.dHeight - (dDatamatrixSize + dBorder);
rect.dRight = dDatamatrixSize + dBorder;
rect.dTop = size.dHeight - dBorder;

// Paint image of data matrix into the specified rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintImage(pGenerator, pDatamatrix, &rect),
_T("Failed to paint data matrix into the specified rectangle. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document 
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add datamatrix image, and append to output document
Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
AddDataMatrix(outDoc, outPage, datamatrixPath);
outDoc.Pages.Add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddDataMatrix(Document document, Page page, string datamatrixPath)
{
// Create content generator
using ContentGenerator generator = new ContentGenerator(page.Content, false);

// Import data matrix
using Stream inMatrix = new FileStream(datamatrixPath, FileMode.Open, FileAccess.Read);

// Create image object for data matrix
Image datamatrix = Image.Create(document, inMatrix);

// Data matrix size
double datamatrixSize = 85;

// Calculate Rectangle for data matrix
Rectangle rect = new Rectangle
{
Left = Border,
Bottom = page.Size.Height - (datamatrixSize + Border),
Right = datamatrixSize + Border,
Top = page.Size.Height - Border
};

// Paint image of data matrix into the specified rectangle
generator.PaintImage(datamatrix, rect);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add data matrix image, and append to output document
Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
addDatamatrix(outDoc, outPage, datamatrixPath);
outDoc.getPages().add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addDatamatrix(Document document, Page page, String datamatrixPath)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(page.getContent(), false);
// Import data matrix
FileStream inMatrix = new FileStream(datamatrixPath, FileStream.Mode.READ_ONLY)) {

// Create image object for data matrix
Image datamatrix = Image.create(document, inMatrix);

// Data matrix size
double datamatrixSize = 85;

// Calculate Rectangle for data matrix
Rectangle rect = new Rectangle(Border, page.getSize().height - (datamatrixSize + Border),
datamatrixSize + Border, page.getSize().height - Border);

// Paint image of data matrix into the specified rectangle
generator.paintImage(datamatrix, rect);
}
}

Add image to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get input and output page lists
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy pages preceding selected page
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 0, iPageNumber - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange, _T("Failed to get page range. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange, _T("Failed to copy page range. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to add page range. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInPageRange);
pInPageRange = NULL;
Ptx_Release(pOutPageRange);
pOutPageRange = NULL;

// Copy selected page an add image
pInPage = PtxPdf_PageList_Get(pInPageList, iPageNumber - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
if (addImage(pOutDoc, pOutPage, szImagePath, 150.0, 150.0) != 0)
goto cleanup;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy remaining pages
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
_T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
_T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addImage(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szImagePath, double x, double y)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxSys_StreamDescriptor imageDescriptor;
FILE* pImageStream = NULL;
TPtxPdfContent_Image* pImage = NULL;

pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);

// Load image from input path
pImageStream = _tfopen(szImagePath, _T("rb"));
PtxSysCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);

// Create image object
pImage = PtxPdfContent_Image_Create(pOutDoc, &imageDescriptor);

double dResolution = 150.0;

TPtxGeomInt_Size size;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Image_GetSize(pImage, &size),
_T("Failed to get image size. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Calculate Rectangle for data matrix
TPtxGeomReal_Rectangle rect;
rect.dLeft = x;
rect.dBottom = y;
rect.dRight = x + (double)size.iWidth * 72.0 / dResolution;
rect.dTop = y + (double)size.iHeight * 72.0 / dResolution;

// Paint image into the specified rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintImage(pGenerator, pImage, &rect),
_T("Failed to paint image. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document 
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy pages preceding selected page and append do output document
PageList inPageRange = inDoc.Pages.GetRange(0, pageNumber - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);

// Copy selected page, add image, and append to output document
Page outPage = Page.Copy(outDoc, inDoc.Pages[pageNumber - 1], copyOptions);
AddImage(outDoc, outPage, imagePath, 150, 150);
outDoc.Pages.Add(outPage);

// Copy remaining pages and append to output document
inPageRange = inDoc.Pages.GetRange(pageNumber, inDoc.Pages.Count - pageNumber);
copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddImage(Document document, Page page, string imagePath, double x, double y)
{
// Create content generator
using ContentGenerator generator = new ContentGenerator(page.Content, false);

// Load image from input path
using Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read);

// Create image object
Image image = Image.Create(document, inImage);
double resolution = 150;

// Calculate rectangle for image
PdfTools.FourHeights.PdfToolbox.Geometry.Integer.Size size = image.Size;
Rectangle rect = new Rectangle
{
Left = x,
Bottom = y,
Right = x + size.Width * 72 / resolution,
Top = y + size.Height * 72 / resolution
};

// Paint image into the specified rectangle
generator.PaintImage(image, rect);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy pages preceding selected page and append to output document
PageList inPageRange = inDoc.getPages().subList(0, pageNumber - 1);
PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);

// Copy selected page, add image, and append to output document
Page outPage = Page.copy(outDoc, inDoc.getPages().get(pageNumber - 1), copyOptions);
addImage(outDoc, outPage, imagePath, 150, 150);
outDoc.getPages().add(outPage);

// Copy remaining pages and append to output document
inPageRange = inDoc.getPages().subList(pageNumber, inDoc.getPages().size());
copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addImage(Document document, Page outPage, String imagePath, double x, double y)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
// Load image from input path
FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
// Create image object
Image image = Image.create(document, inImage);

double resolution = 150;

// Calculate rectangle for image
Size size = image.getSize();
Rectangle rect = new Rectangle(x, y, x + size.getWidth() * 72 / resolution,
y + size.getHeight() * 72 / resolution);

// Paint image into the specified rectangle
generator.paintImage(image, rect);
}
}

Add image mask to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Get the device color space
TPtxPdfContent_ColorSpace* pColorSpace =
PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the device color space. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Chose the RGB color value
double color[] = {1.0, 0.0, 0.0};
size_t nColor = sizeof(color) / sizeof(double);

// Create paint object
pPaint = PtxPdfContent_Paint_Create(pOutDoc, pColorSpace, color, nColor, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get input and output page lists
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy first page an add image mask
pInPage = PtxPdf_PageList_Get(pInPageList, 0);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
if (addImageMask(pOutDoc, pOutPage, szImageMaskPath, 250, 150) != 0)
goto cleanup;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy remaining pages
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
_T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
_T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addImageMask(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szImageMaskPath, double x, double y)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
FILE* pImageStream = NULL;
TPtxSys_StreamDescriptor imageDescriptor;
TPtxPdfContent_ImageMask* pImageMask = NULL;

pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Load image from input path
pImageStream = _tfopen(szImageMaskPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pImageStream, _T("Failed to open image mask file \"%s\".\n"), szImageMaskPath);
PtxSysCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);

// Create image mask object
pImageMask = PtxPdfContent_ImageMask_Create(pOutDoc, &imageDescriptor);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pImageMask, _T("Failed to create image mask obejct. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

double dResolution = 150.0;
TPtxGeomInt_Size size;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ImageMask_GetSize(pImageMask, &size),
_T("Failed to get image mask size. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Calculate Rectangle for data matrix
TPtxGeomReal_Rectangle rect;
rect.dLeft = x;
rect.dBottom = y;
rect.dRight = x + (double)size.iWidth * 72.0 / dResolution;
rect.dTop = y + (double)size.iHeight * 72.0 / dResolution;

// Paint image mask into the specified rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintImageMask(pGenerator, pImageMask, &rect, pPaint),
_T("Failed to paint image mask. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());

cleanup:
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Get the device color space
ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);

// Create paint object
paint = Paint.Create(outDoc, colorSpace, new double[] { 1.0, 0.0, 0.0 }, null);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add image mask, and append to output document
Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
AddImageMask(outDoc, outPage, imageMaskPath, 250, 150);
outDoc.Pages.Add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
    private static void AddImageMask(Document document, Page outPage, string imagePath, 
double x, double y)
{
// Create content generator
using ContentGenerator generator = new ContentGenerator(outPage.Content, false);

// Load image from input path
using Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read);

// Create image mask object
ImageMask imageMask = ImageMask.Create(document, inImage);
double resolution = 150;

// Calculate rectangle for image
PdfTools.FourHeights.PdfToolbox.Geometry.Integer.Size size = imageMask.Size;
Rectangle rect = new Rectangle
{
Left = x,
Bottom = y,
Right = x + size.Width * 72 / resolution,
Top = y + size.Height * 72 / resolution
};

// Paint image mask into the specified rectangle
generator.PaintImageMask(imageMask, rect, paint);
}
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Get the device color space
ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);

// Create paint object
paint = Paint.create(outDoc, colorSpace, new double[] { 1.0, 0.0, 0.0 }, null);

// Copy first page, add image mask, and append to output document
Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
addImageMask(outDoc, outPage, imageMaskPath, 250, 150);
outDoc.getPages().add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addImageMask(Document document, Page outPage, String imagePath, double x, double y)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
// Load image from input path
FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
// Create image mask object
ImageMask imageMask = ImageMask.create(document, inImage);

double resolution = 150;

// Calculate rectangle for image
Size size = imageMask.getSize();
Rectangle rect = new Rectangle(x, y, x + size.getWidth() * 72 / resolution,
y + size.getHeight() * 72 / resolution);

// Paint image mask into the specified rectangle
generator.paintImageMask(imageMask, rect, paint);
}
}

Add line numbers to PDF

Download code sample
        // Open input document
using Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read);
using Document inDoc = Document.Open(inStream, null);

// Create output document
using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Create a font for the line numbers
var lineNumberFont = Font.CreateFromSystem(outDoc, "Arial", null, true);

// Define page copy options
PageCopyOptions pageCopyOptions = new();

// Copy all pages from input to output document
var inPages = inDoc.Pages;
var outPages = PageList.Copy(outDoc, inPages, pageCopyOptions);

// Iterate over all input-output page pairs
var pages = inPages.Zip(outPages);
foreach (var pair in pages)
AddLineNumbers(outDoc, lineNumberFont, pair);

// Add the finished pages to the output document's page list
outDoc.Pages.AddRange(outPages);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AddLineNumbers(Document outDoc, Font lineNumberFont, (Page first, Page second) pair)
{
// Add line numbers to all text found in the input page to the output page

// The input and output page
var inPage = pair.first;
var outPage = pair.second;

// Extract all text fragments
var extractor = new ContentExtractor(inPage.Content)
{
Ungrouping = UngroupingSelection.All
};

// The left-most horizontel position of all text fragments
double leftX = inPage.Size.Width;

// A comparison for doubles that considers distances smaller than the font size as equal
var comparison = new Comparison<double>(
(a, b) =>
{
var d = b - a;
if (Math.Abs(d) < fontSize)
return 0;
return Math.Sign(d);
});

// A container to hold the vertical positions of all text fragments, sorted and without duplicates
SortedSet<double> lineYPositions = new(Comparer<double>.Create(comparison));

// Iterate over all content elements of the input page
foreach (var element in extractor)
{
// Process only text elements
if (element is TextElement textElement)
{
// Iterate over all text fragments
foreach (var fragment in textElement.Text)
{
// Get the fragments base line starting point
var point = fragment.Transform.TransformPoint(new Point { X = fragment.BoundingBox.Left, Y = 0 });

// Update the left-most position
leftX = Math.Min(leftX, point.X);

// Add the vertical position
lineYPositions.Add(point.Y);
}
}
}

// If at least text fragment was found: add line numbers
if (lineYPositions.Count > 0)
{
// Create a text object and use a text generator
var text = Text.Create(outDoc);
using (var textGenerator = new TextGenerator(text, lineNumberFont, fontSize, null))
{
// Iterate over all vertical positions found in the input
foreach (var y in lineYPositions)
{
// The line number string
var lineNumberString = string.Format("{0}", ++lineNumber);

// The width of the line number string when shown on the page
var width = textGenerator.GetWidth(lineNumberString);

// Position line numbers right aligned
// with a given distance to the right-most horizontal position
// and at the vertical position of the current text fragment
textGenerator.MoveTo(new Point { X = leftX - width - distance, Y = y });

// Show the line number string
textGenerator.Show(lineNumberString);
}
}

// Use a content generator to paint the text onto the page
using var contentGenerator = new ContentGenerator(outPage.Content, false);
contentGenerator.PaintText(text);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Create embedded font in output document
Font font = Font.createFromSystem(outDoc, "Arial", null, true);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages from input to output document
PageList inPages = inDoc.getPages();
PageList outPages = PageList.copy(outDoc, inPages, copyOptions);

// Iterate over all input-output page pairs and add line numbers
for (int i = 0; i < inPages.size(); ++i) {
addLineNumbers(outDoc, font, new SimpleEntry<>(inPages.get(i), outPages.get(i)));
}

// Add the finished pages to the output document's page list
outDoc.getPages().addAll(outPages);
}
}
private static void addLineNumbers(Document outDoc, Font lineNumberFont, Entry<Page, Page> pair) throws IOException, PdfToolboxException {
// Add line numbers to all text found in the input page to the output page

// The input and output page
Page inPage = pair.getKey();
Page outPage = pair.getValue();

// Extract all text fragments
ContentExtractor extractor = new ContentExtractor(inPage.getContent());
extractor.setUngrouping(UngroupingSelection.ALL);
// The left-most horizontal position of all text fragments
double leftX = inPage.getSize().getWidth();

Comparator<Double> comparator = new Comparator<Double>() {
@Override
public int compare(Double d1, Double d2) {
Double diff = d2 - d1;
if (Math.abs(diff) < fontSize)
return 0;
return (int) Math.signum(diff);
}
};

SortedSet<Double> lineYPositions = new TreeSet<>(comparator);

for (ContentElement element : extractor) {

// Process only text elements
if (element instanceof TextElement) {
TextElement textElement = (TextElement) element;
// Iterate over all text fragments
for (TextFragment fragment : textElement.getText()) {

// Get the fragments base line starting point
Point point = fragment.getTransform().transformPoint(new Point(fragment.getBoundingBox().left, 0));

// Update the left-most position
leftX = Math.min(leftX, point.x);

// Add the vertical position
lineYPositions.add(point.y);
}
}
}

// If at least one text fragment was found: add line numbers
if (lineYPositions.size() > 0) {

// Create a text object and use a text generator
Text text = Text.create(outDoc);
try (TextGenerator textGenerator = new TextGenerator(text, lineNumberFont, fontSize, null)) {
// Iterate over all vertical positions found in the input
for(double y : lineYPositions) {
// The line number string
String lineNumberString = String.valueOf(++lineNumber);

// The width of the line number string when shown on the page
double width = textGenerator.getWidth(lineNumberString);

// Position line numbers right aligned
// with a given distance to the right-most horizontal position
// and at the vertical position of the current text fragment
textGenerator.moveTo(new Point (leftX - width - distance, y));

// Show the line number string
textGenerator.show(lineNumberString);
}
}
try (ContentGenerator contentGenerator = new ContentGenerator(outPage.getContent(), false)) {
// Use a content generator to paint the text onto the page
contentGenerator.paintText(text);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Add stamp to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&inDescriptor, pInStream, FALSE);
pInDoc = PtxPdf_Document_Open(&inDescriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file %s.\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file %s cannot be closed. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Create embedded font in output document
pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Embedded font cannot be created. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Get the color space
TPtxPdfContent_ColorSpace* pColorSpace =
PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the color space. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Chose the RGB color values
double color[] = {1.0, 0.0, 0.0};
size_t nColor = sizeof(color) / sizeof(double);
pTransparency = PtxPdfContent_Transparency_New(dAlpha);

// Create paint object
pPaint = PtxPdfContent_Paint_Create(pOutDoc, pColorSpace, color, nColor, pTransparency);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Loop through all pages of input
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
for (int i = 0; i < PtxPdf_PageList_GetCount(pInPageList); i++)
{
// Get a list of pages
pInPage = PtxPdf_PageList_Get(pInPageList, i);

// Copy page from input to output
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
_T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Add stamp to page
if (addStamp(pOutDoc, pOutPage, szStampString, pFont, 50) == 1)
{
goto cleanup;
}

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (pOutPage != NULL)
{
Ptx_Release(pOutPage);
pOutPage = NULL;
}

if (pInPage != NULL)
{
Ptx_Release(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addStamp(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szStampString, TPtxPdfContent_Font* pFont,
double dFontSize)
{
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdfContent_Text* pText = NULL;
TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
TPtxGeomReal_AffineTransform trans;
TPtxGeomReal_Point rotationCenter;
double dTextWidth;
double dFontAscent;

TPtxPdfContent_Content* pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create text object
pText = PtxPdfContent_Text_Create(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create a text generator
pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, dFontSize, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Get output page size
TPtxGeomReal_Size size;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
_T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Calculate point and angle of rotation
rotationCenter.dX = size.dWidth / 2.0;
rotationCenter.dY = size.dHeight / 2.0;
double dRotationAngle = atan2(size.dHeight, size.dWidth) / M_PI * 180.0;

// Rotate textinput around the calculated position
PtxGeomReal_AffineTransform_GetIdentity(&trans);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxGeomReal_AffineTransform_Rotate(&trans, dRotationAngle, &rotationCenter),
_T("Failed to rotate textinput around the calculated position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_Transform(pGenerator, &trans),
_T("Failed to modify the current transformation. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Calculate position
TPtxGeomReal_Point position;
dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampString);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
position.dX = (size.dWidth - dTextWidth) / 2.0;
position.dY = (size.dHeight - dFontAscent * dFontSize) / 2.0;

// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
_T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
// Set text rendering
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_SetFill(pTextGenerator, pPaint),
_T("Failed to set fill paint. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
// Add given stamp string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szStampString),
_T("Failed to add stamp. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Close text generator
if (pTextGenerator != NULL)
{
PtxPdfContent_TextGenerator_Close(pTextGenerator);
pTextGenerator = NULL;
}

// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
_T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pTextGenerator != NULL)
PtxPdfContent_TextGenerator_Close(pTextGenerator);
if (pText != NULL)
Ptx_Release(pText);
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);

// Get the color space
ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);

// Choose the RGB color value
double[] color = { 1.0, 0.0, 0.0 };
Transparency transparency = new Transparency(alpha);

// Create paint object with the choosen RGB color
paint = Paint.Create(outDoc, colorSpace, color, transparency);

// Define copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
// Copy page from input to output
Page outPage = Page.Copy(outDoc, inPage, copyOptions);

// Add text to page
AddStamp(outDoc, outPage, stampString);

// Add page to document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddStamp(Document outputDoc, Page outPage, string stampString)
{
// Create content generator and text object
using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
Text text = Text.Create(outputDoc);

// Create text generator
using (TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null))
{
// Calculate point and angle of rotation
Point rotationCenter = new Point
{
X = outPage.Size.Width / 2.0,
Y = outPage.Size.Height / 2.0
};
double rotationAngle = Math.Atan2(outPage.Size.Height,
outPage.Size.Width) / Math.PI * 180.0;

// Rotate textinput around the calculated position
AffineTransform trans = AffineTransform.Identity;
trans.Rotate(rotationAngle, rotationCenter);
gen.Transform(trans);

// Calculate position
Point position = new Point
{
X = (outPage.Size.Width - textgenerator.GetWidth(stampString)) / 2.0,
Y = (outPage.Size.Height - font.Ascent * fontSize) / 2.0
};

// Move to position
textgenerator.MoveTo(position);

// Set text paint
textgenerator.Fill = paint;

// Add given stamp string
textgenerator.ShowLine(stampString);
}
// Paint the positioned text
gen.PaintText(text);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Create embedded font in output document
font = Font.createFromSystem(outDoc, "Arial", "Italic", true);

// Get the color space
ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);

// Choose the RGB color value
double[] color = { 1.0, 0.0, 0.0 };
Transparency transparency = new Transparency(alpha);

// Create paint object
paint = Paint.create(outDoc, colorSpace, color, transparency);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Loop throw all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = Page.copy(outDoc, inPage, copyOptions);

// Add text to page
addStamp(outDoc, outPage, stampString);

// Add page to document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addStamp(Document outputDoc, Page outPage, String stampString)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text text = Text.create(outputDoc);
try (// Create text generator
TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
// Calculate point and angle of rotation
Point rotationCenter = new Point(outPage.getSize().width / 2.0, outPage.getSize().height / 2.0);

// Calculate rotation angle
double rotationAngle = Math.atan2(outPage.getSize().height, outPage.getSize().width) / Math.PI * 180.0;

// Rotate text input around the calculated position
AffineTransform trans = AffineTransform.getIdentity();
trans.rotate(rotationAngle, rotationCenter);
generator.transform(trans);

// Calculate position
Point position = new Point((outPage.getSize().width - textgenerator.getWidth(stampString)) / 2.0,
(outPage.getSize().height - font.getAscent() * fontSize) / 2.0);

// Move to position
textgenerator.moveTo(position);

// Set text paint
textgenerator.setFill(paint);

// Add given stamp string
textgenerator.showLine(stampString);
}

// Paint the positioned text
generator.paintText(text);
}
}

Add text to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Create embedded font in output document
pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get page lists of input and output document
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy first page
pInPage = PtxPdf_PageList_Get(pInPageList, 0);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Add text to copied page
if (addText(pOutDoc, pOutPage, szTextString, pFont, 15) != 0)
goto cleanup;

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Get remaining pages from input
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
_T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy remaining pages to output
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
_T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Add the copied pages to the output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addText(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szTextString, TPtxPdfContent_Font* pFont,
double dFontSize)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdfContent_Text* pText = NULL;
TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
TPtxGeomReal_Size size;
TPtxGeomReal_Point position;
double dFontAscent;

pContent = PtxPdf_Page_GetContent(pOutPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content of output file. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create text object
pText = PtxPdfContent_Text_Create(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Create a text generator
pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, dFontSize, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Get output page size
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
_T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());

// Calculate position
position.dX = dBorder;
position.dY = size.dHeight - dBorder - dFontSize * dFontAscent;

// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
_T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
// Add given text string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szTextString),
_T("Failed to add text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
// Close text generator
PtxPdfContent_TextGenerator_Close(pTextGenerator);
pTextGenerator = NULL;

// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
_T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pTextGenerator != NULL)
PtxPdfContent_TextGenerator_Close(pTextGenerator);
if (pText != NULL)
Ptx_Release(pText);
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Create a font
font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add text, and append to output document
Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
AddText(outDoc, outPage, textString);
outDoc.Pages.Add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddText(Document outputDoc, Page outPage, string textString)
{
// Create content generator and text object
using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
Text text = Text.Create(outputDoc);

// Create text generator
using (TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null))
{
// Calculate position
Point position = new Point
{
X = border,
Y = outPage.Size.Height - border - fontSize * font.Ascent
};

// Move to position
textGenerator.MoveTo(position);
// Add given text string
textGenerator.ShowLine(textString);
}
// Paint the positioned text
gen.PaintText(text);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Create embedded font in output document
font = Font.createFromSystem(outDoc, "Arial", "Italic", true);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy first page, add text, and append to output document
Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
addText(outDoc, outPage, textString);
outDoc.getPages().add(outPage);

// Copy remaining pages and append to output document
PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data (excluding metadata)

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addText(Document outputDoc, Page outPage, String textString)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text text = Text.create(outputDoc);

try (// Create a text generator
TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
// Calculate position
Point position = new Point(border, outPage.getSize().height - border - fontSize * font.getAscent());

// Move to position
textgenerator.moveTo(position);
// Add given text string
textgenerator.showLine(textString);
}

// Paint the positioned text
generator.paintText(text);
}
}

Add vector graphic to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Loop through all pages of input
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
for (int iPage = 1; iPage <= PtxPdf_PageList_GetCount(pInPageList); iPage++)
{
pInPage = PtxPdf_PageList_Get(pInPageList, iPage - 1);

// Copy page from input to output
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
_T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
PtxPdf_Page_GetSize(pOutPage, &size);

// Add text on first page
if (addLine(pOutDoc, pOutPage) == 1)
{
goto cleanup;
}

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (pOutPage != NULL)
{
Ptx_Release(pOutPage);
pOutPage = NULL;
}

if (pInPage != NULL)
{
Ptx_Release(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addLine(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdfContent_Path* pPath = NULL;
TPtxPdfContent_PathGenerator* pPathGenerator = NULL;
TPtxPdfContent_ColorSpace* pDeviceRgbColorSpace = NULL;
double aColor[3];
TPtxPdfContent_Paint* pPaint = NULL;
TPtxPdfContent_Stroke* pStroke;
TPtxGeomReal_Size pageSize;
TPtxGeomReal_Point point;

pContent = PtxPdf_Page_GetContent(pOutPage);
PtxPdf_Page_GetSize(pOutPage, &pageSize);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL(pGenerator, szErrorBuff, Ptx_GetLastError());

// Create a path
pPath = PtxPdfContent_Path_New();
GOTO_CLEANUP_IF_NULL(pPath, szErrorBuff, Ptx_GetLastError());

// Create a path generator
pPathGenerator = PtxPdfContent_PathGenerator_New(pPath);
GOTO_CLEANUP_IF_NULL(pPathGenerator, szErrorBuff, Ptx_GetLastError());

// Draw a line diagonally across the page
point.dX = 10.0;
point.dY = 10.0;
GOTO_CLEANUP_IF_FALSE(PtxPdfContent_PathGenerator_MoveTo(pPathGenerator, &point), szErrorBuff, Ptx_GetLastError());
point.dX = pageSize.dWidth - 10.0;
point.dY = pageSize.dHeight - 10.0;
GOTO_CLEANUP_IF_FALSE(PtxPdfContent_PathGenerator_LineTo(pPathGenerator, &point), szErrorBuff, Ptx_GetLastError());

// Close the path generator in order to finish the path
PtxPdfContent_PathGenerator_Close(pPathGenerator);
pPathGenerator = NULL;

// Create a RGB color space
pDeviceRgbColorSpace =
PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
GOTO_CLEANUP_IF_NULL(pDeviceRgbColorSpace, szErrorBuff, Ptx_GetLastError());

// Initialize a red color
aColor[0] = 1.0;
aColor[1] = 0.0;
aColor[2] = 0.0;

// Create a paint
pPaint =
PtxPdfContent_Paint_Create(pOutDoc, pDeviceRgbColorSpace, aColor, sizeof(aColor) / sizeof(aColor[0]), NULL);
GOTO_CLEANUP_IF_NULL(pPaint, szErrorBuff, Ptx_GetLastError());

// Setup stroking parameters with given paint and line width
pStroke = PtxPdfContent_Stroke_New(pPaint, 10.0);
GOTO_CLEANUP_IF_NULL(pStroke, szErrorBuff, Ptx_GetLastError());

// Draw the path onto the page
GOTO_CLEANUP_IF_FALSE(PtxPdfContent_ContentGenerator_PaintPath(pGenerator, pPath, NULL, pStroke), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pPathGenerator != NULL)
PtxPdfContent_PathGenerator_Close(pPathGenerator);
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document 
using (System.IO.Stream inStream = new System.IO.FileStream(inPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (System.IO.Stream outStream = new System.IO.FileStream(outPath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = Page.Copy(outDoc, inPage, copyOptions);

// Add a line
AddLine(outDoc, outPage);

// Add page to output document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddLine(Document document, Page page)
{
// Create content generator
using ContentGenerator generator = new ContentGenerator(page.Content, false);

// Create a path
Path path = new Path();
using (PathGenerator pathGenerator = new PathGenerator(path))
{
// Draw a line diagonally across the page
Size pageSize = page.Size;
pathGenerator.MoveTo(new Point() { X = 10.0, Y = 10.0 });
pathGenerator.LineTo(new Point() { X = pageSize.Width - 10.0, Y = pageSize.Height - 10.0 });
}

// Create a RGB color space
ColorSpace deviceRgbColorSpace = ColorSpace.CreateProcessColorSpace(document, ProcessColorSpaceType.Rgb);

// Create a red color
double[] color = new double[] { 1.0, 0.0, 0.0 };

// Create a paint
Paint paint = Paint.Create(document, deviceRgbColorSpace, color, null);

// Create stroking parameters with given paint and line width
Stroke stroke = new Stroke(paint, 10.0);

// Draw the path onto the page
generator.PaintPath(path, null, stroke);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = Page.copy(outDoc, inPage, copyOptions);

// Add a line
addLine(outDoc, outPage);

// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void addLine(Document document, Page outPage)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {

// Create a path
Path path = new Path();
try (// Create a path generator
PathGenerator pathGenerator = new PathGenerator(path)) {
// Draw a line diagonally across the page
Size pageSize = outPage.getSize();
pathGenerator.moveTo(new Point(10.0, 10.0));
pathGenerator.lineTo(new Point(pageSize.width - 10.0, pageSize.height - 10.0));
}

// Create a RGB color space
ColorSpace deviceRgbColorSpace = ColorSpace.createProcessColorSpace(document, ProcessColorSpaceType.RGB);

// Create a red color
double[] color = new double[] { 1.0, 0.0, 0.0 };

// Create a paint
Paint paint = Paint.create(document, deviceRgbColorSpace, color, null);

// Create stroking parameters with given paint and line width
Stroke stroke = new Stroke(paint, 10.0);

// Draw the path onto the page
generator.paintPath(path, null, stroke);
}
}

Layout text on PDF page

Download code sample
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.CreateNew, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, null, null))
{
Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);

// Create page
Page outPage = Page.Create(outDoc, PageSize);

// Add text as justified text
LayoutText(outDoc, outPage, textPath, font, 20);

// Add page to document
outDoc.Pages.Add(outPage);
}
private static void LayoutText(Document outputDoc, Page outPage, string textPath, Font font,
double fontSize)
{
// Create content generator
using ContentGenerator gen = new ContentGenerator(outPage.Content, false);

// Create text object
Text text = Text.Create(outputDoc);

// Create text generator
using TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null);

// Calculate position
Point position = new Point
{
X = Border,
Y = outPage.Size.Height - Border
};

// Move to position
textGenerator.MoveTo(position);

// Loop throw all lines of the textinput
string[] lines = File.ReadAllLines(textPath, Encoding.Default);
foreach (string line in lines)
{
// Split string in substrings
string[] substrings = line.Split(new char[] { ' ' }, StringSplitOptions.None);
string currentLine = null;
double maxWidth = outPage.Size.Width - Border * 2;
int wordcount = 0;

// Loop throw all words of input strings
foreach (string word in substrings)
{
string tempLine;

// Concatenate substrings to line
if (currentLine != null)
tempLine = currentLine + " " + word;
else
tempLine = word;

// Calculate the current width of line
double width = textGenerator.GetWidth(currentLine);
if (textGenerator.GetWidth(tempLine) > maxWidth)
{
// Calculate the word spacing
textGenerator.WordSpacing = (maxWidth - width) / (wordcount - 1);
// Paint on new line
textGenerator.ShowLine(currentLine);
textGenerator.WordSpacing = 0;
currentLine = word;
wordcount = 1;
}
else
{
currentLine = tempLine;
wordcount++;
}
}
textGenerator.WordSpacing = 0;
// Add given stamp string
textGenerator.ShowLine(currentLine);
}
// Paint the positioned text
gen.PaintText(text);
}
Download code sample
try (
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, null, null)) {
// Create embedded font in output document
Font font = Font.createFromSystem(outDoc, "Arial", "Italic", true);

// Create page
Page outPage = Page.create(outDoc, new Size(595, 842));

// Add text to document
layoutText(outDoc, outPage, textPath, font, 20);

// Add page to output document
outDoc.getPages().add(outPage);
}
}
private static void layoutText(Document outputDoc, Page outPage, String textPath, Font font, double fontSize)
throws PdfToolboxException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text text = Text.create(outputDoc);

try (// Create a text generator
TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null)) {

// Calculate position
Point position = new Point(Border, outPage.getSize().height - Border);

// Move to position
textGenerator.moveTo(position);

// Loop throw all lines of the textinput
List<String> lines = Files.readAllLines(Paths.get(textPath), Charset.defaultCharset());
for (String line : lines) {
// Split string in substrings
String[] substrings = line.split(" ");
String currentLine = null;
double maxWidth = outPage.getSize().width - (Border * 2);

int wordCount = 0;

// Loop throw all words of input strings
for (String word : substrings) {
String tempLine;

// Concatenate substrings to line
if (currentLine != null) {
tempLine = currentLine + " " + word;
} else {
tempLine = word;
}

// Calculate the current width of line
double width = textGenerator.getWidth(currentLine);

if ((textGenerator.getWidth(tempLine) > maxWidth)) {
// Calculate the word spacing
textGenerator.setWordSpacing((maxWidth - width) / (double) (wordCount - 1));

// Paint on new line
textGenerator.showLine(currentLine);
textGenerator.setWordSpacing(0);
currentLine = word;
wordCount = 1;
} else {
currentLine = tempLine;
wordCount++;
}
}
textGenerator.setWordSpacing(0);
// Add given stamp string
textGenerator.showLine(currentLine);
}
}
// Paint the positioned text
generator.paintText(text);
}
}

Stamp page number to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Create embedded font in output document
pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T(""), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
{
pInPage = PtxPdf_PageList_Get(pInPageList, iPage);

// Copy page from input to output
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
_T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
_T("Failed to get size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Stamp page number on current page of output document
if (addPageNumber(pOutDoc, pOutPage, pFont, iPage + 1) == 1)
{
goto cleanup;
}

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (pOutPage != NULL)
{
Ptx_Release(pOutPage);
pOutPage = NULL;
}

if (pInPage != NULL)
{
Ptx_Release(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
int addPageNumber(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TPtxPdfContent_Font* pFont, int nPageNumber)
{
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdfContent_Text* pText = NULL;
TPtxPdfContent_TextGenerator* pTextGenerator = NULL;

pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create text object
pText = PtxPdfContent_Text_Create(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Create a text generator with the given font, size and position
pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, 8, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Generate string to be stamped as page number
char szStampBuffer[50];
snprintf(szStampBuffer, sizeof(szStampBuffer), _T("Page %d"), nPageNumber);
TCHAR* szStampText = szStampBuffer;

double dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampText);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("Failed to get text width. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Calculate position
TPtxGeomReal_Point position;
position.dX = (size.dWidth / 2) - (dTextWidth / 2);
position.dY = 10;

// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
_T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
// Add given text string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szStampText),
_T("Failed to add given text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Close text generator
PtxPdfContent_TextGenerator_Close(pTextGenerator);
pTextGenerator = NULL;

// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
_T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pTextGenerator != NULL)
PtxPdfContent_TextGenerator_Close(pTextGenerator);
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pText != NULL)
Ptx_Release(pText);
if (pContent != NULL)
Ptx_Release(pContent);

return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Create embedded font in output document
Font font = Font.CreateFromSystem(outDoc, "Arial", string.Empty, true);

// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
// Copy page from input to output
Page outPage = Page.Copy(outDoc, inPage, copyOptions);

// Stamp page number on current page of output document
AddPageNumber(outDoc, outPage, font, currentPageNumber++);

// Add page to output document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddPageNumber(Document outDoc, Page outPage, Font font, int pageNumber)
{
// Create content generator
using ContentGenerator generator = new ContentGenerator(outPage.Content, false);

// Create text object
Text text = Text.Create(outDoc);

// Create a text generator with the given font, size and position
using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
{
// Generate string to be stamped as page number
string stampText = string.Format("Page {0}", pageNumber);

// Calculate position for centering text at bottom of page
Point position = new Point
{
X = (outPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
Y = 10
};

// Position the text
textgenerator.MoveTo(position);
// Add page number
textgenerator.Show(stampText);
}
// Paint the positioned text
generator.PaintText(text);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy pages from input to output
int pageNo = 1;

// Create embedded font in output document
Font font = Font.createFromSystem(outDoc, "Arial", "", true);

// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = Page.copy(outDoc, inPage, copyOptions);

// Stamp page number on current page of output document
applyStamps(outDoc, outPage, font, pageNo++);

// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void applyStamps(Document doc, Page page, Font font, int pageNo) throws PdfToolboxException, IOException {

try (// Create content generator
ContentGenerator generator = new ContentGenerator(page.getContent(), false)) {
// Create text object
Text text = Text.create(doc);

try (// Create a text generator with the given font, size and position
TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {

// Generate string to be stamped as page number
String stampText = String.format("Page %d", pageNo);

// Calculate position for centering text at bottom of page
Point position = new Point((page.getSize().width / 2) - (textgenerator.getWidth(stampText) / 2), 10);

// Position the text
textgenerator.moveTo(position);
// Add page number
textgenerator.show(stampText);
}

// Paint the positioned text
generator.paintText(text);
}
}

Content Modification

Remove glyphs

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Process each page
foreach (var inPage in inDoc.Pages)
{
// Create empty output page
Page outPage = Page.Create(outDoc, inPage.Size);
// Copy page content from input to output and remove glyphs
CopyContentAndRemoveGlyphs(inPage.Content, outPage.Content, outDoc);
// Add the new page to the output document's page list
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void CopyContentAndRemoveGlyphs(Content inContent, Content outContent, Document outDoc)
{
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
using ContentGenerator generator = new ContentGenerator(outContent, false);

// Iterate over all content elements
foreach (ContentElement inElement in extractor)
{
ContentElement outElement;
// Special treatment for group elements
if (inElement is GroupElement inGroupElement)
{
// Create empty output group element
GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
outElement = outGroupElement;
// Call CopyContentAndRemoveGlyphs() recursively for the group element's content
CopyContentAndRemoveGlyphs(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
}
else
{
// Copy the content element to the output document
outElement = ContentElement.Copy(outDoc, inElement);
if (outElement is TextElement outTextElement)
{
// Special treatment for text element
Text text = outTextElement.Text;
// Remove the first two glyphs from each text fragment
foreach (var fragment in text)
{
// Ensure that the fragment has more than two glyphs
if (fragment.Count > 2)
{
// Call RemoveAt twice
fragment.RemoveAt(0);
fragment.RemoveAt(0);
}
}
}
}
// Append the finished output element to the content generator
generator.AppendContentElement(outElement);
}
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Process each page
for (Page inPage : inDoc.getPages()) {
// Create empty output page
Page outPage = Page.create(outDoc, inPage.getSize());
// Copy page content from input to output and remove glyphs
copyContentAndRemoveGlyphs(inPage.getContent(), outPage.getContent(), outDoc);
// Add the new page to the output document's page list
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void copyContentAndRemoveGlyphs(Content inContent, Content outContent, Document outDoc) throws PdfToolboxException, IOException {
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
// Iterate over all content elements
for (ContentElement inElement : extractor) {
ContentElement outElement = null;
// Special treatment for group elements
if (inElement instanceof GroupElement) {
GroupElement inGroupElement = (GroupElement)inElement;
// Create empty output group element
GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
outElement = outGroupElement;
// Call copyContentAndRemoveGlyphs() recursively for the group element's content
copyContentAndRemoveGlyphs(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
} else {
// Copy the content element to the output document
outElement = ContentElement.copy(outDoc, inElement);
if (outElement instanceof TextElement) {
// Special treatment for text element
TextElement outTextElement = (TextElement)outElement;
Text text = outTextElement.getText();
// Remove the first two glyphs from each text fragment
for (int iFragment = 0; iFragment < text.size(); ++iFragment) {
// Ensure that the fragment has more than two glyphs
if (text.get(iFragment).size() > 2) {
// Call remove twice
text.get(iFragment).remove(0);
text.get(iFragment).remove(0);
}
}
}
}
// Append the finished output element to the content generator
generator.appendContentElement(outElement);
}
}
}

Remove White Text from PDF

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Process each page
foreach (var inPage in inDoc.Pages)
{
// Create empty output page
Page outPage = Page.Create(outDoc, inPage.Size);
// Copy page content from input to output
CopyContent(inPage.Content, outPage.Content, outDoc);
// Add the new page to the output document's page list
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void CopyContent(Content inContent, Content outContent, Document outDoc)
{
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
using ContentGenerator generator = new ContentGenerator(outContent, false);

// Iterate over all content elements
foreach (ContentElement inElement in extractor)
{
ContentElement outElement;
// Special treatment for group elements
if (inElement is GroupElement inGroupElement)
{
// Create empty output group element
GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
outElement = outGroupElement;
// Call CopyContent() recursively for the group element's content
CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
}
else
{
// Copy the content element to the output document
outElement = ContentElement.Copy(outDoc, inElement);
if (outElement is TextElement outTextElement)
{
// Special treatment for text element
Text text = outTextElement.Text;
// Remove all those text fragments whose fill and stroke paint is white
for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
{
TextFragment fragment = text[iFragment];
if ((fragment.Fill == null || IsWhite(fragment.Fill.Paint)) &&
(fragment.Stroke == null || IsWhite(fragment.Stroke.Paint)))
text.RemoveAt(iFragment);
}
// Prevent appending an empty text element
if (text.Count == 0)
outElement = null;
}
}
// Append the finished output element to the content generator
if (outElement != null)
generator.AppendContentElement(outElement);
}
}
private static bool IsWhite(Paint paint)
{
ColorSpace colorSpace = paint.ColorSpace;
if (colorSpace is DeviceGrayColorSpace || colorSpace is CalibratedGrayColorSpace ||
colorSpace is DeviceRgbColorSpace || colorSpace is CalibratedRgbColorSpace)
{
// These color spaces are additive: white is 1.0
return paint.Color.Min() == 1.0;
}
if (colorSpace is DeviceCmykColorSpace)
{
// This color space is subtractive: white is 0.0
return paint.Color.Max() == 0.0;
}
return false;
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Process each page
for (Page inPage : inDoc.getPages()) {
// Create empty output page
Page outPage = Page.create(outDoc, inPage.getSize());
// Copy page content from input to output
copyContent(inPage.getContent(), outPage.getContent(), outDoc);
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void copyContent(Content inContent, Content outContent, Document outDoc) throws PdfToolboxException, IOException {
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
// Iterate over all content elements
for (ContentElement inElement : extractor) {
ContentElement outElement = null;
// Special treatment for group elements
if (inElement instanceof GroupElement) {
GroupElement inGroupElement = (GroupElement)inElement;
// Create empty output group element
GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
outElement = outGroupElement;
// Call copyContent() recursively for the group element's content
copyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
} else {
// Copy the content element to the output document
outElement = ContentElement.copy(outDoc, inElement);
if (outElement instanceof TextElement) {
// Special treatment for text element
TextElement outTextElement = (TextElement)outElement;
Text text = outTextElement.getText();
// Remove all those text fragments whose fill and stroke paint is white
for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
TextFragment fragment = text.get(iFragment);
if ((fragment.getFill() == null || isWhite(fragment.getFill().getPaint())) &&
(fragment.getStroke() == null || isWhite(fragment.getStroke().getPaint())))
text.remove(iFragment);
}
// Prevent appending an empty text element
if (text.size() == 0)
outElement = null;
}
}
// Append the finished output element to the content generator
if (outElement != null)
generator.appendContentElement(outElement);
}
}
}
private static boolean isWhite(Paint paint) {
double[] color = paint.getColor();
ColorSpace colorSpace = paint.getColorSpace();
if (colorSpace instanceof DeviceGrayColorSpace || colorSpace instanceof CalibratedGrayColorSpace ||
colorSpace instanceof DeviceRgbColorSpace || colorSpace instanceof CalibratedRgbColorSpace) {
// These color spaces are additive: white is 1.0
for (double value : color)
if (value != 1.0)
return false;
return true;
}
if (colorSpace instanceof DeviceCmykColorSpace) {
// This color space is subtractive: white is 0.0
for (double value : color)
if (value != 0.0)
return false;
return true;
}
return false;
}

Replace Text Fragment in PDF

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Process each page
foreach (var inPage in inDoc.Pages)
{
// Create empty output page
Page outPage = Page.Create(outDoc, inPage.Size);
// Copy page content from input to output and search for string
CopyContent(inPage.Content, outPage.Content, outDoc, searchString);
// If the text was found and deleted, add the replacement text
if (fragment != null)
AddText(outDoc, outPage, replString);
// Add the new page to the output document's page list
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void CopyContent(Content inContent, Content outContent, Document outDoc, string searchString)
{
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
using ContentGenerator generator = new ContentGenerator(outContent, false);

// Iterate over all content elements
foreach (ContentElement inElement in extractor)
{
ContentElement outElement;
// Special treatment for group elements
if (inElement is GroupElement inGroupElement)
{
// Create empty output group element
GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
outElement = outGroupElement;
// Save transform for later restore
AffineTransform currentTransform = overallTransform;
// Update the transform
overallTransform.Concatenate(inGroupElement.Transform);
// Call CopyContent() recursively for the group element's content
CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc, searchString);
// Restore the transform
overallTransform = currentTransform;
}
else
{
// Copy the content element to the output document
outElement = ContentElement.Copy(outDoc, inElement);
if (fragment == null && outElement is TextElement outTextElement)
{
// Special treatment for text element
Text text = outTextElement.Text;
// Find text fragment with string to replace
for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
{
// In this sample, the fragment text must match in its entirety
if (text[iFragment].Text == searchString)
{
// Keep the found fragment for later use
fragment = text[iFragment];
// Update the transform
overallTransform.Concatenate(fragment.Transform);
// Remove the found text fragment from the output
text.RemoveAt(iFragment);
break;
}
}
// Prevent appending an empty text element
if (text.Count == 0)
outElement = null;
}
}
// Append the finished output element to the content generator
if (outElement != null)
generator.AppendContentElement(outElement);
}
}
private static void AddText(Document doc, Page page, string replString)
{
// Create a new text object
Text text = Text.Create(doc);
// Heuristic to map the extracted font base name to a font name and font family
string[] parts = fragment.Font.BaseFont.Split('-');
string family = parts[0];
string style = parts.Length > 1 ? parts[1] : null;
// Create a new font object
Font font = Font.CreateFromSystem(doc, family, style, true);
// Create a text generator and set the original fragment's properties
using (TextGenerator textGenerator = new TextGenerator(text, font, fragment.FontSize, null))
{
textGenerator.CharacterSpacing = fragment.CharacterSpacing;
textGenerator.WordSpacing = fragment.WordSpacing;
textGenerator.HorizontalScaling = fragment.HorizontalScaling;
textGenerator.Rise = fragment.Rise;
textGenerator.Show(replString);
}
// Create a content generator
using ContentGenerator contentGenerator = new ContentGenerator(page.Content, false);
// Apply the computed transform
contentGenerator.Transform(overallTransform);
// Paint the new text
contentGenerator.PaintText(text);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Process each page
for (Page inPage : inDoc.getPages()) {
// Create empty output page
Page outPage = Page.create(outDoc, inPage.getSize());
// Copy page content from input to output and search for string
copyContent(inPage.getContent(), outPage.getContent(), outDoc, searchString);
// If the text was found and deleted, add the replacement text
if (fragment != null)
addText(outDoc, outPage, replString);
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void copyContent(Content inContent, Content outContent, Document outDoc, String searchString) throws PdfToolboxException, IOException {
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
// Iterate over all content elements
for (ContentElement inElement : extractor) {
ContentElement outElement = null;
// Special treatment for group elements
if (inElement instanceof GroupElement) {
GroupElement inGroupElement = (GroupElement)inElement;
// Create empty output group element
GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
outElement = outGroupElement;
// Save transform for later restor
AffineTransform currentTransform = overallTransform;
// Update the transform
overallTransform.concatenate(inGroupElement.getTransform());
// Call copyContent() recursively for the group element's content
copyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc, searchString);
// Restor the transform
overallTransform = currentTransform;
} else {
// Copy the content element to the output document
outElement = ContentElement.copy(outDoc, inElement);
if (fragment == null && outElement instanceof TextElement) {
// Special treatment for text element
TextElement outTextElement = (TextElement)outElement;
Text text = outTextElement.getText();
// Find text fragment with string to replace
for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
// In this sample, the fragment text must match in its entirety
if (text.get(iFragment).getText().equals(searchString)) {
// Keep the found fragment for later use
fragment = text.get(iFragment);
// Update the transform
overallTransform.concatenate(fragment.getTransform());
// Remove the found text fragment from the output
text.remove(iFragment);
break;
}
}
// Prevent appending an empty text element
if (text.size() == 0)
outElement = null;
}
}
// Append the finished output element to the content generator
if (outElement != null)
generator.appendContentElement(outElement);
}
}
}
private static void addText(Document doc, Page page, String replString) throws CorruptException, PdfToolboxException, IOException {
// Create a new text object
Text text = Text.create(doc);
// Heuristic to map the extracted fon base name to a font family and font style
String[] parts = fragment.getFont().getBaseFont().split("-");
String family = parts[0];
String style = parts.length > 1 ? parts[1] : null;
// Create a new font object
Font font = Font.createFromSystem(doc, family, style, true);
// Create a text generator and set the original fragment's properties
try (TextGenerator textGenerator = new TextGenerator(text, font, fragment.getFontSize(), null)) {
textGenerator.setCharacterSpacing(fragment.getCharacterSpacing());
textGenerator.setWordSpacing(fragment.getWordSpacing());
textGenerator.setHorizontalScaling(fragment.getHorizontalScaling());
textGenerator.setRise(fragment.getRise());
textGenerator.show(replString);
}
// Create a content generator
try (ContentGenerator contentGenerator = new ContentGenerator(page.getContent(), false)) {
// Apply the computed transform
contentGenerator.transform(overallTransform);
// Paint the new text
contentGenerator.paintText(text);
}
}

Document Setup

Add metadata to PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Add copied pages to output
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
_T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (argc == 4)
{
// Add metadata from a input file
pMdataStream = _tfopen(szMdatafile, _T("rb"));
GOTO_CLEANUP_IF_NULL(pMdataStream, _T("Failed to open metadata file \"%s\".\n"), szMdatafile);
PtxSysCreateFILEStreamDescriptor(&mdataDescriptor, pMdataStream, 0);

// Get file extension
TCHAR* szExt = _tcsrchr(szMdatafile, '.');
_tcscpy(szExtension, szExt);

if (_tcscmp(szExtension, _T(".pdf")) == 0)
{
// Use the metadata of another PDF file
TPtxPdf_Document* pMetaDoc = PtxPdf_Document_Open(&mdataDescriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetaDoc, _T("Failed to open metadata file. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
TPtxPdf_Metadata* pMetadata = PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pMetaDoc));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)."),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pMetadata),
_T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
}
else
{
// Use the content of an XMP metadata file
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Create(pOutDoc, &mdataDescriptor)),
_T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
}
}
else
{
// Set some metadata properties
TPtxPdf_Metadata* pMetadata = PtxPdf_Document_GetMetadata(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetAuthor(pMetadata, _T("Your Author")),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetTitle(pMetadata, _T("Your Title")),
_T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetSubject(pMetadata, _T("Your Subject")),
_T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetCreator(pMetadata, _T("Your Creator")),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
}
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// Copy document-wide data (excluding metadata)

TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Open input document 
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Set Metadata
if (args.Length == 3)
{
Metadata mdata;

// Add metadata from a input file
using FileStream metaStream = File.OpenRead(mdatafile);
if (mdatafile.EndsWith(".pdf"))
{
// Use the metadata of another PDF file
Document metaDoc = Document.Open(metaStream, "");
mdata = Metadata.Copy(outDoc, metaDoc.Metadata);
}
else
{
// Use the content of an XMP metadata file
mdata = Metadata.Create(outDoc, metaStream);
}
outDoc.Metadata = mdata;
}
else
{
// Set some metadata properties
Metadata metadata = outDoc.Metadata;
metadata.Author = "Your Author";
metadata.Title = "Your Title";
metadata.Subject = "Your Subject";
metadata.Creator = "Your Creator";
}

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data (except metadata)

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outDoc.getPages().addAll(copiedPages);

if (args.length == 3) {
Metadata mdata;

// Add metadata from a input file
FileStream metaStream = new FileStream(mdatafile, FileStream.Mode.READ_ONLY);

if (mdatafile.toLowerCase().endsWith(".pdf")) {
// Use the metadata of another PDF file
Document metaDoc = Document.open(metaStream, null);
mdata = Metadata.copy(outDoc, metaDoc.getMetadata());
} else {
// Use the content of an XMP metadata file
mdata = Metadata.create(outDoc, metaStream);
}
outDoc.setMetadata(mdata);
} else {
// Set some metadata properties
Metadata metadata = outDoc.getMetadata();
metadata.setAuthor("Your Author");
metadata.setTitle("Your Title");
metadata.setSubject("Your Subject");
metadata.setCreator("Your Creator");
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data (excluding metadata)

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Encrypt PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

pEncryption =
PtxPdf_Encryption_New(szUserPwd, szOwnerPwd, ePtxPdf_Permission_Print | ePtxPdf_Permission_DigitalPrint);

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, pEncryption);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Add copied pages to output
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
_T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Create encryption parameters
Encryption encryptionParams = new Encryption(UserPwd, OwnerPwd, Permission.Print |
Permission.DigitalPrint);

// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document and set a user and owner password
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, encryptionParams))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
// Create encryption parameters
Encryption encryptionParams = new Encryption(userPwd, ownerPwd,
EnumSet.of(Permission.PRINT, Permission.DIGITAL_PRINT));

try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document and set a user and owner password
Document outDoc = Document.create(outStream, inDoc.getConformance(), encryptionParams)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Flatten form fields in PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options: enable form field flattening
pCopyOptions = PtxPdf_PageCopyOptions_New();
PtxPdf_PageCopyOptions_SetFormFields(pCopyOptions, ePtxPdfForms_FormFieldCopyStrategy_Flatten);

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Add copied pages to output
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
_T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define copy options including form field flattening
PageCopyOptions copyOptions = new PageCopyOptions();
copyOptions.FormFields = FormFieldCopyStrategy.Flatten;

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define copy options including form field flattening
PageCopyOptions copyOptions = new PageCopyOptions();
copyOptions.setFormFields(FormFieldCopyStrategy.FLATTEN);

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Merge multiple PDFs and create a table of contents page

Download code sample
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, null, null))
{
// Create embedded font in output document
Font font = Font.CreateFromSystem(outDoc, "Arial", string.Empty, true);

// Define page copy options
PageCopyOptions pageCopyOptions = new PageCopyOptions();

var copiedPageLists = new List<Tuple<string, PageList>>(inPaths.Length);

// A page number counter
int pageNumber = 2;

// Copy all input documents pages
foreach (string inPath in inPaths)
{
// Open input document
using Stream inFs = new FileStream(inPath, FileMode.Open, FileAccess.Read);
using Document inDoc = Document.Open(inFs, null);

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, pageCopyOptions);

// Add page numbers to copied pages
foreach (var copiedPage in copiedPages)
{
AddPageNumber(outDoc, copiedPage, font, pageNumber++);
}

// Create outline item
string title = inDoc.Metadata.Title ?? System.IO.Path.GetFileNameWithoutExtension(inPath);
copiedPageLists.Add(new Tuple<string, PageList>(title, copiedPages));
}

// Create table of contents page
var contentsPage = CreateTableOfContents(outDoc, copiedPageLists);
AddPageNumber(outDoc, contentsPage, font, 1);

// Add pages to the output document
PageList outPages = outDoc.Pages;
outPages.Add(contentsPage);
foreach (var tuple in copiedPageLists)
{
outPages.AddRange(tuple.Item2);
}
private static void AddPageNumber(Document outDoc, Page copiedPage, Font font, int pageNumber)
{
// Create content generator
using ContentGenerator generator = new ContentGenerator(copiedPage.Content, false);

// Create text object
Text text = Text.Create(outDoc);

// Create a text generator with the given font, size and position
using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
{
// Generate string to be stamped as page number
string stampText = string.Format("Page {0}", pageNumber);

// Calculate position for centering text at bottom of page
Point position = new Point
{
X = (copiedPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
Y = 10
};

// Position the text
textgenerator.MoveTo(position);
// Add page number
textgenerator.Show(stampText);
}
// Paint the positioned text
generator.PaintText(text);
}
private static Page CreateTableOfContents(Document outDoc, List<Tuple<string, PageList>> copiedPageLists)
{
// Create a new page with size equal to the first page copied
var page = Page.Create(outDoc, copiedPageLists[0].Item2[0].Size);

// Create a font
var font = Font.CreateFromSystem(outDoc, "Arial", null, true);

// Parameters for layout computation
double border = 30;
double textWidth = page.Size.Width - 2 * border;
double chapterTitleSize = 24;
double titleSize = 12;

// The current text location
var location = new Point() { X = border, Y = page.Size.Height - border - chapterTitleSize };

// The page number of the current item in the table of content
int pageNumber = 2;

// Creat a content generator for the table of contents page
using (var contentGenerator = new ContentGenerator(page.Content, false))
{
// Create a text object
var text = Text.Create(outDoc);

// Create a text generator to generate the table of contents. Initially, use the chapter title font size
using (var textGenerator = new TextGenerator(text, font, chapterTitleSize, location))
{
// Show a chapter title
textGenerator.ShowLine("Table of Contents");

// Advance the vertical position
location.Y -= 1.7 * chapterTitleSize;

// Select the font size for an entry in the table of contents
textGenerator.FontSize = titleSize;

// Iterate over all copied page ranges
foreach (var tuple in copiedPageLists)
{
// The title string for the current entry
string title = tuple.Item1;

// The page number string of the target page for this entry
string pageNumberString = string.Format("{0}", pageNumber);

// The width of the page number string
double pageNumberWidth = textGenerator.GetWidth(pageNumberString);

// Compute the number of filler dots to be displayed between the entry title and the page number
int numberOfDots = (int)Math.Floor((textWidth - textGenerator.GetWidth(title) - pageNumberWidth) / textGenerator.GetWidth("."));

// Move to the current location and show the entry's title and the filler dots
textGenerator.MoveTo(location);
textGenerator.Show(title + new string('.', numberOfDots));

// Show the page number
textGenerator.MoveTo(new Point() { X = page.Size.Width - border - pageNumberWidth, Y = location.Y });
textGenerator.Show(pageNumberString);

// Compute the rectangle for the link
var linkRectangle = new Rectangle()
{
Left = border,
Bottom = location.Y + font.Descent * titleSize,
Right = border + textWidth,
Top = location.Y + font.Ascent * titleSize
};

// Create a destination to the first page of the current page range and create a link for this destination
var pageList = tuple.Item2;
var targetPage = pageList[0];
var destination = LocationZoomDestination.Create(outDoc, targetPage, 0, targetPage.Size.Height, null);
var link = InternalLink.Create(outDoc, linkRectangle, destination);

// Add the link to the table of contents page
page.Links.Add(link);

// Advance the location for the next entry
location.Y -= 1.8 * titleSize;
pageNumber += pageList.Count;
}
}

// Paint the generated text
contentGenerator.PaintText(text);
}

// Return the finished table-of-contents page
return page;
}
Download code sample
try (
// Open input document
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, null, null)) {

// Create embedded font in output document
Font font = Font.createFromSystem(outDoc, "Arial", "", true);

// Configure page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

Set<Map.Entry<String, PageList>> copiedPageLists = new HashSet<>(inPaths.length);

// A page number counter
int pageNumber = 2;


// Copy all input documents pages
for (String inPath : inPaths) {
try (// Open input document
Stream inFs = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inFs, null)) {

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);

// Add page numbers to copied pages
for ( Page copiedPage : copiedPages)
{
addPageNumber(outDoc, copiedPage, font, pageNumber++);
}

// Hold the file name without extension
if (inPath == null)
continue;
// Get position of last '.'.
int pos = inPath.lastIndexOf(".");
// If there was a '.', hold the file name only
if (pos != -1)
inPath = inPath.substring(0, pos);

// Create outline item
String title = (inDoc.getMetadata().getTitle() == null ? inPath : inDoc.getMetadata().getTitle());
copiedPageLists.add(new AbstractMap.SimpleEntry<String, PageList>(title, copiedPages));
}
}

// Create table of contents page
Page contentsPage = createTableOfContents(outDoc, copiedPageLists);
addPageNumber(outDoc, contentsPage, font, 1);

// Add pages to the output document
PageList outPages = outDoc.getPages();
outPages.add(contentsPage);
for (Map.Entry<String, PageList> entry : copiedPageLists)
{
outPages.addAll(entry.getValue());
}
private static void addPageNumber(Document outDoc, Page copiedPage, Font font, int pageNumber) throws PdfToolboxException, IOException
{
// Create content generator
try (ContentGenerator generator = new ContentGenerator(copiedPage.getContent(), false)) {
// Create text object
Text text = Text.create(outDoc);

// Create a text generator with the given font, size and position
try (TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
// Generate string to be stamped as page number
String stampText = String.format("Page %d", pageNumber);

// Calculate position for centering text at bottom of page
Point position = new Point();
position.x = (copiedPage.getSize().getWidth() / 2) - (textgenerator.getWidth(stampText) / 2);
position.y = 10;

// Position the text
textgenerator.moveTo(position);
// Add page number
textgenerator.show(stampText);
}

// Paint the positioned text
generator.paintText(text);
}
}
private static Page createTableOfContents(Document outDoc, Set<Map.Entry<String, PageList>> copiedPageLists) throws IOException, PdfToolboxException
{
// Create a new page with size equal to the first page copied
Page page = Page.create(outDoc, copiedPageLists.iterator().next().getValue().get(0).getSize());

// Create a font
Font font = Font.createFromSystem(outDoc, "Arial", null, true);

// Parameters for layout computation
double border = 30;
double textWidth = page.getSize().getWidth() - 2 * border;
double chapterTitleSize = 24;
double titleSize = 12;

// The current text location
Point location = new Point();
location.x = border;
location.y = page.getSize().getHeight() - border - chapterTitleSize;

// The page number of the current item in the table of content
int pageNumber = 2;

// Creat a content generator for the table of contents page
try (ContentGenerator contentGenerator = new ContentGenerator(page.getContent(), false)) {
// Create a text object
Text text = Text.create(outDoc);

// Create a text generator to generate the table of contents. Initially, use the chapter title font size
try (TextGenerator textGenerator = new TextGenerator(text, font, chapterTitleSize, location)) {
// Show a chapter title
textGenerator.showLine("Table of Contents");

// Advance the vertical position
location.y -= 1.7 * chapterTitleSize;

// Select the font size for an entry in the table of contents
textGenerator.setFontSize(titleSize);

// Iterate over all copied page ranges
for (Map.Entry<String, PageList> entry : copiedPageLists)
{
// The title string for the current entry
String title = entry.getKey();

// The page number string of the target page for this entry
String pageNumberString = String.format("%d", pageNumber);

// The width of the page number string
double pageNumberWidth = textGenerator.getWidth(pageNumberString);

// Compute the number of filler dots to be displayed between the entry title and the page number
int numberOfDots = (int)Math.floor((textWidth - textGenerator.getWidth(title) - pageNumberWidth) / textGenerator.getWidth("."));

// Move to the current location and show the entry's title and the filler dots
textGenerator.moveTo(location);
String dots = new String();
for (int i = 0; i < numberOfDots; i++)
{
dots += '.';
}
textGenerator.show(title + dots);

// Show the page number
Point point = new Point();
point.x = page.getSize().getWidth() - border - pageNumberWidth;
point.y = location.y;
textGenerator.moveTo(point);
textGenerator.show(pageNumberString);

// Compute the rectangle for the link
Rectangle linkRectangle = new Rectangle();
linkRectangle.setLeft(border);
linkRectangle.setBottom(location.y + font.getDescent() * titleSize);
linkRectangle.setRight(border + textWidth);
linkRectangle.setTop(location.y + font.getAscent() * titleSize);

// Create a destination to the first page of the current page range and create a link for this destination
PageList pageList = entry.getValue();
Page targetPage = pageList.get(0);
LocationZoomDestination destination = LocationZoomDestination.create(outDoc, targetPage, (double) 0, targetPage.getSize().getHeight(), null);
InternalLink link = InternalLink.create(outDoc, linkRectangle, destination);

// Add the link to the table of contents page
page.getLinks().add(link);

// Advance the location for the next entry
location.y -= 1.8 * titleSize;
pageNumber += pageList.size();
}
}

// Paint the generated text
contentGenerator.paintText(text);
}

// Return the finished table-of-contents page
return page;
}

Merge multiple PDFs

Download code sample
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, NULL, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get output page list
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Merge input documents
for (int i = 1; i < argc - 1; i++)
{
// Open input document
pInStream = _tfopen(szInPath[i], _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath[i]);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath[i], szErrorBuff, Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Append copied pages
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
_T("Failed to add page range. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

Ptx_Release(pInPageList);
pInPageList = NULL;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_Close(pInDoc),
_T("Failed to close input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
pInDoc = NULL;
fclose(pInStream);
pInStream = NULL;
Ptx_Release(pCopiedPages);
pCopiedPages = NULL;
}
Download code sample
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, null, null))
{
// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Get output pages
PageList outPages = outDoc.Pages;

// Merge input documents
for (int i = 0; i < args.Length - 1; i++)
{
// Open input document
using Stream inFs = new FileStream(inPath[i], FileMode.Open, FileAccess.Read);
using Document inDoc = Document.Open(inFs, null);

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outPages.AddRange(copiedPages);
}
}
Download code sample
try (
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, null, null)) {

// Configure page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Get output pages
PageList outPages = outDoc.getPages();

// Merge input document
for (int i = 0; i < args.length - 1; i++) {
try (// Open input document
FileStream inStream = new FileStream(inPath[i], FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outPages.addAll(copiedPages);
}
}
}
}

Merge multiple PDFs with outlines

Download code sample
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, null, null))
{
// Define page copy options, skip outline
PageCopyOptions pageCopyOptions = new PageCopyOptions
{
CopyOutlineItems = false
};

// Define outline copy options
OutlineCopyOptions outlineCopyOptions = new OutlineCopyOptions();

// Get output pages
PageList outPages = outDoc.Pages;

// Merge input documents
foreach (string inPath in inPaths)
{
// Open input document
using Stream inFs = new FileStream(inPath, FileMode.Open, FileAccess.Read);
using Document inDoc = Document.Open(inFs, null);

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, pageCopyOptions);
outPages.AddRange(copiedPages);

// Create outline item
string title = inDoc.Metadata.Title ?? Path.GetFileName(inPath);
Page firstCopiedPage = copiedPages[0];
Destination destination = LocationZoomDestination.Create(outDoc, firstCopiedPage, 0, firstCopiedPage.Size.Height, null);
OutlineItem outlineItem = OutlineItem.Create(outDoc, title, destination);
outDoc.Outline.Add(outlineItem);

// Add outline items from input document as children
OutlineItemList children = outlineItem.Children;
foreach (OutlineItem inputOutline in inDoc.Outline)
children.Add(OutlineItem.Copy(outDoc, inputOutline, outlineCopyOptions));
}
}
Download code sample
try (
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, null, null)) {
// Define page copy options, skip outline
PageCopyOptions pageCopyOptions = new PageCopyOptions();
pageCopyOptions.setCopyOutlineItems(false);

// Define outline copy options
OutlineCopyOptions outlineCopyOptions = new OutlineCopyOptions();

// Get output pages
PageList outPages = outDoc.getPages();

// Merge input document
for (String inPath : inPaths) {
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), pageCopyOptions);
outPages.addAll(copiedPages);

// Create outline item
String title = inDoc.getMetadata().getTitle();
if (title == null)
title = Paths.get(inPath).getFileName().toString();
Page firstCopiedPage = copiedPages.get(0);
Destination destination = LocationZoomDestination.create(outDoc, firstCopiedPage, 0.0,
firstCopiedPage.getSize().getHeight(), null);
OutlineItem outlineItem = OutlineItem.create(outDoc, title, destination);
outDoc.getOutline().add(outlineItem);

// Add outline items from input document as children
OutlineItemList children = outlineItem.getChildren();
for (OutlineItem inputOutline : inDoc.getOutline())
children.add(OutlineItem.copy(outDoc, inputOutline, outlineCopyOptions));
}
}
}
}

Overlay color of PDF

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Create transparency and set blend mode
Transparency transparency = new Transparency(colorAlpha)
{
BlendMode = BlendMode.Multiply
};

// Create colorspace
ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, colorType);

// Create a transparent paint for the given color
Paint paint = Paint.Create(outDoc, colorSpace, color, transparency);
Fill fill = new Fill(paint);

// Get output pages
PageList outPages = outDoc.Pages;

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Loop through all pages
foreach (Page inPage in inDoc.Pages)
{
// Create a new page
Size size = inPage.Size;
Page outPage = Page.Copy(outDoc, inPage, copyOptions);

// Create a content generator
using (ContentGenerator generator = new ContentGenerator(outPage.Content, false))
{
// Compute Rectangle
Rectangle rect = new Rectangle
{
Left = 0,
Bottom = 0,
Right = size.Width,
Top = size.Height
};

// Make a rectangular path the same size as the page
PdfTools.FourHeights.PdfToolbox.Pdf.Content.Path path = new PdfTools.FourHeights.PdfToolbox.Pdf.Content.Path();
using (PathGenerator pathGenerator = new PathGenerator(path))
{
Rectangle pathRect = new Rectangle
{
Left = 0,
Bottom = 0,
Right = size.Width,
Top = size.Height
};
pathGenerator.AddRectangle(pathRect);
}
// Paint the path with the transparent paint
generator.PaintPath(path, fill, null);
}
// Add pages to output document
outPages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Create transparency and set blend mode
Transparency transparency = new Transparency(colorAlpha);
transparency.setBlendMode(BlendMode.MULTIPLY);

// Create colorspace
ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, colorType);

// Create a transparent paint for the given color
Paint paint = Paint.create(outDoc, colorSpace, color, transparency);
Fill fill = new Fill(paint);

// Set copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Loop through all pages
for (Page inPage : inDoc.getPages()) {
// Create a new page
Size size = inPage.getSize();
Page outPage = Page.copy(outDoc, inPage, copyOptions);

try (// Create a content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Calculate rectangle
Rectangle rect = new Rectangle(0, 0, size.width, size.height);

// Make a rectangular path the same size as the page
Path path = new Path();
try (
PathGenerator pathGenerator = new PathGenerator(path)) {
pathGenerator.addRectangle(rect);
}

// Paint the path with the transparent paint
generator.paintPath(path, fill, null);
}

// Add pages to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Add info entries to PDF

Download code sample
// Open input document 
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);

// Set info entry
Metadata metadata = Metadata.Copy(outDoc, inDoc.Metadata);
if (key == "Title")
metadata.Title = value;
else if (key == "Author")
metadata.Author = value;
else if (key == "Subject")
metadata.Subject = value;
else if (key == "Keywords")
metadata.Keywords = value;
else if (key == "CreationDate")
metadata.CreationDate = DateTimeOffset.Parse(value);
else if (key == "ModDate")
throw new Exception("ModDate cannot be set.");
else if (key == "Creator")
metadata.Creator = value;
else if (key == "Producer")
throw new Exception("Producer is set by means of the license key.");
else
metadata.CustomEntries[key] = value;
outDoc.Metadata = metadata;
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data (except metadata)

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outDoc.getPages().addAll(copiedPages);

// Set info entry
Metadata metadata = Metadata.copy(outDoc, inDoc.getMetadata());
if (key.equals("Title"))
metadata.setTitle(value);
else if (key.equals("Author"))
metadata.setAuthor(value);
else if (key.equals("Subject"))
metadata.setSubject(value);
else if (key.equals("Keywords"))
metadata.setKeywords(value);
else if (key.equals("CreationDate")) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd' 'HH:mm:ssZ");
OffsetDateTime creationDate = OffsetDateTime.parse(value, formatter);
metadata.setCreationDate(creationDate);
} else if (key.equals("ModDate"))
throw new Exception("ModDate cannot be set.");
else if (key.equals("Creator"))
metadata.setCreator(value);
else if (key.equals("Producer"))
throw new Exception("Producer is set by means of the license key.");
else
metadata.getCustomEntries().put(key, value);
outDoc.setMetadata(metadata);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data (excluding metadata)

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Set the open-destination of a PDF

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
if (destinationPageNumber < 1 || destinationPageNumber > inDoc.Pages.Count)
throw new ArgumentOutOfRangeException("Given page number is invalid");

// Create output document
using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);

// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);

// Add open destination
Page outPage = copiedPages[destinationPageNumber - 1];
outDoc.OpenDestination = LocationZoomDestination.Create(outDoc, outPage, 0, outPage.Size.Height, null);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Check given page number
if (destinationPageNumber < 1 || destinationPageNumber > inDoc.getPages().size()) {
System.out.println("Given pageNumber is invalid.");
return;
}

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages and append to output document
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
outDoc.getPages().addAll(copiedPages);

// Add open destination
Page outPage = outDoc.getPages().get(destinationPageNumber - 1);
LocationZoomDestination destination = LocationZoomDestination.create(outDoc, outPage, 0.0, outPage.getSize().getHeight(), null);
outDoc.setOpenDestination(destination);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Remove pages from PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int nInPages = PtxPdf_PageList_GetCount(pInPageList);
iStartIndex = MAX(MIN(nInPages - 1, iStartIndex), 0);
nCount = MIN(nInPages - iStartIndex, nCount);
GOTO_CLEANUP_IF_FALSE(nCount > 0, _T("lastPage must be greater or equal to firstPage.\n"));

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Get page range from input pages
pInPageRange = PtxPdf_PageList_GetRange(pInPageList, iStartIndex, nCount);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
_T("Failed to get page range from input document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Copy page range to toutput document
pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange, _T("Failed to copy page range. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Get output pages
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Appende page range to output pages
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
_T("Failed to append page range. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
startIndex = Math.Max(Math.Min(inDoc.Pages.Count - 1, startIndex), 0);
count = Math.Min(inDoc.Pages.Count - startIndex, count);
if (count <= 0)
{
Console.WriteLine("lastPage must be greater or equal to firstPage");
return;
}

// Create output document
using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);

// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Get page range from input pages
PageList inPageRange = inDoc.Pages.GetRange(startIndex, count);

// Copy page range and append to output document
PageList outPageRange = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(outPageRange);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {
// Get pages from input document
PageList inPages = inDoc.getPages();

// Correct and check page indices
startIndex = Math.max(Math.min(inPages.size() - 1, startIndex), 0);
endIndex = Math.max(Math.min(inPages.size(), endIndex), 0);
if (startIndex >= endIndex) {
System.out.println("lastPage must be greater or equal to firstPage");
return;
}
try (
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Get page range from input pages
PageList inPageRange = inPages.subList(startIndex, endIndex);

// Copy page range and append to output document
PageList outPageRange = PageList.copy(outDoc, inPageRange, copyOptions);
outDoc.getPages().addAll(outPageRange);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain mbedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Split at Outlines

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
// Collect all outline items at the given level
List<OutlineItem> outlines = GetOutlines(inDoc.Outline, level);

// Collect all page ranges corresponding to the given outline items
List<Tuple<PageList, OutlineItem>> parts = GetParts(inDoc.Pages, outlines);

// Iterate over all collected parts
foreach (var part in parts)
{
// Turn the outline item's title into a valid file name
string fileName = part.Item2.Title;
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(c, '_');
}
fileName += ".pdf";
fileName = System.IO.Path.Combine(outDir, fileName);

// Create output document
using Stream outStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);

// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions pageCopyOptions = new PageCopyOptions();
pageCopyOptions.CopyOutlineItems = false;

// Copy the pages and add to the output document's page list
PageList outPages = PageList.Copy(outDoc, part.Item1, pageCopyOptions);
outDoc.Pages.AddRange(outPages);

// Copy child outline items
OutlineCopyOptions outlineCopyOptions = new OutlineCopyOptions();
foreach (var child in part.Item2.Children)
{
outDoc.Outline.Add(OutlineItem.Copy(outDoc, child, outlineCopyOptions));
}
}
}
private static List<OutlineItem> GetOutlines(OutlineItemList currentOutlines, int level, int currentLevel = 1)
{
List<OutlineItem> matchingOutlines = new List<OutlineItem>();
// If the current level matches the specified level add the given outline items
if (level == currentLevel)
{
matchingOutlines.AddRange(currentOutlines);
}
else
{
// Otherwise recurse to next level
foreach (var outline in currentOutlines)
{
matchingOutlines.AddRange(GetOutlines(outline.Children, level, currentLevel + 1));
}
}
return matchingOutlines;
}
private static List<Tuple<PageList, OutlineItem>> GetParts(PageList inPages, List<OutlineItem> outlines)
{
// Construct parts according to the given outlines
List<Tuple<PageList, OutlineItem>> parts = new List<Tuple<PageList, OutlineItem>>();

// No parts to be constructed if no outlines are found
if (outlines.Count == 0)
return parts;

// Keep both the last and the next outline items while iterating
OutlineItem lastOutline = null;
var outlineEnumerator = outlines.GetEnumerator();
outlineEnumerator.MoveNext();
OutlineItem nextOutline = outlineEnumerator.Current;

// Keep both, the last and the current page index while iterating
int lastPageIndex = 0;
for (int pageIndex = 0; pageIndex < inPages.Count; pageIndex++)
{
// Check if this page is the destination's page of the next outline
if (inPages[pageIndex].Equals(nextOutline.Destination.Target.Page))
{
// Create a new part if the last outline item is defined and if the page index has increased at least by 1
if (lastOutline != null && pageIndex - lastPageIndex > 0)
parts.Add(new Tuple<PageList, OutlineItem>(inPages.GetRange(lastPageIndex, pageIndex - lastPageIndex), lastOutline));

// Keep the current page index as the last page index used
lastPageIndex = pageIndex;

// Keep the current outline as the last outline used
lastOutline = nextOutline;

// Iterate to the next outline item and stop if none left
if (outlineEnumerator.MoveNext())
nextOutline = outlineEnumerator.Current;
else
break;
}
}
// Add the last part which is assumed to contain all the pages until the end of the document
parts.Add(new Tuple<PageList, OutlineItem>(inPages.GetRange(lastPageIndex, inPages.Count - lastPageIndex), lastOutline));
return parts;
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}

Imposition

Create a booklet from PDF

Download code sample
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// Objects that need releasing or closing
TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
TPtxPdf_Metadata* pInMetadata = NULL;
TPtxPdf_Metadata* pOutMetadata = NULL;
TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
TPtxPdf_FileReferenceList* pInFileRefList = NULL;
TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
TPtxPdf_FileReference* pInFileRef = NULL;
TPtxPdf_FileReference* pOutFileRef = NULL;

iReturnValue = 0;

// Output intent
pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
if (pInOutputIntent != NULL)
{
pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
_T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
_T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Metadata
pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
if (pInMetadata != NULL)
{
pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
_T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Viewer settings
pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
if (pInViewerSettings != NULL)
{
pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
_T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
_T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
Ptx_GetLastError());

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}
Ptx_Release(pInFileRefList);
pInFileRefList = NULL;
Ptx_Release(pOutFileRefList);
pOutFileRefList = NULL;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}

cleanup:
if (pInOutputIntent != NULL)
Ptx_Release(pInOutputIntent);
if (pOutOutputIntent != NULL)
Ptx_Release(pOutOutputIntent);
if (pInMetadata != NULL)
Ptx_Release(pInMetadata);
if (pOutMetadata != NULL)
Ptx_Release(pOutMetadata);
if (pInViewerSettings != NULL)
Ptx_Release(pInViewerSettings);
if (pOutViewerSettings != NULL)
Ptx_Release(pOutViewerSettings);
if (pInFileRefList != NULL)
Ptx_Release(pInFileRefList);
if (pOutFileRefList != NULL)
Ptx_Release(pOutFileRefList);
if (pInFileRef != NULL)
Ptx_Release(pInFileRef);
if (pOutFileRef != NULL)
Ptx_Release(pOutFileRef);
return iReturnValue;
}
int StampPageNumber(TPtxPdf_Document* pDocument, TPtxPdfContent_Font* pFont,
TPtxPdfContent_ContentGenerator* pGenerator, int nPageNo, BOOL bIsLeftPage)
{
// Objects that need releasing or closing
TPtxPdfContent_Text* pText = NULL;
TPtxPdfContent_TextGenerator* pTextGenerator = NULL;

// Create text object
pText = PtxPdfContent_Text_Create(pDocument);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Create text generator
pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, 8.0, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create text generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

TCHAR szStampText[50];
_stprintf(szStampText, _T("Page %d"), nPageNo);

// Get width of stamp text
double dStampWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampText);
if (dStampWidth == 0.0)
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get text width. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Compute position
TPtxGeomReal_Point point = {
.dX = bIsLeftPage ? dBorder + 0.5 * dCellWidth - dStampWidth / 2
: 2 * dBorder + 1.5 * dCellWidth - dStampWidth / 2,
.dY = dBorder,
};

// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &point),
_T("Failed to move to position. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Add page number
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_Show(pTextGenerator, szStampText),
_T("Failed to show text. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

BOOL bClose = PtxPdfContent_TextGenerator_Close(pTextGenerator);
pTextGenerator = NULL;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(bClose, _T("Failed to close text generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
_T("Failed to paint text. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

cleanup:
if (pText != NULL)
Ptx_Release(pText);
if (pTextGenerator != NULL)
PtxPdfContent_TextGenerator_Close(pTextGenerator);
return iReturnValue;
}
void ComputeTargetRect(TPtxGeomReal_Rectangle* pRectangle, const TPtxGeomReal_Size* pBBox, BOOL bIsLeftPage)
{
// Compute factor for fitting page into rectangle
double dScale = MIN(dCellWidth / pBBox->dWidth, dCellHeight / pBBox->dHeight);
double dGroupWidth = pBBox->dWidth * dScale;
double dGroupHeight = pBBox->dHeight * dScale;

// Compute x-value
double dGroupXPos =
bIsLeftPage ? dCellLeft + (dCellWidth - dGroupWidth) / 2 : dCellRight + (dCellWidth - dGroupWidth) / 2;

// Compute y-value
double dGroupYPos = dCellYPos + (dCellHeight - dGroupHeight) / 2;

// Set rectangle
pRectangle->dLeft = dGroupXPos;
pRectangle->dBottom = dGroupYPos;
pRectangle->dRight = dGroupXPos + dGroupWidth;
pRectangle->dTop = dGroupYPos + dGroupHeight;
}
int CreateBooklet(TPtxPdf_PageList* pInDocList, TPtxPdf_Document* pOutDoc, TPtxPdf_PageList* pOutDocList,
int nLeftPageIndex, int nRightPageIndex, TPtxPdfContent_Font* pFont)
{
// Objects that need releasing or closing
TPtxPdf_PageCopyOptions* pCopyOptions = NULL;
TPtxPdf_Page* pOutPage = NULL;
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdf_Page* pInPage = NULL;
TPtxPdfContent_Group* pGroup = NULL;

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Create page object
pOutPage = PtxPdf_Page_Create(pOutDoc, &pageSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create page object. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Create content generator
pContent = PtxPdf_Page_GetContent(pOutPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create content generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

int nPageCount = PtxPdf_PageList_GetCount(pInDocList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get page list count. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Left page
if (nLeftPageIndex < nPageCount)
{
// Get the input page
pInPage = PtxPdf_PageList_Get(pInDocList, nLeftPageIndex);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Copy page from input to output
pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Compute group location
TPtxGeomReal_Size groupSize;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
_T("Failed to get group size. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
TPtxGeomReal_Rectangle targetRect;
ComputeTargetRect(&targetRect, &groupSize, TRUE);

// Paint group at location
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
_T("Failed to paint group. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());

// Add page number to page
if (StampPageNumber(pOutDoc, pFont, pGenerator, nLeftPageIndex + 1, TRUE) != 0)
goto cleanup;

Ptx_Release(pInPage);
pInPage = NULL;
Ptx_Release(pGroup);
pGroup = NULL;
}

// Right page
if (nRightPageIndex < nPageCount)
{
// Get the input Page
pInPage = PtxPdf_PageList_Get(pInDocList, nRightPageIndex);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());

// Copy page from input to output
pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Compute group location
TPtxGeomReal_Size groupSize;
PtxPdfContent_Group_GetSize(pGroup, &groupSize);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
_T("Failed to get group size. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
TPtxGeomReal_Rectangle targetRect;
ComputeTargetRect(&targetRect, &groupSize, FALSE);

// Paint group on the Computed rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
_T("Failed to paint group. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());

// Add page number to page
if (StampPageNumber(pOutDoc, pFont, pGenerator, nRightPageIndex + 1, FALSE) != 0)
goto cleanup;
}

BOOL bClose = PtxPdfContent_ContentGenerator_Close(pGenerator);
pGenerator = NULL;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(bClose, _T("Failed to close content generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutDocList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());

cleanup:
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pCopyOptions != NULL)
Ptx_Release(pCopyOptions);
if (pOutPage != NULL)
Ptx_Release(pOutPage);
if (pContent != NULL)
Ptx_Release(pContent);
if (pInPage != NULL)
Ptx_Release(pInPage);
if (pGroup != NULL)
Ptx_Release(pGroup);
return iReturnValue;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Create a font
Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);

// Copy pages
PageList inPages = inDoc.Pages;
PageList outPages = outDoc.Pages;
int numberOfSheets = (inPages.Count + 3) / 4;

for (int sheetNumber = 0; sheetNumber < numberOfSheets; ++sheetNumber)
{

// Add on front side
CreateBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
2 * sheetNumber, font);

// Add on back side
CreateBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
4 * numberOfSheets - 2 * sheetNumber - 2, font);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void CreateBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
int rightPageIndex, Font font)
{
// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Create page object
Page outpage = Page.Create(outDoc, PageSize);

// Create content generator
using (ContentGenerator generator = new ContentGenerator(outpage.Content, false))
{
// Left page
if (leftPageIndex < inPages.Count)
{
// Copy page from input to output
Page leftPage = inPages[leftPageIndex];
Group leftGroup = Group.CopyFromPage(outDoc, leftPage, copyOptions);

// Paint group on the calculated rectangle
generator.PaintGroup(leftGroup, ComputTargetRect(leftGroup.Size, true), null);

// Add page number to page
StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
}

// Right page
if (rightPageIndex < inPages.Count)
{
// Copy page from input to output
Page rigthPage = inPages[rightPageIndex];
Group rightGroup = Group.CopyFromPage(outDoc, rigthPage, copyOptions);

// Paint group on the calculated rectangle
generator.PaintGroup(rightGroup, ComputTargetRect(rightGroup.Size, false), null);

// Add page number to page
StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
}
}
// Add page to output document
outPages.Add(outpage);
}
private static Rectangle ComputTargetRect(Size bbox, bool isLeftPage)
{
// Calculate factor for fitting page into rectangle
double scale = Math.Min(CellWidth / bbox.Width, CellHeight / bbox.Height);
double groupWidth = bbox.Width * scale;
double groupHeight = bbox.Height * scale;

// Calculate x-value
double groupXPos = isLeftPage ? CellLeft + (CellWidth - groupWidth) / 2 :
CellRight + (CellWidth - groupWidth) / 2;

// Calculate y-value
double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;

// Calculate rectangle
return new Rectangle
{
Left = groupXPos,
Bottom = groupYPos,
Right = groupXPos + groupWidth,
Top = groupYPos + groupHeight
};
}
private static void StampPageNumber(Document document, Font font, ContentGenerator generator,
int PageNo, bool isLeftPage)
{
// Create text object
Text text = Text.Create(document);

// Create text generator
using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
{
string stampText = string.Format("Page {0}", PageNo);

// Get width of stamp text
double width = textgenerator.GetWidth(stampText);

// Calculate position
double x = isLeftPage ? Border + 0.5 * CellWidth - width / 2 :
2 * Border + 1.5 * CellWidth - width / 2;
double y = Border;

// Move to position
textgenerator.MoveTo(new Point { X = x, Y = y});

// Add page number
textgenerator.Show(stampText);
}
// Paint the positioned text
generator.PaintText(text);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
Font font = Font.createFromSystem(outDoc, "Arial", "Italic", true);

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Copy pages
PageList inPages = inDoc.getPages();
PageList outPages = outDoc.getPages();
int numberOfSheets = (inPages.size() + 3) / 4;

for (int sheetNumber = 0; sheetNumber < numberOfSheets; ++sheetNumber) {
// Add on front side
createBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
2 * sheetNumber, font);

// Add on back side
createBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
4 * numberOfSheets - 2 * sheetNumber - 2, font);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}
private static void createBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
int rightPageIndex, Font font) throws PdfToolboxException, IOException {
// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Create page object
Page outPage = Page.create(outDoc, new Size(PageWidth, PageHeight));

try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {

// Left page
if (leftPageIndex < inPages.size()) {
Page leftPage = inPages.get(leftPageIndex);

// Copy page from input to output
Group leftGroup = Group.copyFromPage(outDoc, leftPage, copyOptions);

// Paint group on the calculated rectangle
generator.paintGroup(leftGroup, computeTargetRect(leftGroup.getSize(), true), null);

// Add page number to page
StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
}

// Right page
if (rightPageIndex < inPages.size()) {
Page rightPage = inPages.get(rightPageIndex);

// Copy page from input to output
Group rightGroup = Group.copyFromPage(outDoc, rightPage, copyOptions);

// Paint group on the calculated rectangle
generator.paintGroup(rightGroup, computeTargetRect(rightGroup.getSize(), false), null);

// Add page number to page
StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
}
}
// Add page to output document
outPages.add(outPage);
}
private static Rectangle computeTargetRect(Size bbox, Boolean isLeftPage) {
// Calculate factor for fitting page into rectangle
double scale = Math.min(CellWidth / bbox.width, CellHeight / bbox.height);
double groupWidth = bbox.width * scale;
double groupHeight = bbox.height * scale;

// Calculate x-value
double groupXPos = isLeftPage ? CellLeft + (CellWidth - groupWidth) / 2 :
CellRight + (CellWidth - groupWidth) / 2;

// Calculate y-value
double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;

// Calculate rectangle
return new Rectangle(groupXPos, groupYPos, groupXPos + groupWidth, groupYPos + groupHeight);
}
private static void StampPageNumber(Document document, Font font, ContentGenerator generator, int pageNo,
boolean isLeftPage) throws PdfToolboxException, IOException {
// Create text object
Text text = Text.create(document);

try (// Create text generator
TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
String stampText = String.format("Page %d", pageNo);

// Get width of stamp text
double width = textgenerator.getWidth(stampText);

// Calculate position
double x = isLeftPage ? Border + 0.5 * CellWidth - width / 2 :
2 * Border + 1.5 * CellWidth - width / 2;
double y = Border;

// Move to position
textgenerator.moveTo(new Point(x, y));

// Add page number
textgenerator.show(stampText);
}

// Paint the positioned text
generator.paintText(text);
}

Fit pages to specific page format

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
{
TPtxGeomReal_Size pageSize;
TPtxGeomReal_Size rotatedSize;
BOOL bRotate;

pInPage = PtxPdf_PageList_Get(pInPageList, iPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());

pOutPage = NULL;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pInPage, &pageSize), _T("%s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

bRotate = bAllowRotate && (pageSize.dHeight >= pageSize.dWidth) != (targetSize.dHeight >= targetSize.dWidth);
if (bRotate)
{
rotatedSize.dWidth = pageSize.dHeight;
rotatedSize.dHeight = pageSize.dHeight;
}
else
{
rotatedSize = pageSize;
}

if (rotatedSize.dWidth == targetSize.dWidth && rotatedSize.dHeight == targetSize.dWidth)
{
// If size is correct, copy page only
pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
_T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (bRotate)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_Rotate(pOutPage, ePtxGeom_Rotation_Clockwise),
_T("Failed to rotate page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
}
}
else
{
TPtxPdfContent_Group* pGroup = NULL;
TPtxPdfContent_Content* pContent = NULL;
TPtxGeomReal_AffineTransform transform;
TPtxGeomReal_Point position;
TPtxGeomReal_Point point;

// Create a new page of correct size and fit existing page onto it
pOutPage = PtxPdf_Page_Create(pOutDoc, &targetSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create a new page. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Copy page as group
pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Calculate scaling and position of group
double scale = MIN(targetSize.dWidth / rotatedSize.dWidth, targetSize.dHeight / rotatedSize.dHeight);

// Calculate position
position.dX = (targetSize.dWidth - pageSize.dWidth * scale) / 2;
position.dY = (targetSize.dHeight - pageSize.dHeight * scale) / 2;

pContent = PtxPdf_Page_GetContent(pOutPage);

// Create content generator
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator,
_T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

// Calculate and apply transformation
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxGeomReal_AffineTransform_GetIdentity(&transform),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxGeomReal_AffineTransform_Translate(&transform, position.dX, position.dY),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxGeomReal_AffineTransform_Scale(&transform, scale, scale),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());

point.dX = pageSize.dWidth / 2.0;
point.dY = pageSize.dHeight / 2.0;

// Rotate input file
if (bRotate)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxGeomReal_AffineTransform_Rotate(&transform, 90, &point),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
}
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_Transform(pGenerator, &transform),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());

// Paint form
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, NULL, NULL),
_T("Failed to paint the group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

PtxPdfContent_ContentGenerator_Close(pGenerator);
pGenerator = NULL;

if (pGenerator != NULL)
Ptx_Release(pGenerator);
if (pGroup != NULL)
Ptx_Release(pGroup);
}

// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (pOutPage != NULL)
{
Ptx_Release(pOutPage);
pOutPage = NULL;
}

if (pInPage != NULL)
{
Ptx_Release(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy pages
foreach (Page inPage in inDoc.Pages)
{
Page outPage = null;
Size pageSize = inPage.Size;

bool rotate = AllowRotate &&
(pageSize.Height >= pageSize.Width) != (TargetSize.Height >= TargetSize.Width);
Size rotatedSize = pageSize;

if (rotate)
rotatedSize = new Size { Width = pageSize.Height, Height = pageSize.Width };

if (rotatedSize.Width == TargetSize.Width && rotatedSize.Height == TargetSize.Width)
{
// If size is correct, copy page only
outPage = Page.Copy(outDoc, inPage, copyOptions);

if (rotate)
outPage.Rotate(Rotation.Clockwise);
}
else
{
// Create new page of correct size and fit existing page onto it
outPage = Page.Create(outDoc, TargetSize);

// Copy page as group
Group group = Group.CopyFromPage(outDoc, inPage, copyOptions);
// Calculate scaling and position of group
double scale = Math.Min(TargetSize.Width / rotatedSize.Width,
TargetSize.Height / rotatedSize.Height);

// Calculate position
Point position = new Point
{
X = (TargetSize.Width - pageSize.Width * scale) / 2,
Y = (TargetSize.Height - pageSize.Height * scale) / 2
};

// Create content generator
using ContentGenerator generator = new ContentGenerator(outPage.Content, false);

// Calculate and apply transformation
AffineTransform transform = AffineTransform.Identity;
transform.Translate(position.X, position.Y);
transform.Scale(scale, scale);

Point point = new Point()
{
X = pageSize.Width / 2.0,
Y = pageSize.Height / 2.0
};

// Rotate input file
if (rotate)
transform.Rotate(90, point);
generator.Transform(transform);

// Paint group
generator.PaintGroup(group, null, null);
}
// Add page to output document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy pages
for (Page inPage : inDoc.getPages()) {
Page outPage = null;
Size pageSize = inPage.getSize();

boolean rotate = AllowRotate &&
(pageSize.height >= pageSize.width) != (TargetHeight >= TargetWidth);
Size rotatedSize = pageSize;

if (rotate)
rotatedSize = new Size(pageSize.height, pageSize.width);

if (rotatedSize.width == TargetWidth && rotatedSize.height == TargetWidth) {
// If size is correct, copy page only
outPage = Page.copy(outDoc, inPage, copyOptions);

if (rotate)
outPage.rotate(Rotation.CLOCKWISE);
} else {
// Create new page of correct size and fit existing page onto it
outPage = Page.create(outDoc, new Size(TargetWidth, TargetHeight));

// Copy page as group
Group group = Group.copyFromPage(outDoc, inPage, copyOptions);
// Calculate scaling and position of group
double scale = Math.min(TargetWidth / rotatedSize.width,
TargetHeight / rotatedSize.height);

// Calculate position
Point position = new Point(
(TargetWidth - pageSize.width * scale) / 2,
(TargetHeight - pageSize.height * scale) / 2);

try(// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Calculate and apply transformation
AffineTransform transform = AffineTransform.getIdentity();
transform.translate(position.x, position.y);
transform.scale(scale, scale);

Point point = new Point(pageSize.width / 2.0, pageSize.height / 2.0);

// Rotate input file
if (rotate)
transform.rotate(90, point);
generator.transform(transform);

// Paint group
generator.paintGroup(group, null, null);
}
}
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Place multiple pages on one page

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
_T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
int nPageCount = 0;
for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
{
pInPage = PtxPdf_PageList_Get(pInPageList, iPage);

if (nPageCount == nNx * nNy)
{
// Add to output document
PtxPdfContent_ContentGenerator_Close(pGenerator);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
Ptx_Release(pOutPage);
pOutPage = NULL;
nPageCount = 0;
}
if (pOutPage == NULL)
{
// Create a new output page
pOutPage = PtxPdf_Page_Create(pOutDoc, &PageSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
_T("Failed to create a new output page. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
TPtxPdfContent_Content* pContent = PtxPdf_Page_GetContent(pOutPage);
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator,
_T("Failed to create content generator. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
}

// Get area where group has to be
int x = nPageCount % nNx;
int y = nNy - (nPageCount / nNx) - 1;

// Calculate cell size
TPtxGeomReal_Size cellSize;
cellSize.dWidth = (PageSize.dWidth - ((nNx + 1) * dBorder)) / nNx;
cellSize.dHeight = (PageSize.dHeight - ((nNy + 1) * dBorder)) / nNy;

// Calculate cell position
TPtxGeomReal_Point cellPosition;
cellPosition.dX = dBorder + x * (cellSize.dWidth + dBorder);
cellPosition.dY = dBorder + y * (cellSize.dHeight + dBorder);

// Copy page group from input to output
pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pGroup, _T("Failed to copy page group from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Calculate group position
TPtxGeomReal_Size groupSize;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
_T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
double dScale = MIN(cellSize.dWidth / groupSize.dWidth, cellSize.dHeight / groupSize.dHeight);

// Calculate target size
TPtxGeomReal_Size targetSize;
targetSize.dWidth = groupSize.dWidth * dScale;
targetSize.dHeight = groupSize.dHeight * dScale;

// Calculate position
TPtxGeomReal_Point targetPos;
targetPos.dX = cellPosition.dX + ((cellSize.dWidth - targetSize.dWidth) / 2);
targetPos.dY = cellPosition.dY + ((cellSize.dHeight - targetSize.dHeight) / 2);

// Calculate rectangle
TPtxGeomReal_Rectangle targetRect;
targetRect.dLeft = targetPos.dX;
targetRect.dBottom = targetPos.dY;
targetRect.dRight = targetPos.dX + targetSize.dWidth;
targetRect.dTop = targetPos.dY + targetSize.dHeight;

// Add group to page
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
_T("Failed to paint the group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());

if (pGroup != NULL)
{
Ptx_Release(pGroup);
pGroup = NULL;
}
if (pInPage != NULL)
{
Ptx_Release(pInPage);
pInPage = NULL;
}

nPageCount++;
}

// Add partially filled page
if (pOutPage != NULL)
{
PtxPdfContent_ContentGenerator_Close(pGenerator);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
Ptx_Release(pOutPage);
pOutPage = NULL;
}

int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
// Create output document
using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
PageList outPages = outDoc.Pages;
int pageCount = 0;
ContentGenerator generator = null;
Page outPage = null;

// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
if (pageCount == Nx * Ny)
{
// Add to output document
generator.Dispose();
outPages.Add(outPage);
outPage = null;
pageCount = 0;
}
if (outPage == null)
{
// Create a new output page
outPage = Page.Create(outDoc, PageSize);
generator = new ContentGenerator(outPage.Content, false);
}

// Get area where group has to be
int x = pageCount % Nx;
int y = Ny - (pageCount / Nx) - 1;

// Compute cell size
Size cellSize = new Size
{
Width = (PageSize.Width - ((Nx + 1) * Border)) / Nx,
Height = (PageSize.Height - ((Ny + 1) * Border)) / Ny
};

// Compute cell position
Point cellPosition = new Point
{
X = Border + x * (cellSize.Width + Border),
Y = Border + y * (cellSize.Height + Border)
};

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy page as group from input to output
Group group = Group.CopyFromPage(outDoc, inPage, copyOptions);

// Compute group position
Size groupSize = group.Size;
double scale = Math.Min(cellSize.Width / groupSize.Width,
cellSize.Height / groupSize.Height);

// Compute target size
Size targetSize = new Size
{
Width = groupSize.Width * scale,
Height = groupSize.Height * scale
};

// Compute position
Point targetPos = new Point
{
X = cellPosition.X + ((cellSize.Width - targetSize.Width) / 2),
Y = cellPosition.Y + ((cellSize.Height - targetSize.Height) / 2)
};

// Compute rectangle
Rectangle targetRect = new Rectangle
{
Left = targetPos.X,
Bottom = targetPos.Y,
Right = targetPos.X + targetSize.Width,
Top = targetPos.Y + targetSize.Height
};

// Add group to page
generator.PaintGroup(group, targetRect, null);
pageCount++;
}
// Add page
if (outPage != null)
{
generator.Dispose();
outPages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {
try (
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
PageList outPages = outDoc.getPages();
int pageCount = 0;
ContentGenerator generator = null;
Page outPage = null;

// A4 portrait
Size pageSize = new Size(595, 842);

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Copy pages
for (Page inPage : inDoc.getPages()) {

if (pageCount == Nx * Ny) {
// Add to output document
generator.close();
outPages.add(outPage);
outPage = null;
pageCount = 0;
}
if (outPage == null) {
// Create a new output page
outPage = Page.create(outDoc, pageSize);
generator = new ContentGenerator(outPage.getContent(), false);
}

// Get area where group has to be
int x = pageCount % Nx;
int y = Ny - (pageCount / Nx) - 1;

// Calculate cell size
Size cellSize = new Size((pageSize.width - ((Nx + 1) * Border)) / Nx,
(pageSize.height - ((Ny + 1) * Border)) / Ny);

// Calculate cell position
Point cellPosition = new Point(Border + x * (cellSize.width + Border),
Border + y * (cellSize.height + Border));

// Set copy option
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy page group from input to output
Group group = Group.copyFromPage(outDoc, inPage, copyOptions);

// Calculate group position
Size groupSize = group.getSize();
double scale = Math.min(cellSize.width / groupSize.width,
cellSize.height / groupSize.height);

// Calculate target size
Size targetSize = new Size(groupSize.width * scale, groupSize.height * scale);

// Calculate position
Point targetPos = new Point(cellPosition.x + ((cellSize.width - targetSize.width) / 2),
cellPosition.y + ((cellSize.height - targetSize.height) / 2));

// Calculate rectangle
Rectangle targetRect = new Rectangle(targetPos.x, targetPos.y,
targetPos.x + targetSize.width, targetPos.y + targetSize.height);

// Add group to page
generator.paintGroup(group, targetRect, null);

pageCount++;
}
// Add page
if (outPage != null) {
generator.close();
outPages.add(outPage);
}
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Set page orientation

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
iConformance = PtxPdf_Document_GetConformance(pInDoc);
pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
szOutPath, szErrorBuff, Ptx_GetLastError());

// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
_T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();

// Copy all pages
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

// Rotate given pages by 90 degrees
for (int i = 0; i < ARRAY_SIZE(aPageNumbers); i++)
{
pOutPage = PtxPdf_PageList_Get(pCopiedPages, aPageNumbers[i] - 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to get copied page. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_Rotate(pOutPage, ePtxGeom_Rotation_Clockwise),
_T("Failed to rotate page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
}

// Add pages to output document
pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
_T("Failed to add copied pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
TPtxPdf_FileReferenceList* pInFileRefList;
TPtxPdf_FileReferenceList* pOutFileRefList;

// Output intent
if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
return FALSE;

// Metadata
if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
FALSE)
return FALSE;

// Viewer settings
if (PtxPdf_Document_SetViewerSettings(
pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
return FALSE;

// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
if (PtxPdf_FileReferenceList_Add(
pOutFileRefList,
PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
return FALSE;

return TRUE;
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))

// Create output document
using (Stream outFs = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outFs, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);

// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);

// Rotate selected pages by 90 degrees
foreach (var pageNumber in pageNumbers)
{
copiedPages[pageNumber - 1].Rotate(Rotation.Clockwise);
}

// Add pages to output document
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data

// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);

// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);

// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {

// Copy document-wide data
copyDocumentData(inDoc, outDoc);

// Set copy options and flatten annotations, form fields and signatures
PageCopyOptions copyOptions = new PageCopyOptions();

// Copy all pages
PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);

// Rotate selected pages by 90 degrees
for (int pageNumber : pageNumbers) {
copiedPages.get(pageNumber - 1).rotate(Rotation.CLOCKWISE);
}

// Add pages to output document
outDoc.getPages().addAll(copiedPages);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws PdfToolboxException, IOException {
// Copy document-wide data

// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));

// Metadata
outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));

// Viewer settings
outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));

// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));

// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
}

Information Extraction

Extract all images and image masks from a PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Loop over all pages and extract images
pInPageList = PtxPdf_Document_GetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
_T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

for (int iPageNo = 0; iPageNo < PtxPdf_PageList_GetCount(pInPageList); iPageNo++)
{
pPage = PtxPdf_PageList_Get(pInPageList, iPageNo);
pContent = PtxPdf_Page_GetContent(pPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content from page %d. %s (ErrorCode: 0x%08x).\n"),
iPageNo + 1, szErrorBuff, Ptx_GetLastError());

pExtractor = PtxPdfContent_ContentExtractor_New(pContent);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pExtractor,
_T("Failed to create content extractor. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(extractImages(pExtractor, iPageNo + 1, szOutputDir),
_T("Error occurred while extracting images. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());

if (pPage != NULL)
{
Ptx_Release(pPage);
pPage = NULL;
}
if (pContent != NULL)
{
Ptx_Release(pContent);
pContent = NULL;
}
}

int extractImages(TPtxPdfContent_ContentExtractor* pExtractor, int iPageNo, const TCHAR* szOutputDir)
{
int iImgCount = 0;
int iImgMaskCount = 0;
TPtxPdfContent_ContentExtractorIterator* pIterator = NULL;
TPtxPdfContent_ContentElement* pContentElement = NULL;
TPtxPdfContent_Image* pImage = NULL;
TPtxPdfContent_ImageMask* pImageMask = NULL;
TCHAR* szExtension = NULL;
FILE* pOutStream = NULL;

pIterator = PtxPdfContent_ContentExtractor_GetIterator(pExtractor);
GOTO_CLEANUP_IF_NULL(pIterator, _T("Failed to get iterator.\n"));
PtxPdfContent_ContentExtractorIterator_MoveNext(pIterator);
while (pContentElement = PtxPdfContent_ContentExtractorIterator_GetValue(pIterator))
{
TPtxPdfContent_ContentElementType iType = PtxPdfContent_ContentElement_GetType(pContentElement);
if (iType == ePtxPdfContent_ContentElementType_ImageElement)
{
iImgCount++;
pImage = PtxPdfContent_ImageElement_GetImage((TPtxPdfContent_ImageElement*)pContentElement);
GOTO_CLEANUP_IF_NULL(pImage, _T("Failed to get image.\n"));

const TPtxPdfContent_ImageType iImageType = PtxPdfContent_Image_GetDefaultImageType(pImage);
if (iImageType == ePtxPdfContent_ImageType_Jpeg)
szExtension = _T(".jpg");
else
szExtension = _T(".tiff");

TCHAR szOutPath[256] = {'\0'};
_stprintf(szOutPath, _T("%s/image_page%d_%d%s"), szOutputDir, iPageNo, iImgCount, szExtension);

pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);

TPtxSys_StreamDescriptor outDescriptor;
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
if (PtxPdfContent_Image_Extract(pImage, &outDescriptor, NULL) == FALSE)
{
if (Ptx_GetLastError() == ePtx_Error_Generic)
{
nBufSize = Ptx_GetLastErrorMessage(NULL, 0);
Ptx_GetLastErrorMessage(szErrorBuff, MIN(ARRAY_SIZE(szErrorBuff), nBufSize));
_tprintf(szErrorBuff);
}
else
return FALSE;
}

if (pImage != NULL)
{
Ptx_Release(pImage);
pImage = NULL;
}
if (pOutStream != NULL)
{
fclose(pOutStream);
pOutStream = NULL;
}
}
else if (iType == ePtxPdfContent_ContentElementType_ImageMaskElement)
{
iImgMaskCount++;
pImageMask = PtxPdfContent_ImageMaskElement_GetImageMask((TPtxPdfContent_ImageMaskElement*)pContentElement);
GOTO_CLEANUP_IF_NULL(pImageMask, _T("Failed to get image.\n"));

szExtension = _T(".tiff");

TCHAR szOutPath[256] = {'\0'};
_stprintf(szOutPath, _T("%s/image_mask_page%d_%d%s"), szOutputDir, iPageNo, iImgMaskCount, szExtension);

pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);

TPtxSys_StreamDescriptor outDescriptor;
PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
if (PtxPdfContent_ImageMask_Extract(pImageMask, &outDescriptor, NULL) == FALSE)
{
if (Ptx_GetLastError() == ePtx_Error_Generic)
{
nBufSize = Ptx_GetLastErrorMessage(NULL, 0);
Ptx_GetLastErrorMessage(szErrorBuff, MIN(ARRAY_SIZE(szErrorBuff), nBufSize));
_tprintf(szErrorBuff);
}
else
return FALSE;
}

if (pImageMask != NULL)
{
Ptx_Release(pImageMask);
pImageMask = NULL;
}
if (pOutStream != NULL)
{
fclose(pOutStream);
pOutStream = NULL;
}
}
if (pContentElement != NULL)
{
Ptx_Release(pContentElement);
pContentElement = NULL;
}
PtxPdfContent_ContentExtractorIterator_MoveNext(pIterator);
}

cleanup:
if (pImage != NULL)
Ptx_Release(pImage);
if (pImageMask != NULL)
Ptx_Release(pImageMask);
if (pContentElement != NULL)
Ptx_Release(pContentElement);
if (pIterator != NULL)
Ptx_Release(pIterator);
if (pOutStream != NULL)
fclose(pOutStream);

return iReturnValue == 1 ? FALSE : TRUE;
}
Download code sample
// Open input document
using (Stream stream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document doc = Document.Open(stream, null))
{
// Loop over all pages and extract images
for (int i = 0; i < doc.Pages.Count; i++)
{
ContentExtractor extractor = new ContentExtractor(doc.Pages[i].Content);
ExtractImages(extractor, i + 1, outputDir);
}
}
private static void ExtractImages(ContentExtractor extractor, int pageNo, string outputDir)
{
int imgCount = 0;
int imgMaskCount = 0;
foreach (ContentElement contentElement in extractor)
{
if (contentElement is ImageElement element)
{
imgCount++;
string extension = ".tiff";
switch (element.Image.DefaultImageType)
{
case ImageType.Jpeg:
extension = ".jpg";
break;
case ImageType.Tiff:
extension = ".tiff";
break;
default:
break;
}
string outputPath = System.IO.Path.Combine(outputDir, $"image_page{pageNo}_{imgCount}{extension}");

try
{
using (Stream imageStream = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
{
element.Image.Extract(imageStream);
}
}
catch (GenericException ex)
{
Console.WriteLine(ex.ToString());
}
}
else if (contentElement is ImageMaskElement maskElement)
{
imgMaskCount++;
string extension = ".tiff";
string outputPath = System.IO.Path.Combine(outputDir, $"image_mask_page{pageNo}_{imgMaskCount}{extension}");
try
{
using (Stream imageStream = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
{
maskElement.ImageMask.Extract(imageStream);
}
}
catch (GenericException ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {

// Loop over all pages and extract images
for (int i = 0; i < inDoc.getPages().size(); i++) {
ContentExtractor extractor = new ContentExtractor(inDoc.getPages().get(i).getContent());
extractImages(extractor, i + 1, outputDir);
}
}
private static void extractImages(ContentExtractor extractor, int pageNo, String outputDir) throws IOException {
int imgCount = 0;
int imgMaskCount = 0;
for (Object elementObj : extractor) {
if (elementObj instanceof ImageElement) {
ImageElement element = (ImageElement) elementObj;
imgCount++;
String extension = ".tiff";
switch (element.getImage().getDefaultImageType()) {
case JPEG:
extension = ".jpg";
break;
case TIFF:
extension = ".tiff";
break;
default:
break;
}
String outputPath = Paths.get(outputDir, "image_page" + pageNo + "_" + imgCount + extension).toString();
try (FileStream imageStream = new FileStream(outputPath, FileStream.Mode.READ_WRITE_NEW)) {
element.getImage().extract(imageStream);
} catch (GenericException ex) {
System.out.println(ex.toString());
}
}
else if (elementObj instanceof ImageMaskElement) {
ImageMaskElement element = (ImageMaskElement) elementObj;
imgMaskCount++;
String extension = ".tiff";
String outputPath = Paths.get(outputDir, "image_mask_page" + pageNo + "_" + imgMaskCount + extension).toString();
try (FileStream imageStream = new FileStream(outputPath, FileStream.Mode.READ_WRITE_NEW)) {
element.getImageMask().extract(imageStream);
} catch (GenericException ex) {
System.out.println(ex.toString());
}
}
}
}

List bounds of page content

Download code sample
// Open input document
using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (Document doc = Document.Open(stream, null))
{
// Iterate over all pages
int pageNumber = 1;
foreach (Page page in doc.Pages)
{
// Print page size
Console.WriteLine("Page {0}", pageNumber++);
Size size = page.Size;
Console.WriteLine(" Size:");
Console.WriteLine(" Width: {0}", size.Width);
Console.WriteLine(" Height: {0}", size.Height);

// Compute rectangular bounding box of all content on page
Rectangle contentBox = new Rectangle()
{
Left = double.MaxValue,
Bottom = double.MaxValue,
Right = double.MinValue,
Top = double.MinValue,
};
ContentExtractor extractor = new ContentExtractor(page.Content);
foreach (ContentElement element in extractor)
{
// Enlarge the content box for each content element
AffineTransform tr = element.Transform;
Rectangle box = element.BoundingBox;

// The location on the page is given by the transformed points
Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Left, Y = box.Bottom, }));
Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Right, Y = box.Bottom, }));
Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Right, Y = box.Top, }));
Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Left, Y = box.Top, }));
}
Console.WriteLine(" Content bounding box:");
Console.WriteLine(" Left: {0}", contentBox.Left);
Console.WriteLine(" Bottom: {0}", contentBox.Bottom);
Console.WriteLine(" Right: {0}", contentBox.Right);
Console.WriteLine(" Top: {0}", contentBox.Top);
}
}
static void Enlarge(ref Rectangle box, Point point)
{
// Enlarge box if point lies outside of box
if (point.X < box.Left)
box.Left = point.X;
else if (point.X > box.Right)
box.Right = point.X;
if (point.Y < box.Bottom)
box.Bottom = point.Y;
else if (point.Y > box.Top)
box.Top = point.Y;
}
Download code sample
try (// Open input document
FileStream stream = new FileStream(path, FileStream.Mode.READ_ONLY);
Document doc = Document.open(stream, null)) {
// Iterate over all pages
int pageNumber = 1;
for (Page page : doc.getPages()) {
// Print page size
System.out.format("Page %d\n", pageNumber++);
Size size = page.getSize();
System.out.println(" Size:");
System.out.format(" Width: %f\n", size.getWidth());
System.out.format(" Height: %f\n", size.getHeight());

// Compute rectangular bounding box of all content on page
Rectangle contentBox = new Rectangle(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
ContentExtractor extractor = new ContentExtractor(page.getContent());
for (ContentElement element : extractor) {
// Enlarge the content box for each content element
AffineTransform tr = element.getTransform();
Rectangle box = element.getBoundingBox();

// The location on the page is given by the transformed points
contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getLeft(), box.getBottom())));
contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getRight(), box.getBottom())));
contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getRight(), box.getTop())));
contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getLeft(), box.getTop())));
}
System.out.println(" Content bounding box:");
System.out.format(" Left: %f\n", contentBox.getLeft());
System.out.format(" Bottom: %f\n", contentBox.getBottom());
System.out.format(" Right: %f\n", contentBox.getRight());
System.out.format(" Top: %f\n", contentBox.getTop());
}
}
static Rectangle enlarge(Rectangle box, Point point) {
// Enlarge box if point lies outside of box
if (point.getX() < box.getLeft())
box.setLeft(point.getX());
else if (point.getX() > box.getRight())
box.setRight(point.getX());
if (point.getY() < box.getBottom())
box.setBottom(point.getY());
else if (point.getY() > box.getTop())
box.setTop(point.getY());
return box;
}

List document information of PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Conformance
TPtxPdf_Conformance conformance = PtxPdf_Document_GetConformance(pInDoc);
if (conformance == 0)
{
GOTO_CLEANUP(szErrorBuff, Ptx_GetLastError());
}
_tprintf(_T("Conformance: "));
switch (conformance)
{
case ePtxPdf_Conformance_Pdf10:
_tprintf(_T("PDF 1.0\n"));
break;
case ePtxPdf_Conformance_Pdf11:
_tprintf(_T("PDF 1.1\n"));
break;
case ePtxPdf_Conformance_Pdf12:
_tprintf(_T("PDF 1.2\n"));
break;
case ePtxPdf_Conformance_Pdf13:
_tprintf(_T("PDF 1.3\n"));
break;
case ePtxPdf_Conformance_Pdf14:
_tprintf(_T("PDF 1.4\n"));
break;
case ePtxPdf_Conformance_Pdf15:
_tprintf(_T("PDF 1.5\n"));
break;
case ePtxPdf_Conformance_Pdf16:
_tprintf(_T("PDF 1.6\n"));
break;
case ePtxPdf_Conformance_Pdf17:
_tprintf(_T("PDF 1.7\n"));
break;
case ePtxPdf_Conformance_Pdf20:
_tprintf(_T("PDF 2.0\n"));
break;
case ePtxPdf_Conformance_PdfA1B:
_tprintf(_T("PDF/A1-b\n"));
break;
case ePtxPdf_Conformance_PdfA1A:
_tprintf(_T("PDF/A1-a\n"));
break;
case ePtxPdf_Conformance_PdfA2B:
_tprintf(_T("PDF/A2-b\n"));
break;
case ePtxPdf_Conformance_PdfA2U:
_tprintf(_T("PDF/A2-u\n"));
break;
case ePtxPdf_Conformance_PdfA2A:
_tprintf(_T("PDF/A2-a\n"));
break;
case ePtxPdf_Conformance_PdfA3B:
_tprintf(_T("PDF/A3-b\n"));
break;
case ePtxPdf_Conformance_PdfA3U:
_tprintf(_T("PDF/A3-u\n"));
break;
case ePtxPdf_Conformance_PdfA3A:
_tprintf(_T("PDF/A3-a\n"));
break;
}

// Encryption information
TPtxPdf_Permission permissions;
BOOL iRet = PtxPdf_Document_GetPermissions(pInDoc, &permissions);
if (iRet == FALSE)
{
if (Ptx_GetLastError() != ePtx_Error_Success)
GOTO_CLEANUP(szErrorBuff, Ptx_GetLastError());
_tprintf(_T("Not encrypted\n"));
}
else
{
_tprintf(_T("Encryption:\n"));
_tprintf(_T(" - Permissions: "));
if (permissions & ePtxPdf_Permission_Print)
_tprintf(_T("Print, "));
if (permissions & ePtxPdf_Permission_Modify)
_tprintf(_T("Modify, "));
if (permissions & ePtxPdf_Permission_Copy)
_tprintf(_T("Copy, "));
if (permissions & ePtxPdf_Permission_Annotate)
_tprintf(_T("Annotate, "));
if (permissions & ePtxPdf_Permission_FillForms)
_tprintf(_T("FillForms, "));
if (permissions & ePtxPdf_Permission_SupportDisabilities)
_tprintf(_T("SupportDisabilities, "));
if (permissions & ePtxPdf_Permission_Assemble)
_tprintf(_T("Assemble, "));
if (permissions & ePtxPdf_Permission_DigitalPrint)
_tprintf(_T("DigitalPrint, "));
_tprintf(_T("\n"));
}

// Get metadata of input PDF
pMetadata = PtxPdf_Document_GetMetadata(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());
_tprintf(_T("Document information:\n"));

// Get title
size_t nTitle = PtxPdf_Metadata_GetTitle(pMetadata, NULL, 0);
if (nTitle != 0)
{
TCHAR* szTitle = (TCHAR*)malloc(nTitle * sizeof(TCHAR));
if (szTitle != NULL)
{
PtxPdf_Metadata_GetTitle(pMetadata, szTitle, nTitle);
_tprintf(_T(" - Title: %s\n"), szTitle);
free(szTitle);
}
}

// Get author
size_t nAuthor = PtxPdf_Metadata_GetAuthor(pMetadata, NULL, 0);
if (nAuthor != 0)
{
TCHAR* szAuthor = (TCHAR*)malloc(nAuthor * sizeof(TCHAR));
if (szAuthor != NULL)
{
PtxPdf_Metadata_GetAuthor(pMetadata, szAuthor, nAuthor);
_tprintf(_T(" - Author: %s\n"), szAuthor);
free(szAuthor);
}
}

// Get creator
size_t nCreator = PtxPdf_Metadata_GetCreator(pMetadata, NULL, 0);
if (nCreator != 0)
{
TCHAR* szCreator = (TCHAR*)malloc(nCreator * sizeof(TCHAR));
if (szCreator != NULL)
{
PtxPdf_Metadata_GetCreator(pMetadata, szCreator, nCreator);
_tprintf(_T(" - Creator: %s\n"), szCreator);
free(szCreator);
}
}

// Get producer
size_t nProducer = PtxPdf_Metadata_GetProducer(pMetadata, NULL, 0);
if (nProducer != 0)
{
TCHAR* szProducer = (TCHAR*)malloc(nProducer * sizeof(TCHAR));
if (szProducer != NULL)
{
PtxPdf_Metadata_GetProducer(pMetadata, szProducer, nProducer);
_tprintf(_T(" - Producer: %s\n"), szProducer);
free(szProducer);
}
}

// Get subject
size_t nSubject = PtxPdf_Metadata_GetSubject(pMetadata, NULL, 0);
if (nSubject != 0)
{
TCHAR* szSubject = (TCHAR*)malloc(nSubject * sizeof(TCHAR));
if (szSubject != NULL)
{
PtxPdf_Metadata_GetSubject(pMetadata, szSubject, nSubject);
_tprintf(_T(" - Subject: %s\n"), szSubject);
free(szSubject);
}
}

// Get keywords
size_t nKeywords = PtxPdf_Metadata_GetKeywords(pMetadata, NULL, 0);
if (nKeywords != 0)
{
TCHAR* szKeywords = (TCHAR*)malloc(nKeywords * sizeof(TCHAR));
if (szKeywords != NULL)
{
PtxPdf_Metadata_GetKeywords(pMetadata, szKeywords, nKeywords);
_tprintf(_T(" - Keywords: %s\n"), szKeywords);
free(szKeywords);
}
}

// Get creation date
if (PtxPdf_Metadata_GetCreationDate(pMetadata, &date) == TRUE)
{
_tprintf(_T(" - Creation Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear, date.iMonth, date.iDay,
date.iHour, date.iMinute, date.iSecond, date.iTZSign >= 0 ? '+' : '-', date.iTZHour, date.iTZMinute);
}

// Get modification date
if (PtxPdf_Metadata_GetModificationDate(pMetadata, &date) == TRUE)
{
_tprintf(_T(" - Modification Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear, date.iMonth,
date.iDay, date.iHour, date.iMinute, date.iSecond, date.iTZSign >= 0 ? '+' : '-', date.iTZHour,
date.iTZMinute);
}

// Get custom entries
_tprintf(_T("Custom entries:\n"));
TPtx_StringMap* pCustomEntries = PtxPdf_Metadata_GetCustomEntries(pMetadata);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCustomEntries, _T("Failed to get custom entries. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
for (int i = Ptx_StringMap_GetBegin(pCustomEntries), iEnd = Ptx_StringMap_GetEnd(pCustomEntries); i != iEnd;
i = Ptx_StringMap_GetNext(pCustomEntries, i))
{
size_t nKeySize = Ptx_StringMap_GetKey(pCustomEntries, i, NULL, 0);
TCHAR* szKey = (TCHAR*)malloc(nKeySize * sizeof(TCHAR));
nKeySize = Ptx_StringMap_GetKey(pCustomEntries, i, szKey, nKeySize);

size_t nValueSize = Ptx_StringMap_GetValue(pCustomEntries, i, NULL, 0);
TCHAR* szValue = (TCHAR*)malloc(nValueSize * sizeof(TCHAR));
nValueSize = Ptx_StringMap_GetValue(pCustomEntries, i, szValue, nValueSize);

if (szKey && nKeySize && szValue && nValueSize)
_tprintf(_T(" - %s: %s\n"), szKey, szValue);

free(szKey);
free(szValue);
}

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
// Conformance
Console.WriteLine("Conformance: {0}", inDoc.Conformance.ToString());

// Encryption information
Permission? permissions = inDoc.Permissions;
if (!permissions.HasValue)
{
Console.WriteLine("Not encrypted");
}
else
{
Console.WriteLine("Encryption:");
Console.Write(" - Permissions: ");
foreach (Enum flag in Enum.GetValues(typeof(Permission)))
if (permissions.Value.HasFlag(flag))
Console.Write("{0}, ", flag.ToString());
Console.WriteLine();
}

// Get metadata
Metadata metadata = inDoc.Metadata;
Console.WriteLine("Document information:");

// Get title
string title = metadata.Title;
if (title != null)
Console.WriteLine(" - Title: {0}", title);

// Get author
string author = metadata.Author;
if (author != null)
Console.WriteLine(" - Author: {0}", author);

// Get subject
string subject = metadata.Subject;
if (subject != null)
Console.WriteLine(" - Subject: {0}", subject);

// Get keywords
string keywords = metadata.Keywords;
if (keywords != null)
Console.WriteLine(" - Keywords: {0}", keywords);

// Get creation date
DateTimeOffset? creationDate = metadata.CreationDate;
if (creationDate != null)
Console.WriteLine(" - Creation Date: {0}", creationDate);

// Get modification date
DateTimeOffset? modificationDate = metadata.ModificationDate;
if (modificationDate != null)
Console.WriteLine(" - Modification Date: {0}", modificationDate);

// Get creator
string creator = metadata.Creator;
if (creator != null)
Console.WriteLine(" - Creator: {0}", creator);

// Get producer
string producer = metadata.Producer;
if (producer != null)
Console.WriteLine(" - Producer: {0}", producer);

// Custom entries
Console.WriteLine("Custom entries:");
foreach (var entry in metadata.CustomEntries)
Console.WriteLine(" - {0}: {1}", entry.Key, entry.Value);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {
// Conformance
System.out.format("Conformance: %s\n", inDoc.getConformance().toString());

// Encryption information
EnumSet<Permission> permissions = inDoc.getPermissions();
if (permissions == null) {
System.out.println("Not encrypted");
} else {
System.out.println("Encryption:");
System.out.print(" - Permissions: ");
for (Permission permission : permissions) {
System.out.format("%s, ", permission.toString());
}
System.out.println();
}

// Get metadata of input PDF
Metadata metadata = inDoc.getMetadata();
System.out.format("Document information:\n");

// Get title
String title = metadata.getTitle();
if (title != null)
System.out.format(" - Title: %s\n", title);

// Get author
String author = metadata.getAuthor();
if (author != null)
System.out.format(" - Author: %s\n", author);

// Get subject
String subject = metadata.getSubject();
if (subject != null)
System.out.format(" - Subject: %s\n", subject);

// Get keywords
String keywords = metadata.getKeywords();
if (keywords != null)
System.out.format(" - Keywords: %s\n", keywords);

// Get creation date
OffsetDateTime creationDate = metadata.getCreationDate();
if (creationDate != null)
System.out.format(" - Creation Date: %s\n", creationDate.toString());

// Get modification date
OffsetDateTime modificationDate = metadata.getModificationDate();
if (modificationDate != null)
System.out.format(" - Modification Date: %s\n", modificationDate.toString());

// Get creator
String creator = metadata.getCreator();
if (creator != null)
System.out.format(" - Creator: %s\n", creator);

// Get producer
String producer = metadata.getProducer();
if (producer != null)
System.out.format(" - Producer: %s\n", producer);

// Custom entries
System.out.format("Custom entries:\n");
for (Map.Entry<String, String> entry : metadata.getCustomEntries().entrySet())
System.out.format(" - %s: %s\n", entry.getKey(), entry.getValue());
}

List Signatures in PDF

Download code sample
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
szInPath, szErrorBuff, Ptx_GetLastError());

// Get signatures of input PDF
pSignatureFields = PtxPdf_Document_GetSignatureFields(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pSignatureFields,
_T("Failed to get signatures of input PDF. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
_tprintf(_T("Number of signature fields: %d\n"), PtxPdfForms_SignatureFieldList_GetCount(pSignatureFields));

for (int i = 0; i < PtxPdfForms_SignatureFieldList_GetCount(pSignatureFields); i++)
{
pSig = PtxPdfForms_SignatureFieldList_Get(pSignatureFields, i);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pSig, _T("Failed to get signature. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
Ptx_GetLastError());

TPtxPdfForms_SignatureFieldType iFieldType = PtxPdfForms_SignatureField_GetType(pSig);
if (iFieldType == ePtxPdfForms_SignatureFieldType_Signature ||
iFieldType == ePtxPdfForms_SignatureFieldType_DocMdpSignature ||
iFieldType == ePtxPdfForms_SignatureFieldType_DocumentSignature)
{
// List name
size_t nName = PtxPdfForms_SignedSignatureField_GetName(pSig, NULL, 0);
_tprintf(_T("- %s fields"), PtxPdfForms_SignatureField_IsVisible(pSig) ? _T("Visible") : _T("Invisible"));
if (nName != 0)
{
TCHAR* szName = (TCHAR*)malloc(nName * sizeof(TCHAR));
if (szName != NULL)
{
PtxPdfForms_SignedSignatureField_GetName(pSig, szName, nName);
_tprintf(_T(", signed by: %s"), szName);
free(szName);
}
}
_tprintf(_T("\n"));

// List location
size_t nLocation = PtxPdfForms_Signature_GetLocation(pSig, NULL, 0);
if (nLocation != 0)
{
TCHAR* szLocation = (TCHAR*)malloc(nLocation * sizeof(TCHAR));
if (szLocation != NULL)
{
PtxPdfForms_Signature_GetLocation(pSig, szLocation, nLocation);
_tprintf(_T(" - Location: %s\n"), szLocation);
free(szLocation);
}
}

// List reason
size_t nReason = PtxPdfForms_Signature_GetReason(pSig, NULL, 0);
if (nReason != 0)
{
TCHAR* szReason = (TCHAR*)malloc(nReason * sizeof(TCHAR));
if (szReason != NULL)
{
PtxPdfForms_Signature_GetReason(pSig, szReason, nReason);
_tprintf(_T(" - Reason: %s\n"), szReason);
free(szReason);
}
}

// List contact info
size_t nContactInfo = PtxPdfForms_Signature_GetContactInfo(pSig, NULL, 0);
if (nContactInfo != 0)
{
TCHAR* szContactInfo = (TCHAR*)malloc(nContactInfo * sizeof(TCHAR));
if (szContactInfo != NULL)
{
PtxPdfForms_Signature_GetContactInfo(pSig, szContactInfo, nContactInfo);
_tprintf(_T(" - Contact info: %s\n"), szContactInfo);
free(szContactInfo);
}
}

// List date
if (PtxPdfForms_SignedSignatureField_GetDate(pSig, &date) == TRUE)
{
_tprintf(_T(" - Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear, date.iMonth, date.iDay,
date.iHour, date.iMinute, date.iSecond, date.iTZSign >= 0 ? '+' : '-', date.iTZHour,
date.iTZMinute);
}
}
else
{
_tprintf(_T("- %s field, not signed\n"),
PtxPdfForms_SignatureField_IsVisible(pSig) ? _T("Visible") : _T("Invisible"));
}
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
SignatureFieldList signatureFields = inDoc.SignatureFields;
Console.WriteLine("Number of signature fields: {0}", signatureFields.Count);
foreach (SignatureField field in signatureFields)
{
if (field is Signature sig)
{
// List name
string name = sig.Name;
Console.WriteLine("- {0} fields, signed by: {1}",
sig.IsVisible ? "Visible" : "Invisible", name ?? "(Unknown name)");

// List location
string location = sig.Location;
if (location != null)
Console.WriteLine(" - Location: {0}", location);

// List reason
string reason = sig.Reason;
if (reason != null)
Console.WriteLine(" - Reason: {0}", reason);

// List contact info
string contactInfo = sig.ContactInfo;
if (contactInfo != null)
Console.WriteLine(" - Contact info: {0}", contactInfo);

// List date
DateTimeOffset? date = sig.Date;
if (date != null)
Console.WriteLine(" - Date: {0}", date.Value);
}
else
Console.WriteLine("- {0} field, not signed", field.IsVisible ? "Visible" : "Invisible");
}
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {
SignatureFieldList signatureFields = inDoc.getSignatureFields();
System.out.format("Number of signature fields: %d\n", signatureFields.size());

for (SignatureField field : signatureFields) {
if (field instanceof Signature) {
Signature sig = (Signature)field;
// List name
String name = sig.getName();
System.out.format("- %s field, signed by: %s\n", sig.getIsVisible() ? "Visible" : "Invisible",
name != null ? name : "(Unknown name)");

// List location
String location = sig.getLocation();
if (location != null)
System.out.format(" - Location: %s\n", location);

// List reason
String reason = sig.getReason();
if (reason != null)
System.out.format(" - Reason: %s\n", reason);

// List contact info
String contactInfo = sig.getContactInfo();
if (contactInfo != null)
System.out.format(" - Contact info: %s\n", contactInfo);

// List date
OffsetDateTime date = sig.getDate();
if (date != null)
System.out.format(" - Date: %s\n", date.toString());
} else {
System.out.format("- %s field, not signed\n", field.getIsVisible() ? "Visible" : "Invisible");
}
}
}
Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
PrintOutlineItems(inDoc.Outline, "", inDoc);
}
static void PrintOutlineItem(OutlineItem item, string indentation, Document document)
{
string title = item.Title;
Console.Out.Write("{0}{1}", indentation, title);
Destination dest = item.Destination;
if (dest != null)
{
int pageNumber = document.Pages.IndexOf(dest.Target.Page) + 1;
string dots = new string('.', 78 - indentation.Length - title.Length - pageNumber.ToString().Length);
Console.Out.Write(" {0} {1}", dots, pageNumber);
}
Console.Out.WriteLine();
PrintOutlineItems(item.Children, indentation + " ", document);
}
static void PrintOutlineItems(OutlineItemList outlineItems, string indentation, Document document)
{
foreach (var item in outlineItems)
PrintOutlineItem(item, indentation, document);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {
printOutlineItems(inDoc.getOutline(), "", inDoc);
}
static void printOutlineItem(OutlineItem item, String indentation, Document document) throws PdfToolboxException {
String title = item.getTitle();
System.out.format("%s%s", indentation, title);
Destination dest = item.getDestination();
if (dest != null) {
int pageNumber = document.getPages().indexOf(dest.getTarget().getPage()) + 1;
char[] dots = new char[78 - indentation.length() - title.length() - Integer.toString(pageNumber).length()];
Arrays.fill(dots, '.');
System.out.format(" %s %d", new String(dots), pageNumber);
}
System.out.println();
printOutlineItems(item.getChildren(), indentation + " ", document);
}
static void printOutlineItems(OutlineItemList outlineItems, String indentation, Document document)
throws PdfToolboxException {
for (OutlineItem item : outlineItems)
printOutlineItem(item, indentation, document);
}

Extract all text from PDF

Download code sample
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
int pageNumber = 1;

// Process each page
foreach (var inPage in inDoc.Pages)
{
Console.WriteLine("==========");
Console.WriteLine($"Page: {pageNumber++}");
Console.WriteLine("==========");

ContentExtractor extractor = new ContentExtractor(inPage.Content);
extractor.Ungrouping = UngroupingSelection.All;

// Iterate over all content elements and only process text elements
foreach (ContentElement element in extractor)
if (element is TextElement textElement)
WriteText(textElement.Text);
}
}
private static void WriteText(Text text)
{
string textPart = "";

// Write all text fragments
// Determine heuristically if there is a space between two text fragments
for (int iFragment = 0; iFragment < text.Count; iFragment++)
{

TextFragment currFragment = text[iFragment];
if (iFragment == 0)
textPart += currFragment.Text;
else
{
TextFragment lastFragment = text[iFragment - 1];
if (currFragment.CharacterSpacing != lastFragment.CharacterSpacing ||
currFragment.FontSize != lastFragment.FontSize ||
currFragment.HorizontalScaling != lastFragment.HorizontalScaling ||
currFragment.Rise != lastFragment.Rise ||
currFragment.WordSpacing != lastFragment.WordSpacing)
textPart += $" {currFragment.Text}";
else
{
Point currentBotLeft = currFragment.Transform.TransformRectangle(currFragment.BoundingBox).BottomLeft;
Point beforeBotRight = lastFragment.Transform.TransformRectangle(lastFragment.BoundingBox).BottomRight;

if (beforeBotRight.X < currentBotLeft.X - 0.7 * currFragment.FontSize ||
beforeBotRight.Y < currentBotLeft.Y - 0.1 * currFragment.FontSize ||
currentBotLeft.Y < beforeBotRight.Y - 0.1 * currFragment.FontSize)
textPart += $" {currFragment.Text}";
else
textPart += currFragment.Text;
}
}
}
Console.WriteLine(textPart);
}
Download code sample
try (// Open input document
FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
Document inDoc = Document.open(inStream, null)) {
int pageNumber = 1;

// Process each page
for (Page inPage : inDoc.getPages()) {
System.out.println("==========");
System.out.println("Page: " + pageNumber++);
System.out.println("==========");

ContentExtractor extractor = new ContentExtractor(inPage.getContent());
extractor.setUngrouping(UngroupingSelection.ALL);

// Iterate over all content elements and only process text elements
for (ContentElement element : extractor) {
if (element instanceof TextElement)
writeText(((TextElement) element).getText());
}
}
}
private static void writeText(Text text) {
String textPart = "";

// Write all text fragments
// Determine heuristically if there is a space between two text fragments
for (int iFragment = 0; iFragment < text.size(); iFragment++) {
TextFragment currFragment = text.get(iFragment);
if (iFragment == 0)
textPart += currFragment.getText();
else {
TextFragment lastFragment = text.get(iFragment - 1);
if (currFragment.getCharacterSpacing() != lastFragment.getCharacterSpacing() ||
currFragment.getFontSize() != lastFragment.getFontSize() ||
currFragment.getHorizontalScaling() != lastFragment.getHorizontalScaling() ||
currFragment.getRise() != lastFragment.getRise() ||
currFragment.getWordSpacing() != lastFragment.getWordSpacing()) {
textPart += " ";
textPart += currFragment.getText();
}
else {
Point currentBotLeft = currFragment.getTransform().transformRectangle(currFragment.getBoundingBox()).getBottomLeft();
Point beforeBotRight = lastFragment.getTransform().transformRectangle(lastFragment.getBoundingBox()).getBottomRight();

if (beforeBotRight.getX() < currentBotLeft.getX() - 0.7 * currFragment.getFontSize() ||
beforeBotRight.getY() < currentBotLeft.getY() - 0.1 * currFragment.getFontSize() ||
currentBotLeft.getY() < beforeBotRight.getY() - 0.1 * currFragment.getFontSize()) {
textPart += " ";
textPart += currFragment.getText();
}
else
textPart += currFragment.getText();
}
}
}
System.out.println(textPart);
}