I am using itext5 to create pdf files with painted non-removable watermarks as follows:
public class TestWatermark {
public static String resourcesPath = "C:\\Users\\java\\Desktop\\TestWaterMark\\";
public static String FILE_NAME = resourcesPath + "test.pdf";
public static void main(String[] args) throws IOException {
System.out.println("########## STARTED ADDING WATERMARK ###########");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] byteArray = Files.readAllBytes(Paths.get(FILE_NAME));
String watermarkText = "confidential";
String fontPath = resourcesPath + "myCustomFont.ttf";
Font arabicFont = FontFactory.getFont(fontPath, BaseFont.IDENTITY_H, 16);
BaseFont baseFont = arabicFont.getBaseFont();
PdfReader reader = new PdfReader(byteArray);
PdfStamper stamper = new PdfStamper(reader, baos);
int numberOfPages = reader.getNumberOfPages();
float height = baseFont.getAscentPoint(watermarkText, 24) + baseFont.getDescentPoint(watermarkText, 24);
for (int i = 1; i <= numberOfPages; i++) {
Rectangle pageSize = reader.getPageSizeWithRotation(i);
PdfContentByte overContent = stamper.getOverContent(i);
PdfPatternPainter bodyPainter = stamper.getOverContent(i).createPattern(pageSize.getWidth(),
pageSize.getHeight());
BaseColor baseColor = new BaseColor(10, 10, 10);
bodyPainter.setColorStroke(baseColor);
bodyPainter.setColorFill(baseColor);
bodyPainter.setLineWidth(0.85f);
bodyPainter.setLineDash(0.2f, 0.2f, 0.2f);
PdfGState state = new PdfGState();
state.setFillOpacity(0.3f);
overContent.saveState();
overContent.setGState(state);
for (float x = 70f; x < pageSize.getWidth(); x += height + 100) {
for (float y = 90; y < pageSize.getHeight(); y += height + 100) {
bodyPainter.beginText();
bodyPainter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_FILL);
bodyPainter.setFontAndSize(baseFont, 13);
bodyPainter.showTextAlignedKerned(Element.ALIGN_MIDDLE, watermarkText, x, y, 45f);
bodyPainter.endText();
overContent.setColorFill(new PatternColor(bodyPainter));
overContent.rectangle(pageSize.getLeft(), pageSize.getBottom(), pageSize.getWidth(),
pageSize.getHeight());
overContent.fill();
}
}
overContent.restoreState();
}
stamper.close();
reader.close();
byteArray = baos.toByteArray();
File outputFile = new File(resourcesPath + "output.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
Files.write(outputFile.toPath(), byteArray);
System.out.println("########## FINISHED ADDING WATERMARK ###########");
} catch (Exception e) {
e.printStackTrace();
}
}
}
the above code makes the watermark non-selectable and non-removable in the Adobe Pro editing function but the issue is when opening this pdf file from the VMware Workspace ONE Boxer email, the watermark is not displayed!
Any advice on how to fix this issue?
UPDATE: the following code works fine in Boxer PDF Viewer and the watermark is showing fine, but the issue is that this watermark is selectable and removable by adobe pro:
public class TestWatermark2 {
public static String resourcesPath = "C:\\Users\\java\\Desktop\\TestWaterMark\\";
public static String FILE_NAME = resourcesPath + "test.pdf";
public static void main(String[] args) throws IOException {
System.out.println("########## STARTED ADDING WATERMARK ###########");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] byteArray = Files.readAllBytes(Paths.get(FILE_NAME));
String watermarkText = "confidential";
String fontPath = resourcesPath + "myCustomFont.ttf";
Font arabicFont = FontFactory.getFont(fontPath, BaseFont.IDENTITY_H, 16);
BaseFont baseFont = arabicFont.getBaseFont();
PdfReader reader = new PdfReader(byteArray);
PdfStamper stamper = new PdfStamper(reader, baos);
Phrase watermarkPhrase = new Phrase(watermarkText, arabicFont);
int numberOfPages = reader.getNumberOfPages();
float height = baseFont.getAscentPoint(watermarkText, 24) + baseFont.getDescentPoint(watermarkText, 24);
for (int i = 1; i <= numberOfPages; i++) {
Rectangle pageSize = reader.getPageSizeWithRotation(i);
PdfContentByte overContent = stamper.getOverContent(i);
PdfGState state = new PdfGState();
state.setFillOpacity(0.3f);
overContent.saveState();
overContent.setGState(state);
for (float x = 70f; x < pageSize.getWidth(); x += height + 100) {
for (float y = 90; y < pageSize.getHeight(); y += height + 100) {
ColumnText.showTextAligned(overContent, Element.ALIGN_CENTER, watermarkPhrase, x, y, 45f,
PdfWriter.RUN_DIRECTION_RTL, ColumnText.DIGITS_AN2EN);
}
}
overContent.restoreState();
}
stamper.close();
reader.close();
byteArray = baos.toByteArray();
File outputFile = new File(resourcesPath + "output.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
Files.write(outputFile.toPath(), byteArray);
System.out.println("########## FINISHED ADDING WATERMARK ###########");
} catch (Exception e) {
e.printStackTrace();
}
}
}
UPDATE2: I tried mkl solution and it is working very fine but it has one small issue if the watermark text is arabic it is getting displayed incorrect LTR as in the attached image:
ColumnText.showTextAligned
it appears in the Boxer PDF Viewer with no issues, see my updated code – StereoisomerismoverContent.setColorFill ... overContent.fill();
after the double loop. That loop after all constructs the pattern, so it may be better to use the pattern only after the loop. I assume, though, that this is unrelated to the Boxer issue. – Such