What is the proper way to add rich text annotation in PDFBox? - java

I add three annotations into empty PDF:
call .setContents("...")
call .setRichContents("...");
call .setContents("..."); and .setRichContents("...");
First annotation displays properly in Adobe Reader and in Preview (on Mac).
Second annotation displays properly in Adobe Reader only (as formatted text), and empty box in Preview.
Third annotation displays as plain text Simple text content for Test Case 3 from the method .setContent in Adobe Reader ( NOT rich text from the method .setRichContents and PDF tag /RC!) and in Preview.
Text for comments in PDF contains rich formatted elements, I need to show them in annotations. I assume that Preview doesn't support rich text in annotations.
I've tried to re-save PDF in Adobe Reader and then open in Preview - after that I see all comments in Adobe Reader (with rich text) and in Preview (as not formatted text).
Question: how to show rich formatted annotation in Adobe Reader and plain text in Preview?
My code:
PDDocument document = new PDDocument();
PDPage blankPage = new PDPage();
document.addPage(blankPage);
List<PDAnnotation> annotations = document.getPage(0).getAnnotations();
float pageHeight = document.getPage(0).getCropBox().getHeight();
PDAnnotationText text_TC1 = new PDAnnotationText();
PDRectangle positionTC1 = new PDRectangle();
positionTC1.setLowerLeftX(10);
positionTC1.setLowerLeftY(pageHeight - 10);
positionTC1.setUpperRightX(20);
positionTC1.setUpperRightY(pageHeight - 20);
text_TC1.setContents("Simple text content for Test Case 1.");
text_TC1.setRectangle(positionTC1);
text_TC1.setOpen(true);
text_TC1.constructAppearances();
annotations.add(text_TC1);
PDAnnotationText text_TC2 = new PDAnnotationText();
PDRectangle positionTC2 = new PDRectangle();
positionTC2.setLowerLeftX(10);
positionTC2.setLowerLeftY(pageHeight - 110);
positionTC2.setUpperRightX(20);
positionTC2.setUpperRightY(pageHeight - 120);
text_TC2.setRichContents("<body xmlns=\"http://www.w3.org/1999/xhtml\">" +
"<p><span style=\"font-weight:bold\">Rich</span> <span style=\"font-style:italic\">text content</span> for Test Case 2.</p>" +
"</body>");
text_TC2.setRectangle(positionTC2);
text_TC2.setOpen(true);
text_TC2.constructAppearances();
annotations.add(text_TC2);
PDAnnotationText text_TC3 = new PDAnnotationText();
PDRectangle positionTC3 = new PDRectangle();
positionTC3.setLowerLeftX(10);
positionTC3.setLowerLeftY(pageHeight - 210);
positionTC3.setUpperRightX(20);
positionTC3.setUpperRightY(pageHeight - 220);
text_TC3.setContents("Simple text content for Test Case 3.");
text_TC3.setRichContents("<body xmlns=\"http://www.w3.org/1999/xhtml\">" +
"<p><span style=\"font-weight:bold\">Rich</span> <span style=\"font-style:italic\">text content</span> for Test Case 3.</p>" +
"</body>");
text_TC3.setRectangle(positionTC3);
text_TC3.setOpen(true);
text_TC3.constructAppearances();
annotations.add(text_TC3);
document.save("test_so.pdf");
document.close();
Update 2022-05-08: I've found a workaround solution - add comments via import XFDF:
PDDocument document = new PDDocument();
PDPage blankPage = new PDPage();
document.addPage(blankPage);
FDFDocument fdfDoc = FDFDocument.loadXFDF("test.xfdf");
List<FDFAnnotation> fdfAnnots = fdfDoc.getCatalog().getFDF().getAnnotations();
List<PDAnnotation> pdfannots = new ArrayList<>();
for (int i=0; i<fdfDoc.getCatalog().getFDF().getAnnotations().size(); i++) {
FDFAnnotation fdfannot = fdfAnnots.get(i);
PDAnnotation pdfannot = PDAnnotation.createAnnotation(fdfannot.getCOSObject());
pdfannots.add(pdfannot);
}
document.getPage(0).setAnnotations(pdfannots);
fdfDoc.close();
document.save("test.pdf");
document.close();

Related

Apache PDFBox - Adobe Acrobat prompts saving

I'm using Apache PDFBox version 2.0.16 to add paging to an existing PDF file.
My method is working great, the generated PDF is fine. However, when I open the file with Adobe Acrobat Reader, if I try to close the file, it prompts an alert asking me if I want to save the file even though I haven't edited anything, and the file is not editable at first.
I can't manage to understand what's happening, and how to prevent it from prompting saving
My code is the following :
private void paging(ByteArrayOutputStream os) throws IOException {
PDDocument doc = PDDocument.load(new ByteArrayInputStream(os.toByteArray()));
PDFont font = getFont(doc);
PDPageTree pages = doc.getDocumentCatalog().getPages();
for (int i = 0; i < pages.getCount(); i++) {
PDPage page = pages.get(i);
PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, false);
contentStream.beginText();
contentStream.setFont(font, FONT_SIZE);
contentStream.setNonStrokingColor(Color.BLACK);
contentStream.newLineAtOffset(page.getCropBox().getWidth() - 40, 15);
contentStream.showText((i + 1) + " / " + pages.getCount());
contentStream.endText();
contentStream.close();
}
doc.save(os);
doc.close();
}
reset 'os' before saving, so that your ByteArrayOutputStream gets cleared and positioned at the beginning.
os.reset();
Also call load() directly with the byte array:
PDDocument.load(os.toByteArray());
and update to the current version, which is 2.0.19 at this time.

write on existing form-pdf with pdfbox

I am relativly new to Java and I want to replace an existing iText based Javascript with pdfbox. (Java 2.0)
I have a pdf-Formsheet (but this sheet has no Acroform entries) and I want to fill it with information (Name, Birthdate and so on). The pdf is in a rectangular special size (like a contact card).
My code so far:
File file = new File("ToBeFilled.pdf");
PDDocument document = PDDocument.load(file);
System.out.println("PDF loaded");
//Retrieving the page
PDPage page = (PDPage)document.getPages().get( 0 );
PDFont font = PDType1Font.HELVETICA_BOLD;
PDPageContentStream content = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true);
content.beginText();
//Setting the font to the Content stream
content.setFont(font, 30);
//Setting the position for the line (float x, float y), (0,0) = lower left corner
content.newLineAtOffset(100, 400);
String text = "This is the sample document and we are adding content to it.";
String text1 = "This is an example of adding text to a page in the pdf document. we can add as many lines";
String text2 = "as we want like this using the ShowText() method of the ContentStream class";
//Adding text in the form of string
content.showText(text);
//Adding text in the form of string
content.newLine();
content.showText(text1);
content.newLine();
content.showText(text2);
//Ending the content stream
content.endText();
System.out.println("Text added");
content.close();
//Saving the document
document.save("newPrint.pdf");
//Closing the document
document.close();
The text does not show. What am I missing here? I thought with the correct text-positions I could simply write on the pdf?
The source is working.
Maybe your content.newLineAtOffset(100, 400); is too huge - out of bounds - for your little card.
By the way, you have to setLeading(float) to use newLine() meaningfuly.

PDFBox incorrect text appearance after copy/paste

I’m using PDFBox 2.0.4 to create PDF documents with acroForms. Here is my test code example:
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
PDAcroForm acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);
String dir = "../testPdfBox/src/main/resources/fonts/";
PDType0Font font = PDType0Font.load(document, new File(dir + "Roboto-Regular.ttf"));
PDResources resources = new PDResources();
String fontName = resources.add(font).getName();
acroForm.setDefaultResources(resources);
String defaultAppearanceString = format("/%s 12 Tf 0 g", fontName);
acroForm.setDefaultAppearance(defaultAppearanceString);
PDTextField field = new PDTextField(acroForm);
field.setPartialName("SampleField");
field.setDefaultAppearance(defaultAppearanceString);
acroForm.getFields().add(field);
PDAnnotationWidget widget = field.getWidgets().get(0);
PDRectangle rect = new PDRectangle(50, 750, 200, 50);
widget.setRectangle(rect);
widget.setPage(page);
widget.setPrinted(true);
page.getAnnotations().add(widget);
field.setValue("Sample field 123456");
acroForm.flatten();
document.save("target/SimpleForm.pdf");
document.close();
Everything works fine. But when I try to copy text from the created document and paste it to the NotePad or Word it becomes squares.
􀀷􀁅􀁑􀁔􀁐􀁉􀀄􀁊􀁍􀁉􀁐􀁈􀀄􀀕􀀖􀀗􀀘􀀙􀀚
I search a lot about this problem. The most popular answer is that there is no toUnicode cmap in created PDF. So I explore my document with CanOpener for Acrobat:
Yes, there is no toUnicode cmap, but everything works properly, if not to use acroForm.flatten(). When form fields are not flattened, I can copy/paste text from the document and it looks correct. Nevertheless I need all fields to be flattened.
So, I have two questions:
Why there is a problem with copy/pasting text in flattened form, and everything is ok in non-flattened?
What can I do to avoid problem with text copy/pasting?
Is there only one solution - to create toUnicode CMap by my own, like in this example?
My test pdf files are available here.
Please replace
PDType0Font font = PDType0Font.load(document, new File(dir + "Roboto-Regular.ttf"));
with
PDType0Font font = PDType0Font.load(document, new FileInputStream(dir + "Roboto-Regular.ttf"), false);
This makes sure that the font is embedded in full and not just as a subset.

How to add text watermark to pdf in Java using Apache PDFBox?

I am not getting any tutorial for adding a text watermark in a PDF file? Can you all please guide me, I am very new to PDFBOX.
Its not duplicate, the link in the comment didn't help me. I want to add text, not an image to the pdf.
Here is an example using PDFBox 2.0.2. This will load a PDF and write some text in the bottom right corner in a red transparent font. If it is a multiple page PDF the watermark will appear on every page. It might not be production ready, as I am not sure if there are some additional null conditions that need to be checked, but it should get you running in the right direction.
Keep in mind that this particular block of code will not modify the original PDF, but will create a new PDF using the Tmp_(filename) as the output.
private static void watermarkPDF (File fileStored) {
File tmpPDF;
PDDocument doc;
tmpPDF = new File(fileStored.getParent() + System.getProperty("file.separator") +"Tmp_"+fileStored.getName());
doc = PDDocument.load(fileStored);
for(PDPage page:doc.getPages()){
PDPageContentStream cs = new PDPageContentStream(doc, page, AppendMode.APPEND, true, true);
String ts = "Some sample text";
PDFont font = PDType1Font.HELVETICA_BOLD;
float fontSize = 14.0f;
PDResources resources = page.getResources();
PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
r0.setNonStrokingAlphaConstant(0.5f);
cs.setGraphicsStateParameters(r0);
cs.setNonStrokingColor(255,0,0);//Red
cs.beginText();
cs.setFont(font, fontSize);
cs.setTextMatrix(Matrix.getTranslateInstance(0f,0f));
cs.showText(ts);
cs.endText();
}
cs.close();
}
doc.save(tmpPDF);
}

Insert image as new layer to existing PDF using PdfBox 1.8.8

I'm using PDFBox in my application to modify existing PDF files.
I need to place a barcode to the first page of the PDF document.
So first i create new PDF file with inserted barcode:
PDDocument document = new PDDocument();
PDXObjectImage ximage = new PDPixelMap(document, awtImage);
PDPage pag = new PDPage(new PDRectangle(ximage.getWidth(), ximage.getHeight()));
document.addPage(pag);
PDPageContentStream stream = new PDPageContentStream(document, pag, false, false);
stream.drawXObject(ximage, 0, 0, ximage.getWidth(), ximage.getHeight());
stream.close();
Then i try to place it as new layer into existing PDF:
Point barlocation = new Point(0,0);
float Height = page.getMediaBox().getHeight();
float Width = page.getMediaBox().getWidth();
barlocation.setLocation(Width - pag.getMediaBox().getWidth(), Height - pag.getMediaBox().getHeight()); //I need to place it in the top right corner
LayerUtility layerUtility = new LayerUtility(doc);
List bigPages = doc.getDocumentCatalog().getAllPages();
PDXObjectForm firstForm = layerUtility.importPageAsForm(document, 0);
AffineTransform affineTransform = new AffineTransform();
affineTransform.translate(barlocation.x , barlocation.y);
layerUtility.appendFormAsLayer((PDPage) bigPages.get(0), firstForm, affineTransform, "barcode layer");
doc.save(path);
doc.close();
So it works well with PDF document ver 1.5 (created in MS Word 2010/2013). But it's not working correctly with PDF document version 1.6 position and size of the inserted layer are wrong (i can't post an image, so you can see the result here:http://img4.imagetitan.com/img.php?image=11_capture567.png
What should I change? Thanks for reading and sorry for my bad English.

Categories

Resources