I have a requirement to add adobe form fields to an existing pdf.
The problem I encounter is when adding fields to a rotated page, the resulting form field text orientation is incorrect.
e.g. A page that is rotated 90 degrees clockwise, results in form field where the text is "vertical".
Is there a workaround to get form fields created with the correct orientation?
The appearance characteristics dictionary (/MK entry) of the widget has an /R entry where the rotation can be set. See e.g. this file.
PDAppearanceCharacteristicsDictionary fieldAppearance
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fieldAppearance.setRotation(90);
widget.setAppearanceCharacteristics(fieldAppearance);
You may have to adjust your coordinates. To find the best coordinates, use PDFDebugger and hover at the place you want your field to be.
Update:
For checkmarks (and radio buttons) where the appearance stream is created by the user and not by PDFBox (as seen here or in the PDFBox example) you need to set the matrix yourself like this (for 90°):
yesAP.setMatrix(AffineTransform.getQuadrantRotateInstance(1, rect.getWidth(), 0));
The "1" here is for 90°. The translation needs to be adjusted for the other rotations.
Related
I am setting a margin for a pdf and checking if the contents of the page are exceeding the margin.
I am easily able to do that if the contents of a page are just text.
Here s what I am doing:
I am using TextMarginFinder. I will set the left margin values of the pdf based on the book size. and check with the finder.getLlx(); since finder.getLlx(); will get me the left most position of a text in that page.
TextMarginFinder finder;
if(leftmar>=finder.getLlx())
{
errormargin=1; //left margin error
System.out.println("Page: "+i+"Margin Error:LeftMArginError ");
}
But this does not work in case if the page contains an image. Although the image goes outside of the margin, I am not getting the error with the above code since the finder.getLlx(); function seems to work only for texts.
Two Questions:
1) While looping through the pages in pdf, if there is an image in that page, how can I check if that particular page contains an image?
2) If it contains an image, how can I obtain its extreme positions?
Update after mkl suggestion
if(leftmar>=finder.getLlx())
{
errormargin=1; //left margin error
System.out.println("finder.getLlx() value ="+finder.getLlx()+", leftmar Value="+leftmar);
}
if(rightmar<= finder.getUrx()){
errormargin=1; //right margin error
System.out.println("finder.getUrx() value ="+finder.getUrx()+", rightmar Value="+rightmar);
}
if(margintop >= finder.getUry()){
errormargin=3; //top margin error
System.out.println("finder.getUry() value ="+finder.getUry()+", margintop Value="+margintop);
}
if(marginbottom >= finder.getLly()){
errormargin=3; //bottom margin error
System.out.println("finder.getLly() value ="+finder.getLly()+", marginbottom Value="+marginbottom);
}
This is more an answer to what the OP actually wanted, a way to retrieve the bounding box of all content on a page.
The OP already uses the iText TextMarginFinder render listener class to determine the bounding box of the text on page. In the context of this answer an analogous class MarginFinder has been developed which does not only consider text but also other kind of content, e.g. bitmap images and vector graphics.
Thus, replacing the use of TextMarginFinder by MarginFinder allows to find the bounding box of any content on the page.
Please be aware:
Any content is considered, the margin finder does not check whether the content makes a difference. E.g. think about white text, white bitmap areas, or white rectangles, all are considered content and, therefore, the bounding box encompasses such invisible content, too. Especially the latter example, white rectangles, might be a problem here or there as some software first paints a white rectangle over the whole page area.
Clipping paths are not considered. Thus, even content that never is drawn (because it is clipped away) makes the bounding box expand.
Page borders are not considered, either. Thus, off-page content like printer marks may make the bounding box expand even more.
The code calculating the bounding box for vector graphics is not correct: it simply returns the bounding box of all control points which in case of Bezier curves may be false. Its ignoring line widths and wedge types also results in somewhat-off coordinates.
Annotations are not considered. Thus, the resulting bounding box may be to small if annotations are expected to also be considered, e.g. for forms.
In spite of these shortcomings, the render listener usually returns correct results. If this is not enough, the class can be extended accordingly.
PS: Anyone who is interested in the original question may find answers in the MarginFinder render listener class and its use.
Question:
With PDFBox, how can I create a link annotation with "mouse over" color effect (aka rollover / mouse hover)?
It means that when I hover my mouse cursor over a link in a PDF file (without clicking it), the link changes to a different color. And if I mouse the cursor away, the link changes backs to the original color.
For example:
The effect that I am looking for is similar to the links at stackoverflow website. When you hover the mouse cursor over (without clicking) the "Ask Question" button, the link changes from grey to orange. When you move the cursor away, the color changes back to grey. See following picture for example: I want to achieve exactly the same effect in a PDF file.
What I have tried:
In PDF Reference Sixth Edition, it is described that:
the rollover appearance is used when the user moves the cursor into the annotation’s active area without pressing the mouse button"
and
[rollover appearance] are defined in an appearance dictionary, which in turn is the value of the AP entry in the annotation dictionary
Also,
In the PDFBox, there is a PDAppearanceDictionary class, which has a setRolloverAppearance() method.
This is the farthest I can get. I don't know how to use PDAppearanceDictionary class (if this is indeed the right class to use) in conjunction with a PDAnnotationLink class, in order to achieve my desired result.
I have tried finding examples on Google in vain.
In short
There was some uncertainty about whether or not such a rollover effect is possible. Using fairly current Adobe PDF viewers (Reader XI and Acrobat 9.5) for displaying, the desired rollover effect did not turn up for a link annotation. The effect did turn up, though, for a button widget (carrying the same URL action).
In detail
The test code feeds either a PDAnnotationLink or a PDAnnotationWidget customized as a pushbutton to a method which embeds the respective annotation in a document and adds normal and rollover appearances to it:
void createRollover(PDAnnotation annotation, String filename) throws IOException, COSVisitorException
{
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
List<PDAnnotation> annotations = page.getAnnotations();
float x = 100;
float y = 500;
String text = "PDFBox";
PDFont font = PDType1Font.HELVETICA_BOLD;
float textWidth = font.getStringWidth(text) / 1000 * 18;
PDPageContentStream contents = new PDPageContentStream(document, page);
contents.beginText();
contents.setFont(font, 18);
contents.moveTextPositionByAmount(x, y);
contents.drawString(text);
contents.endText();
contents.close();
PDAppearanceDictionary appearanceDictionary = new PDAppearanceDictionary();
PDAppearanceStream normal = createAppearanceStream(document, textWidth, font, "0.5 0.5 0.5 rg");
PDAppearanceStream rollover = createAppearanceStream(document, textWidth, font, "1 0.7 0.5 rg");
PDAppearanceStream down = createAppearanceStream(document, textWidth, font, "0 0 0 rg");
appearanceDictionary.setNormalAppearance(normal);
appearanceDictionary.setRolloverAppearance(rollover);
appearanceDictionary.setDownAppearance(down);
annotation.setAppearance(appearanceDictionary);
PDRectangle position = new PDRectangle();
position.setLowerLeftX(x);
position.setLowerLeftY(y - 5);
position.setUpperRightX(x + textWidth);
position.setUpperRightY(y + 20);
annotation.setRectangle(position);
annotations.add(annotation);
document.save(new File(RESULT_FOLDER, filename));
document.close();
}
In case of the PDAnnotationLink:
In case of the pushbutton PDAnnotationWidget:
Backgrounds:
The OP in his question and #Tilman in a comment referred to the PDF specification:
An annotation may define as many as three separate appearances: [...]
• The rollover appearance shall be used when the user moves the cursor into the annotation’s active area without pressing the mouse button. [...]
The normal, rollover, and down appearances shall be defined in an appearance dictionary, which in turn is the value of the AP entry in the annotation dictionary
and, therefore, thought:
So it should be possible
They did not consider, though, that the specification introduces the appearance dictionary as:
AP dictionary (Optional; PDF 1.2) An appearance dictionary specifying how the annotation shall be presented visually on the page (see 12.5.5, “Appearance Streams”). Individual annotation handlers may ignore this entry and provide their own appearances.
Thus, what at first glance seemed to be an unconditional requirement ("The rollover appearance shall be used when...") turns out to be ignorable if the annotation handler in a PDF viewer has its own ideas.
tl;dr: it is completely up to the PDF viewer in question to decide which appearance streams it uses and which it ignores and replaces in its own ways.
If making use of annotation appearance streams, one should always make sure that one also supplies the information most plausibly used if the given appearances are ignored, e.g. having regular page content beneath a link annotation.
It's important to understand that a "link" annotation in PDF simply represents a selectable area. It's a rectangle that may or may not have text under it, and is not tied to any specific text in any way ("hyperlinked" text just happens to be in the linked zone of the document). Acrobat and Reader have some "extra" features to "guess" at which text is used in links, and mark used links a different color, but from a PDF perspective a link is just a rectangle. You can give the link annotation itself a rollover effect, this has the effect of changing the appearance of the link rectangle itself. Examples include having the previously invisible rectangular outline appear when you mouseover, or having a visible rectangular outline change color. You can play around with these in Acrobat's link properties menu to get a better understanding.
However, that is the only type of rollover you will be able to achieve using link annotations. To reproduce what happens with web links, you will want to look into other workarounds. Examples include creating an Xobject form of the text with an alternate rollover appearance, creating the text as a image-based button with a rollover appearance, or even using Flash. I hope this helps explain what is and isn't possible with link annotations themselves!
How does one fill out a horizontal pdf form with the PDFBox library?
I access my fields and fill them using the supplied example code and it works fine. But, if the pdf page is tilted horizontally the filled out text are still left in the vertical position.
I have tried rotating the page first and then filling the form but the fields seem to be independent. I have also tried formatting the field through the various set methods defined for PDField and PDTextbox but this has no effect either.
Finally, I know that some of the rotation properties are controlled through the PDAnnotation and PDAnnotationWidget but trying to set their PDAppearanceCharacteristics has no effect on the initial text rotation. Rather, a user is required to interact with the field in order for this to take effect.
Thanking in advance,
J3lly
I am writing text from right to left.
how can i add an image at the end of the text (alligned nicely)?
The question isn't entirely clear.
The order of objects added to a Document is always respected, except in the case of Image objects. If an Image object doesn't fit the page, it can be forwarded to the next page, and other content can be added first. If you want to avoid this, use writer.setStrictImageSequence(true);
However: you're writing from Right to Left (probably in Hebrew), so the above doesn't apply, not the previous answer by Anshu. You can only use RTL in ColumnText and PdfPTable.
It's not clear what you want to do.
Do you want to add an Image at the bottom of the text? That's easy: just add the text first, then add the Image. Do you want to add an Image inline? In that case, you can wrap the Image in a Chunk as is done in this example: http://itextpdf.com/examples/iia.php?id=54
My interpretation is: you want to add the image at the bottom left, and you want the text to be added next to the image. That's more difficult to achieve. You'd need to add the Image and the text separately. Add the Image at an absolute position and add the text using 'irregular columns'. That is: ColumnText in text mode (as opposed to composite mode). For an example showing how to use irregular columns, see http://itextpdf.com/examples/iia.php?id=67
Anybody knows if there are any special coordinates in iText to global positioning an image at the bottom right of the document?
I'm not sure it exists...
First we need to know if you're talking about a Document that is created from scratch or about adding an Image to an existing document.
If you create a document from scratch, then the coordinate of the bottom-right depends on the page size you've used when creating the Document object. For instance: for an A4 page, the bottom right corner has x = 595 ; y = 0 (the measurements are done in 'user unit' which correspond with points by default). So if you want to position an image in the bottom right corner, you need to use img.setAbsolutePosition(595 - img.getScaledWidth(), 0); and then just use document.add(img); to add the image.
DISCLAIMER: if you use a page size that differs from the default, or if you define a CropBox, you'll need to adapt the coordinates accordingly.
If you want to add an image to an existing document, you need to inspect the page size, and you need to check if there's a CropBox. You need to calculate the offset of the image based on these values. Again you can use setAbsolutePosition(), but you need to add the image to a PdfContentByte object obtained using the getOverContent() or getUnderContent() method (assuming that you're using PdfStamper).