Toolbox add-on code samples
Start using the Toolbox add-on library with code samples. Integrate low-level access to the content of PDF files into your application in Java, .NET, and C.
info
Select a code sample in a specific language and download it. The code samples illustrate how to integrate the SDK into your projects for specific use cases. Each code sample includes a README file that gives instructions on how to run the code sample to process one or multiple files.
tip
Do you miss a specific sample and want us to include it here? Let us know through the Contact page, and we'll add it to our sample backlog.
Annotations
Add annotations to PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 // Create output document
6 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
7 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
8
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy first page and add annotations
16 Page outPage = CopyAndAddAnnotations(outDoc, inDoc.Pages[0], copyOptions);
17
18 // Add the page to the output document's page list
19 outDoc.Pages.Add(outPage);
20
21 // Copy the remaining pages and add to the output document's page list
22 PageList inPages = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
23 PageList outPages = PageList.Copy(outDoc, inPages, copyOptions);
24 outDoc.Pages.AddRange(outPages);
25}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static Page CopyAndAddAnnotations(Document outDoc, Page inPage, PageCopyOptions copyOptions)
2{
3 // Copy page to output document
4 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
5
6 // Make a RGB color space
7 ColorSpace rgb = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);
8
9 // Get the page size for positioning annotations
10 Size pageSize = outPage.Size;
11
12 // Get the output page's list of annotations for adding annotations
13 AnnotationList annotations = outPage.Annotations;
14
15 // Create a sticky note and add to output page's annotations
16 Paint green = Paint.Create(outDoc, rgb, new double[] { 0, 1, 0 }, null);
17 Point stickyNoteTopLeft = new Point() { X = 10, Y = pageSize.Height - 10 };
18 StickyNote stickyNote = StickyNote.Create(outDoc, stickyNoteTopLeft, "Hello world!", green);
19 annotations.Add(stickyNote);
20
21 // Create an ellipse and add to output page's annotations
22 Paint blue = Paint.Create(outDoc, rgb, new double[] { 0, 0, 1 }, null);
23 Paint yellow = Paint.Create(outDoc, rgb, new double[] { 1, 1, 0 }, null);
24 Rectangle ellipseBox = new Rectangle() { Left = 10, Bottom = pageSize.Height - 60, Right = 70, Top = pageSize.Height - 20 };
25 EllipseAnnotation ellipse = EllipseAnnotation.Create(outDoc, ellipseBox, new Stroke(blue, 1.5), yellow);
26 annotations.Add(ellipse);
27
28 // Create a free text and add to output page's annotations
29 Paint yellowTransp = Paint.Create(outDoc, rgb, new double[] { 1, 1, 0 }, new Transparency(0.5));
30 Rectangle freeTextBox = new Rectangle() { Left = 10, Bottom = pageSize.Height - 170, Right = 120, Top = pageSize.Height - 70 };
31 FreeText freeText = FreeText.Create(outDoc, freeTextBox, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellowTransp);
32 annotations.Add(freeText);
33
34 // A highlight and a web-link to be fitted on existing page content elements
35 Highlight highlight = null;
36 WebLink webLink = null;
37 // Extract content elements from the input page
38 ContentExtractor extractor = new ContentExtractor(inPage.Content);
39 foreach (ContentElement element in extractor)
40 {
41 // Take the first text element
42 if (highlight == null && element is TextElement textElement)
43 {
44 // Get the quadrilaterals of this text element
45 QuadrilateralList quadrilaterals = new QuadrilateralList();
46 foreach (TextFragment fragment in textElement.Text)
47 quadrilaterals.Add(fragment.Transform.TransformRectangle(fragment.BoundingBox));
48
49 // Create a highlight and add to output page's annotations
50 highlight = Highlight.CreateFromQuadrilaterals(outDoc, quadrilaterals, yellow);
51 annotations.Add(highlight);
52 }
53
54 // Take the first image element
55 if (webLink == null && element is ImageElement)
56 {
57 // Get the quadrilateral of this image
58 QuadrilateralList quadrilaterals = new QuadrilateralList();
59 quadrilaterals.Add(element.Transform.TransformRectangle(element.BoundingBox));
60
61 // Create a web-link and add to the output page's links
62 webLink = WebLink.CreateFromQuadrilaterals(outDoc, quadrilaterals, "https://www.pdf-tools.com");
63 Paint red = Paint.Create(outDoc, rgb, new double[] { 1, 0, 0 }, null);
64 webLink.BorderStyle = new Stroke(red, 1.5);
65 outPage.Links.Add(webLink);
66 }
67
68 // Exit loop if highlight and webLink have been created
69 if (highlight != null && webLink != null)
70 break;
71 }
72
73 // return the finished page
74 return outPage;
75}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 // Create file stream
5 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
6 try (// Create output document
7 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
8
9 // Copy document-wide data
10 copyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy first page and add annotations
16 Page outPage = copyAndAddAnnotations(outDoc, inDoc.getPages().get(0), copyOptions);
17
18 // Add the page to the output document's page list
19 outDoc.getPages().add(outPage);
20
21 // Copy the remaining pages and add to the output document's page list
22 PageList inPages = inDoc.getPages().subList(1, inDoc.getPages().size());
23 PageList outPages = PageList.copy(outDoc, inPages, copyOptions);
24 outDoc.getPages().addAll(outPages);
25 }
26}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static Page copyAndAddAnnotations(Document outDoc, Page inPage, PageCopyOptions copyOptions) throws ConformanceException, CorruptException, IOException, UnsupportedFeatureException {
2 // Copy page to output document
3 Page outPage = Page.copy(outDoc, inPage, copyOptions);
4
5 // Make a RGB color space
6 ColorSpace rgb = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);
7
8 // Get the page size for positioning annotations
9 Size pageSize = outPage.getSize();
10
11 // Get the output page's list of annotations for adding annotations
12 AnnotationList annotations = outPage.getAnnotations();
13
14 // Create a sticky note and add to output page's annotations
15 Paint green = Paint.create(outDoc, rgb, new double[] { 0, 1, 0 }, null);
16 Point stickyNoteTopLeft = new Point(10, pageSize.height - 10 );
17 StickyNote stickyNote = StickyNote.create(outDoc, stickyNoteTopLeft, "Hello world!", green);
18 annotations.add(stickyNote);
19
20 // Create an ellipse and add to output page's annotations
21 Paint blue = Paint.create(outDoc, rgb, new double[] { 0, 0, 1 }, null);
22 Paint yellow = Paint.create(outDoc, rgb, new double[] { 1, 1, 0 }, null);
23 Rectangle ellipseBox = new Rectangle(10, pageSize.height - 60, 70, pageSize.height - 20);
24 EllipseAnnotation ellipse = EllipseAnnotation.create(outDoc, ellipseBox, new Stroke(blue, 1.5), yellow);
25 annotations.add(ellipse);
26
27 // Create a free text and add to output page's annotations
28 Paint yellowTransp = Paint.create(outDoc, rgb, new double[] { 1, 1, 0 }, new Transparency(0.5));
29 Rectangle freeTextBox = new Rectangle(10, pageSize.height - 170, 120, pageSize.height - 70);
30 FreeText freeText = FreeText.create(outDoc, freeTextBox, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellowTransp);
31 annotations.add(freeText);
32
33 // A highlight and a web-link to be fitted on existing page content elements
34 Highlight highlight = null;
35 WebLink webLink = null;
36 // Extract content elements from the input page
37 ContentExtractor extractor = new ContentExtractor(inPage.getContent());
38 for (ContentElement element : extractor) {
39 // Take the first text element
40 if (highlight == null && element instanceof TextElement) {
41 TextElement textElement = (TextElement)element;
42 // Get the quadrilaterals of this text element
43 QuadrilateralList quadrilaterals = new QuadrilateralList();
44 for (TextFragment fragment : textElement.getText())
45 quadrilaterals.add(fragment.getTransform().transformRectangle(fragment.getBoundingBox()));
46
47 // Create a highlight and add to output page's annotations
48 highlight = Highlight.createFromQuadrilaterals(outDoc, quadrilaterals, yellow);
49 annotations.add(highlight);
50 }
51
52 // Take the first image element
53 if (webLink == null && element instanceof ImageElement) {
54 // Get the quadrilateral of this image
55 QuadrilateralList quadrilaterals = new QuadrilateralList();
56 quadrilaterals.add(element.getTransform().transformRectangle(element.getBoundingBox()));
57
58 // Create a web-link and add to the output page's links
59 webLink = WebLink.createFromQuadrilaterals(outDoc, quadrilaterals, "https://www.pdf-tools.com");
60 Paint red = Paint.create(outDoc, rgb, new double[] { 1, 0, 0 }, null);
61 webLink.setBorderStyle(new Stroke(red, 1.5));
62 outPage.getLinks().add(webLink);
63 }
64
65 // Exit loop if highlight and webLink have been created
66 if (highlight != null && webLink != null)
67 break;
68 }
69
70 // return the finished page
71 return outPage;
72}
Annotations and Form Fields
Add Form Field
1using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
2using (Document inDoc = Document.Open(inStream, null))
3
4// Create output document
5using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
6using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
7{
8 // Copy document-wide data
9 CopyDocumentData(inDoc, outDoc);
10
11 // Copy all form fields
12 FieldNodeMap inFormFields = inDoc.FormFields;
13 FieldNodeMap outFormFields = outDoc.FormFields;
14 foreach (KeyValuePair<string, FieldNode> inPair in inFormFields)
15 {
16 FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inPair.Value);
17 outFormFields.Add(inPair.Key, outFormFieldNode);
18 }
19
20 // Define page copy options
21 PageCopyOptions copyOptions = new PageCopyOptions
22 {
23 FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
24 UnsignedSignatures = CopyStrategy.Remove,
25 };
26
27 // Copy first page
28 Page inPage = inDoc.Pages[0];
29 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
30
31 // Add different types of form fields to the output page
32 AddCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle { Left = 50, Bottom = 300, Right = 70, Top = 320 });
33 AddComboBox(outDoc, "Combo Box ID", new string[] { "item 1", "item 2" }, "item 1", outPage, new Rectangle { Left = 50, Bottom = 260, Right = 210, Top = 280 });
34 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 });
35 AddRadioButtonGroup(outDoc, "Radio Button ID", new string[] { "A", "B", "C" }, 0, outPage, new Rectangle { Left = 50, Bottom = 120, Right = 210, Top = 140 });
36 AddGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle { Left = 50, Bottom = 80, Right = 210, Top = 100 });
37
38 // Add page to output document
39 outDoc.Pages.Add(outPage);
40
41 // Copy remaining pages and append to output document
42 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
43 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
44 outDoc.Pages.AddRange(copiedPages);
45}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddCheckBox(Document doc, string id, bool isChecked, Page page, Rectangle rectangle)
2{
3 // Create a check box
4 CheckBox checkBox = CheckBox.Create(doc);
5
6 // Add the check box to the document
7 doc.FormFields.Add(id, checkBox);
8
9 // Set the check box's state
10 checkBox.Checked = isChecked;
11
12 // Create a widget and add it to the page's widgets
13 page.Widgets.Add(checkBox.AddNewWidget(rectangle));
14}
1private static void AddComboBox(Document doc, string id, string[] itemNames, string value, Page page, Rectangle rectangle)
2{
3 // Create a combo box
4 ComboBox comboBox = ComboBox.Create(doc);
5
6 // Add the combo box to the document
7 doc.FormFields.Add(id, comboBox);
8
9 // Loop over all given item names
10 foreach (string itemName in itemNames)
11 {
12 // Create a new choice item
13 ChoiceItem item = comboBox.AddNewItem(itemName);
14
15 // Check whether this is the chosen item name
16 if (value.Equals(itemName))
17 comboBox.ChosenItem = item;
18 }
19 if (comboBox.ChosenItem == null && !string.IsNullOrEmpty(value))
20 {
21 // If no item has been chosen then assume we want to set the editable item
22 comboBox.CanEdit = true;
23 comboBox.EditableItemName = value;
24 }
25
26 // Create a widget and add it to the page's widgets
27 page.Widgets.Add(comboBox.AddNewWidget(rectangle));
28}
1private static void AddListBox(Document doc, string id, string[] itemNames, string[] chosenNames, Page page, Rectangle rectangle)
2{
3 // Create a list box
4 ListBox listBox = ListBox.Create(doc);
5
6 // Add the list box to the document
7 doc.FormFields.Add(id, listBox);
8
9 // Allow multiple selections
10 listBox.AllowMultiSelect = true;
11 ChoiceItemList chosenItems = listBox.ChosenItems;
12
13 // Loop over all given item names
14 foreach (string itemName in itemNames)
15 {
16 // Create a new choice item
17 ChoiceItem item = listBox.AddNewItem(itemName);
18
19 // Check whether to add to the chosen items
20 if (chosenNames.Contains(itemName))
21 chosenItems.Add(item);
22 }
23
24 // Create a widget and add it to the page's widgets
25 page.Widgets.Add(listBox.AddNewWidget(rectangle));
26}
1private static void AddRadioButtonGroup(Document doc, string id, string[] buttonNames, int chosen, Page page, Rectangle rectangle)
2{
3 // Create a radio button group
4 RadioButtonGroup group = RadioButtonGroup.Create(doc);
5
6 // Get the page's widgets
7 WidgetList widgets = page.Widgets;
8
9 // Add the radio button group to the document
10 doc.FormFields.Add(id, group);
11
12 // We partition the given rectangle horizontally into sub-rectangles, one for each button
13 // Compute the width of the sub-rectangles
14 double buttonWidth = (rectangle.Right - rectangle.Left) / buttonNames.Length;
15
16 // Loop over all button names
17 for (int i = 0; i < buttonNames.Length; i++)
18 {
19 // Compute the sub-rectangle for this button
20 Rectangle buttonRectangle = new Rectangle()
21 {
22 Left = rectangle.Left + i * buttonWidth,
23 Bottom = rectangle.Bottom,
24 Right = rectangle.Left + (i + 1) * buttonWidth,
25 Top = rectangle.Top
26 };
27
28 // Create the button and an associated widget
29 RadioButton button = group.AddNewButton(buttonNames[i]);
30 Widget widget = button.AddNewWidget(buttonRectangle);
31
32 // Check if this is the chosen button
33 if (i == chosen)
34 group.ChosenButton = button;
35
36 // Add the widget to the page's widgets
37 widgets.Add(widget);
38 }
39}
1private static void AddGeneralTextField(Document doc, string id, string value, Page page, Rectangle rectangle)
2{
3 // Create a general text field
4 GeneralTextField field = GeneralTextField.Create(doc);
5
6 // Add the field to the document
7 doc.FormFields.Add(id, field);
8
9 // Set the text value
10 field.Text = value;
11
12 // Create a widget and add it to the page's widgets
13 page.Widgets.Add(field.AddNewWidget(rectangle));
14}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Copy all form fields
12 FieldNodeMap inFormFields = inDoc.getFormFields();
13 FieldNodeMap outFormFields = outDoc.getFormFields();
14 for (Entry<String, FieldNode> entry : inFormFields.entrySet())
15 outFormFields.put(entry.getKey(), FieldNode.copy(outDoc, entry.getValue()));
16
17 // Define page copy options
18 PageCopyOptions copyOptions = new PageCopyOptions();
19 copyOptions.setFormFields(FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS);
20 copyOptions.setUnsignedSignatures(CopyStrategy.REMOVE);
21
22 // Copy first page
23 Page inPage = inDoc.getPages().get(0);
24 Page outPage = Page.copy(outDoc, inPage, copyOptions);
25
26 // Add different types of form fields to the output page
27 addCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle(50, 300, 70, 320));
28 addComboBox(outDoc, "Combo Box ID", new String[] { "item 1", "item 2" }, "item 1", outPage,
29 new Rectangle(50, 260, 210, 280));
30 addListBox(outDoc, "List Box ID", new String[] { "item 1", "item 2", "item 3" },
31 new String[] { "item 1", "item 3" }, outPage, new Rectangle(50, 160, 210, 240));
32 addRadioButtonGroup(outDoc, "Radio Button ID", new String[] { "A", "B", "C" }, 0, outPage,
33 new Rectangle(50, 120, 210, 140));
34 addGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle(50, 80, 210, 100));
35
36 // Add page to output document
37 outDoc.getPages().add(outPage);
38
39 // Copy remaining pages and append to output document
40 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
41 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
42 outDoc.getPages().addAll(copiedPages);
43 }
44}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addCheckBox(Document doc, String id, boolean isChecked, Page page, Rectangle rectangle)
2 throws ToolboxException {
3 // Create a check box
4 CheckBox checkBox = CheckBox.create(doc);
5
6 // Add the check box to the document
7 doc.getFormFields().put(id, checkBox);
8
9 // Set the check box's state
10 checkBox.setChecked(isChecked);
11
12 // Create a widget and add it to the page's widgets
13 page.getWidgets().add(checkBox.addNewWidget(rectangle));
14}
15
1private static void addListBox(Document doc, String id, String[] itemNames, String[] chosenNames, Page page,
2 Rectangle rectangle) throws ToolboxException {
3 List<String> chosenNamesList = Arrays.asList(chosenNames);
4
5 // Create a list box
6 ListBox listBox = ListBox.create(doc);
7
8 // Add the list box to the document
9 doc.getFormFields().put(id, listBox);
10
11 // Allow multiple selections
12 listBox.setAllowMultiSelect(true);
13
14 // Get the list of chosen items
15 ChoiceItemList chosenItems = listBox.getChosenItems();
16
17 // Loop over all given item names
18 for (String itemName : itemNames) {
19 ChoiceItem item = listBox.addNewItem(itemName);
20 // Check whether to add to the chosen items
21 if (chosenNamesList.contains(itemName))
22 chosenItems.add(item);
23 }
24
25 // Create a widget and add it to the page's widgets
26 page.getWidgets().add(listBox.addNewWidget(rectangle));
27}
28
1private static void addComboBox(Document doc, String id, String[] itemNames, String value, Page page,
2 Rectangle rectangle) throws ToolboxException {
3 // Create a combo box
4 ComboBox comboBox = ComboBox.create(doc);
5
6 // Add the combo box to the document
7 doc.getFormFields().put(id, comboBox);
8
9 // Loop over all given item names
10 for (String itemName : itemNames) {
11 ChoiceItem item = comboBox.addNewItem(itemName);
12 // Check whether to add to the chosen items
13 if (value.equals(itemName))
14 comboBox.setChosenItem(item);
15 }
16 if (comboBox.getChosenItem() == null && !(value == null || value.isEmpty())) {
17 // If no item has been chosen then assume we want to set the editable item
18 comboBox.setCanEdit(true);
19 comboBox.setEditableItemName(value);
20 }
21
22 // Create a widget and add it to the page's widgets
23 page.getWidgets().add(comboBox.addNewWidget(rectangle));
24}
25
1private static void addRadioButtonGroup(Document doc, String id, String[] buttonNames, int chosen, Page page,
2 Rectangle rectangle) throws ToolboxException {
3 // Create a radio button group
4 RadioButtonGroup group = RadioButtonGroup.create(doc);
5
6 // Add the radio button group to the document
7 doc.getFormFields().put(id, group);
8
9 // We partition the given rectangle horizontally into sub-rectangles, one for
10 // each button
11 // Compute the width of the sub-rectangles
12 double buttonWidth = (rectangle.right - rectangle.left) / buttonNames.length;
13
14 // Get the page's widgets
15 WidgetList widgets = page.getWidgets();
16
17 // Loop over all button names
18 for (int i = 0; i < buttonNames.length; i++) {
19 // Compute the sub-rectangle for this button
20 Rectangle buttonRectangle = new Rectangle(rectangle.left + i * buttonWidth, rectangle.bottom,
21 rectangle.left + (i + 1) * buttonWidth, rectangle.top);
22
23 // Create the button and an associated widget
24 RadioButton button = group.addNewButton(buttonNames[i]);
25 Widget widget = button.addNewWidget(buttonRectangle);
26
27 // Check if this is the chosen button
28 if (i == chosen)
29 group.setChosenButton(button);
30
31 // Add the widget to the page's widgets
32 widgets.add(widget);
33 }
34}
35
1private static void addGeneralTextField(Document doc, String id, String value, Page page, Rectangle rectangle)
2 throws ToolboxException {
3 // Create a general text field
4 GeneralTextField field = GeneralTextField.create(doc);
5
6 // Add the field to the document
7 doc.getFormFields().put(id, field);
8
9 // Set the check box's state
10 field.setText(value);
11
12 // Create a widget and add it to the page's widgets
13 page.getWidgets().add(field.addNewWidget(rectangle));
14}
Fill Form Fields
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Objects that need releasing or closing
4 TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
5 TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
6 TPtxPdf_Metadata* pInMetadata = NULL;
7 TPtxPdf_Metadata* pOutMetadata = NULL;
8 TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
9 TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
10 TPtxPdf_FileReferenceList* pInFileRefList = NULL;
11 TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
12 TPtxPdf_FileReference* pInFileRef = NULL;
13 TPtxPdf_FileReference* pOutFileRef = NULL;
14
15 iReturnValue = 0;
16
17 // Output intent
18 pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
19 if (pInOutputIntent != NULL)
20 {
21 pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
22 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
23 _T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
24 szErrorBuff, Ptx_GetLastError());
25 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
26 _T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
27 Ptx_GetLastError());
28 }
29 else
30 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
31 Ptx_GetLastError());
32
33 // Metadata
34 pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
35 if (pInMetadata != NULL)
36 {
37 pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
38 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
39 szErrorBuff, Ptx_GetLastError());
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
41 _T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
42 Ptx_GetLastError());
43 }
44 else
45 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
46 Ptx_GetLastError());
47
48 // Viewer settings
49 pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
50 if (pInViewerSettings != NULL)
51 {
52 pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
53 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
54 _T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
55 Ptx_GetLastError());
56 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
57 _T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
58 Ptx_GetLastError());
59 }
60 else
61 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
62 Ptx_GetLastError());
63
64 // Associated files (for PDF/A-3 and PDF 2.0 only)
65 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
66 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
67 szErrorBuff, Ptx_GetLastError());
68 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
69 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
70 szErrorBuff, Ptx_GetLastError());
71 int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
72 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
73 szErrorBuff, Ptx_GetLastError());
74 for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
75 {
76 pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
77 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
78 szErrorBuff, Ptx_GetLastError());
79 pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
80 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
81 szErrorBuff, Ptx_GetLastError());
82 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
83 _T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
84 Ptx_GetLastError());
85 Ptx_Release(pInFileRef);
86 pInFileRef = NULL;
87 Ptx_Release(pOutFileRef);
88 pOutFileRef = NULL;
89 }
90 Ptx_Release(pInFileRefList);
91 pInFileRefList = NULL;
92 Ptx_Release(pOutFileRefList);
93 pOutFileRefList = NULL;
94
95 // Plain embedded files
96 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
97 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
98 pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
99 szErrorBuff, Ptx_GetLastError());
100 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
101 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
102 pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
103 szErrorBuff, Ptx_GetLastError());
104 nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
105 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
106 szErrorBuff, Ptx_GetLastError());
107 for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
108 {
109 pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
110 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
111 szErrorBuff, Ptx_GetLastError());
112 pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
113 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
114 szErrorBuff, Ptx_GetLastError());
115 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
116 _T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
117 Ptx_GetLastError());
118 Ptx_Release(pInFileRef);
119 pInFileRef = NULL;
120 Ptx_Release(pOutFileRef);
121 pOutFileRef = NULL;
122 }
123
124cleanup:
125 if (pInOutputIntent != NULL)
126 Ptx_Release(pInOutputIntent);
127 if (pOutOutputIntent != NULL)
128 Ptx_Release(pOutOutputIntent);
129 if (pInMetadata != NULL)
130 Ptx_Release(pInMetadata);
131 if (pOutMetadata != NULL)
132 Ptx_Release(pOutMetadata);
133 if (pInViewerSettings != NULL)
134 Ptx_Release(pInViewerSettings);
135 if (pOutViewerSettings != NULL)
136 Ptx_Release(pOutViewerSettings);
137 if (pInFileRefList != NULL)
138 Ptx_Release(pInFileRefList);
139 if (pOutFileRefList != NULL)
140 Ptx_Release(pOutFileRefList);
141 if (pInFileRef != NULL)
142 Ptx_Release(pInFileRef);
143 if (pOutFileRef != NULL)
144 Ptx_Release(pOutFileRef);
145 return iReturnValue;
146}
1int copyFields(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Objects that need releasing or closing
4 TPtxPdfForms_FieldNodeMap* pInFields = NULL;
5 TPtxPdfForms_FieldNodeMap* pOutFields = NULL;
6 TCHAR* szFieldKey = NULL;
7 TPtxPdfForms_FieldNode* pInFieldNode = NULL;
8 TPtxPdfForms_FieldNode* pOutFieldNode = NULL;
9
10 iReturnValue = 0;
11
12 pInFields = PtxPdf_Document_GetFormFields(pInDoc);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFields,
14 _T("Failed to get form fields of the input document. %s (ErrorCode: 0x%08x).\n"),
15 szErrorBuff, Ptx_GetLastError());
16
17 pOutFields = PtxPdf_Document_GetFormFields(pOutDoc);
18 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFields,
19 _T("Failed to get form fields of the output document. %s (ErrorCode: 0x%08x).\n"),
20 szErrorBuff, Ptx_GetLastError());
21
22 for (int iField = PtxPdfForms_FieldNodeMap_GetBegin(pInFields);
23 iField != PtxPdfForms_FieldNodeMap_GetEnd(pInFields);
24 iField = PtxPdfForms_FieldNodeMap_GetNext(pInFields, iField))
25 {
26 if (iField == 0)
27 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
28 Ptx_GetLastError());
29 // Get key
30 size_t nKey = PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, 0);
31 GOTO_CLEANUP_IF_ZERO(nKey, _T("Failed to get form field key\n"));
32 szFieldKey = (TCHAR*)malloc(nKey * sizeof(TCHAR*));
33 GOTO_CLEANUP_IF_NULL(szFieldKey, _T("Failed to allocate memory for field key\n"));
34 if (PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, nKey) != nKey)
35 {
36 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field key. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
37 Ptx_GetLastError());
38 }
39 // Get input field node
40 pInFieldNode = PtxPdfForms_FieldNodeMap_GetValue(pInFields, iField);
41 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFieldNode, _T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"),
42 szErrorBuff, Ptx_GetLastError());
43 // Copy field node to output document
44 pOutFieldNode = PtxPdfForms_FieldNode_Copy(pOutDoc, pInFieldNode);
45 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFieldNode, _T("Failed to copy form field. %s (ErrorCode: 0x%08x)\n"),
46 szErrorBuff, Ptx_GetLastError());
47 // Add copied field node to output fields
48 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_FieldNodeMap_Set(pOutFields, szFieldKey, pOutFieldNode),
49 _T("Failed to add form field \"%s\". %s (ErrorCode: 0x%08x)\n"), szFieldKey,
50 szErrorBuff, Ptx_GetLastError());
51 // Clean up for next iteration
52 free(szFieldKey);
53 szFieldKey = NULL;
54 Ptx_Release(pOutFieldNode);
55 pOutFieldNode = NULL;
56 Ptx_Release(pInFieldNode);
57 pInFieldNode = NULL;
58 }
59
60cleanup:
61 if (pOutFieldNode != NULL)
62 Ptx_Release(pOutFieldNode);
63 if (pInFieldNode != NULL)
64 Ptx_Release(pInFieldNode);
65 if (szFieldKey != NULL)
66 free(szFieldKey);
67 if (pOutFields != NULL)
68 Ptx_Release(pOutFields);
69 if (pInFields != NULL)
70 Ptx_Release(pInFields);
71 return iReturnValue;
72}
1int fillFormField(TPtxPdfForms_Field* pField, const TCHAR* szValue)
2{
3 // Objects that need releasing or closing
4 TPtxPdfForms_RadioButtonList* pButtonList = NULL;
5 TPtxPdfForms_RadioButton* pButton = NULL;
6 TPtxPdfForms_ChoiceItemList* pChoiceItemList = NULL;
7 TPtxPdfForms_ChoiceItem* pItem = NULL;
8 TCHAR* szName = NULL;
9
10 // Other variables
11 TPtxPdfForms_FieldType iType = 0;
12 TPtxPdfForms_CheckBox* pCheckBox = NULL;
13 TPtxPdfForms_RadioButtonGroup* pRadioButtonGroup = NULL;
14
15 iReturnValue = 0;
16 iType = PtxPdfForms_Field_GetType(pField);
17
18 if (iType == ePtxPdfForms_FieldType_GeneralTextField || iType == ePtxPdfForms_FieldType_CombTextField)
19 {
20 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_TextField_SetText((TPtxPdfForms_TextField*)pField, szValue),
21 _T("Failed to set text field value. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
22 Ptx_GetLastError());
23 }
24 else if (iType == ePtxPdfForms_FieldType_CheckBox)
25 {
26 pCheckBox = (TPtxPdfForms_CheckBox*)pField;
27 if (_tcscmp(szValue, _T("on")) == 0)
28 {
29 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, TRUE),
30 _T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
31 Ptx_GetLastError());
32 }
33 else
34 {
35 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, FALSE),
36 _T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
37 Ptx_GetLastError());
38 }
39 }
40 else if (iType == ePtxPdfForms_FieldType_RadioButtonGroup)
41 {
42 pRadioButtonGroup = (TPtxPdfForms_RadioButtonGroup*)pField;
43 pButtonList = PtxPdfForms_RadioButtonGroup_GetButtons(pRadioButtonGroup);
44 for (int iButton = 0; iButton < PtxPdfForms_RadioButtonList_GetCount(pButtonList); iButton++)
45 {
46 pButton = PtxPdfForms_RadioButtonList_Get(pButtonList, iButton);
47 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pButton, _T("Failed to get radio button. %s (ErrorCode: 0x%08x)\n"),
48 szErrorBuff, Ptx_GetLastError())
49 size_t nName = PtxPdfForms_RadioButton_GetExportName(pButton, szName, 0);
50 GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get radio button name\n"));
51 szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
52 GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for radio button name\n"));
53 if (PtxPdfForms_RadioButton_GetExportName(pButton, szName, nName) != nName)
54 {
55 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get radio button name. %s (ErrorCode: 0x%08x)\n"),
56 szErrorBuff, Ptx_GetLastError());
57 }
58 if (_tcscmp(szValue, szName) == 0)
59 {
60 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
61 PtxPdfForms_RadioButtonGroup_SetChosenButton(pRadioButtonGroup, pButton),
62 _T("Failed to set radio button. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
63 }
64 free(szName);
65 szName = NULL;
66 Ptx_Release(pButton);
67 pButton = NULL;
68 }
69 }
70 else if (iType == ePtxPdfForms_FieldType_ComboBox || iType == ePtxPdfForms_FieldType_ListBox)
71 {
72 pChoiceItemList = PtxPdfForms_ChoiceField_GetItems((TPtxPdfForms_ChoiceField*)pField);
73 for (int iItem = 0; iItem < PtxPdfForms_ChoiceItemList_GetCount(pChoiceItemList); iItem++)
74 {
75 pItem = PtxPdfForms_ChoiceItemList_Get(pChoiceItemList, iItem);
76 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pItem,
77 _T("Failed to get item from choice field. %s (ErrorCode: 0x%08x)\n"),
78 szErrorBuff, Ptx_GetLastError());
79 size_t nName = PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, 0);
80 GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get choice item name\n"));
81 szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
82 GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for choice item name\n"));
83 if (PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, nName) != nName)
84 {
85 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get choice item name. %s (ErrorCode: 0x%08x)\n"),
86 szErrorBuff, Ptx_GetLastError());
87 }
88 if (_tcscmp(szValue, szName) == 0)
89 {
90 break;
91 }
92 free(szName);
93 szName = NULL;
94 Ptx_Release(pItem);
95 pItem = NULL;
96 }
97 if (pItem != NULL)
98 {
99 free(szName);
100 szName = NULL;
101 if (iType == ePtxPdfForms_FieldType_ComboBox)
102 {
103 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
104 PtxPdfForms_ComboBox_SetChosenItem((TPtxPdfForms_ComboBox*)pField, pItem),
105 _T("Failed to set choice item for combo box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
106 Ptx_GetLastError());
107 }
108 else // iType == ePtxPdfForms_FieldType_ListBox
109 {
110 Ptx_Release(pChoiceItemList);
111 pChoiceItemList = PtxPdfForms_ListBox_GetChosenItems((TPtxPdfForms_ListBox*)pField);
112 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
113 pChoiceItemList, _T("Failed to get list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
114 szErrorBuff, Ptx_GetLastError());
115 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
116 PtxPdfForms_ChoiceItemList_Clear(pChoiceItemList),
117 _T("Failed to clear list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
118 Ptx_GetLastError());
119 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
120 PtxPdfForms_ChoiceItemList_Add(pChoiceItemList, pItem),
121 _T("Failed to add item to list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
122 szErrorBuff, Ptx_GetLastError());
123 }
124 }
125 }
126
127cleanup:
128 if (szName != NULL)
129 free(szName);
130 if (pItem == NULL)
131 Ptx_Release(pItem);
132 if (pChoiceItemList == NULL)
133 Ptx_Release(pChoiceItemList);
134 if (pButton != NULL)
135 Ptx_Release(pButton);
136 if (pButtonList != NULL)
137 Ptx_Release(pButton);
138
139 return iReturnValue;
140}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 FieldNodeMap outFields = outDoc.FormFields;
13
14 // Copy all form fields
15 FieldNodeMap inFields = inDoc.FormFields;
16 foreach (var inPair in inFields)
17 {
18 FieldNode inFieldNode = inPair.Value;
19 FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inFieldNode);
20 outFields.Add(inPair.Key, outFormFieldNode);
21 }
22
23 // Find the given field, exception thrown if not found
24 var selectedNode = outFields.Lookup(fieldIdentifier);
25 if (selectedNode is Field selectedField)
26 FillFormField(selectedField, fieldValue);
27
28 // Configure copying options for updating existing widgets and removing signature fields
29 PageCopyOptions copyOptions = new PageCopyOptions
30 {
31 FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
32 UnsignedSignatures = CopyStrategy.Remove,
33 };
34
35 // Copy all pages and append to output document
36 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
37 outDoc.Pages.AddRange(copiedPages);
38}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1static void FillFormField(Field formField, string value)
2{
3 // Apply the value, depending on the field type
4 if (formField is TextField textField)
5 {
6 // Set the text
7 textField.Text = value;
8 }
9 else if (formField is CheckBox checkBox)
10 {
11 // Check or un-check
12 checkBox.Checked = "on".Equals(value, StringComparison.CurrentCultureIgnoreCase);
13 }
14 else if (formField is RadioButtonGroup group)
15 {
16 // Search the buttons for given name
17 foreach (var button in group.Buttons)
18 {
19 if (value.Equals(button.ExportName))
20 {
21 // Found: Select this button
22 group.ChosenButton = button;
23 break;
24 }
25 }
26 }
27 else if (formField is ComboBox comboBox)
28 {
29 // Search for the given item
30 foreach (var item in comboBox.Items)
31 {
32 if (value.Equals(item.DisplayName))
33 {
34 // Found: Select this item.
35 comboBox.ChosenItem = item;
36 break;
37 }
38 }
39 }
40 else if (formField is ListBox listBox)
41 {
42 // Search for the given item
43 foreach (var item in listBox.Items)
44 {
45 if (value.Equals(item.DisplayName))
46 {
47 // Found: Set this item as the only selected item
48 var itemList = listBox.ChosenItems;
49 itemList.Clear();
50 itemList.Add(item);
51 break;
52 }
53 }
54 }
55}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Copy all form fields
12 FieldNodeMap inFormFields = inDoc.getFormFields();
13 FieldNodeMap outFormFields = outDoc.getFormFields();
14 for (Entry<String, FieldNode> entry : inFormFields.entrySet())
15 outFormFields.put(entry.getKey(), FieldNode.copy(outDoc, entry.getValue()));
16
17 // Find the given field, exception thrown if not found
18 Field selectedField = (Field) outFormFields.lookup(fieldIdentifier);
19 fillFormField(selectedField, fieldValue);
20
21 // Configure copying options for updating existing widgets and removing signature fields
22 PageCopyOptions copyOptions = new PageCopyOptions();
23 copyOptions.setFormFields(FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS);
24 copyOptions.setUnsignedSignatures(CopyStrategy.REMOVE);
25
26 // Copy all pages and append to output document
27 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
28 outDoc.getPages().addAll(copiedPages);
29 }
30}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void fillFormField(Field formField, String value) throws ToolboxException {
2 // Apply the value, depending on the field type
3 if (formField instanceof TextField) {
4 // Set the text
5 TextField textField = (TextField) formField;
6 textField.setText(value);
7 } else if (formField instanceof CheckBox) {
8 // Check or un-check
9 CheckBox checkBox = (CheckBox) formField;
10 checkBox.setChecked(value.equalsIgnoreCase("on"));
11 } else if (formField instanceof RadioButtonGroup) {
12 // Search the buttons for given name
13 RadioButtonGroup group = (RadioButtonGroup) formField;
14 for (RadioButton button : group.getButtons()) {
15 if (value.equals(button.getExportName())) {
16 // Found: Select this button
17 group.setChosenButton(button);
18 break;
19 }
20 }
21 } else if (formField instanceof ComboBox) {
22 // Search for the given item
23 ComboBox comboBox = (ComboBox) formField;
24 for (ChoiceItem item : comboBox.getItems()) {
25 if (value.equals(item.getDisplayName())) {
26 // Found: Select this item
27 comboBox.setChosenItem(item);
28 break;
29 }
30 }
31 } else if (formField instanceof ListBox) {
32 // Search for the given item
33 ListBox listBox = (ListBox) formField;
34 for (ChoiceItem item : listBox.getItems()) {
35 if (value.equals(item.getDisplayName())) {
36 // Found: Set this item as the only selected item
37 ChoiceItemList itemList = listBox.getChosenItems();
38 itemList.clear();
39 itemList.add(item);
40 break;
41 }
42 }
43 }
44}
Content Addition
Add barcode to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create file stream
10pFontStream = _tfopen(szFontPath, _T("rb"));
11GOTO_CLEANUP_IF_NULL(pFontStream, _T("Failed to open font file."));
12PtxSysCreateFILEStreamDescriptor(&fontDescriptor, pFontStream, 0);
13
14// Create output document
15pOutStream = _tfopen(szOutPath, _T("wb+"));
16GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
17PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
18iConformance = PtxPdf_Document_GetConformance(pInDoc);
19pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
21 szOutPath, szErrorBuff, Ptx_GetLastError());
22pFont = PtxPdfContent_Font_Create(pOutDoc, &fontDescriptor, TRUE);
23GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
24 Ptx_GetLastError());
25
26// Copy document-wide data
27GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
28 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
29 Ptx_GetLastError());
30
31// Configure copy options
32pCopyOptions = PtxPdf_PageCopyOptions_New();
33
34// Get page lists of input and output document
35pInPageList = PtxPdf_Document_GetPages(pInDoc);
36GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
37 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
38 szErrorBuff, Ptx_GetLastError());
39pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
40GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
41 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43
44// Copy first page
45pInPage = PtxPdf_PageList_Get(pInPageList, 0);
46GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
47 szErrorBuff, Ptx_GetLastError());
48pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
49GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
50 Ptx_GetLastError());
51
52// Add barcode image to copied page
53if (addBarcode(pOutDoc, pOutPage, szBarcode, pFont, 50) != 0)
54 goto cleanup;
55
56// Add page to output document
57GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
58 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
59 szErrorBuff, Ptx_GetLastError());
60
61// Get remaining pages from input
62pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
63GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
64 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
65 szErrorBuff, Ptx_GetLastError());
66
67// Copy remaining pages to output
68pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
69GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
70 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
71 szErrorBuff, Ptx_GetLastError());
72
73// Add the copied pages to the output document
74GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
75 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
76 szErrorBuff, Ptx_GetLastError());
77
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addBarcode(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szBarcode, TPtxPdfContent_Font* pFont,
2 double dFontSize)
3{
4 TPtxPdfContent_Content* pContent = NULL;
5 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
6 TPtxPdfContent_Text* pBarcodeText = NULL;
7 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Create text object
17 pBarcodeText = PtxPdfContent_Text_Create(pOutDoc);
18 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pBarcodeText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
19 szErrorBuff, Ptx_GetLastError());
20
21 // Create text generator
22 pTextGenerator = PtxPdfContent_TextGenerator_New(pBarcodeText, pFont, dFontSize, NULL);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
24 szErrorBuff, Ptx_GetLastError());
25
26 // Calculate position
27 TPtxGeomReal_Size size;
28 PtxPdf_Page_GetSize(pOutPage, &size);
29 TPtxGeomReal_Point position;
30 double dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szBarcode);
31 GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
32 double dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
33 GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontAscent, _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
34 double dFontDescent = PtxPdfContent_Font_GetDescent(pFont);
35 GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontDescent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff,
36 Ptx_GetLastError());
37 position.dX = size.dWidth - (dTextWidth + dBorder);
38 position.dY = size.dHeight - (dFontSize * (dFontAscent + dFontDescent) + dBorder);
39
40 // Move to position
41 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
42 _T("Failed to move to position %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
43 Ptx_GetLastError());
44 // Add given barcode string
45 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szBarcode),
46 _T("Failed to add barcode string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
47 Ptx_GetLastError());
48
49 // Close text generator
50 if (pTextGenerator != NULL)
51 PtxPdfContent_TextGenerator_Close(pTextGenerator);
52
53 // Paint the positioned barcode text
54 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pBarcodeText),
55 _T("Failed to paint the positioned barcode text. %s (ErrorCode: 0x%08x).\n"),
56 szErrorBuff, Ptx_GetLastError());
57
58cleanup:
59 if (pGenerator != NULL)
60 PtxPdfContent_ContentGenerator_Close(pGenerator);
61
62 return iReturnValue;
63}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create file stream
6using (Stream fontStream = new FileStream(fontPath, FileMode.Open, FileAccess.Read))
7
8// Create output document
9using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
10using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
11{
12 // Copy document-wide data
13 CopyDocumentData(inDoc, outDoc);
14
15 // Create embedded font in output document
16 Font font = Font.Create(outDoc, fontStream, true);
17
18 // Define page copy options
19 PageCopyOptions copyOptions = new PageCopyOptions();
20
21 // Copy first page, add barcode, and append to output document
22 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
23 AddBarcode(outDoc, outPage, barcode, font, 50);
24 outDoc.Pages.Add(outPage);
25
26 // Copy remaining pages and append to output document
27 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
28 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
29 outDoc.Pages.AddRange(copiedPages);
30}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddBarcode(Document outputDoc, Page outPage, string barcode,
2 Font font, double fontSize)
3{
4 // Create content generator
5 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
6
7 // Create text object
8 Text barcodeText = Text.Create(outputDoc);
9
10 // Create text generator
11 using (TextGenerator textGenerator = new TextGenerator(barcodeText, font, fontSize, null))
12 {
13 // Calculate position
14 Point position = new Point
15 {
16 X = outPage.Size.Width - (textGenerator.GetWidth(barcode) + Border),
17 Y = outPage.Size.Height - (fontSize * (font.Ascent + font.Descent) + Border)
18 };
19
20 // Move to position
21 textGenerator.MoveTo(position);
22 // Add given barcode string
23 textGenerator.ShowLine(barcode);
24 }
25 // Paint the positioned barcode text
26 gen.PaintText(barcodeText);
27}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 // Create file stream
5 FileStream fontStream = new FileStream(fontPath, FileStream.Mode.READ_ONLY);
6 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
7 try (// Create output document
8 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
9
10 // Copy document-wide data
11 copyDocumentData(inDoc, outDoc);
12
13 // Create embedded font in output document
14 Font font = Font.create(outDoc, fontStream, true);
15
16 // Define page copy options
17 PageCopyOptions copyOptions = new PageCopyOptions();
18
19 // Copy first page, add barcode, and append to output document
20 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
21 addBarcode(outDoc, outPage, barcode, font, 50);
22 outDoc.getPages().add(outPage);
23
24 // Copy remaining pages and append to output document
25 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
26 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
27 outDoc.getPages().addAll(copiedPages);
28 }
29}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addBarcode(Document outputDoc, Page outPage, String barcode, Font font, double fontSize) throws ToolboxException, IOException {
2 try (// Create content generator
3 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
4 // Create text object
5 Text barcodeText = Text.create(outputDoc);
6
7 // Create a text generator
8 TextGenerator textgenerator = new TextGenerator(barcodeText, font, fontSize, null);
9
10 // Calculate position
11 Point position = new Point(outPage.getSize().width - (textgenerator.getWidth(barcode) + Border),
12 outPage.getSize().height - (fontSize * (font.getAscent() + font.getDescent()) + Border));
13
14 // Move to position
15 textgenerator.moveTo(position);
16 // Add given barcode string
17 textgenerator.showLine(barcode);
18 // Close text generator
19 textgenerator.close();
20
21 // Paint the positioned barcode text
22 generator.paintText(barcodeText);
23 }
24}
Add Data Matrix to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Configure copy options
29pCopyOptions = PtxPdf_PageCopyOptions_New();
30
31// Get page lists of input and output document
32pInPageList = PtxPdf_Document_GetPages(pInDoc);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
34 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
35 szErrorBuff, Ptx_GetLastError());
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40
41// Copy first page
42pInPage = PtxPdf_PageList_Get(pInPageList, 0);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
44 szErrorBuff, Ptx_GetLastError());
45pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
46GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
47 Ptx_GetLastError());
48
49// Add datamatrix image to copied page
50if (addDataMatrix(pOutDoc, pOutPage, szDatamatrixPath) != 0)
51 goto cleanup;
52
53// Add page to output document
54GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
55 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
56 szErrorBuff, Ptx_GetLastError());
57
58// Get remaining pages from input
59pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
60GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
61 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63
64// Copy remaining pages to output
65pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
67 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69
70// Add the copied pages to the output document
71GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
72 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
73 szErrorBuff, Ptx_GetLastError());
74
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addDataMatrix(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szDataMatrixPath)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxSys_StreamDescriptor datamatrixDescriptor;
6 FILE* pDatamatrixStream = NULL;
7 TPtxPdfContent_Image* pDatamatrix = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Import data matrix
17 pDatamatrixStream = _tfopen(szDataMatrixPath, _T("rb"));
18 GOTO_CLEANUP_IF_NULL(pDatamatrixStream, _T("Failed to open data matrix file \"%s\".\n"), szDataMatrixPath);
19 PtxSysCreateFILEStreamDescriptor(&datamatrixDescriptor, pDatamatrixStream, 0);
20
21 // Create image object for data matrix
22 pDatamatrix = PtxPdfContent_Image_Create(pOutDoc, &datamatrixDescriptor);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pDatamatrix, _T("Failed to create image object. %s (ErrorCode: 0x%08x).\n"),
24 szErrorBuff, Ptx_GetLastError());
25
26 // Data matrix size
27 double dDatamatrixSize = 85.0;
28
29 // Calculate Rectangle for data matrix
30 TPtxGeomReal_Size size;
31 PtxPdf_Page_GetSize(pOutPage, &size);
32 TPtxGeomReal_Rectangle rect;
33 rect.dLeft = dBorder;
34 rect.dBottom = size.dHeight - (dDatamatrixSize + dBorder);
35 rect.dRight = dDatamatrixSize + dBorder;
36 rect.dTop = size.dHeight - dBorder;
37
38 // Paint image of data matrix into the specified rectangle
39 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
40 PtxPdfContent_ContentGenerator_PaintImage(pGenerator, pDatamatrix, &rect),
41 _T("Failed to paint data matrix into the specified rectangle. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
42 Ptx_GetLastError());
43
44cleanup:
45 if (pGenerator != NULL)
46 PtxPdfContent_ContentGenerator_Close(pGenerator);
47 if (pContent != NULL)
48 Ptx_Release(pContent);
49
50 return iReturnValue;
51}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy first page, add datamatrix image, and append to output document
16 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
17 AddDataMatrix(outDoc, outPage, datamatrixPath);
18 outDoc.Pages.Add(outPage);
19
20 // Copy remaining pages and append to output document
21 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
22 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
23 outDoc.Pages.AddRange(copiedPages);
24}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddDataMatrix(Document document, Page page, string datamatrixPath)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(page.Content, false);
5
6 // Import data matrix
7 using Stream inMatrix = new FileStream(datamatrixPath, FileMode.Open, FileAccess.Read);
8
9 // Create image object for data matrix
10 Image datamatrix = Image.Create(document, inMatrix);
11
12 // Data matrix size
13 double datamatrixSize = 85;
14
15 // Calculate Rectangle for data matrix
16 Rectangle rect = new Rectangle
17 {
18 Left = Border,
19 Bottom = page.Size.Height - (datamatrixSize + Border),
20 Right = datamatrixSize + Border,
21 Top = page.Size.Height - Border
22 };
23
24 // Paint image of data matrix into the specified rectangle
25 generator.PaintImage(datamatrix, rect);
26}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy first page, add data matrix image, and append to output document
15 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
16 addDatamatrix(outDoc, outPage, datamatrixPath);
17 outDoc.getPages().add(outPage);
18
19 // Copy remaining pages and append to output document
20 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
21 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
22 outDoc.getPages().addAll(copiedPages);
23 }
24}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addDatamatrix(Document document, Page page, String datamatrixPath)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(page.getContent(), false);
5 // Import data matrix
6 FileStream inMatrix = new FileStream(datamatrixPath, FileStream.Mode.READ_ONLY)) {
7
8 // Create image object for data matrix
9 Image datamatrix = Image.create(document, inMatrix);
10
11 // Data matrix size
12 double datamatrixSize = 85;
13
14 // Calculate Rectangle for data matrix
15 Rectangle rect = new Rectangle(Border, page.getSize().height - (datamatrixSize + Border),
16 datamatrixSize + Border, page.getSize().height - Border);
17
18 // Paint image of data matrix into the specified rectangle
19 generator.paintImage(datamatrix, rect);
20 }
21}
Add image to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Get input and output page lists
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
33 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
34 szErrorBuff, Ptx_GetLastError());
35
36// Copy pages preceding selected page
37pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 0, iPageNumber - 1);
38GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange, _T("Failed to get page range. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
41GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange, _T("Failed to copy page range. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
44 _T("Failed to add page range. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
45 Ptx_GetLastError());
46Ptx_Release(pInPageRange);
47pInPageRange = NULL;
48Ptx_Release(pOutPageRange);
49pOutPageRange = NULL;
50
51// Copy selected page an add image
52pInPage = PtxPdf_PageList_Get(pInPageList, iPageNumber - 1);
53GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
54 Ptx_GetLastError());
55pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
56GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
57 Ptx_GetLastError());
58if (addImage(pOutDoc, pOutPage, szImagePath, 150.0, 150.0) != 0)
59 goto cleanup;
60GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
61 _T("Failed to add page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
62 Ptx_GetLastError());
63
64// Copy remaining pages
65pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
67 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
70GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
71 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
72 szErrorBuff, Ptx_GetLastError());
73GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
74 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
75 szErrorBuff, Ptx_GetLastError());
76
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addImage(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szImagePath, double x, double y)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxSys_StreamDescriptor imageDescriptor;
6 FILE* pImageStream = NULL;
7 TPtxPdfContent_Image* pImage = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13
14 // Load image from input path
15 pImageStream = _tfopen(szImagePath, _T("rb"));
16 PtxSysCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);
17
18 // Create image object
19 pImage = PtxPdfContent_Image_Create(pOutDoc, &imageDescriptor);
20
21 double dResolution = 150.0;
22
23 TPtxGeomInt_Size size;
24 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Image_GetSize(pImage, &size),
25 _T("Failed to get image size. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28 // Calculate Rectangle for data matrix
29 TPtxGeomReal_Rectangle rect;
30 rect.dLeft = x;
31 rect.dBottom = y;
32 rect.dRight = x + (double)size.iWidth * 72.0 / dResolution;
33 rect.dTop = y + (double)size.iHeight * 72.0 / dResolution;
34
35 // Paint image into the specified rectangle
36 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintImage(pGenerator, pImage, &rect),
37 _T("Failed to paint image. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
38 Ptx_GetLastError());
39
40cleanup:
41 if (pGenerator != NULL)
42 PtxPdfContent_ContentGenerator_Close(pGenerator);
43 if (pContent != NULL)
44 Ptx_Release(pContent);
45
46 return iReturnValue;
47}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy pages preceding selected page and append do output document
16 PageList inPageRange = inDoc.Pages.GetRange(0, pageNumber - 1);
17 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
18 outDoc.Pages.AddRange(copiedPages);
19
20 // Copy selected page, add image, and append to output document
21 Page outPage = Page.Copy(outDoc, inDoc.Pages[pageNumber - 1], copyOptions);
22 AddImage(outDoc, outPage, imagePath, 150, 150);
23 outDoc.Pages.Add(outPage);
24
25 // Copy remaining pages and append to output document
26 inPageRange = inDoc.Pages.GetRange(pageNumber, inDoc.Pages.Count - pageNumber);
27 copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
28 outDoc.Pages.AddRange(copiedPages);
29}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddImage(Document document, Page page, string imagePath, double x, double y)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(page.Content, false);
5
6 // Load image from input path
7 using Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
8
9 // Create image object
10 Image image = Image.Create(document, inImage);
11 double resolution = 150;
12
13 // Calculate rectangle for image
14 PdfTools.Toolbox.Geometry.Integer.Size size = image.Size;
15 Rectangle rect = new Rectangle
16 {
17 Left = x,
18 Bottom = y,
19 Right = x + size.Width * 72 / resolution,
20 Top = y + size.Height * 72 / resolution
21 };
22
23 // Paint image into the specified rectangle
24 generator.PaintImage(image, rect);
25}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy pages preceding selected page and append to output document
15 PageList inPageRange = inDoc.getPages().subList(0, pageNumber - 1);
16 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
17 outDoc.getPages().addAll(copiedPages);
18
19 // Copy selected page, add image, and append to output document
20 Page outPage = Page.copy(outDoc, inDoc.getPages().get(pageNumber - 1), copyOptions);
21 addImage(outDoc, outPage, imagePath, 150, 150);
22 outDoc.getPages().add(outPage);
23
24 // Copy remaining pages and append to output document
25 inPageRange = inDoc.getPages().subList(pageNumber, inDoc.getPages().size());
26 copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
27 outDoc.getPages().addAll(copiedPages);
28 }
29}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addImage(Document document, Page outPage, String imagePath, double x, double y)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
5 // Load image from input path
6 FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
7 // Create image object
8 Image image = Image.create(document, inImage);
9
10 double resolution = 150;
11
12 // Calculate rectangle for image
13 Size size = image.getSize();
14 Rectangle rect = new Rectangle(x, y, x + size.getWidth() * 72 / resolution,
15 y + size.getHeight() * 72 / resolution);
16
17 // Paint image into the specified rectangle
18 generator.paintImage(image, rect);
19 }
20}
Add image mask to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
7 Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
16 Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Get the device color space
24TPtxPdfContent_ColorSpace* pColorSpace =
25 PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
26GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the device color space. %s (ErrorCode: 0x%08x).\n"),
27 szErrorBuff, Ptx_GetLastError());
28
29// Chose the RGB color value
30double color[] = {1.0, 0.0, 0.0};
31size_t nColor = sizeof(color) / sizeof(double);
32
33// Create paint object
34pPaint = PtxPdfContent_Paint_Create(pOutDoc, pColorSpace, color, nColor, NULL);
35GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"),
36 szErrorBuff, Ptx_GetLastError());
37
38// Configure copy options
39pCopyOptions = PtxPdf_PageCopyOptions_New();
40
41// Get input and output page lists
42pInPageList = PtxPdf_Document_GetPages(pInDoc);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
44 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
45 szErrorBuff, Ptx_GetLastError());
46pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
47GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
48 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
49 szErrorBuff, Ptx_GetLastError());
50
51// Copy first page an add image mask
52pInPage = PtxPdf_PageList_Get(pInPageList, 0);
53GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
54 Ptx_GetLastError());
55pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
56GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
57 Ptx_GetLastError());
58if (addImageMask(pOutDoc, pOutPage, szImageMaskPath, 250, 150) != 0)
59 goto cleanup;
60GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
61 _T("Failed to add page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
62 Ptx_GetLastError());
63
64// Copy remaining pages
65pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
67 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
70GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
71 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
72 szErrorBuff, Ptx_GetLastError());
73GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
74 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
75 szErrorBuff, Ptx_GetLastError());
76
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addImageMask(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szImageMaskPath, double x, double y)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 FILE* pImageStream = NULL;
6 TPtxSys_StreamDescriptor imageDescriptor;
7 TPtxPdfContent_ImageMask* pImageMask = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Load image from input path
17 pImageStream = _tfopen(szImageMaskPath, _T("rb"));
18 GOTO_CLEANUP_IF_NULL(pImageStream, _T("Failed to open image mask file \"%s\".\n"), szImageMaskPath);
19 PtxSysCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);
20
21 // Create image mask object
22 pImageMask = PtxPdfContent_ImageMask_Create(pOutDoc, &imageDescriptor);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pImageMask, _T("Failed to create image mask obejct. %s (ErrorCode: 0x%08x).\n"),
24 szErrorBuff, Ptx_GetLastError());
25
26 double dResolution = 150.0;
27 TPtxGeomInt_Size size;
28 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ImageMask_GetSize(pImageMask, &size),
29 _T("Failed to get image mask size. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
30 Ptx_GetLastError());
31
32 // Calculate Rectangle for data matrix
33 TPtxGeomReal_Rectangle rect;
34 rect.dLeft = x;
35 rect.dBottom = y;
36 rect.dRight = x + (double)size.iWidth * 72.0 / dResolution;
37 rect.dTop = y + (double)size.iHeight * 72.0 / dResolution;
38
39 // Paint image mask into the specified rectangle
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
41 PtxPdfContent_ContentGenerator_PaintImageMask(pGenerator, pImageMask, &rect, pPaint),
42 _T("Failed to paint image mask. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
43
44cleanup:
45 if (pGenerator != NULL)
46 PtxPdfContent_ContentGenerator_Close(pGenerator);
47 if (pContent != NULL)
48 Ptx_Release(pContent);
49
50 return iReturnValue;
51}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Get the device color space
13 ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);
14
15 // Create paint object
16 paint = Paint.Create(outDoc, colorSpace, new double[] { 1.0, 0.0, 0.0 }, null);
17
18 // Define page copy options
19 PageCopyOptions copyOptions = new PageCopyOptions();
20
21 // Copy first page, add image mask, and append to output document
22 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
23 AddImageMask(outDoc, outPage, imageMaskPath, 250, 150);
24 outDoc.Pages.Add(outPage);
25
26 // Copy remaining pages and append to output document
27 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
28 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
29 outDoc.Pages.AddRange(copiedPages);
30}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1 private static void AddImageMask(Document document, Page outPage, string imagePath,
2 double x, double y)
3 {
4 // Create content generator
5 using ContentGenerator generator = new ContentGenerator(outPage.Content, false);
6
7 // Load image from input path
8 using Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
9
10 // Create image mask object
11 ImageMask imageMask = ImageMask.Create(document, inImage);
12 double resolution = 150;
13
14 // Calculate rectangle for image
15 PdfTools.Toolbox.Geometry.Integer.Size size = imageMask.Size;
16 Rectangle rect = new Rectangle
17 {
18 Left = x,
19 Bottom = y,
20 Right = x + size.Width * 72 / resolution,
21 Top = y + size.Height * 72 / resolution
22 };
23
24 // Paint image mask into the specified rectangle
25 generator.PaintImageMask(imageMask, rect, paint);
26 }
27}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Get the device color space
15 ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);
16
17 // Create paint object
18 paint = Paint.create(outDoc, colorSpace, new double[] { 1.0, 0.0, 0.0 }, null);
19
20 // Copy first page, add image mask, and append to output document
21 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
22 addImageMask(outDoc, outPage, imageMaskPath, 250, 150);
23 outDoc.getPages().add(outPage);
24
25 // Copy remaining pages and append to output document
26 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
27 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
28 outDoc.getPages().addAll(copiedPages);
29 }
30}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addImageMask(Document document, Page outPage, String imagePath, double x, double y)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
5 // Load image from input path
6 FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
7 // Create image mask object
8 ImageMask imageMask = ImageMask.create(document, inImage);
9
10 double resolution = 150;
11
12 // Calculate rectangle for image
13 Size size = imageMask.getSize();
14 Rectangle rect = new Rectangle(x, y, x + size.getWidth() * 72 / resolution,
15 y + size.getHeight() * 72 / resolution);
16
17 // Paint image mask into the specified rectangle
18 generator.paintImageMask(imageMask, rect, paint);
19 }
20}
Add line numbers to PDF
1 // Open input document
2 using Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read);
3 using Document inDoc = Document.Open(inStream, null);
4
5 // Create output document
6 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
7 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
8 // Copy document-wide data
9 CopyDocumentData(inDoc, outDoc);
10
11 // Create a font for the line numbers
12 var lineNumberFont = Font.CreateFromSystem(outDoc, "Arial", null, true);
13
14 // Define page copy options
15 PageCopyOptions pageCopyOptions = new();
16
17 // Copy all pages from input to output document
18 var inPages = inDoc.Pages;
19 var outPages = PageList.Copy(outDoc, inPages, pageCopyOptions);
20
21 // Iterate over all input-output page pairs
22 var pages = inPages.Zip(outPages);
23 foreach (var pair in pages)
24 AddLineNumbers(outDoc, lineNumberFont, pair);
25
26 // Add the finished pages to the output document's page list
27 outDoc.Pages.AddRange(outPages);
28 }
29 catch (Exception ex)
30 {
31 Console.WriteLine(ex.Message);
32 }
33}
34
1private static void AddLineNumbers(Document outDoc, Font lineNumberFont, (Page first, Page second) pair)
2{
3 // Add line numbers to all text found in the input page to the output page
4
5 // The input and output page
6 var inPage = pair.first;
7 var outPage = pair.second;
8
9 // Extract all text fragments
10 var extractor = new ContentExtractor(inPage.Content)
11 {
12 Ungrouping = UngroupingSelection.All
13 };
14
15 // The left-most horizontel position of all text fragments
16 double leftX = inPage.Size.Width;
17
18 // A comparison for doubles that considers distances smaller than the font size as equal
19 var comparison = new Comparison<double>(
20 (a, b) =>
21 {
22 var d = b - a;
23 if (Math.Abs(d) < fontSize)
24 return 0;
25 return Math.Sign(d);
26 });
27
28 // A container to hold the vertical positions of all text fragments, sorted and without duplicates
29 SortedSet<double> lineYPositions = new(Comparer<double>.Create(comparison));
30
31 // Iterate over all content elements of the input page
32 foreach (var element in extractor)
33 {
34 // Process only text elements
35 if (element is TextElement textElement)
36 {
37 // Iterate over all text fragments
38 foreach (var fragment in textElement.Text)
39 {
40 // Get the fragments base line starting point
41 var point = fragment.Transform.TransformPoint(new Point { X = fragment.BoundingBox.Left, Y = 0 });
42
43 // Update the left-most position
44 leftX = Math.Min(leftX, point.X);
45
46 // Add the vertical position
47 lineYPositions.Add(point.Y);
48 }
49 }
50 }
51
52 // If at least text fragment was found: add line numbers
53 if (lineYPositions.Count > 0)
54 {
55 // Create a text object and use a text generator
56 var text = Text.Create(outDoc);
57 using (var textGenerator = new TextGenerator(text, lineNumberFont, fontSize, null))
58 {
59 // Iterate over all vertical positions found in the input
60 foreach (var y in lineYPositions)
61 {
62 // The line number string
63 var lineNumberString = string.Format("{0}", ++lineNumber);
64
65 // The width of the line number string when shown on the page
66 var width = textGenerator.GetWidth(lineNumberString);
67
68 // Position line numbers right aligned
69 // with a given distance to the right-most horizontal position
70 // and at the vertical position of the current text fragment
71 textGenerator.MoveTo(new Point { X = leftX - width - distance, Y = y });
72
73 // Show the line number string
74 textGenerator.Show(lineNumberString);
75 }
76 }
77
78 // Use a content generator to paint the text onto the page
79 using var contentGenerator = new ContentGenerator(outPage.Content, false);
80 contentGenerator.PaintText(text);
81 }
82}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
6 // Copy document-wide data
7 copyDocumentData(inDoc, outDoc);
8
9 // Create embedded font in output document
10 Font font = Font.createFromSystem(outDoc, "Arial", null, true);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy all pages from input to output document
16 PageList inPages = inDoc.getPages();
17 PageList outPages = PageList.copy(outDoc, inPages, copyOptions);
18
19 // Iterate over all input-output page pairs and add line numbers
20 for (int i = 0; i < inPages.size(); ++i) {
21 addLineNumbers(outDoc, font, new SimpleEntry<>(inPages.get(i), outPages.get(i)));
22 }
23
24 // Add the finished pages to the output document's page list
25 outDoc.getPages().addAll(outPages);
26 }
27}
1private static void addLineNumbers(Document outDoc, Font lineNumberFont, Entry<Page, Page> pair) throws IOException, ToolboxException {
2 // Add line numbers to all text found in the input page to the output page
3
4 // The input and output page
5 Page inPage = pair.getKey();
6 Page outPage = pair.getValue();
7
8 // Extract all text fragments
9 ContentExtractor extractor = new ContentExtractor(inPage.getContent());
10 extractor.setUngrouping(UngroupingSelection.ALL);
11 // The left-most horizontal position of all text fragments
12 double leftX = inPage.getSize().getWidth();
13
14 Comparator<Double> comparator = new Comparator<Double>() {
15 @Override
16 public int compare(Double d1, Double d2) {
17 Double diff = d2 - d1;
18 if (Math.abs(diff) < fontSize)
19 return 0;
20 return (int) Math.signum(diff);
21 }
22 };
23
24 SortedSet<Double> lineYPositions = new TreeSet<>(comparator);
25
26 for (ContentElement element : extractor) {
27
28 // Process only text elements
29 if (element instanceof TextElement) {
30 TextElement textElement = (TextElement) element;
31 // Iterate over all text fragments
32 for (TextFragment fragment : textElement.getText()) {
33
34 // Get the fragments base line starting point
35 Point point = fragment.getTransform().transformPoint(new Point(fragment.getBoundingBox().left, 0));
36
37 // Update the left-most position
38 leftX = Math.min(leftX, point.x);
39
40 // Add the vertical position
41 lineYPositions.add(point.y);
42 }
43 }
44 }
45
46 // If at least one text fragment was found: add line numbers
47 if (lineYPositions.size() > 0) {
48
49 // Create a text object and use a text generator
50 Text text = Text.create(outDoc);
51 try (TextGenerator textGenerator = new TextGenerator(text, lineNumberFont, fontSize, null)) {
52 // Iterate over all vertical positions found in the input
53 for(double y : lineYPositions) {
54 // The line number string
55 String lineNumberString = String.valueOf(++lineNumber);
56
57 // The width of the line number string when shown on the page
58 double width = textGenerator.getWidth(lineNumberString);
59
60 // Position line numbers right aligned
61 // with a given distance to the right-most horizontal position
62 // and at the vertical position of the current text fragment
63 textGenerator.moveTo(new Point (leftX - width - distance, y));
64
65 // Show the line number string
66 textGenerator.show(lineNumberString);
67 }
68 }
69 try (ContentGenerator contentGenerator = new ContentGenerator(outPage.getContent(), false)) {
70 // Use a content generator to paint the text onto the page
71 contentGenerator.paintText(text);
72 }
73 }
74}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
Add stamp to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&inDescriptor, pInStream, FALSE);
5pInDoc = PtxPdf_Document_Open(&inDescriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file %s.\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file %s cannot be closed. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Embedded font cannot be created. %s (ErrorCode: 0x%08x).\n"),
21 szErrorBuff, Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Get the color space
29TPtxPdfContent_ColorSpace* pColorSpace =
30 PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
31GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the color space. %s (ErrorCode: 0x%08x).\n"),
32 szErrorBuff, Ptx_GetLastError());
33
34// Chose the RGB color values
35double color[] = {1.0, 0.0, 0.0};
36size_t nColor = sizeof(color) / sizeof(double);
37pTransparency = PtxPdfContent_Transparency_New(dAlpha);
38
39// Create paint object
40pPaint = PtxPdfContent_Paint_Create(pOutDoc, pColorSpace, color, nColor, pTransparency);
41GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43
44// Configure copy options
45pCopyOptions = PtxPdf_PageCopyOptions_New();
46
47// Loop through all pages of input
48pInPageList = PtxPdf_Document_GetPages(pInDoc);
49GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
50 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
51 szErrorBuff, Ptx_GetLastError());
52pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
53GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
54 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
55 szErrorBuff, Ptx_GetLastError());
56for (int i = 0; i < PtxPdf_PageList_GetCount(pInPageList); i++)
57{
58 // Get a list of pages
59 pInPage = PtxPdf_PageList_Get(pInPageList, i);
60
61 // Copy page from input to output
62 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
63 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
64 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
65 szErrorBuff, Ptx_GetLastError());
66
67 // Add stamp to page
68 if (addStamp(pOutDoc, pOutPage, szStampString, pFont, 50) == 1)
69 {
70 goto cleanup;
71 }
72
73 // Add page to output document
74 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
75 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
76 szErrorBuff, Ptx_GetLastError());
77
78 if (pOutPage != NULL)
79 {
80 Ptx_Release(pOutPage);
81 pOutPage = NULL;
82 }
83
84 if (pInPage != NULL)
85 {
86 Ptx_Release(pInPage);
87 pInPage = NULL;
88 }
89}
90
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addStamp(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szStampString, TPtxPdfContent_Font* pFont,
2 double dFontSize)
3{
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxPdfContent_Text* pText = NULL;
6 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
7 TPtxGeomReal_AffineTransform trans;
8 TPtxGeomReal_Point rotationCenter;
9 double dTextWidth;
10 double dFontAscent;
11
12 TPtxPdfContent_Content* pContent = PtxPdf_Page_GetContent(pOutPage);
13
14 // Create content generator
15 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
16 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
17 szErrorBuff, Ptx_GetLastError());
18
19 // Create text object
20 pText = PtxPdfContent_Text_Create(pOutDoc);
21 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
22 szErrorBuff, Ptx_GetLastError());
23
24 // Create a text generator
25 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, dFontSize, NULL);
26 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
27 szErrorBuff, Ptx_GetLastError());
28
29 // Get output page size
30 TPtxGeomReal_Size size;
31 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
32 _T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
33 Ptx_GetLastError());
34
35 // Calculate point and angle of rotation
36 rotationCenter.dX = size.dWidth / 2.0;
37 rotationCenter.dY = size.dHeight / 2.0;
38 double dRotationAngle = atan2(size.dHeight, size.dWidth) / M_PI * 180.0;
39
40 // Rotate textinput around the calculated position
41 PtxGeomReal_AffineTransform_GetIdentity(&trans);
42 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
43 PtxGeomReal_AffineTransform_Rotate(&trans, dRotationAngle, &rotationCenter),
44 _T("Failed to rotate textinput around the calculated position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
45 Ptx_GetLastError());
46 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_Transform(pGenerator, &trans),
47 _T("Failed to modify the current transformation. %s (ErrorCode: 0x%08x).\n"),
48 szErrorBuff, Ptx_GetLastError());
49
50 // Calculate position
51 TPtxGeomReal_Point position;
52 dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampString);
53 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
54 dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
55 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
56 position.dX = (size.dWidth - dTextWidth) / 2.0;
57 position.dY = (size.dHeight - dFontAscent * dFontSize) / 2.0;
58
59 // Move to position
60 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
61 _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
62 Ptx_GetLastError());
63 // Set text rendering
64 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_SetFill(pTextGenerator, pPaint),
65 _T("Failed to set fill paint. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
66 Ptx_GetLastError());
67 // Add given stamp string
68 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szStampString),
69 _T("Failed to add stamp. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
70 Ptx_GetLastError());
71
72 // Close text generator
73 if (pTextGenerator != NULL)
74 {
75 PtxPdfContent_TextGenerator_Close(pTextGenerator);
76 pTextGenerator = NULL;
77 }
78
79 // Paint the positioned text
80 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
81 _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
82 Ptx_GetLastError());
83
84cleanup:
85 if (pTextGenerator != NULL)
86 PtxPdfContent_TextGenerator_Close(pTextGenerator);
87 if (pText != NULL)
88 Ptx_Release(pText);
89 if (pGenerator != NULL)
90 PtxPdfContent_ContentGenerator_Close(pGenerator);
91 if (pContent != NULL)
92 Ptx_Release(pContent);
93
94 return iReturnValue;
95}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
13
14 // Get the color space
15 ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);
16
17 // Choose the RGB color value
18 double[] color = { 1.0, 0.0, 0.0 };
19 Transparency transparency = new Transparency(alpha);
20
21 // Create paint object with the choosen RGB color
22 paint = Paint.Create(outDoc, colorSpace, color, transparency);
23
24 // Define copy options
25 PageCopyOptions copyOptions = new PageCopyOptions();
26
27 // Copy all pages from input document
28 foreach (Page inPage in inDoc.Pages)
29 {
30 // Copy page from input to output
31 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
32
33 // Add text to page
34 AddStamp(outDoc, outPage, stampString);
35
36 // Add page to document
37 outDoc.Pages.Add(outPage);
38 }
39}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddStamp(Document outputDoc, Page outPage, string stampString)
2{
3 // Create content generator and text object
4 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
5 Text text = Text.Create(outputDoc);
6
7 // Create text generator
8 using (TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null))
9 {
10 // Calculate point and angle of rotation
11 Point rotationCenter = new Point
12 {
13 X = outPage.Size.Width / 2.0,
14 Y = outPage.Size.Height / 2.0
15 };
16 double rotationAngle = Math.Atan2(outPage.Size.Height,
17 outPage.Size.Width) / Math.PI * 180.0;
18
19 // Rotate textinput around the calculated position
20 AffineTransform trans = AffineTransform.Identity;
21 trans.Rotate(rotationAngle, rotationCenter);
22 gen.Transform(trans);
23
24 // Calculate position
25 Point position = new Point
26 {
27 X = (outPage.Size.Width - textgenerator.GetWidth(stampString)) / 2.0,
28 Y = (outPage.Size.Height - font.Ascent * fontSize) / 2.0
29 };
30
31 // Move to position
32 textgenerator.MoveTo(position);
33
34 // Set text paint
35 textgenerator.Fill = paint;
36
37 // Add given stamp string
38 textgenerator.ShowLine(stampString);
39 }
40 // Paint the positioned text
41 gen.PaintText(text);
42}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7 // Copy document-wide data
8 copyDocumentData(inDoc, outDoc);
9
10 // Create embedded font in output document
11 font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
12
13 // Get the color space
14 ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);
15
16 // Choose the RGB color value
17 double[] color = { 1.0, 0.0, 0.0 };
18 Transparency transparency = new Transparency(alpha);
19
20 // Create paint object
21 paint = Paint.create(outDoc, colorSpace, color, transparency);
22
23 // Define page copy options
24 PageCopyOptions copyOptions = new PageCopyOptions();
25
26 // Loop throw all pages of input
27 for (Page inPage : inDoc.getPages()) {
28 // Copy page from input to output
29 Page outPage = Page.copy(outDoc, inPage, copyOptions);
30
31 // Add text to page
32 addStamp(outDoc, outPage, stampString);
33
34 // Add page to document
35 outDoc.getPages().add(outPage);
36 }
37 }
38}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addStamp(Document outputDoc, Page outPage, String stampString)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outputDoc);
7 try (// Create text generator
8 TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
9 // Calculate point and angle of rotation
10 Point rotationCenter = new Point(outPage.getSize().width / 2.0, outPage.getSize().height / 2.0);
11
12 // Calculate rotation angle
13 double rotationAngle = Math.atan2(outPage.getSize().height, outPage.getSize().width) / Math.PI * 180.0;
14
15 // Rotate text input around the calculated position
16 AffineTransform trans = AffineTransform.getIdentity();
17 trans.rotate(rotationAngle, rotationCenter);
18 generator.transform(trans);
19
20 // Calculate position
21 Point position = new Point((outPage.getSize().width - textgenerator.getWidth(stampString)) / 2.0,
22 (outPage.getSize().height - font.getAscent() * fontSize) / 2.0);
23
24 // Move to position
25 textgenerator.moveTo(position);
26
27 // Set text paint
28 textgenerator.setFill(paint);
29
30 // Add given stamp string
31 textgenerator.showLine(stampString);
32 }
33
34 // Paint the positioned text
35 generator.paintText(text);
36 }
37}
Add text to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Configure copy options
29pCopyOptions = PtxPdf_PageCopyOptions_New();
30
31// Get page lists of input and output document
32pInPageList = PtxPdf_Document_GetPages(pInDoc);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
34 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
35 szErrorBuff, Ptx_GetLastError());
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40
41// Copy first page
42pInPage = PtxPdf_PageList_Get(pInPageList, 0);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
44 szErrorBuff, Ptx_GetLastError());
45pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
46GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
47 Ptx_GetLastError());
48
49// Add text to copied page
50if (addText(pOutDoc, pOutPage, szTextString, pFont, 15) != 0)
51 goto cleanup;
52
53// Add page to output document
54GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
55 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
56 szErrorBuff, Ptx_GetLastError());
57
58// Get remaining pages from input
59pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
60GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
61 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63
64// Copy remaining pages to output
65pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
67 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69
70// Add the copied pages to the output document
71GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
72 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
73 szErrorBuff, Ptx_GetLastError());
74
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addText(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szTextString, TPtxPdfContent_Font* pFont,
2 double dFontSize)
3{
4 TPtxPdfContent_Content* pContent = NULL;
5 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
6 TPtxPdfContent_Text* pText = NULL;
7 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
8 TPtxGeomReal_Size size;
9 TPtxGeomReal_Point position;
10 double dFontAscent;
11
12 pContent = PtxPdf_Page_GetContent(pOutPage);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content of output file. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Create content generator
17 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
18 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
19 szErrorBuff, Ptx_GetLastError());
20
21 // Create text object
22 pText = PtxPdfContent_Text_Create(pOutDoc);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
24 Ptx_GetLastError());
25
26 // Create a text generator
27 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, dFontSize, NULL);
28 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
29 szErrorBuff, Ptx_GetLastError());
30
31 // Get output page size
32 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
33 _T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
34 Ptx_GetLastError());
35
36 dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
37 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
38
39 // Calculate position
40 position.dX = dBorder;
41 position.dY = size.dHeight - dBorder - dFontSize * dFontAscent;
42
43 // Move to position
44 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
45 _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
46 Ptx_GetLastError());
47 // Add given text string
48 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szTextString),
49 _T("Failed to add text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
50 Ptx_GetLastError());
51 // Close text generator
52 PtxPdfContent_TextGenerator_Close(pTextGenerator);
53 pTextGenerator = NULL;
54
55 // Paint the positioned text
56 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
57 _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
58 Ptx_GetLastError());
59
60cleanup:
61 if (pTextGenerator != NULL)
62 PtxPdfContent_TextGenerator_Close(pTextGenerator);
63 if (pText != NULL)
64 Ptx_Release(pText);
65 if (pGenerator != NULL)
66 PtxPdfContent_ContentGenerator_Close(pGenerator);
67 if (pContent != NULL)
68 Ptx_Release(pContent);
69
70 return iReturnValue;
71}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Create a font
13 font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
14
15 // Define page copy options
16 PageCopyOptions copyOptions = new PageCopyOptions();
17
18 // Copy first page, add text, and append to output document
19 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
20 AddText(outDoc, outPage, textString);
21 outDoc.Pages.Add(outPage);
22
23 // Copy remaining pages and append to output document
24 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
25 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
26 outDoc.Pages.AddRange(copiedPages);
27}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddText(Document outputDoc, Page outPage, string textString)
2{
3 // Create content generator and text object
4 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
5 Text text = Text.Create(outputDoc);
6
7 // Create text generator
8 using (TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null))
9 {
10 // Calculate position
11 Point position = new Point
12 {
13 X = border,
14 Y = outPage.Size.Height - border - fontSize * font.Ascent
15 };
16
17 // Move to position
18 textGenerator.MoveTo(position);
19 // Add given text string
20 textGenerator.ShowLine(textString);
21 }
22 // Paint the positioned text
23 gen.PaintText(text);
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7 // Copy document-wide data
8 copyDocumentData(inDoc, outDoc);
9
10 // Create embedded font in output document
11 font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
12
13 // Define page copy options
14 PageCopyOptions copyOptions = new PageCopyOptions();
15
16 // Copy first page, add text, and append to output document
17 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
18 addText(outDoc, outPage, textString);
19 outDoc.getPages().add(outPage);
20
21 // Copy remaining pages and append to output document
22 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
23 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
24 outDoc.getPages().addAll(copiedPages);
25 }
26}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data (excluding metadata)
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Viewer settings
9 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
10
11 // Associated files (for PDF/A-3 and PDF 2.0 only)
12 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
13 for (FileReference inFileRef : inDoc.getAssociatedFiles())
14 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
15
16 // Plain embedded files
17 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
18 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
19 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
20}
1private static void addText(Document outputDoc, Page outPage, String textString)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outputDoc);
7
8 try (// Create a text generator
9 TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
10 // Calculate position
11 Point position = new Point(border, outPage.getSize().height - border - fontSize * font.getAscent());
12
13 // Move to position
14 textgenerator.moveTo(position);
15 // Add given text string
16 textgenerator.showLine(textString);
17 }
18
19 // Paint the positioned text
20 generator.paintText(text);
21 }
22}
1# Open input document
2with io.FileIO(input_file_path, 'rb') as input_file:
3 input_descriptor = StreamDescriptor(input_file)
4 input_document = pdf_document_open(input_descriptor, "")
5 if not input_document:
6 print(f"Input file {input_file_path} cannot be opened.")
7 exit(1)
8
9 # Create output document
10 with io.FileIO(output_file_path, 'wb+') as output_file:
11 output_descriptor = StreamDescriptor(output_file)
12 conformance = pdf_document_getconformance(input_document)
13 output_document = pdf_document_create(output_descriptor, conformance, None)
14 if not output_document:
15 print(f"Output file {output_file_path} cannot be created.")
16 exit(1)
17
18 # Create embedded font in output document
19 font = pdfcontent_font_createfromsystem(output_document, "Arial", "Italic", True)
20 if not font:
21 print("Failed to create font.")
22 exit(1)
23
24 # Copy document-wide data
25 if not copy_document_data(input_document, output_document):
26 print("Failed to copy document-wide data.")
27 exit(1)
28
29 # Configure copy options
30 copy_options = pdf_pagecopyoptions_new()
31
32 # Get page lists of input and output document
33 input_page_list = pdf_document_getpages(input_document)
34 if not input_page_list:
35 print("Failed to get the pages of the input document.")
36 exit(1)
37 output_page_list = pdf_document_getpages(output_document)
38 if not output_page_list:
39 print("Failed to get the pages of the output document.")
40 exit(1)
41
42 # Copy first page
43 input_page = pdf_pagelist_get(input_page_list, 0)
44 if not input_page:
45 print("Failed to get the first page.")
46 exit(1)
47 output_page = pdf_page_copy(output_document, input_page, copy_options)
48 if not output_page:
49 print("Failed to copy page.")
50 exit(1)
51
52 # Add text to copied page
53 if add_text(output_document, output_page, text_string, font, 15) != 0:
54 exit(1)
55
56 # Add page to output document
57 if not pdf_pagelist_add(output_page_list, output_page):
58 print("Failed to add page to output document.")
59 exit(1)
60
61 # Get remaining pages from input
62 input_page_range = pdf_pagelist_getrange(input_page_list, 1, pdf_pagelist_getcount(input_page_list) - 1)
63 if not input_page_range:
64 print("Failed to get page range from input document.")
65 exit(1)
66
67 # Copy remaining pages to output
68 output_page_range = pdf_pagelist_copy(output_document, input_page_range, copy_options)
69 if not output_page_range:
70 print("Failed to copy page range to output document.")
71 exit(1)
72
73 # Add the copied pages to the output document
74 if not pdf_pagelist_addrange(output_page_list, output_page_range):
75 print("Failed to add page range to output page list.")
76 exit(1)
77
78 pdf_document_close(output_document)
79 pdf_document_close(input_document)
80
1def copy_document_data(in_doc, out_doc):
2 # Copy document-wide data (excluding metadata)
3
4 # Output intent
5 if pdf_document_getoutputintent(in_doc) is not None:
6 if not pdf_document_setoutputintent(out_doc, pdfcontent_iccbasedcolorspace_copy(out_doc, pdf_document_getoutputintent(in_doc))):
7 return False
8
9 # Metadata
10 if not pdf_document_setmetadata(out_doc, pdf_metadata_copy(out_doc, pdf_document_getmetadata(in_doc))):
11 return False
12
13 # Viewer settings
14 if not pdf_document_setviewersettings(out_doc, pdfnav_viewersettings_copy(out_doc, pdf_document_getviewersettings(in_doc))):
15 return False
16
17 # Associated files (for PDF/A-3 and PDF 2.0 only)
18 in_file_ref_list = pdf_document_getassociatedfiles(in_doc)
19 out_file_ref_list = pdf_document_getassociatedfiles(out_doc)
20 if in_file_ref_list is None or out_file_ref_list is None:
21 return False
22 for i in range(pdf_filereferencelist_getcount(in_file_ref_list)):
23 file_ref = pdf_filereference_copy(out_doc, pdf_filereferencelist_get(in_file_ref_list, i))
24 if not pdf_filereferencelist_add(out_file_ref_list, file_ref):
25 return False
26
27 # Plain embedded files
28 in_file_ref_list = pdf_document_getplainembeddedfiles(in_doc)
29 out_file_ref_list = pdf_document_getplainembeddedfiles(out_doc)
30 if in_file_ref_list is None or out_file_ref_list is None:
31 return False
32 for i in range(pdf_filereferencelist_getcount(in_file_ref_list)):
33 file_ref = pdf_filereference_copy(out_doc, pdf_filereferencelist_get(in_file_ref_list, i))
34 if not pdf_filereferencelist_add(out_file_ref_list, file_ref):
35 return False
36
37 return True
38
1def add_text(out_doc, out_page, text_string, font, font_size):
2 border = 40.0
3 try:
4 content = pdf_page_getcontent(out_page)
5 if not content:
6 print("Failed to get content of output file.")
7 return 1
8
9 # Create content generator
10 generator = pdfcontent_contentgenerator_new(content, False)
11 if not generator:
12 print("Failed to create a content generator.")
13 return 1
14
15 # Create text object
16 text = pdfcontent_text_create(out_doc)
17 if not text:
18 print("Failed to create text object.")
19 return 1
20
21 # Create a text generator
22 text_generator = pdfcontent_textgenerator_new(text, font, font_size, None)
23 if not text_generator:
24 print("Failed to create a text generator.")
25 return 1
26
27 # Get output page size
28 size = GeomRealSize()
29 if not pdf_page_getsize(out_page, size):
30 print("Failed to read page size.")
31 return 1
32
33 font_ascent = pdfcontent_font_getascent(font)
34 if font_ascent == 0.0:
35 print("Failed to get font ascent.")
36 return 1
37
38 # Calculate position
39 position = GeomRealPoint()
40 position.x = border
41 position.y = size.height - border - font_size * font_ascent
42
43 # Move to position
44 if not pdfcontent_textgenerator_moveto(text_generator, position):
45 print("Failed to move to position.")
46 return 1
47
48 # Add given text string
49 if not pdfcontent_textgenerator_showline(text_generator, text_string):
50 print("Failed to add text string.")
51 return 1
52
53 # Close text generator
54 pdfcontent_textgenerator_close(text_generator)
55 text_generator = None
56
57 # Paint the positioned text
58 if not pdfcontent_contentgenerator_painttext(generator, text):
59 print("Failed to paint the positioned text.")
60 return 1
61
62 except Exception as e:
63 print(f"An error occurred: {e}")
64 return 1
65 finally:
66 if text_generator:
67 pdfcontent_textgenerator_close(text_generator)
68 if text:
69 release(text)
70 if generator:
71 pdfcontent_contentgenerator_close(generator)
72 if content:
73 release(content)
74
75 return 0
76
Add vector graphic to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Loop through all pages of input
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
33 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
34 szErrorBuff, Ptx_GetLastError());
35for (int iPage = 1; iPage <= PtxPdf_PageList_GetCount(pInPageList); iPage++)
36{
37 pInPage = PtxPdf_PageList_Get(pInPageList, iPage - 1);
38
39 // Copy page from input to output
40 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
41 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
42 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
43 szErrorBuff, Ptx_GetLastError());
44 PtxPdf_Page_GetSize(pOutPage, &size);
45
46 // Add text on first page
47 if (addLine(pOutDoc, pOutPage) == 1)
48 {
49 goto cleanup;
50 }
51
52 // Add page to output document
53 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
54 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
55 szErrorBuff, Ptx_GetLastError());
56
57 if (pOutPage != NULL)
58 {
59 Ptx_Release(pOutPage);
60 pOutPage = NULL;
61 }
62
63 if (pInPage != NULL)
64 {
65 Ptx_Release(pInPage);
66 pInPage = NULL;
67 }
68}
69
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addLine(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxPdfContent_Path* pPath = NULL;
6 TPtxPdfContent_PathGenerator* pPathGenerator = NULL;
7 TPtxPdfContent_ColorSpace* pDeviceRgbColorSpace = NULL;
8 double aColor[3];
9 TPtxPdfContent_Paint* pPaint = NULL;
10 TPtxPdfContent_Stroke* pStroke;
11 TPtxGeomReal_Size pageSize;
12 TPtxGeomReal_Point point;
13
14 pContent = PtxPdf_Page_GetContent(pOutPage);
15 PtxPdf_Page_GetSize(pOutPage, &pageSize);
16
17 // Create content generator
18 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
19 GOTO_CLEANUP_IF_NULL(pGenerator, szErrorBuff, Ptx_GetLastError());
20
21 // Create a path
22 pPath = PtxPdfContent_Path_New();
23 GOTO_CLEANUP_IF_NULL(pPath, szErrorBuff, Ptx_GetLastError());
24
25 // Create a path generator
26 pPathGenerator = PtxPdfContent_PathGenerator_New(pPath);
27 GOTO_CLEANUP_IF_NULL(pPathGenerator, szErrorBuff, Ptx_GetLastError());
28
29 // Draw a line diagonally across the page
30 point.dX = 10.0;
31 point.dY = 10.0;
32 GOTO_CLEANUP_IF_FALSE(PtxPdfContent_PathGenerator_MoveTo(pPathGenerator, &point), szErrorBuff, Ptx_GetLastError());
33 point.dX = pageSize.dWidth - 10.0;
34 point.dY = pageSize.dHeight - 10.0;
35 GOTO_CLEANUP_IF_FALSE(PtxPdfContent_PathGenerator_LineTo(pPathGenerator, &point), szErrorBuff, Ptx_GetLastError());
36
37 // Close the path generator in order to finish the path
38 PtxPdfContent_PathGenerator_Close(pPathGenerator);
39 pPathGenerator = NULL;
40
41 // Create a RGB color space
42 pDeviceRgbColorSpace =
43 PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
44 GOTO_CLEANUP_IF_NULL(pDeviceRgbColorSpace, szErrorBuff, Ptx_GetLastError());
45
46 // Initialize a red color
47 aColor[0] = 1.0;
48 aColor[1] = 0.0;
49 aColor[2] = 0.0;
50
51 // Create a paint
52 pPaint =
53 PtxPdfContent_Paint_Create(pOutDoc, pDeviceRgbColorSpace, aColor, sizeof(aColor) / sizeof(aColor[0]), NULL);
54 GOTO_CLEANUP_IF_NULL(pPaint, szErrorBuff, Ptx_GetLastError());
55
56 // Setup stroking parameters with given paint and line width
57 pStroke = PtxPdfContent_Stroke_New(pPaint, 10.0);
58 GOTO_CLEANUP_IF_NULL(pStroke, szErrorBuff, Ptx_GetLastError());
59
60 // Draw the path onto the page
61 GOTO_CLEANUP_IF_FALSE(PtxPdfContent_ContentGenerator_PaintPath(pGenerator, pPath, NULL, pStroke), szErrorBuff,
62 Ptx_GetLastError());
63
64cleanup:
65 if (pPathGenerator != NULL)
66 PtxPdfContent_PathGenerator_Close(pPathGenerator);
67 if (pGenerator != NULL)
68 PtxPdfContent_ContentGenerator_Close(pGenerator);
69 if (pContent != NULL)
70 Ptx_Release(pContent);
71
72 return iReturnValue;
73}
1// Open input document
2using (System.IO.Stream inStream = new System.IO.FileStream(inPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (System.IO.Stream outStream = new System.IO.FileStream(outPath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy all pages from input document
16 foreach (Page inPage in inDoc.Pages)
17 {
18 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
19
20 // Add a line
21 AddLine(outDoc, outPage);
22
23 // Add page to output document
24 outDoc.Pages.Add(outPage);
25 }
26}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddLine(Document document, Page page)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(page.Content, false);
5
6 // Create a path
7 Path path = new Path();
8 using (PathGenerator pathGenerator = new PathGenerator(path))
9 {
10 // Draw a line diagonally across the page
11 Size pageSize = page.Size;
12 pathGenerator.MoveTo(new Point() { X = 10.0, Y = 10.0 });
13 pathGenerator.LineTo(new Point() { X = pageSize.Width - 10.0, Y = pageSize.Height - 10.0 });
14 }
15
16 // Create a RGB color space
17 ColorSpace deviceRgbColorSpace = ColorSpace.CreateProcessColorSpace(document, ProcessColorSpaceType.Rgb);
18
19 // Create a red color
20 double[] color = new double[] { 1.0, 0.0, 0.0 };
21
22 // Create a paint
23 Paint paint = Paint.Create(document, deviceRgbColorSpace, color, null);
24
25 // Create stroking parameters with given paint and line width
26 Stroke stroke = new Stroke(paint, 10.0);
27
28 // Draw the path onto the page
29 generator.PaintPath(path, null, stroke);
30}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy all pages
15 for (Page inPage : inDoc.getPages()) {
16 // Copy page from input to output
17 Page outPage = Page.copy(outDoc, inPage, copyOptions);
18
19 // Add a line
20 addLine(outDoc, outPage);
21
22 // Add page to output document
23 outDoc.getPages().add(outPage);
24 }
25 }
26}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addLine(Document document, Page outPage)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5
6 // Create a path
7 Path path = new Path();
8 try (// Create a path generator
9 PathGenerator pathGenerator = new PathGenerator(path)) {
10 // Draw a line diagonally across the page
11 Size pageSize = outPage.getSize();
12 pathGenerator.moveTo(new Point(10.0, 10.0));
13 pathGenerator.lineTo(new Point(pageSize.width - 10.0, pageSize.height - 10.0));
14 }
15
16 // Create a RGB color space
17 ColorSpace deviceRgbColorSpace = ColorSpace.createProcessColorSpace(document, ProcessColorSpaceType.RGB);
18
19 // Create a red color
20 double[] color = new double[] { 1.0, 0.0, 0.0 };
21
22 // Create a paint
23 Paint paint = Paint.create(document, deviceRgbColorSpace, color, null);
24
25 // Create stroking parameters with given paint and line width
26 Stroke stroke = new Stroke(paint, 10.0);
27
28 // Draw the path onto the page
29 generator.paintPath(path, null, stroke);
30 }
31}
Layout text on PDF page
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.CreateNew, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, null, null))
4{
5 Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
6
7 // Create page
8 Page outPage = Page.Create(outDoc, PageSize);
9
10 // Add text as justified text
11 LayoutText(outDoc, outPage, textPath, font, 20);
12
13 // Add page to document
14 outDoc.Pages.Add(outPage);
15}
1private static void LayoutText(Document outputDoc, Page outPage, string textPath, Font font,
2 double fontSize)
3{
4 // Create content generator
5 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
6
7 // Create text object
8 Text text = Text.Create(outputDoc);
9
10 // Create text generator
11 using TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null);
12
13 // Calculate position
14 Point position = new Point
15 {
16 X = Border,
17 Y = outPage.Size.Height - Border
18 };
19
20 // Move to position
21 textGenerator.MoveTo(position);
22
23 // Loop throw all lines of the textinput
24 string[] lines = File.ReadAllLines(textPath, Encoding.Default);
25 foreach (string line in lines)
26 {
27 // Split string in substrings
28 string[] substrings = line.Split(new char[] { ' ' }, StringSplitOptions.None);
29 string currentLine = null;
30 double maxWidth = outPage.Size.Width - Border * 2;
31 int wordcount = 0;
32
33 // Loop throw all words of input strings
34 foreach (string word in substrings)
35 {
36 string tempLine;
37
38 // Concatenate substrings to line
39 if (currentLine != null)
40 tempLine = currentLine + " " + word;
41 else
42 tempLine = word;
43
44 // Calculate the current width of line
45 double width = textGenerator.GetWidth(currentLine);
46 if (textGenerator.GetWidth(tempLine) > maxWidth)
47 {
48 // Calculate the word spacing
49 textGenerator.WordSpacing = (maxWidth - width) / (wordcount - 1);
50 // Paint on new line
51 textGenerator.ShowLine(currentLine);
52 textGenerator.WordSpacing = 0;
53 currentLine = word;
54 wordcount = 1;
55 }
56 else
57 {
58 currentLine = tempLine;
59 wordcount++;
60 }
61 }
62 textGenerator.WordSpacing = 0;
63 // Add given stamp string
64 textGenerator.ShowLine(currentLine);
65 }
66 // Paint the positioned text
67 gen.PaintText(text);
68}
1try (
2 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
3 try (// Create output document
4 Document outDoc = Document.create(outStream, null, null)) {
5 // Create embedded font in output document
6 Font font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
7
8 // Create page
9 Page outPage = Page.create(outDoc, new Size(595, 842));
10
11 // Add text to document
12 layoutText(outDoc, outPage, textPath, font, 20);
13
14 // Add page to output document
15 outDoc.getPages().add(outPage);
16 }
17}
1private static void layoutText(Document outputDoc, Page outPage, String textPath, Font font, double fontSize)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outputDoc);
7
8 try (// Create a text generator
9 TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null)) {
10
11 // Calculate position
12 Point position = new Point(Border, outPage.getSize().height - Border);
13
14 // Move to position
15 textGenerator.moveTo(position);
16
17 // Loop throw all lines of the textinput
18 List<String> lines = Files.readAllLines(Paths.get(textPath), Charset.defaultCharset());
19 for (String line : lines) {
20 // Split string in substrings
21 String[] substrings = line.split(" ");
22 String currentLine = null;
23 double maxWidth = outPage.getSize().width - (Border * 2);
24
25 int wordCount = 0;
26
27 // Loop throw all words of input strings
28 for (String word : substrings) {
29 String tempLine;
30
31 // Concatenate substrings to line
32 if (currentLine != null) {
33 tempLine = currentLine + " " + word;
34 } else {
35 tempLine = word;
36 }
37
38 // Calculate the current width of line
39 double width = textGenerator.getWidth(currentLine);
40
41 if ((textGenerator.getWidth(tempLine) > maxWidth)) {
42 // Calculate the word spacing
43 textGenerator.setWordSpacing((maxWidth - width) / (double) (wordCount - 1));
44
45 // Paint on new line
46 textGenerator.showLine(currentLine);
47 textGenerator.setWordSpacing(0);
48 currentLine = word;
49 wordCount = 1;
50 } else {
51 currentLine = tempLine;
52 wordCount++;
53 }
54 }
55 textGenerator.setWordSpacing(0);
56 // Add given stamp string
57 textGenerator.showLine(currentLine);
58 }
59 }
60 // Paint the positioned text
61 generator.paintText(text);
62 }
63}
Stamp page number to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T(""), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Configure copy options
29pCopyOptions = PtxPdf_PageCopyOptions_New();
30
31// Copy all pages
32pInPageList = PtxPdf_Document_GetPages(pInDoc);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
34 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
35 szErrorBuff, Ptx_GetLastError());
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
41{
42 pInPage = PtxPdf_PageList_Get(pInPageList, iPage);
43
44 // Copy page from input to output
45 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
46 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
47 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
48 szErrorBuff, Ptx_GetLastError());
49 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
50 _T("Failed to get size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
51 Ptx_GetLastError());
52
53 // Stamp page number on current page of output document
54 if (addPageNumber(pOutDoc, pOutPage, pFont, iPage + 1) == 1)
55 {
56 goto cleanup;
57 }
58
59 // Add page to output document
60 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
61 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63
64 if (pOutPage != NULL)
65 {
66 Ptx_Release(pOutPage);
67 pOutPage = NULL;
68 }
69
70 if (pInPage != NULL)
71 {
72 Ptx_Release(pInPage);
73 pInPage = NULL;
74 }
75}
76
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addPageNumber(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TPtxPdfContent_Font* pFont, int nPageNumber)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxPdfContent_Text* pText = NULL;
6 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
7
8 pContent = PtxPdf_Page_GetContent(pOutPage);
9
10 // Create content generator
11 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
12 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
13 szErrorBuff, Ptx_GetLastError());
14
15 // Create text object
16 pText = PtxPdfContent_Text_Create(pOutDoc);
17 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
18 szErrorBuff, Ptx_GetLastError());
19
20 // Create a text generator with the given font, size and position
21 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, 8, NULL);
22 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
23 szErrorBuff, Ptx_GetLastError());
24
25 // Generate string to be stamped as page number
26 char szStampBuffer[50];
27 snprintf(szStampBuffer, sizeof(szStampBuffer), _T("Page %d"), nPageNumber);
28 TCHAR* szStampText = szStampBuffer;
29
30 double dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampText);
31 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("Failed to get text width. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
32 Ptx_GetLastError());
33
34 // Calculate position
35 TPtxGeomReal_Point position;
36 position.dX = (size.dWidth / 2) - (dTextWidth / 2);
37 position.dY = 10;
38
39 // Move to position
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
41 _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
42 Ptx_GetLastError());
43 // Add given text string
44 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szStampText),
45 _T("Failed to add given text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
46 Ptx_GetLastError());
47
48 // Close text generator
49 PtxPdfContent_TextGenerator_Close(pTextGenerator);
50 pTextGenerator = NULL;
51
52 // Paint the positioned text
53 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
54 _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
55 Ptx_GetLastError());
56
57cleanup:
58 if (pTextGenerator != NULL)
59 PtxPdfContent_TextGenerator_Close(pTextGenerator);
60 if (pGenerator != NULL)
61 PtxPdfContent_ContentGenerator_Close(pGenerator);
62 if (pText != NULL)
63 Ptx_Release(pText);
64 if (pContent != NULL)
65 Ptx_Release(pContent);
66
67 return iReturnValue;
68}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Create embedded font in output document
16 Font font = Font.CreateFromSystem(outDoc, "Arial", string.Empty, true);
17
18 // Copy all pages from input document
19 int currentPageNumber = 1;
20 foreach (Page inPage in inDoc.Pages)
21 {
22 // Copy page from input to output
23 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
24
25 // Stamp page number on current page of output document
26 AddPageNumber(outDoc, outPage, font, currentPageNumber++);
27
28 // Add page to output document
29 outDoc.Pages.Add(outPage);
30 }
31}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddPageNumber(Document outDoc, Page outPage, Font font, int pageNumber)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(outPage.Content, false);
5
6 // Create text object
7 Text text = Text.Create(outDoc);
8
9 // Create a text generator with the given font, size and position
10 using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
11 {
12 // Generate string to be stamped as page number
13 string stampText = string.Format("Page {0}", pageNumber);
14
15 // Calculate position for centering text at bottom of page
16 Point position = new Point
17 {
18 X = (outPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
19 Y = 10
20 };
21
22 // Position the text
23 textgenerator.MoveTo(position);
24 // Add page number
25 textgenerator.Show(stampText);
26 }
27 // Paint the positioned text
28 generator.PaintText(text);
29}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy pages from input to output
15 int pageNo = 1;
16
17 // Create embedded font in output document
18 Font font = Font.createFromSystem(outDoc, "Arial", "", true);
19
20 // Loop through all pages of input
21 for (Page inPage : inDoc.getPages()) {
22 // Copy page from input to output
23 Page outPage = Page.copy(outDoc, inPage, copyOptions);
24
25 // Stamp page number on current page of output document
26 applyStamps(outDoc, outPage, font, pageNo++);
27
28 // Add page to output document
29 outDoc.getPages().add(outPage);
30 }
31 }
32}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void applyStamps(Document doc, Page page, Font font, int pageNo) throws ToolboxException, IOException {
2
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(page.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(doc);
7
8 try (// Create a text generator with the given font, size and position
9 TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
10
11 // Generate string to be stamped as page number
12 String stampText = String.format("Page %d", pageNo);
13
14 // Calculate position for centering text at bottom of page
15 Point position = new Point((page.getSize().width / 2) - (textgenerator.getWidth(stampText) / 2), 10);
16
17 // Position the text
18 textgenerator.moveTo(position);
19 // Add page number
20 textgenerator.show(stampText);
21 }
22
23 // Paint the positioned text
24 generator.paintText(text);
25 }
26}
Content Modification
Remove glyphs
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Process each page
13 foreach (var inPage in inDoc.Pages)
14 {
15 // Create empty output page
16 Page outPage = Page.Create(outDoc, inPage.Size);
17 // Copy page content from input to output and remove glyphs
18 CopyContentAndRemoveGlyphs(inPage.Content, outPage.Content, outDoc);
19 // Add the new page to the output document's page list
20 outDoc.Pages.Add(outPage);
21 }
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CopyContentAndRemoveGlyphs(Content inContent, Content outContent, Document outDoc)
2{
3 // Use a content extractor and a content generator to copy content
4 ContentExtractor extractor = new ContentExtractor(inContent);
5 using ContentGenerator generator = new ContentGenerator(outContent, false);
6
7 // Iterate over all content elements
8 foreach (ContentElement inElement in extractor)
9 {
10 ContentElement outElement;
11 // Special treatment for group elements
12 if (inElement is GroupElement inGroupElement)
13 {
14 // Create empty output group element
15 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
16 outElement = outGroupElement;
17 // Call CopyContentAndRemoveGlyphs() recursively for the group element's content
18 CopyContentAndRemoveGlyphs(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
19 }
20 else
21 {
22 // Copy the content element to the output document
23 outElement = ContentElement.Copy(outDoc, inElement);
24 if (outElement is TextElement outTextElement)
25 {
26 // Special treatment for text element
27 Text text = outTextElement.Text;
28 // Remove the first two glyphs from each text fragment
29 foreach (var fragment in text)
30 {
31 // Ensure that the fragment has more than two glyphs
32 if (fragment.Count > 2)
33 {
34 // Call RemoveAt twice
35 fragment.RemoveAt(0);
36 fragment.RemoveAt(0);
37 }
38 }
39 }
40 }
41 // Append the finished output element to the content generator
42 generator.AppendContentElement(outElement);
43 }
44}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Process each page
12 for (Page inPage : inDoc.getPages()) {
13 // Create empty output page
14 Page outPage = Page.create(outDoc, inPage.getSize());
15 // Copy page content from input to output and remove glyphs
16 copyContentAndRemoveGlyphs(inPage.getContent(), outPage.getContent(), outDoc);
17 // Add the new page to the output document's page list
18 outDoc.getPages().add(outPage);
19 }
20 }
21}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void copyContentAndRemoveGlyphs(Content inContent, Content outContent, Document outDoc) throws ToolboxException, IOException {
2 // Use a content extractor and a content generator to copy content
3 ContentExtractor extractor = new ContentExtractor(inContent);
4 try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
5 // Iterate over all content elements
6 for (ContentElement inElement : extractor) {
7 ContentElement outElement = null;
8 // Special treatment for group elements
9 if (inElement instanceof GroupElement) {
10 GroupElement inGroupElement = (GroupElement)inElement;
11 // Create empty output group element
12 GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
13 outElement = outGroupElement;
14 // Call copyContentAndRemoveGlyphs() recursively for the group element's content
15 copyContentAndRemoveGlyphs(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
16 } else {
17 // Copy the content element to the output document
18 outElement = ContentElement.copy(outDoc, inElement);
19 if (outElement instanceof TextElement) {
20 // Special treatment for text element
21 TextElement outTextElement = (TextElement)outElement;
22 Text text = outTextElement.getText();
23 // Remove the first two glyphs from each text fragment
24 for (int iFragment = 0; iFragment < text.size(); ++iFragment) {
25 // Ensure that the fragment has more than two glyphs
26 if (text.get(iFragment).size() > 2) {
27 // Call remove twice
28 text.get(iFragment).remove(0);
29 text.get(iFragment).remove(0);
30 }
31 }
32 }
33 }
34 // Append the finished output element to the content generator
35 generator.appendContentElement(outElement);
36 }
37 }
38}
Remove White Text from PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Process each page
13 foreach (var inPage in inDoc.Pages)
14 {
15 // Create empty output page
16 Page outPage = Page.Create(outDoc, inPage.Size);
17 // Copy page content from input to output
18 CopyContent(inPage.Content, outPage.Content, outDoc);
19 // Add the new page to the output document's page list
20 outDoc.Pages.Add(outPage);
21 }
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CopyContent(Content inContent, Content outContent, Document outDoc)
2{
3 // Use a content extractor and a content generator to copy content
4 ContentExtractor extractor = new ContentExtractor(inContent);
5 using ContentGenerator generator = new ContentGenerator(outContent, false);
6
7 // Iterate over all content elements
8 foreach (ContentElement inElement in extractor)
9 {
10 ContentElement outElement;
11 // Special treatment for group elements
12 if (inElement is GroupElement inGroupElement)
13 {
14 // Create empty output group element
15 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
16 outElement = outGroupElement;
17 // Call CopyContent() recursively for the group element's content
18 CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
19 }
20 else
21 {
22 // Copy the content element to the output document
23 outElement = ContentElement.Copy(outDoc, inElement);
24 if (outElement is TextElement outTextElement)
25 {
26 // Special treatment for text element
27 Text text = outTextElement.Text;
28 // Remove all those text fragments whose fill and stroke paint is white
29 for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
30 {
31 TextFragment fragment = text[iFragment];
32 if ((fragment.Fill == null || IsWhite(fragment.Fill.Paint)) &&
33 (fragment.Stroke == null || IsWhite(fragment.Stroke.Paint)))
34 text.RemoveAt(iFragment);
35 }
36 // Prevent appending an empty text element
37 if (text.Count == 0)
38 outElement = null;
39 }
40 }
41 // Append the finished output element to the content generator
42 if (outElement != null)
43 generator.AppendContentElement(outElement);
44 }
45}
1private static bool IsWhite(Paint paint)
2{
3 ColorSpace colorSpace = paint.ColorSpace;
4 if (colorSpace is DeviceGrayColorSpace || colorSpace is CalibratedGrayColorSpace ||
5 colorSpace is DeviceRgbColorSpace || colorSpace is CalibratedRgbColorSpace)
6 {
7 // These color spaces are additive: white is 1.0
8 return paint.Color.Min() == 1.0;
9 }
10 if (colorSpace is DeviceCmykColorSpace)
11 {
12 // This color space is subtractive: white is 0.0
13 return paint.Color.Max() == 0.0;
14 }
15 return false;
16}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Process each page
12 for (Page inPage : inDoc.getPages()) {
13 // Create empty output page
14 Page outPage = Page.create(outDoc, inPage.getSize());
15 // Copy page content from input to output
16 copyContent(inPage.getContent(), outPage.getContent(), outDoc);
17 // Add page to output document
18 outDoc.getPages().add(outPage);
19 }
20 }
21}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void copyContent(Content inContent, Content outContent, Document outDoc) throws ToolboxException, IOException {
2 // Use a content extractor and a content generator to copy content
3 ContentExtractor extractor = new ContentExtractor(inContent);
4 try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
5 // Iterate over all content elements
6 for (ContentElement inElement : extractor) {
7 ContentElement outElement = null;
8 // Special treatment for group elements
9 if (inElement instanceof GroupElement) {
10 GroupElement inGroupElement = (GroupElement)inElement;
11 // Create empty output group element
12 GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
13 outElement = outGroupElement;
14 // Call copyContent() recursively for the group element's content
15 copyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
16 } else {
17 // Copy the content element to the output document
18 outElement = ContentElement.copy(outDoc, inElement);
19 if (outElement instanceof TextElement) {
20 // Special treatment for text element
21 TextElement outTextElement = (TextElement)outElement;
22 Text text = outTextElement.getText();
23 // Remove all those text fragments whose fill and stroke paint is white
24 for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
25 TextFragment fragment = text.get(iFragment);
26 if ((fragment.getFill() == null || isWhite(fragment.getFill().getPaint())) &&
27 (fragment.getStroke() == null || isWhite(fragment.getStroke().getPaint())))
28 text.remove(iFragment);
29 }
30 // Prevent appending an empty text element
31 if (text.size() == 0)
32 outElement = null;
33 }
34 }
35 // Append the finished output element to the content generator
36 if (outElement != null)
37 generator.appendContentElement(outElement);
38 }
39 }
40}
1private static boolean isWhite(Paint paint) {
2 double[] color = paint.getColor();
3 ColorSpace colorSpace = paint.getColorSpace();
4 if (colorSpace instanceof DeviceGrayColorSpace || colorSpace instanceof CalibratedGrayColorSpace ||
5 colorSpace instanceof DeviceRgbColorSpace || colorSpace instanceof CalibratedRgbColorSpace) {
6 // These color spaces are additive: white is 1.0
7 for (double value : color)
8 if (value != 1.0)
9 return false;
10 return true;
11 }
12 if (colorSpace instanceof DeviceCmykColorSpace) {
13 // This color space is subtractive: white is 0.0
14 for (double value : color)
15 if (value != 0.0)
16 return false;
17 return true;
18 }
19 return false;
20}
Replace Text Fragment in PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Process each page
13 foreach (var inPage in inDoc.Pages)
14 {
15 // Create empty output page
16 Page outPage = Page.Create(outDoc, inPage.Size);
17 // Copy page content from input to output and search for string
18 CopyContent(inPage.Content, outPage.Content, outDoc, searchString);
19 // If the text was found and deleted, add the replacement text
20 if (fragment != null)
21 AddText(outDoc, outPage, replString);
22 // Add the new page to the output document's page list
23 outDoc.Pages.Add(outPage);
24 }
25}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CopyContent(Content inContent, Content outContent, Document outDoc, string searchString)
2{
3 // Use a content extractor and a content generator to copy content
4 ContentExtractor extractor = new ContentExtractor(inContent);
5 using ContentGenerator generator = new ContentGenerator(outContent, false);
6
7 // Iterate over all content elements
8 foreach (ContentElement inElement in extractor)
9 {
10 ContentElement outElement;
11 // Special treatment for group elements
12 if (inElement is GroupElement inGroupElement)
13 {
14 // Create empty output group element
15 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
16 outElement = outGroupElement;
17 // Save transform for later restore
18 AffineTransform currentTransform = overallTransform;
19 // Update the transform
20 overallTransform.Concatenate(inGroupElement.Transform);
21 // Call CopyContent() recursively for the group element's content
22 CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc, searchString);
23 // Restore the transform
24 overallTransform = currentTransform;
25 }
26 else
27 {
28 // Copy the content element to the output document
29 outElement = ContentElement.Copy(outDoc, inElement);
30 if (fragment == null && outElement is TextElement outTextElement)
31 {
32 // Special treatment for text element
33 Text text = outTextElement.Text;
34 // Find text fragment with string to replace
35 for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
36 {
37 // In this sample, the fragment text must match in its entirety
38 if (text[iFragment].Text == searchString)
39 {
40 // Keep the found fragment for later use
41 fragment = text[iFragment];
42 // Update the transform
43 overallTransform.Concatenate(fragment.Transform);
44 // Remove the found text fragment from the output
45 text.RemoveAt(iFragment);
46 break;
47 }
48 }
49 // Prevent appending an empty text element
50 if (text.Count == 0)
51 outElement = null;
52 }
53 }
54 // Append the finished output element to the content generator
55 if (outElement != null)
56 generator.AppendContentElement(outElement);
57 }
58}
1private static void AddText(Document doc, Page page, string replString)
2{
3 // Create a new text object
4 Text text = Text.Create(doc);
5 // Heuristic to map the extracted font base name to a font name and font family
6 string[] parts = fragment.Font.BaseFont.Split('-');
7 string family = parts[0];
8 string style = parts.Length > 1 ? parts[1] : null;
9 // Create a new font object
10 Font font = Font.CreateFromSystem(doc, family, style, true);
11 // Create a text generator and set the original fragment's properties
12 using (TextGenerator textGenerator = new TextGenerator(text, font, fragment.FontSize, null))
13 {
14 textGenerator.CharacterSpacing = fragment.CharacterSpacing;
15 textGenerator.WordSpacing = fragment.WordSpacing;
16 textGenerator.HorizontalScaling = fragment.HorizontalScaling;
17 textGenerator.Rise = fragment.Rise;
18 textGenerator.Show(replString);
19 }
20 // Create a content generator
21 using ContentGenerator contentGenerator = new ContentGenerator(page.Content, false);
22 // Apply the computed transform
23 contentGenerator.Transform(overallTransform);
24 // Paint the new text
25 contentGenerator.PaintText(text);
26}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Process each page
12 for (Page inPage : inDoc.getPages()) {
13 // Create empty output page
14 Page outPage = Page.create(outDoc, inPage.getSize());
15 // Copy page content from input to output and search for string
16 copyContent(inPage.getContent(), outPage.getContent(), outDoc, searchString);
17 // If the text was found and deleted, add the replacement text
18 if (fragment != null)
19 addText(outDoc, outPage, replString);
20 // Add page to output document
21 outDoc.getPages().add(outPage);
22 }
23 }
24}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void copyContent(Content inContent, Content outContent, Document outDoc, String searchString) throws ToolboxException, IOException {
2 // Use a content extractor and a content generator to copy content
3 ContentExtractor extractor = new ContentExtractor(inContent);
4 try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
5 // Iterate over all content elements
6 for (ContentElement inElement : extractor) {
7 ContentElement outElement = null;
8 // Special treatment for group elements
9 if (inElement instanceof GroupElement) {
10 GroupElement inGroupElement = (GroupElement)inElement;
11 // Create empty output group element
12 GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
13 outElement = outGroupElement;
14 // Save transform for later restor
15 AffineTransform currentTransform = overallTransform;
16 // Update the transform
17 overallTransform.concatenate(inGroupElement.getTransform());
18 // Call copyContent() recursively for the group element's content
19 copyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc, searchString);
20 // Restor the transform
21 overallTransform = currentTransform;
22 } else {
23 // Copy the content element to the output document
24 outElement = ContentElement.copy(outDoc, inElement);
25 if (fragment == null && outElement instanceof TextElement) {
26 // Special treatment for text element
27 TextElement outTextElement = (TextElement)outElement;
28 Text text = outTextElement.getText();
29 // Find text fragment with string to replace
30 for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
31 // In this sample, the fragment text must match in its entirety
32 if (text.get(iFragment).getText().equals(searchString)) {
33 // Keep the found fragment for later use
34 fragment = text.get(iFragment);
35 // Update the transform
36 overallTransform.concatenate(fragment.getTransform());
37 // Remove the found text fragment from the output
38 text.remove(iFragment);
39 break;
40 }
41 }
42 // Prevent appending an empty text element
43 if (text.size() == 0)
44 outElement = null;
45 }
46 }
47 // Append the finished output element to the content generator
48 if (outElement != null)
49 generator.appendContentElement(outElement);
50 }
51 }
52}
1private static void addText(Document doc, Page page, String replString) throws CorruptException, ToolboxException, IOException {
2 // Create a new text object
3 Text text = Text.create(doc);
4 // Heuristic to map the extracted fon base name to a font family and font style
5 String[] parts = fragment.getFont().getBaseFont().split("-");
6 String family = parts[0];
7 String style = parts.length > 1 ? parts[1] : null;
8 // Create a new font object
9 Font font = Font.createFromSystem(doc, family, style, true);
10 // Create a text generator and set the original fragment's properties
11 try (TextGenerator textGenerator = new TextGenerator(text, font, fragment.getFontSize(), null)) {
12 textGenerator.setCharacterSpacing(fragment.getCharacterSpacing());
13 textGenerator.setWordSpacing(fragment.getWordSpacing());
14 textGenerator.setHorizontalScaling(fragment.getHorizontalScaling());
15 textGenerator.setRise(fragment.getRise());
16 textGenerator.show(replString);
17 }
18 // Create a content generator
19 try (ContentGenerator contentGenerator = new ContentGenerator(page.getContent(), false)) {
20 // Apply the computed transform
21 contentGenerator.transform(overallTransform);
22 // Paint the new text
23 contentGenerator.paintText(text);
24 }
25}
Custom Validation
Validate custom properties of a PDF file
1var iniFile = new IniFile(args[1]);
2var password = args.Length == 3 ? args[2] : null;
3var documentValidator = new DocumentValidator(iniFile, args[0], password);
4
5try
6{
7 if (documentValidator.ValidateDocument())
8 Console.WriteLine("\nThe document does conform the specified properties.");
9 else
10 Console.WriteLine("\nThe document does not conform the specified properties.");
11}
12catch (Exception ex)
13{
14 Console.WriteLine("The document could not be validated. The following error happened: " + ex.Message);
15 return;
16}
1public class IniFile
2{
3 private Dictionary<string, Dictionary<string, string>> _data;
4
5 public IniFile(string path)
6 {
7 _data = new Dictionary<string, Dictionary<string, string>>();
8 Load(path);
9 }
10
11 private void Load(string path)
12 {
13 var lines = File.ReadAllLines(path);
14 var currentSection = "";
15
16 foreach (var line in lines)
17 {
18 var trimmedLine = line.Trim();
19
20 if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(";") || trimmedLine.StartsWith("#"))
21 {
22 continue; // Skip empty lines and comments
23 }
24
25 if (trimmedLine.StartsWith("[") && trimmedLine.EndsWith("]"))
26 {
27 currentSection = trimmedLine.Substring(1, trimmedLine.Length - 2).Trim();
28 if (!_data.ContainsKey(currentSection))
29 {
30 _data[currentSection] = new Dictionary<string, string>();
31 }
32 else
33 {
34 throw new FormatException("Duplicate section: " + currentSection);
35 }
36 }
37 else if (currentSection != null)
38 {
39 var keyValuePair = trimmedLine.Split(new[] { '=' });
40 if (keyValuePair.Length == 2)
41 {
42 var key = keyValuePair[0].Trim();
43 var value = keyValuePair[1].Trim();
44 _data[currentSection][key] = value;
45 }
46 }
47 }
48 }
49
50 public string? GetValue(string section, string key, string? defaultValue = null)
51 {
52 if (_data.TryGetValue(section, out var sectionData))
53 {
54 if (sectionData.TryGetValue(key, out var value))
55 {
56 return value;
57 }
58 }
59 return defaultValue;
60 }
61
62 public List<string> GetKeysMatchingPattern(string section, string pattern)
63 {
64 var matchingKeys = new List<string>();
65
66 if (_data.TryGetValue(section, out var sectionData))
67 {
68 foreach (var key in sectionData.Keys)
69 {
70 if (Regex.IsMatch(key, pattern, RegexOptions.IgnoreCase))
71 {
72 matchingKeys.Add(sectionData[key]);
73 }
74 }
75 }
76
77 return matchingKeys;
78 }
79}
1public class DocumentValidator
2{
3 private readonly IniFile _iniFile;
4 private readonly string _inputPath;
5 private readonly string? _pdfPassword;
6
7 // Tolerance used for size comparison: default 3pt
8 private string _sizeTolerance = "3.0";
9 private string? _iniMaxPageSize;
10 private string? _iniMaxPdfVersionStr;
11 private string? _iniEncryption;
12 private string? _iniFileSize;
13 private string? _iniEmbedding;
14 private readonly List<string> _embeddingExceptionFonts;
15
16 public DocumentValidator(IniFile iniFile, string inputPath, string? pdfPassword = null)
17 {
18 _iniFile = iniFile;
19 _inputPath = inputPath;
20 _pdfPassword = pdfPassword;
21
22 // Extract values from INI file
23 string? iniSizeTolerance = iniFile.GetValue("Pages", "SizeTolerance");
24 _sizeTolerance = !string.IsNullOrEmpty(iniSizeTolerance) ? iniSizeTolerance : _sizeTolerance;
25 _iniMaxPageSize = _iniFile.GetValue("Pages", "MaxPageSize");
26 _iniMaxPdfVersionStr = _iniFile.GetValue("File", "MaxPdfVersion");
27 _iniEncryption = _iniFile.GetValue("File", "Encryption");
28 _iniFileSize = _iniFile.GetValue("File", "FileSize");
29 _iniEmbedding = _iniFile.GetValue("Fonts", "Embedding");
30 _embeddingExceptionFonts = _iniFile.GetKeysMatchingPattern("Fonts", @"EmbeddingExcFont\d+");
31 }
32
33 public bool ValidateDocument()
34 {
35 var isValid = ValidateFileSize(_inputPath);
36
37 try
38 {
39 using var inpath = File.OpenRead(_inputPath);
40 using var inDocumentToolbox = Document.Open(inpath, _pdfPassword);
41
42 isValid &= ValidateConformance(inDocumentToolbox.Conformance);
43 isValid &= ValidateEncryption(inDocumentToolbox.Permissions);
44 isValid &= ValidatePagesSize(inDocumentToolbox);
45 isValid &= ValidateFonts(inDocumentToolbox);
46 }
47 catch (PasswordException)
48 {
49 if (_pdfPassword == null)
50 Console.WriteLine("The content of the document could not be validated as it is password protected. Please provide a password.");
51 else
52 Console.WriteLine("The content of the document could not be validated as the password provided is not correct.");
53
54 return false;
55 }
56
57 return isValid;
58 }
59
60 private bool ValidateFileSize(string inputPath)
61 {
62 var fileInfo = new FileInfo(inputPath);
63 var fileSizeInMB = fileInfo.Length / (1024.0 * 1024.0);
64
65 if (_iniFileSize != null)
66 {
67 var iniFileSizeInMB = Convert.ToDouble(_iniFileSize);
68 if (fileSizeInMB <= iniFileSizeInMB)
69 {
70 Console.WriteLine("The PDF file size does not exceed the specified custom limit.");
71
72 return true;
73 }
74 else
75 {
76 Console.WriteLine("The PDF file size exceeds the specified custom limit.");
77
78 return false;
79 }
80 }
81
82 return true;
83 }
84
85 private bool ValidateConformance(Conformance currentConformance)
86 {
87 if (_iniMaxPdfVersionStr != null)
88 {
89 if (ConformanceValidator.ValidateConformance(_iniMaxPdfVersionStr, currentConformance))
90 {
91 Console.WriteLine("The PDF version does not exceed the specified custom maximum version.");
92
93 return true;
94 }
95 else
96 {
97 Console.WriteLine("The PDF version exceeds the specified custom maximum version.");
98
99 return false;
100 }
101 }
102
103 return true;
104 }
105
106 private bool ValidateEncryption(Permission? permissions)
107 {
108 if (_iniEncryption != null)
109 {
110 if (_iniEncryption.ToLower() == "true" && permissions == null)
111 {
112 Console.WriteLine("Encryption not conform: the PDF file is not encrypted. The custom encryption value specifies that the PDF file should be encrypted.");
113
114 return false;
115 }
116 else if (_iniEncryption.ToLower() == "false" && permissions != null)
117 {
118 Console.WriteLine("Encryption not conform: the PDF file is encrypted. The custom encryption value specifies that the PDF file should not be encrypted.");
119
120 return false;
121 }
122 else
123 {
124 Console.WriteLine("The PDF encryption is conform to the specified custom value.");
125
126 return true;
127 }
128 }
129
130 return true;
131 }
132
133 private bool ValidatePagesSize(Document inDocToolbox)
134 {
135 var isValid = true;
136
137 if (_iniMaxPageSize != null)
138 {
139 var pageNumber = 0;
140 foreach (var page in inDocToolbox.Pages)
141 {
142 pageNumber++;
143 var sizeWithInt = new Size { Width = (int)page.Size.Width, Height = (int)page.Size.Height };
144
145 isValid &= ValidatePageSize(pageNumber, sizeWithInt);
146 }
147 }
148
149 return isValid;
150 }
151
152 private bool ValidatePageSize(int pageNumber, Size pageSize)
153 {
154 if (_iniMaxPageSize != null)
155 {
156 var validator = new PageSizeValidator(_iniMaxPageSize, _sizeTolerance);
157 if (validator.ValidatePageSize(pageNumber, pageSize))
158 {
159 Console.WriteLine("The size of page " + pageNumber + " is within the specified custom maximum page size value.");
160
161 return true;
162 }
163 else
164 {
165 Console.WriteLine("The size of page " + pageNumber + " exceeds the specified custom maximum page size value.");
166
167 return false;
168 }
169 }
170
171 return true;
172 }
173
174 private bool ValidateFonts(Document inDocumentToolbox)
175 {
176 var isValid = true;
177
178 if (_iniEmbedding != null)
179 {
180 var embeddingRequired = _iniEmbedding.ToLower() == "true";
181 var pageNumber = 0;
182
183 foreach (var page in inDocumentToolbox.Pages)
184 {
185 pageNumber++;
186 var extractor = new ContentExtractor(page.Content)
187 {
188 Ungrouping = UngroupingSelection.SafelyUngroupable
189 };
190
191 foreach (ContentElement element in extractor)
192 {
193 if (element is TextElement textElement)
194 {
195 foreach (var fragment in textElement.Text)
196 {
197 var fontName = fragment.Font.BaseFont;
198 var isEmbedded = fragment.Font.IsEmbedded;
199
200 // Check if the font is in the exception list
201 var isCurrentFontAnException = _embeddingExceptionFonts.Exists(exception => Regex.IsMatch(fontName, exception.Replace("*", ".*"), RegexOptions.IgnoreCase));
202
203 // Validate based on the embedding setting
204 // _iniEmbedding = true => The font has to be embedded or it should appear in the exception list
205 // _iniEmbedding = false => The font cannot be embedded or it should appear in the exception list
206 if ((embeddingRequired && !isEmbedded && !isCurrentFontAnException) || (!embeddingRequired && isEmbedded && !isCurrentFontAnException))
207 {
208 isValid = false;
209 var statusText = embeddingRequired ? "be embedded" : "not be embedded";
210 Console.WriteLine("The font '" + fontName + "' on page " + pageNumber + " should " + statusText + " as specified by the property 'Embedding' or it should be added to the list of exceptions.");
211 }
212 else
213 {
214 var statusText = embeddingRequired != isEmbedded ? "in the exception list" : isEmbedded ? "embedded" : "not embedded";
215 Console.WriteLine("The font '" + fontName + "' on page " + pageNumber + " is conform to the 'Embedding' property as it is " + statusText + ".");
216 }
217 }
218 }
219 }
220 }
221 }
222
223 return isValid;
224 }
225}
1public class PageSizeValidator
2{
3 private readonly Size maxSize;
4 private readonly double sizeTolerance;
5
6 // Named page sizes like "Letter", "A4", etc.
7 private static readonly Dictionary<string, Size> NamedPageSizes = new Dictionary<string, Size>(StringComparer.OrdinalIgnoreCase)
8{
9 { "Letter", new Size { Width = 612, Height = 792 } }, // 8.5 x 11 inches in points
10 { "A0", new Size { Width = 2384, Height = 3370 } },
11 { "A1", new Size { Width = 1684, Height = 2384 } },
12 { "A2", new Size { Width = 1191, Height = 1684 } },
13 { "A3", new Size { Width = 842, Height = 1191 } },
14 { "A4", new Size { Width = 595, Height = 842 } }, // 210 x 297 mm in points
15 { "A5", new Size { Width = 420, Height = 595 } },
16 { "A6", new Size { Width = 298, Height = 420 } },
17 { "A7", new Size { Width = 210, Height = 298 } },
18 { "A8", new Size { Width = 147, Height = 210 } },
19 { "A9", new Size { Width = 105, Height = 147 } },
20 { "A10", new Size { Width = 74, Height = 105 } },
21 { "DL", new Size { Width = 283, Height = 595 } } // 99 x 210 mm in points
22};
23
24 public PageSizeValidator(string maxPageSizeStr, string sizeToleranceStr)
25 {
26 maxSize = ParsePageSize(maxPageSizeStr);
27 sizeTolerance = ParseSizeTolerance(sizeToleranceStr);
28 }
29
30 private Size ParsePageSize(string maxPageSize)
31 {
32 // First, check if it's a named size
33 if (NamedPageSizes.TryGetValue(maxPageSize, out var namedSize))
34 {
35 return namedSize;
36 }
37
38 // If not a named size, try to parse it as a custom size
39 var match = Regex.Match(maxPageSize, @"(\d+(\.\d+)?)\s*x\s*(\d+(\.\d+)?)(\s*(pt|in|cm|mm))?", RegexOptions.IgnoreCase);
40 if (!match.Success) throw new ArgumentException("Invalid MaxPageSize format: " + maxPageSize);
41
42 double width = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
43 double height = double.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);
44 string unit = match.Groups[6].Value.ToLower();
45
46 return unit switch
47 {
48 "in" => new Size { Width = (int)(width * 72), Height = (int)(height * 72) },
49 "cm" => new Size { Width = (int)(width * 28.3465), Height = (int)(height * 28.3465) },
50 "mm" => new Size { Width = (int)(width * 2.83465), Height = (int)(height * 2.83465) },
51 "pt" or "" => new Size { Width = (int)width, Height = (int)height },
52 _ => throw new ArgumentException("Unsupported unit: " + unit),
53 };
54 }
55
56 private double ParseSizeTolerance(string sizeToleranceStr)
57 {
58 if (string.IsNullOrEmpty(sizeToleranceStr)) return 3; // Default tolerance in points
59
60 var match = Regex.Match(sizeToleranceStr, @"(\d+(\.\d+)?)\s*(%)?", RegexOptions.IgnoreCase);
61 if (!match.Success) throw new ArgumentException("Invalid SizeTolerance format: " + sizeToleranceStr);
62
63 double value = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
64 return match.Groups[3].Success ? value / 100.0 : value; // Percentage tolerance or direct value
65 }
66
67 public bool ValidatePageSize(int pageNumber, Size actualSize)
68 {
69 // Check both portrait and landscape orientations
70 bool isValid = (actualSize.Width <= maxSize.Width + sizeTolerance && actualSize.Height <= maxSize.Height + sizeTolerance) ||
71 (actualSize.Height <= maxSize.Width + sizeTolerance && actualSize.Width <= maxSize.Height + sizeTolerance);
72
73 return isValid;
74 }
75}
1public class ConformanceValidator
2{
3 private static readonly Dictionary<string, Conformance> VersionMap = new Dictionary<string, Conformance>(StringComparer.OrdinalIgnoreCase)
4 {
5 { "1.0", Conformance.Pdf10 },
6 { "1.1", Conformance.Pdf11 },
7 { "1.2", Conformance.Pdf12 },
8 { "1.3", Conformance.Pdf13 },
9 { "1.4", Conformance.Pdf14 },
10 { "1.5", Conformance.Pdf15 },
11 { "1.6", Conformance.Pdf16 },
12 { "1.7", Conformance.Pdf17 },
13 { "2.0", Conformance.Pdf20 }
14 };
15
16 public static Conformance ParseVersionString(string version)
17 {
18 // Split the version string into parts based on the '.' delimiter
19 string[] versionParts = version.Split('.');
20
21 // Ensure there are only two parts (major and minor)
22 if (versionParts.Length == 2)
23 {
24 // Construct the major.minor version string (e.g., "1.7")
25 string majorMinorVersion = versionParts[0] + "." + versionParts[1];
26
27 // Try to get the corresponding Conformance enum value from the dictionary
28 if (VersionMap.TryGetValue(majorMinorVersion, out Conformance conformance))
29 {
30 return conformance;
31 }
32 }
33
34 // If the version is not supported, throw an exception
35 throw new ArgumentException("Unsupported version or conformance level: " + version);
36 }
37
38 public static bool ValidateConformance(string maxPdfVersionStr, Conformance currentConformance)
39 {
40 var maxPdfConformance = ParseVersionString(maxPdfVersionStr);
41 // Convert the current conformance level to the corresponding PDF version (Major.Minor) as it can be based on the PDF/A version
42 var currentConformanceVersion = GetVersionFromConformance(currentConformance);
43
44 return (int)currentConformanceVersion <= (int)maxPdfConformance;
45 }
46
47 public static Conformance GetVersionFromConformance(Conformance conformance)
48 {
49 if (VersionMap.ContainsValue(conformance))
50 {
51 return conformance;
52 }
53
54 switch (conformance)
55 {
56 case Conformance.PdfA1A:
57 case Conformance.PdfA1B:
58 return Conformance.Pdf14; // PDF/A-1 is based on PDF 1.4
59
60 case Conformance.PdfA2A:
61 case Conformance.PdfA2B:
62 case Conformance.PdfA2U:
63 case Conformance.PdfA3A:
64 case Conformance.PdfA3B:
65 case Conformance.PdfA3U:
66 return Conformance.Pdf17; // PDF/A-2 and PDF/A-3 are based on PDF 1.7
67
68 default:
69 throw new ArgumentException("Unsupported conformance level: " + conformance.ToString());
70 }
71 }
72}
1String pdfPath = args[0];
2String iniPath = args[1];
3String password = null;
4if (args.length == 3)
5 password = args[2];
6
7IniFile iniFile = new IniFile(iniPath);
8DocumentValidator documentValidator = new DocumentValidator(iniFile, pdfPath, password);
9
10try {
11 if (documentValidator.validateDocument())
12 System.out.println("\nThe document does conform the specified properties.");
13 else
14 System.out.println("\nThe document does not conform the specified properties.");
15}
16catch(Exception e) {
17 System.out.println("The document could not be validated. The following error happened: " + e.getMessage());
18
19 System.exit(-1);
20}
21
1public static class IniFile {
2 private final Map<String, Map<String, String>> sections = new LinkedHashMap<>();
3
4 public IniFile(String path) throws IOException {
5 load(path);
6 }
7
8 private void load(String path) throws IOException {
9 try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
10 String currentSection = null;
11 String line;
12
13 while ((line = reader.readLine()) != null) {
14 line = line.trim();
15
16 if (line.isEmpty() || line.startsWith(";") || line.startsWith("#")) {
17 // Skip empty lines and comments
18 continue;
19 }
20
21 if (line.startsWith("[") && line.endsWith("]")) {
22 // New section
23 currentSection = line.substring(1, line.length() - 1).trim();
24 sections.putIfAbsent(currentSection, new LinkedHashMap<>());
25 } else if (currentSection != null) {
26 // Key-value pair within a section
27 String[] keyValue = line.split("=", 2);
28 if (keyValue.length == 2) {
29 sections.get(currentSection).put(keyValue[0].trim(), keyValue[1].trim());
30 }
31 }
32 }
33 }
34 }
35
36 public String getValue(String section, String key, String defaultValue) {
37 Map<String, String> sectionData = sections.get(section);
38 if (sectionData != null) {
39 return sectionData.getOrDefault(key, defaultValue);
40 }
41 return defaultValue;
42 }
43
44 public String getValue(String section, String key) {
45 return getValue(section, key, null);
46 }
47
48 public List<String> getKeysMatchingPattern(String section, String pattern) {
49 List<String> matchingKeys = new ArrayList<>();
50
51 Map<String, String> sectionData = sections.get(section);
52 if (sectionData != null) {
53 Pattern regexPattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
54 for (String key : sectionData.keySet()) {
55 Matcher matcher = regexPattern.matcher(key);
56 if (matcher.find()) {
57 matchingKeys.add(sectionData.get(key));
58 }
59 }
60 }
61
62 return matchingKeys;
63 }
64}
1 public static class DocumentValidator {
2
3 private final String inputPath;
4 private String pdfPassword;
5
6 // Tolerance used for size comparison: default 3pt
7 private String sizeTolerance = "3.0";
8 private String iniMaxPageSize;
9 private String iniMaxPdfVersionStr;
10 private String iniEncryption;
11 private String iniFileSize;
12 private String iniEmbedding;
13 private final List<String> embeddingExceptionFonts;
14
15
16 public DocumentValidator(IniFile iniFile, String inputPath, String pdfPassword) {
17 this.inputPath = inputPath;
18 this.pdfPassword = pdfPassword;
19
20 // Extract values from INI file
21 String iniSizeTolerance = iniFile.getValue("Pages", "SizeTolerance");
22 this.sizeTolerance = (iniSizeTolerance != null && !iniSizeTolerance.isEmpty()) ? iniSizeTolerance : this.sizeTolerance;
23 this.iniMaxPageSize = iniFile.getValue("Pages", "MaxPageSize");
24 this.iniMaxPdfVersionStr = iniFile.getValue("File", "MaxPdfVersion");
25 this.iniEncryption = iniFile.getValue("File", "Encryption");
26 this.iniFileSize = iniFile.getValue("File", "FileSize");
27 this.iniEmbedding = iniFile.getValue("Fonts", "Embedding");
28 this.embeddingExceptionFonts = iniFile.getKeysMatchingPattern("Fonts", "EmbeddingExcFont\\d+");
29 }
30
31 public boolean validateDocument() throws IOException, CorruptException, ConformanceException, UnsupportedFeatureException, ToolboxException {
32 boolean isValid = validateFileSize(inputPath);
33
34 try (FileStream inStream = new FileStream(inputPath, FileStream.Mode.READ_ONLY);
35 Document inDocToolbox = Document.open(inStream, pdfPassword)) {
36
37 isValid &= validateConformance(inDocToolbox.getConformance());
38 isValid &= validateEncryption(inDocToolbox.getPermissions());
39 isValid &= validatePagesSize(inDocToolbox);
40 isValid &= validateFonts(inDocToolbox);
41 }
42 catch(PasswordException e) {
43 if (pdfPassword == null)
44 System.out.println("The content of the document could not be validated as it is password protected. Please provide a password.");
45 else
46 System.out.println("The content of the document could not be validated as the password provided is not correct.");
47
48 return false;
49 }
50
51 return isValid;
52 }
53
54 private boolean validateFileSize(String inputPath) {
55 File file = new File(inputPath);
56 double fileSizeInMB = file.length() / (1024.0 * 1024.0);
57
58 if (iniFileSize != null) {
59 double iniFileSizeInMB = Double.parseDouble(iniFileSize);
60 if (fileSizeInMB <= iniFileSizeInMB) {
61 System.out.println("The PDF file size does not exceed the specified custom limit.");
62 return true;
63 } else {
64 System.out.println("The PDF file size exceeds the specified custom limit.");
65 return false;
66 }
67 }
68 return true;
69 }
70
71 private boolean validateConformance(Conformance currentConformance) {
72 if (iniMaxPdfVersionStr != null) {
73 if (ConformanceValidator.validateConformance(iniMaxPdfVersionStr, currentConformance)) {
74 System.out.println("The PDF version does not exceed the specified custom maximum version.");
75 return true;
76 } else {
77 System.out.println("The PDF version exceeds the specified custom maximum version.");
78 return false;
79 }
80 }
81
82 return true;
83 }
84
85 private boolean validateEncryption(EnumSet<Permission> enumSet) {
86 if (iniEncryption != null) {
87 boolean isEncrypted = enumSet != null;
88
89 if ("true".equalsIgnoreCase(iniEncryption) && !isEncrypted) {
90 System.out.println("Encryption not conform: the PDF file is not encrypted. The custom encryption value specifies that the PDF file should be encrypted.");
91 return false;
92 } else if ("false".equalsIgnoreCase(iniEncryption) && isEncrypted) {
93 System.out.println("Encryption not conform: the PDF file is encrypted. The custom encryption value specifies that the PDF file should not be encrypted.");
94 return false;
95 } else {
96 System.out.println("The PDF encryption is conform to the specified custom value.");
97 return true;
98 }
99 }
100 return true;
101 }
102
103 private boolean validatePagesSize(Document inDocToolbox) {
104 boolean isValid = true;
105
106 if (iniMaxPageSize != null) {
107 int pageNumber = 0;
108 for (Page page : inDocToolbox.getPages()) {
109 pageNumber++;
110 com.pdftools.toolbox.geometry.real.Size pageSize = page.getSize();
111 isValid &= validatePageSize(pageNumber, pageSize);
112 }
113 }
114
115 return isValid;
116 }
117
118 private boolean validatePageSize(int pageNumber, com.pdftools.toolbox.geometry.real.Size pageSize) {
119 if (iniMaxPageSize != null) {
120 PageSizeValidator validator = new PageSizeValidator(iniMaxPageSize, sizeTolerance);
121 if (validator.validatePageSize(pageSize.getWidth(), pageSize.getHeight())) {
122 System.out.println(String.format("The size of page %d is within the specified custom maximum page size value.", pageNumber));
123 return true;
124 } else {
125 System.out.println(String.format("The size of page %d exceeds the specified custom maximum page size value.", pageNumber));
126 return false;
127 }
128 }
129
130 return true;
131 }
132
133 public boolean validateFonts(Document inDocumentToolbox) throws CorruptException, IOException {
134 boolean isValid = true;
135
136 if (iniEmbedding != null)
137 {
138 boolean embeddingRequired = "true".equalsIgnoreCase(iniEmbedding);
139 int pageNumber = 0;
140
141 for (Page page : inDocumentToolbox.getPages()) {
142 pageNumber++;
143 ContentExtractor extractor = new ContentExtractor(page.getContent());
144 extractor.setUngrouping(UngroupingSelection.ALL);
145
146 for (ContentElement element : extractor) {
147 if (element instanceof TextElement) {
148 TextElement textElement = (TextElement) element;
149 Text text = textElement.getText();
150
151 for (int iFragment = 0; iFragment < text.size(); iFragment++) {
152 TextFragment currFragment = text.get(iFragment);
153 String fontName = currFragment.getFont().getBaseFont();
154 boolean isEmbedded = currFragment.getFont().getIsEmbedded();
155
156 // Check if the font is in the exception list
157 boolean isCurrentFontAnException = embeddingExceptionFonts.stream()
158 .anyMatch(exception -> Pattern.compile(exception.replace("*", ".*"), Pattern.CASE_INSENSITIVE).matcher(fontName).matches());
159
160 // Validate based on the embedding setting
161 // _iniEmbedding = true => The font has to be embedded or it should appear in the exception list
162 // _iniEmbedding = false => The font cannot be embedded or it should appear in the exception list
163 if ((embeddingRequired && !isEmbedded && !isCurrentFontAnException) || (!embeddingRequired && isEmbedded && !isCurrentFontAnException)) {
164 isValid = false;
165 String statusText = embeddingRequired ? "be embedded" : "not be embedded";
166 System.out.println("The font '" + fontName + "' on page " + pageNumber + " should " + statusText + " as specified by the property 'Embedding' or it should be added to the list of exceptions.");
167 }
168 else {
169 String statusText = embeddingRequired != isEmbedded ? "in the exception list" : isEmbedded ? "embedded" : "not embedded";
170 System.out.println("The font '" + fontName + "' on page " + pageNumber + " is conform to the 'Embedding' property as it is " + statusText + ".");
171 }
172 }
173 }
174 }
175 }
176 }
177
178 return isValid;
179 }
180 }
1public static class ConformanceValidator {
2 private static final Map<String, Conformance> versionMap = new HashMap<>();
3
4 static {
5 versionMap.put("1.0", Conformance.PDF10);
6 versionMap.put("1.1", Conformance.PDF11);
7 versionMap.put("1.2", Conformance.PDF12);
8 versionMap.put("1.3", Conformance.PDF13);
9 versionMap.put("1.4", Conformance.PDF14);
10 versionMap.put("1.5", Conformance.PDF15);
11 versionMap.put("1.6", Conformance.PDF16);
12 versionMap.put("1.7", Conformance.PDF17);
13 versionMap.put("2.0", Conformance.PDF20);
14 }
15
16 public static Conformance parseVersionString(String version) {
17 // Extract the major and minor version numbers (e.g., "1.7")
18 String[] versionParts = version.split("\\.");
19 if (versionParts.length == 2) {
20 String majorMinorVersion = versionParts[0] + "." + versionParts[1];
21 Conformance conformance = versionMap.get(majorMinorVersion);
22 if (conformance != null) {
23 return conformance;
24 }
25 }
26
27 throw new IllegalArgumentException("Unsupported version or conformance level: " + version);
28 }
29
30 public static boolean validateConformance(String maxPdfVersionStr, Conformance currentConformance) {
31 Conformance maxPdfConformance = parseVersionString(maxPdfVersionStr);
32 // Convert the current conformance level to the corresponding PDF version (Major.Minor) as it can be based on the PDF/A version
33 Conformance currentConformanceVersion = getVersionFromConformance(currentConformance);
34
35 return currentConformanceVersion.ordinal() <= maxPdfConformance.ordinal();
36 }
37
38 public static Conformance getVersionFromConformance(Conformance conformance) {
39 if (versionMap.containsValue(conformance)) {
40 return conformance;
41 }
42
43 switch (conformance) {
44 case PDF_A1_A:
45 case PDF_A1_B:
46 return Conformance.PDF14; // PDF/A-1 is based on PDF 1.4
47
48 case PDF_A2_A:
49 case PDF_A2_B:
50 case PDF_A2_U:
51 case PDF_A3_A:
52 case PDF_A3_B:
53 case PDF_A3_U:
54 return Conformance.PDF17; // PDF/A-2 and PDF/A-3 are based on PDF 1.7
55
56 default:
57 throw new IllegalArgumentException("Unsupported conformance level: " + conformance);
58 }
59 }
60}
1public static class PageSizeValidator {
2 private final double maxWidth;
3 private final double maxHeight;
4 private final double sizeTolerance;
5
6 // Named page sizes like "Letter", "A4", etc.
7 private static final Map<String, double[]> NAMED_PAGE_SIZES = new HashMap<>();
8
9 static {
10 NAMED_PAGE_SIZES.put("Letter", new double[]{612, 792}); // 8.5 x 11 inches in points
11 NAMED_PAGE_SIZES.put("A0", new double[]{2384, 3370});
12 NAMED_PAGE_SIZES.put("A1", new double[]{1684, 2384});
13 NAMED_PAGE_SIZES.put("A2", new double[]{1191, 1684});
14 NAMED_PAGE_SIZES.put("A3", new double[]{842, 1191});
15 NAMED_PAGE_SIZES.put("A4", new double[]{595, 842}); // 210 x 297 mm in points
16 NAMED_PAGE_SIZES.put("A5", new double[]{420, 595});
17 NAMED_PAGE_SIZES.put("A6", new double[]{298, 420});
18 NAMED_PAGE_SIZES.put("A7", new double[]{210, 298});
19 NAMED_PAGE_SIZES.put("A8", new double[]{147, 210});
20 NAMED_PAGE_SIZES.put("A9", new double[]{105, 147});
21 NAMED_PAGE_SIZES.put("A10", new double[]{74, 105});
22 NAMED_PAGE_SIZES.put("DL", new double[]{283, 595}); // 99 x 210 mm in points
23 }
24
25 public PageSizeValidator(String maxPageSize, String sizeToleranceStr) {
26 double[] size = parsePageSize(maxPageSize);
27 this.maxWidth = size[0];
28 this.maxHeight = size[1];
29 this.sizeTolerance = parseSizeTolerance(sizeToleranceStr);
30 }
31
32 private double[] parsePageSize(String maxPageSize) {
33 if (maxPageSize == null || maxPageSize.isEmpty()) {
34 throw new IllegalArgumentException("MaxPageSize cannot be null or empty");
35 }
36
37 // First, check if it's a named size
38 if (NAMED_PAGE_SIZES.containsKey(maxPageSize)) {
39 return NAMED_PAGE_SIZES.get(maxPageSize);
40 }
41
42 // If not a named size, try to parse it as a custom size
43 Pattern pattern = Pattern.compile("(\\d+(\\.\\d+)?)\\s*x\\s*(\\d+(\\.\\d+)?)(\\s*(pt|in|cm|mm))?", Pattern.CASE_INSENSITIVE);
44 Matcher matcher = pattern.matcher(maxPageSize);
45 if (!matcher.matches()) {
46 throw new IllegalArgumentException("Invalid MaxPageSize format: " + maxPageSize);
47 }
48
49 double width = Double.parseDouble(matcher.group(1));
50 double height = Double.parseDouble(matcher.group(3));
51 String unit = matcher.group(6).toLowerCase();
52
53 switch (unit) {
54 case "in":
55 return new double[]{width * 72, height * 72};
56 case "cm":
57 return new double[]{width * 28.3465, height * 28.3465};
58 case "mm":
59 return new double[]{width * 2.83465, height * 2.83465};
60 case "pt":
61 default:
62 return new double[]{width, height};
63 }
64 }
65
66 private double parseSizeTolerance(String sizeToleranceStr) {
67 if (sizeToleranceStr == null || sizeToleranceStr.isEmpty()) {
68 return 3; // Default tolerance in points
69 }
70
71 Pattern pattern = Pattern.compile("(\\d+(\\.\\d+)?)\\s*(%)?", Pattern.CASE_INSENSITIVE);
72 Matcher matcher = pattern.matcher(sizeToleranceStr);
73 if (!matcher.matches()) {
74 throw new IllegalArgumentException("Invalid SizeTolerance format: " + sizeToleranceStr);
75 }
76
77 double value = Double.parseDouble(matcher.group(1));
78 return matcher.group(3) != null ? value / 100.0 : value; // Percentage tolerance or direct value
79 }
80
81 public boolean validatePageSize(double actualWidth, double actualHeight) {
82 // Check both portrait and landscape orientations
83 boolean isValid = (actualWidth <= maxWidth + sizeTolerance && actualHeight <= maxHeight + sizeTolerance) ||
84 (actualHeight <= maxWidth + sizeTolerance && actualWidth <= maxHeight + sizeTolerance);
85
86 return isValid;
87 }
88}
Document Setup
Add metadata to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Copy all pages
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
33 Ptx_GetLastError());
34
35// Add copied pages to output
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
41 _T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43
44if (argc == 4)
45{
46 // Add metadata from a input file
47 pMdataStream = _tfopen(szMdatafile, _T("rb"));
48 GOTO_CLEANUP_IF_NULL(pMdataStream, _T("Failed to open metadata file \"%s\".\n"), szMdatafile);
49 PtxSysCreateFILEStreamDescriptor(&mdataDescriptor, pMdataStream, 0);
50
51 // Get file extension
52 TCHAR* szExt = _tcsrchr(szMdatafile, '.');
53 _tcscpy(szExtension, szExt);
54
55 if (_tcscmp(szExtension, _T(".pdf")) == 0)
56 {
57 // Use the metadata of another PDF file
58 TPtxPdf_Document* pMetaDoc = PtxPdf_Document_Open(&mdataDescriptor, _T(""));
59 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetaDoc, _T("Failed to open metadata file. %s (ErrorCode: 0x%08x).\n"),
60 szErrorBuff, Ptx_GetLastError());
61 TPtxPdf_Metadata* pMetadata = PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pMetaDoc));
62 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)."),
63 szErrorBuff, Ptx_GetLastError());
64 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pMetadata),
65 _T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
66 Ptx_GetLastError());
67 }
68 else
69 {
70 // Use the content of an XMP metadata file
71 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
72 PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Create(pOutDoc, &mdataDescriptor)),
73 _T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
74 }
75}
76else
77{
78 // Set some metadata properties
79 TPtxPdf_Metadata* pMetadata = PtxPdf_Document_GetMetadata(pOutDoc);
80 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"),
81 szErrorBuff, Ptx_GetLastError());
82 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetAuthor(pMetadata, _T("Your Author")),
83 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
84 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetTitle(pMetadata, _T("Your Title")),
85 _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
86 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetSubject(pMetadata, _T("Your Subject")),
87 _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
88 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetCreator(pMetadata, _T("Your Creator")),
89 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
90}
91
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Copy document-wide data (excluding metadata)
4
5 TPtxPdf_FileReferenceList* pInFileRefList;
6 TPtxPdf_FileReferenceList* pOutFileRefList;
7
8 // Output intent
9 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
10 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
11 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
12 return FALSE;
13
14 // Viewer settings
15 if (PtxPdf_Document_SetViewerSettings(
16 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
17 return FALSE;
18
19 // Associated files (for PDF/A-3 and PDF 2.0 only)
20 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
21 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
22 if (pInFileRefList == NULL || pOutFileRefList == NULL)
23 return FALSE;
24 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
25 if (PtxPdf_FileReferenceList_Add(
26 pOutFileRefList,
27 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
28 return FALSE;
29
30 // Plain embedded files
31 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
32 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
33 if (pInFileRefList == NULL || pOutFileRefList == NULL)
34 return FALSE;
35 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
36 if (PtxPdf_FileReferenceList_Add(
37 pOutFileRefList,
38 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
39 return FALSE;
40
41 return TRUE;
42}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Set Metadata
13 if (args.Length == 3)
14 {
15 Metadata mdata;
16
17 // Add metadata from a input file
18 using FileStream metaStream = File.OpenRead(mdatafile);
19 if (mdatafile.EndsWith(".pdf"))
20 {
21 // Use the metadata of another PDF file
22 Document metaDoc = Document.Open(metaStream, "");
23 mdata = Metadata.Copy(outDoc, metaDoc.Metadata);
24 }
25 else
26 {
27 // Use the content of an XMP metadata file
28 mdata = Metadata.Create(outDoc, metaStream);
29 }
30 outDoc.Metadata = mdata;
31 }
32 else
33 {
34 // Set some metadata properties
35 Metadata metadata = outDoc.Metadata;
36 metadata.Author = "Your Author";
37 metadata.Title = "Your Title";
38 metadata.Subject = "Your Subject";
39 metadata.Creator = "Your Creator";
40 }
41
42 // Define page copy options
43 PageCopyOptions copyOptions = new PageCopyOptions();
44
45 // Copy all pages and append to output document
46 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
47 outDoc.Pages.AddRange(copiedPages);
48}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data (except metadata)
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Viewer settings
10 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
11
12 // Associated files (for PDF/A-3 and PDF 2.0 only)
13 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
14 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
15 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
16
17 // Plain embedded files
18 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
19 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
20 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
21}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy all pages and append to output document
15 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
16 outDoc.getPages().addAll(copiedPages);
17
18 if (args.length == 3) {
19 Metadata mdata;
20
21 // Add metadata from a input file
22 FileStream metaStream = new FileStream(mdatafile, FileStream.Mode.READ_ONLY);
23
24 if (mdatafile.toLowerCase().endsWith(".pdf")) {
25 // Use the metadata of another PDF file
26 Document metaDoc = Document.open(metaStream, null);
27 mdata = Metadata.copy(outDoc, metaDoc.getMetadata());
28 } else {
29 // Use the content of an XMP metadata file
30 mdata = Metadata.create(outDoc, metaStream);
31 }
32 outDoc.setMetadata(mdata);
33 } else {
34 // Set some metadata properties
35 Metadata metadata = outDoc.getMetadata();
36 metadata.setAuthor("Your Author");
37 metadata.setTitle("Your Title");
38 metadata.setSubject("Your Subject");
39 metadata.setCreator("Your Creator");
40 }
41 }
42}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data (excluding metadata)
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Viewer settings
9 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
10
11 // Associated files (for PDF/A-3 and PDF 2.0 only)
12 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
13 for (FileReference inFileRef : inDoc.getAssociatedFiles())
14 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
15
16 // Plain embedded files
17 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
18 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
19 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
20}
1# Open input document
2with io.FileIO(input_file_path, 'rb') as input_file:
3 input_descriptor = StreamDescriptor(input_file)
4 input_document = pdf_document_open(input_descriptor, "")
5 if not input_document:
6 print(f"Input file {input_file_path} cannot be opened.")
7 exit(1)
8
9 # Create output document
10 with io.FileIO(output_file_path, 'wb+') as output_file:
11 output_descriptor = StreamDescriptor(output_file)
12 conformance = pdf_document_getconformance(input_document)
13 output_document = pdf_document_create(output_descriptor, conformance, None)
14 if not output_document:
15 print(f"Output file {output_file_path} cannot be created.")
16 exit(1)
17
18 # Copy document-wide data
19 if not copy_document_data(input_document, output_document):
20 print("Failed to copy document-wide data.")
21 exit(1)
22
23 # Configure copy options
24 copy_options = pdf_pagecopyoptions_new()
25
26 # Copy all pages
27 input_page_list = pdf_document_getpages(input_document)
28 if not input_page_list:
29 print("Failed to get pages of the input document.")
30 exit(1)
31
32 copied_pages = pdf_pagelist_copy(output_document, input_page_list, copy_options)
33 if not copied_pages:
34 print("Failed to copy pages.")
35 exit(1)
36
37 # Add copied pages to output
38 output_page_list = pdf_document_getpages(output_document)
39 if not output_page_list:
40 print("Failed to get pages of the output document.")
41 exit(1)
42
43 if not pdf_pagelist_addrange(output_page_list, copied_pages):
44 print("Failed to add copied pages to output.")
45 exit(1)
46
47 if metadata_file_path:
48 # Add metadata from a input file
49 with io.FileIO(metadata_file_path, 'rb') as metadata_file:
50 metadata_descriptor = StreamDescriptor(metadata_file)
51
52 # Get file extension
53 ext = metadata_file_path.split('.')[-1]
54
55 if ext == 'pdf':
56 # Use the metadata of another PDF file
57 meta_doc = pdf_document_open(metadata_descriptor, "")
58 if not meta_doc:
59 print("Failed to open metadata file.")
60 exit(1)
61
62 metadata = pdf_metadata_copy(output_document, pdf_document_getmetadata(meta_doc))
63 if not metadata or not pdf_document_setmetadata(output_document, metadata):
64 print("Failed to copy metadata.")
65 exit(1)
66 else:
67 # Use the content of an XMP metadata file
68 if not pdf_document_setmetadata(output_document, pdf_metadata_create(output_document, metadata_descriptor)):
69 print("Failed to set metadata.")
70 exit(1)
71 else:
72 # Set some metadata properties
73 metadata = pdf_document_getmetadata(output_document)
74 if not metadata:
75 print("Failed to get metadata.")
76 exit(1)
77
78 if not pdf_metadata_setauthor(metadata, "Your Author") or \
79 not pdf_metadata_settitle(metadata, "Your Title") or \
80 not pdf_metadata_setsubject(metadata, "Your Subject") or \
81 not pdf_metadata_setcreator(metadata, "Your Creator"):
82 print("Failed to set metadata properties.")
83 exit(1)
84
85 pdf_document_close(output_document)
86 pdf_document_close(input_document)
87
1def copy_document_data(in_doc, out_doc):
2 # Copy document-wide data (excluding metadata)
3 in_file_ref_list = pdf_document_getassociatedfiles(in_doc)
4 out_file_ref_list = pdf_document_getassociatedfiles(out_doc)
5
6 if not in_file_ref_list or not out_file_ref_list:
7 return False
8
9 for i in range(pdf_filereferencelist_getcount(in_file_ref_list)):
10 file_ref = pdf_filereference_copy(out_doc, pdf_filereferencelist_get(in_file_ref_list, i))
11 if not pdf_filereferencelist_add(out_file_ref_list, file_ref):
12 return False
13
14 in_file_ref_list = pdf_document_getplainembeddedfiles(in_doc)
15 out_file_ref_list = pdf_document_getplainembeddedfiles(out_doc)
16
17 if not in_file_ref_list or not out_file_ref_list:
18 return False
19
20 for i in range(pdf_filereferencelist_getcount(in_file_ref_list)):
21 file_ref = pdf_filereference_copy(out_doc, pdf_filereferencelist_get(in_file_ref_list, i))
22 if not pdf_filereferencelist_add(out_file_ref_list, file_ref):
23 return False
24
25 return True
26
Encrypt PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9pEncryption =
10 PtxPdf_Encryption_New(szUserPwd, szOwnerPwd, ePtxPdf_Permission_Print | ePtxPdf_Permission_DigitalPrint);
11
12// Create output document
13pOutStream = _tfopen(szOutPath, _T("wb+"));
14GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
15PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
16iConformance = PtxPdf_Document_GetConformance(pInDoc);
17pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, pEncryption);
18GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
19 szOutPath, szErrorBuff, Ptx_GetLastError());
20
21// Copy document-wide data
22GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
23 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
24 Ptx_GetLastError());
25
26// Configure copy options
27pCopyOptions = PtxPdf_PageCopyOptions_New();
28
29// Copy all pages
30pInPageList = PtxPdf_Document_GetPages(pInDoc);
31GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
32 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
33 szErrorBuff, Ptx_GetLastError());
34pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
35GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
36 Ptx_GetLastError());
37
38// Add copied pages to output
39pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
40GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
41 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
44 _T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
45 szErrorBuff, Ptx_GetLastError());
46
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Create encryption parameters
2Encryption encryptionParams = new Encryption(UserPwd, OwnerPwd, Permission.Print |
3 Permission.DigitalPrint);
4
5// Open input document
6using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
7using (Document inDoc = Document.Open(inStream, null))
8
9// Create output document and set a user and owner password
10using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
11using (Document outDoc = Document.Create(outStream, inDoc.Conformance, encryptionParams))
12{
13 // Copy document-wide data
14 CopyDocumentData(inDoc, outDoc);
15
16 // Define page copy options
17 PageCopyOptions copyOptions = new PageCopyOptions();
18
19 // Copy all pages and append to output document
20 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
21 outDoc.Pages.AddRange(copiedPages);
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1// Create encryption parameters
2Encryption encryptionParams = new Encryption(userPwd, ownerPwd,
3 EnumSet.of(Permission.PRINT, Permission.DIGITAL_PRINT));
4
5try (// Open input document
6 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
7 Document inDoc = Document.open(inStream, null);
8 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
9 try (// Create output document and set a user and owner password
10 Document outDoc = Document.create(outStream, inDoc.getConformance(), encryptionParams)) {
11
12 // Copy document-wide data
13 copyDocumentData(inDoc, outDoc);
14
15 // Define page copy options
16 PageCopyOptions copyOptions = new PageCopyOptions();
17
18 // Copy all pages and append to output document
19 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
20 outDoc.getPages().addAll(copiedPages);
21 }
22}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
Flatten form fields in PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options: enable form field flattening
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25PtxPdf_PageCopyOptions_SetFormFields(pCopyOptions, ePtxPdfForms_FormFieldCopyStrategy_Flatten);
26
27// Copy all pages
28pInPageList = PtxPdf_Document_GetPages(pInDoc);
29GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
30 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
31 szErrorBuff, Ptx_GetLastError());
32pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
34 Ptx_GetLastError());
35
36// Add copied pages to output
37pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
38GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
39 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
40 szErrorBuff, Ptx_GetLastError());
41GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
42 _T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
43 szErrorBuff, Ptx_GetLastError());
44
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define copy options including form field flattening
13 PageCopyOptions copyOptions = new PageCopyOptions();
14 copyOptions.FormFields = FormFieldCopyStrategy.Flatten;
15
16 // Copy all pages and append to output document
17 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
18 outDoc.Pages.AddRange(copiedPages);
19}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define copy options including form field flattening
12 PageCopyOptions copyOptions = new PageCopyOptions();
13 copyOptions.setFormFields(FormFieldCopyStrategy.FLATTEN);
14
15 // Copy all pages and append to output document
16 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
17 outDoc.getPages().addAll(copiedPages);
18 }
19}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
Merge multiple PDFs and create a table of contents page
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, null, null))
4{
5 // Create embedded font in output document
6 Font font = Font.CreateFromSystem(outDoc, "Arial", string.Empty, true);
7
8 // Define page copy options
9 PageCopyOptions pageCopyOptions = new PageCopyOptions();
10
11 var copiedPageLists = new List<Tuple<string, PageList>>(inPaths.Length);
12
13 // A page number counter
14 int pageNumber = 2;
15
16 // Copy all input documents pages
17 foreach (string inPath in inPaths)
18 {
19 // Open input document
20 using Stream inFs = new FileStream(inPath, FileMode.Open, FileAccess.Read);
21 using Document inDoc = Document.Open(inFs, null);
22
23 // Copy all pages and append to output document
24 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, pageCopyOptions);
25
26 // Add page numbers to copied pages
27 foreach (var copiedPage in copiedPages)
28 {
29 AddPageNumber(outDoc, copiedPage, font, pageNumber++);
30 }
31
32 // Create outline item
33 string title = inDoc.Metadata.Title ?? System.IO.Path.GetFileNameWithoutExtension(inPath);
34 copiedPageLists.Add(new Tuple<string, PageList>(title, copiedPages));
35 }
36
37 // Create table of contents page
38 var contentsPage = CreateTableOfContents(outDoc, copiedPageLists);
39 AddPageNumber(outDoc, contentsPage, font, 1);
40
41 // Add pages to the output document
42 PageList outPages = outDoc.Pages;
43 outPages.Add(contentsPage);
44 foreach (var tuple in copiedPageLists)
45 {
46 outPages.AddRange(tuple.Item2);
47 }
1private static void AddPageNumber(Document outDoc, Page copiedPage, Font font, int pageNumber)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(copiedPage.Content, false);
5
6 // Create text object
7 Text text = Text.Create(outDoc);
8
9 // Create a text generator with the given font, size and position
10 using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
11 {
12 // Generate string to be stamped as page number
13 string stampText = string.Format("Page {0}", pageNumber);
14
15 // Calculate position for centering text at bottom of page
16 Point position = new Point
17 {
18 X = (copiedPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
19 Y = 10
20 };
21
22 // Position the text
23 textgenerator.MoveTo(position);
24 // Add page number
25 textgenerator.Show(stampText);
26 }
27 // Paint the positioned text
28 generator.PaintText(text);
29}
1private static Page CreateTableOfContents(Document outDoc, List<Tuple<string, PageList>> copiedPageLists)
2{
3 // Create a new page with size equal to the first page copied
4 var page = Page.Create(outDoc, copiedPageLists[0].Item2[0].Size);
5
6 // Create a font
7 var font = Font.CreateFromSystem(outDoc, "Arial", null, true);
8
9 // Parameters for layout computation
10 double border = 30;
11 double textWidth = page.Size.Width - 2 * border;
12 double chapterTitleSize = 24;
13 double titleSize = 12;
14
15 // The current text location
16 var location = new Point() { X = border, Y = page.Size.Height - border - chapterTitleSize };
17
18 // The page number of the current item in the table of content
19 int pageNumber = 2;
20
21 // Creat a content generator for the table of contents page
22 using (var contentGenerator = new ContentGenerator(page.Content, false))
23 {
24 // Create a text object
25 var text = Text.Create(outDoc);
26
27 // Create a text generator to generate the table of contents. Initially, use the chapter title font size
28 using (var textGenerator = new TextGenerator(text, font, chapterTitleSize, location))
29 {
30 // Show a chapter title
31 textGenerator.ShowLine("Table of Contents");
32
33 // Advance the vertical position
34 location.Y -= 1.7 * chapterTitleSize;
35
36 // Select the font size for an entry in the table of contents
37 textGenerator.FontSize = titleSize;
38
39 // Iterate over all copied page ranges
40 foreach (var tuple in copiedPageLists)
41 {
42 // The title string for the current entry
43 string title = tuple.Item1;
44
45 // The page number string of the target page for this entry
46 string pageNumberString = string.Format("{0}", pageNumber);
47
48 // The width of the page number string
49 double pageNumberWidth = textGenerator.GetWidth(pageNumberString);
50
51 // Compute the number of filler dots to be displayed between the entry title and the page number
52 int numberOfDots = (int)Math.Floor((textWidth - textGenerator.GetWidth(title) - pageNumberWidth) / textGenerator.GetWidth("."));
53
54 // Move to the current location and show the entry's title and the filler dots
55 textGenerator.MoveTo(location);
56 textGenerator.Show(title + new string('.', numberOfDots));
57
58 // Show the page number
59 textGenerator.MoveTo(new Point() { X = page.Size.Width - border - pageNumberWidth, Y = location.Y });
60 textGenerator.Show(pageNumberString);
61
62 // Compute the rectangle for the link
63 var linkRectangle = new Rectangle()
64 {
65 Left = border,
66 Bottom = location.Y + font.Descent * titleSize,
67 Right = border + textWidth,
68 Top = location.Y + font.Ascent * titleSize
69 };
70
71 // Create a destination to the first page of the current page range and create a link for this destination
72 var pageList = tuple.Item2;
73 var targetPage = pageList[0];
74 var destination = LocationZoomDestination.Create(outDoc, targetPage, 0, targetPage.Size.Height, null);
75 var link = InternalLink.Create(outDoc, linkRectangle, destination);
76
77 // Add the link to the table of contents page
78 page.Links.Add(link);
79
80 // Advance the location for the next entry
81 location.Y -= 1.8 * titleSize;
82 pageNumber += pageList.Count;
83 }
84 }
85
86 // Paint the generated text
87 contentGenerator.PaintText(text);
88 }
89
90 // Return the finished table-of-contents page
91 return page;
92}
1try (
2 // Open input document
3 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
4 try (// Create output document
5 Document outDoc = Document.create(outStream, null, null)) {
6
7 // Create embedded font in output document
8 Font font = Font.createFromSystem(outDoc, "Arial", "", true);
9
10 // Configure page copy options
11 PageCopyOptions copyOptions = new PageCopyOptions();
12
13 Set<Map.Entry<String, PageList>> copiedPageLists = new HashSet<>(inPaths.length);
14
15 // A page number counter
16 int pageNumber = 2;
17
18
19 // Copy all input documents pages
20 for (String inPath : inPaths) {
21 try (// Open input document
22 Stream inFs = new FileStream(inPath, FileStream.Mode.READ_ONLY);
23 Document inDoc = Document.open(inFs, null)) {
24
25 // Copy all pages and append to output document
26 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
27
28 // Add page numbers to copied pages
29 for ( Page copiedPage : copiedPages)
30 {
31 addPageNumber(outDoc, copiedPage, font, pageNumber++);
32 }
33
34 // Hold the file name without extension
35 if (inPath == null)
36 continue;
37 // Get position of last '.'.
38 int pos = inPath.lastIndexOf(".");
39 // If there was a '.', hold the file name only
40 if (pos != -1)
41 inPath = inPath.substring(0, pos);
42
43 // Create outline item
44 String title = (inDoc.getMetadata().getTitle() == null ? inPath : inDoc.getMetadata().getTitle());
45 copiedPageLists.add(new AbstractMap.SimpleEntry<String, PageList>(title, copiedPages));
46 }
47 }
48
49 // Create table of contents page
50 Page contentsPage = createTableOfContents(outDoc, copiedPageLists);
51 addPageNumber(outDoc, contentsPage, font, 1);
52
53 // Add pages to the output document
54 PageList outPages = outDoc.getPages();
55 outPages.add(contentsPage);
56 for (Map.Entry<String, PageList> entry : copiedPageLists)
57 {
58 outPages.addAll(entry.getValue());
59 }
1private static void addPageNumber(Document outDoc, Page copiedPage, Font font, int pageNumber) throws ToolboxException, IOException
2{
3 // Create content generator
4 try (ContentGenerator generator = new ContentGenerator(copiedPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outDoc);
7
8 // Create a text generator with the given font, size and position
9 try (TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
10 // Generate string to be stamped as page number
11 String stampText = String.format("Page %d", pageNumber);
12
13 // Calculate position for centering text at bottom of page
14 Point position = new Point();
15 position.x = (copiedPage.getSize().getWidth() / 2) - (textgenerator.getWidth(stampText) / 2);
16 position.y = 10;
17
18 // Position the text
19 textgenerator.moveTo(position);
20 // Add page number
21 textgenerator.show(stampText);
22 }
23
24 // Paint the positioned text
25 generator.paintText(text);
26 }
27}
1private static Page createTableOfContents(Document outDoc, Set<Map.Entry<String, PageList>> copiedPageLists) throws IOException, ToolboxException
2{
3 // Create a new page with size equal to the first page copied
4 Page page = Page.create(outDoc, copiedPageLists.iterator().next().getValue().get(0).getSize());
5
6 // Create a font
7 Font font = Font.createFromSystem(outDoc, "Arial", null, true);
8
9 // Parameters for layout computation
10 double border = 30;
11 double textWidth = page.getSize().getWidth() - 2 * border;
12 double chapterTitleSize = 24;
13 double titleSize = 12;
14
15 // The current text location
16 Point location = new Point();
17 location.x = border;
18 location.y = page.getSize().getHeight() - border - chapterTitleSize;
19
20 // The page number of the current item in the table of content
21 int pageNumber = 2;
22
23 // Creat a content generator for the table of contents page
24 try (ContentGenerator contentGenerator = new ContentGenerator(page.getContent(), false)) {
25 // Create a text object
26 Text text = Text.create(outDoc);
27
28 // Create a text generator to generate the table of contents. Initially, use the chapter title font size
29 try (TextGenerator textGenerator = new TextGenerator(text, font, chapterTitleSize, location)) {
30 // Show a chapter title
31 textGenerator.showLine("Table of Contents");
32
33 // Advance the vertical position
34 location.y -= 1.7 * chapterTitleSize;
35
36 // Select the font size for an entry in the table of contents
37 textGenerator.setFontSize(titleSize);
38
39 // Iterate over all copied page ranges
40 for (Map.Entry<String, PageList> entry : copiedPageLists)
41 {
42 // The title string for the current entry
43 String title = entry.getKey();
44
45 // The page number string of the target page for this entry
46 String pageNumberString = String.format("%d", pageNumber);
47
48 // The width of the page number string
49 double pageNumberWidth = textGenerator.getWidth(pageNumberString);
50
51 // Compute the number of filler dots to be displayed between the entry title and the page number
52 int numberOfDots = (int)Math.floor((textWidth - textGenerator.getWidth(title) - pageNumberWidth) / textGenerator.getWidth("."));
53
54 // Move to the current location and show the entry's title and the filler dots
55 textGenerator.moveTo(location);
56 String dots = new String();
57 for (int i = 0; i < numberOfDots; i++)
58 {
59 dots += '.';
60 }
61 textGenerator.show(title + dots);
62
63 // Show the page number
64 Point point = new Point();
65 point.x = page.getSize().getWidth() - border - pageNumberWidth;
66 point.y = location.y;
67 textGenerator.moveTo(point);
68 textGenerator.show(pageNumberString);
69
70 // Compute the rectangle for the link
71 Rectangle linkRectangle = new Rectangle();
72 linkRectangle.setLeft(border);
73 linkRectangle.setBottom(location.y + font.getDescent() * titleSize);
74 linkRectangle.setRight(border + textWidth);
75 linkRectangle.setTop(location.y + font.getAscent() * titleSize);
76
77 // Create a destination to the first page of the current page range and create a link for this destination
78 PageList pageList = entry.getValue();
79 Page targetPage = pageList.get(0);
80 LocationZoomDestination destination = LocationZoomDestination.create(outDoc, targetPage, (double) 0, targetPage.getSize().getHeight(), null);
81 InternalLink link = InternalLink.create(outDoc, linkRectangle, destination);
82
83 // Add the link to the table of contents page
84 page.getLinks().add(link);
85
86 // Advance the location for the next entry
87 location.y -= 1.8 * titleSize;
88 pageNumber += pageList.size();
89 }
90 }
91
92 // Paint the generated text
93 contentGenerator.paintText(text);
94 }
95
96 // Return the finished table-of-contents page
97 return page;
98}