Q: When I add text markup annotations at the location returned by findText(), sometimes, the location of the text markup is off. This seems to happen when the PDF is cropped or rotated. Can you explain how to fix this?

A: When a page has a rotation or a crop box, PDF coordinates and display / view coordinates will differ.

Our TextPosition object currently return quadrilaterals in view coordinates, which means that the coordinates takes into account the CropBox and the rotation of the page. But to add annotations on the page, coordinates need to be passed on in PDF coordinates (or MediaBox coordinates).

To transform from view coordinates back to PDF coordinates, you will need to use the transform below:

 
private static AffineTransform getViewToPDFXForm(PDFPage page)
{
double width = page.getDisplayWidth();
double height = page.getDisplayHeight();
if (page.getPageRotation() % 180 != 0)
{
width = page.getDisplayHeight();
height = page.getDisplayWidth();
}
 
// Handle the crop box location
AffineTransform xForm = AffineTransform.getTranslateInstance(page.getDisplayX(), page.getDisplayY());
 
// Handle the page rotation
AffineTransform rotXForm = AffineTransform.getRotateInstance(Math.toRadians(-page.getPageRotation()));
Point2D.Double widthHeight = new Point2D.Double(width, height);
rotXForm.transform(widthHeight, widthHeight);
if (widthHeight.getX() < 0)
{
rotXForm.translate(0, -height);
}
if (widthHeight.getY() < 0)
{
rotXForm.translate(-width, 0);
}
xForm.concatenate(rotXForm);
return xForm;
}

Download a Full Java Sample SearchAndHighlight.java that shows how to search text in a PDF documents and then add a text markup, making use of the transform above to change from view coordinates to PDF coordinates.