package jnpf.fileStorage.dms;
|
|
import jnpf.dmsEntity.preview.model.DmsWatermarkPositionSnapshot;
|
import jnpf.dmsEntity.preview.model.DmsWatermarkSnapshot;
|
import jnpf.exception.DataException;
|
import org.apache.pdfbox.Loader;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDPage;
|
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
import org.junit.Test;
|
|
import java.awt.image.BufferedImage;
|
import java.io.ByteArrayOutputStream;
|
import java.math.BigDecimal;
|
import java.util.List;
|
|
import static org.junit.Assert.*;
|
import static org.mockito.Mockito.mock;
|
|
public class DmsPdfWatermarkServiceTest {
|
private final DmsPdfWatermarkService service = new DmsPdfWatermarkService(
|
new DmsDocxWatermarkService(mock(DmsCommonFileStorage.class)));
|
|
@Test
|
public void stampsSelectedPdfPageAndKeepsOtherPagesUntouched() throws Exception {
|
byte[] source = pdf(2);
|
DmsWatermarkSnapshot mark = watermark();
|
mark.setRenderPages(List.of(2));
|
mark.setContent("Page {/CurrPage} of {/TotalPage}");
|
|
byte[] result = service.apply(source, List.of(mark));
|
|
try (PDDocument original = Loader.loadPDF(source);
|
PDDocument stamped = Loader.loadPDF(result)) {
|
assertEquals(2, stamped.getNumberOfPages());
|
assertEquals(darkPixels(new PDFRenderer(original).renderImageWithDPI(0, 72)),
|
darkPixels(new PDFRenderer(stamped).renderImageWithDPI(0, 72)));
|
assertTrue(darkPixels(new PDFRenderer(stamped).renderImageWithDPI(1, 72)) > 20);
|
}
|
}
|
|
@Test
|
public void rejectsOutOfRangePageWithoutReturningSource() throws Exception {
|
DmsWatermarkSnapshot mark = watermark();
|
mark.setRenderPages(List.of(3));
|
assertThrows(DataException.class, () -> service.apply(pdf(2), List.of(mark)));
|
}
|
|
@Test
|
public void usesLandscapeCoordinatesForRotatedA4AndA3Pages() throws Exception {
|
DmsWatermarkSnapshot mark = watermark();
|
mark.setContent("CHECK");
|
mark.setMarkWidthMm(new BigDecimal("30"));
|
mark.setMarkHeightMm(new BigDecimal("15"));
|
DmsWatermarkPositionSnapshot a4 = mark.getPositions().get(0);
|
a4.setPaperType("A4");
|
a4.setLandscapeXMm(new BigDecimal("180"));
|
a4.setLandscapeYMm(new BigDecimal("40"));
|
DmsWatermarkPositionSnapshot a3 = new DmsWatermarkPositionSnapshot();
|
a3.setPaperType("A3");
|
a3.setPaperWidthMm(new BigDecimal("297"));
|
a3.setPaperHeightMm(new BigDecimal("420"));
|
a3.setPortraitXMm(new BigDecimal("10"));
|
a3.setPortraitYMm(new BigDecimal("20"));
|
a3.setLandscapeXMm(new BigDecimal("350"));
|
a3.setLandscapeYMm(new BigDecimal("50"));
|
mark.setPositions(List.of(a4, a3));
|
|
byte[] source;
|
try (PDDocument document = new PDDocument();
|
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
PDPage first = new PDPage(PDRectangle.A4);
|
first.setRotation(90);
|
document.addPage(first);
|
PDPage second = new PDPage(PDRectangle.A3);
|
second.setRotation(270);
|
document.addPage(second);
|
PDPage third = new PDPage(PDRectangle.A4);
|
third.setRotation(180);
|
document.addPage(third);
|
document.save(output);
|
source = output.toByteArray();
|
}
|
|
try (PDDocument stamped = Loader.loadPDF(service.apply(source, List.of(mark)))) {
|
PDFRenderer renderer = new PDFRenderer(stamped);
|
assertWatermarkWithin(renderer.renderImageWithDPI(0, 72), 180, 40, 30, 15);
|
assertWatermarkWithin(renderer.renderImageWithDPI(1, 72), 350, 50, 30, 15);
|
assertWatermarkWithin(renderer.renderImageWithDPI(2, 72), 65, 138, 30, 15);
|
}
|
}
|
|
private void assertWatermarkWithin(BufferedImage image, int xMm, int yMm, int widthMm, int heightMm) {
|
int minX = (int) Math.floor(xMm * 72D / 25.4D) - 2;
|
int maxX = (int) Math.ceil((xMm + widthMm) * 72D / 25.4D) + 2;
|
int minY = (int) Math.floor(yMm * 72D / 25.4D) - 2;
|
int maxY = (int) Math.ceil((yMm + heightMm) * 72D / 25.4D) + 2;
|
int visible = 0;
|
for (int y = 0; y < image.getHeight(); y++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
if ((image.getRGB(x, y) & 0x00ffffff) >= 0x00808080) continue;
|
visible++;
|
assertTrue("Watermark used the wrong paper position", x >= minX && x <= maxX && y >= minY && y <= maxY);
|
}
|
}
|
assertTrue("Expected a visible watermark", visible > 0);
|
}
|
|
private byte[] pdf(int pages) throws Exception {
|
try (PDDocument document = new PDDocument();
|
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
for (int i = 0; i < pages; i++) document.addPage(new PDPage(PDRectangle.A4));
|
document.save(output);
|
return output.toByteArray();
|
}
|
}
|
|
private DmsWatermarkSnapshot watermark() {
|
DmsWatermarkSnapshot mark = new DmsWatermarkSnapshot();
|
mark.setWatermarkType("TEXT");
|
mark.setContent("CONFIDENTIAL");
|
mark.setFontFamily("SansSerif");
|
mark.setFontColor("#000000");
|
mark.setFontSize(18);
|
mark.setOpacity(100);
|
mark.setLayoutMode("POSITION");
|
mark.setMarkWidthMm(new BigDecimal("80"));
|
mark.setMarkHeightMm(new BigDecimal("20"));
|
DmsWatermarkPositionSnapshot position = new DmsWatermarkPositionSnapshot();
|
position.setPaperWidthMm(new BigDecimal("210"));
|
position.setPaperHeightMm(new BigDecimal("297"));
|
position.setPortraitXMm(new BigDecimal("65"));
|
position.setPortraitYMm(new BigDecimal("138"));
|
mark.setPositions(List.of(position));
|
return mark;
|
}
|
|
private long darkPixels(BufferedImage image) {
|
long count = 0;
|
for (int y = 0; y < image.getHeight(); y++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
if ((image.getRGB(x, y) & 0x00ffffff) < 0x00808080) count++;
|
}
|
}
|
return count;
|
}
|
}
|