diff --git a/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/DssSigningEngine.java b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/DssSigningEngine.java index d2df1027..3cd864f7 100644 --- a/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/DssSigningEngine.java +++ b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/DssSigningEngine.java @@ -53,9 +53,12 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDRectangle; +import eu.europa.esig.dss.alert.LogOnStatusAlert; import eu.europa.esig.dss.enumerations.CertificationPermission; import eu.europa.esig.dss.enumerations.DigestAlgorithm; import eu.europa.esig.dss.enumerations.SignatureLevel; +import eu.europa.esig.dss.enumerations.TextWrapping; +import eu.europa.esig.dss.pdf.PdfSignatureFieldPositionChecker; import eu.europa.esig.dss.model.DSSDocument; import eu.europa.esig.dss.model.FileDocument; import eu.europa.esig.dss.model.SignatureValue; @@ -64,6 +67,8 @@ import eu.europa.esig.dss.pades.PAdESSignatureParameters; import eu.europa.esig.dss.pades.SignatureFieldParameters; import eu.europa.esig.dss.pades.SignatureImageParameters; +import net.sf.jsignpdf.engine.dss.pdfbox.JSignPdfPdfObjFactory; +import net.sf.jsignpdf.engine.dss.pdfbox.JSignPdfSignatureImageParameters; import eu.europa.esig.dss.pades.SignatureImageTextParameters; import eu.europa.esig.dss.pades.signature.PAdESService; import eu.europa.esig.dss.service.http.commons.TimestampDataLoader; @@ -300,6 +305,14 @@ public boolean sign(final BasicSignerOptions options, final EngineConfig engineC } final PAdESService service = new PAdESService(verifier); + // Use custom PDF object factory with background-image layering + // and tolerant signature field position checking + JSignPdfPdfObjFactory pdfObjFactory = new JSignPdfPdfObjFactory(); + PdfSignatureFieldPositionChecker positionChecker = new PdfSignatureFieldPositionChecker(); + positionChecker.setAlertOnSignatureFieldOverlap(new LogOnStatusAlert()); + pdfObjFactory.setPdfSignatureFieldPositionChecker(positionChecker); + service.setPdfObjFactory(pdfObjFactory); + if (useTsa) { LOGGER.info(RES.get("console.creatingTsaClient")); service.setTspSource(buildTspSource(options, parameters, digestAlgorithm, proxyConfig)); @@ -551,7 +564,7 @@ private AccessPermission buildAccessPermission(BasicSignerOptions options) { private void configureVisibleSignature(PAdESSignatureParameters parameters, BasicSignerOptions options, Certificate[] chain, Calendar signingCal, File inFile) throws Exception { - final SignatureImageParameters imageParams = new SignatureImageParameters(); + final JSignPdfSignatureImageParameters imageParams = new JSignPdfSignatureImageParameters(); int page = options.getPage(); float pageWidth; @@ -590,19 +603,34 @@ private void configureVisibleSignature(PAdESSignatureParameters parameters, Basi final RenderMode renderMode = options.getRenderMode(); final boolean withGraphic = renderMode == RenderMode.GRAPHIC_AND_DESCRIPTION; - // DSS renders a single signature image. In GRAPHIC_AND_DESCRIPTION mode that image is the signature - // graphic (options.imgPath); in the other render modes it is the background image (options.bgImgPath). - // The two are mutually exclusive here (unlike OpenPDF, which layers them), and we never silently - // substitute one for the other: a graphic render mode with no graphic configured yields text only. - final String imagePath = withGraphic ? options.getImgPath() : options.getBgImgPath(); - if (imagePath != null) { - LOGGER.info(RES.get("console.createImage", imagePath)); - imageParams.setImage(new FileDocument(imagePath)); + // Background image (drawn first, behind everything) — available in all modes + final String bgImgPath = options.getBgImgPath(); + if (bgImgPath != null) { + LOGGER.info(RES.get("console.createImage", bgImgPath)); + imageParams.setBackgroundImage(new FileDocument(bgImgPath)); + imageParams.setBackgroundScale(options.getBgImgScale()); + } + + // Foreground signature graphic (drawn above background, below text) — used in GRAPHIC_AND_DESCRIPTION mode + if (withGraphic) { + final String imgPath = options.getImgPath(); + if (imgPath != null) { + LOGGER.info(RES.get("console.createImage", imgPath)); + imageParams.setImage(new FileDocument(imgPath)); + } } LOGGER.info(RES.get("console.setL2Text")); final SignatureImageTextParameters textParams = new SignatureImageTextParameters(); textParams.setText(buildSignatureText(options, chain, signingCal)); + // FILL_BOX_AND_LINEBREAK: DSS auto-calculates the largest font that fits + // the signature rectangle, wrapping lines as needed. The font-size field + // in the GUI is used as the starting reference but the actual size is + // driven entirely by the box dimensions in this mode. + textParams.setTextWrapping(TextWrapping.FILL_BOX_AND_LINEBREAK); + // Transparent text background so the background image shows through. + // (DSS defaults to solid white which would paint over the image.) + textParams.setBackgroundColor(null); final DSSFont font = DssFontUtils.getVisibleSignatureFont(); if (font != null) { float fontSize = options.getL2TextFontSize(); diff --git a/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfOverlaySignatureDrawer.java b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfOverlaySignatureDrawer.java new file mode 100644 index 00000000..02236709 --- /dev/null +++ b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfOverlaySignatureDrawer.java @@ -0,0 +1,415 @@ +package net.sf.jsignpdf.engine.dss.pdfbox; + +import eu.europa.esig.dss.model.DSSDocument; +import eu.europa.esig.dss.pades.DSSFileFont; +import eu.europa.esig.dss.pades.DSSFont; +import eu.europa.esig.dss.pades.PAdESUtils; +import eu.europa.esig.dss.pades.SignatureImageParameters; +import eu.europa.esig.dss.pades.SignatureImageTextParameters; +import eu.europa.esig.dss.pdf.AnnotationBox; +import eu.europa.esig.dss.pdf.pdfbox.PdfBoxUtils; +import eu.europa.esig.dss.pdf.pdfbox.visible.AbstractPdfBoxSignatureDrawer; +import eu.europa.esig.dss.pdf.pdfbox.visible.PdfBoxNativeFont; +import eu.europa.esig.dss.pdf.pdfbox.visible.nativedrawer.PdfBoxDSSFontMetrics; +import eu.europa.esig.dss.pdf.pdfbox.visible.nativedrawer.PdfBoxFontMapper; +import eu.europa.esig.dss.pdf.visible.DSSFontMetrics; +import eu.europa.esig.dss.pdf.visible.ImageRotationUtils; +import eu.europa.esig.dss.pdf.visible.ImageUtils; +import eu.europa.esig.dss.pdf.visible.SignatureFieldDimensionAndPosition; +import eu.europa.esig.dss.spi.signature.resources.DSSResourcesHandler; +import eu.europa.esig.dss.spi.signature.resources.DSSResourcesHandlerBuilder; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.io.IOUtils; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDType0Font; +import org.apache.pdfbox.pdmodel.graphics.color.PDColor; +import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace; +import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray; +import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB; +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.apache.pdfbox.pdmodel.interactive.form.PDField; +import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; +import org.apache.pdfbox.util.Matrix; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + +/* + * Custom DSS PDFBox drawer for JSignPdf. + * Draws background, then image, then overlays text on top. + */ +public class JSignPdfOverlaySignatureDrawer extends AbstractPdfBoxSignatureDrawer { + + private static final Logger LOG = LoggerFactory.getLogger(JSignPdfOverlaySignatureDrawer.class); + + private PDFont pdFont; + + private DSSResourcesHandlerBuilder resourcesHandlerBuilder = PAdESUtils.DEFAULT_RESOURCES_HANDLER_BUILDER; + + public void setResourcesHandlerBuilder(DSSResourcesHandlerBuilder resourcesHandlerBuilder) { + this.resourcesHandlerBuilder = resourcesHandlerBuilder; + } + + @Override + public void init(SignatureImageParameters parameters, PDDocument document, SignatureOptions signatureOptions) + throws IOException { + super.init(parameters, document, signatureOptions); + if (!parameters.getTextParameters().isEmpty()) { + this.pdFont = initFont(); + } + } + + private PDFont initFont() throws IOException { + DSSFont dssFont = parameters.getTextParameters().getFont(); + if (dssFont instanceof PdfBoxNativeFont) { + PdfBoxNativeFont nativeFont = (PdfBoxNativeFont) dssFont; + return nativeFont.getFont(); + } + if (dssFont instanceof DSSFileFont) { + DSSFileFont fileFont = (DSSFileFont) dssFont; + try (InputStream is = fileFont.getInputStream()) { + return PDType0Font.load(document, is, fileFont.isEmbedFontSubset()); + } + } + return PdfBoxFontMapper.getPDFont(dssFont.getJavaFont()); + } + + @Override + protected DSSFontMetrics getDSSFontMetrics() { + return new PdfBoxDSSFontMetrics(pdFont); + } + + /** + * Caps the DSS-calculated text size at the user's preferred font size. + * With {@link TextWrapping#FILL_BOX_AND_LINEBREAK}, DSS ignores the font + * size and may produce oversized text on large boxes. This override uses + * the user's font size as an upper bound: text still auto-scales DOWN for + * small boxes, but never exceeds the preferred size. + */ + @Override + public SignatureFieldDimensionAndPosition buildSignatureFieldBox() { + SignatureFieldDimensionAndPosition dim = super.buildSignatureFieldBox(); + SignatureImageTextParameters textParams = parameters.getTextParameters(); + if (textParams != null && textParams.getFont() != null) { + float preferredSize = textParams.getFont().getSize(); + if (preferredSize > 0f && dim.getTextSize() > preferredSize) { + dim.setTextSize(preferredSize); + } + } + return dim; + } + + @Override + public void draw() throws IOException { + try (DSSResourcesHandler resourcesHandler = resourcesHandlerBuilder.createResourcesHandler(); + OutputStream os = resourcesHandler.createOutputStream(); + PDDocument doc = new PDDocument()) { + + int pageNumber = parameters.getFieldParameters().getPage() - ImageUtils.DEFAULT_FIRST_PAGE; + PDPage originalPage = document.getPage(pageNumber); + SignatureFieldDimensionAndPosition dimensionAndPosition = buildSignatureFieldBox(); + + PDPage page = new PDPage(originalPage.getMediaBox()); + doc.addPage(page); + PDAcroForm acroForm = new PDAcroForm(doc); + doc.getDocumentCatalog().setAcroForm(acroForm); + PDSignatureField signatureField = new PDSignatureField(acroForm); + PDAnnotationWidget widget = signatureField.getWidgets().get(0); + List acroFormFields = acroForm.getFields(); + acroForm.setSignaturesExist(true); + acroForm.setAppendOnly(true); + acroForm.getCOSObject().setDirect(true); + acroFormFields.add(signatureField); + + PDRectangle rectangle = getPdRectangle(dimensionAndPosition); + widget.setRectangle(rectangle); + + PDAppearanceDictionary appearance = PdfBoxUtils.createSignatureAppearanceDictionary(doc, rectangle); + widget.setAppearance(appearance); + + PDAppearanceStream appearanceStream = appearance.getNormalAppearance().getAppearanceStream(); + try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) { + rotateSignature(cs, rectangle, dimensionAndPosition); + setFieldBackground(cs, parameters.getBackgroundColor()); + DSSDocument background = null; + float backgroundScale = 0f; + if (parameters instanceof JSignPdfSignatureImageParameters) { + JSignPdfSignatureImageParameters jsignParams = (JSignPdfSignatureImageParameters) parameters; + background = jsignParams.getBackgroundImage(); + backgroundScale = jsignParams.getBackgroundScale(); + } + + if (background != null) { + setBackgroundImage(cs, doc, dimensionAndPosition, background, backgroundScale); + } + setImageScaledToBox(cs, doc, dimensionAndPosition, parameters.getImage()); + setText(cs, dimensionAndPosition, parameters); + } + + doc.save(os); + DSSDocument document = resourcesHandler.writeToDSSDocument(); + try (InputStream is = document.openStream()) { + signatureOptions.setVisualSignature(is); + } + } + } + + private void rotateSignature(PDPageContentStream cs, PDRectangle rectangle, + SignatureFieldDimensionAndPosition dimensionAndPosition) throws IOException { + switch (dimensionAndPosition.getGlobalRotation()) { + case ImageRotationUtils.ANGLE_90: + cs.transform(Matrix.getRotateInstance(Math.toRadians(ImageRotationUtils.ANGLE_270), 0, 0)); + cs.transform(Matrix.getTranslateInstance(-rectangle.getHeight(), 0)); + break; + case ImageRotationUtils.ANGLE_180: + cs.transform(Matrix.getRotateInstance(Math.toRadians(ImageRotationUtils.ANGLE_180), 0, 0)); + cs.transform(Matrix.getTranslateInstance(-rectangle.getWidth(), -rectangle.getHeight())); + break; + case ImageRotationUtils.ANGLE_270: + cs.transform(Matrix.getRotateInstance(Math.toRadians(ImageRotationUtils.ANGLE_90), 0, 0)); + cs.transform(Matrix.getTranslateInstance(0, -rectangle.getWidth())); + break; + case ImageRotationUtils.ANGLE_360: + case ImageRotationUtils.ANGLE_0: + break; + default: + throw new IllegalStateException(ImageRotationUtils.SUPPORTED_ANGLES_ERROR_MESSAGE); + } + } + + private void setFieldBackground(PDPageContentStream cs, Color color) throws IOException { + setBackground(cs, color, new PDRectangle(-5000, -5000, 10000, 10000)); + } + + private void setBackground(PDPageContentStream cs, Color color, PDRectangle rect) throws IOException { + if (color != null) { + setAlphaChannel(cs, color); + setNonStrokingColor(cs, color); + cs.addRect(rect.getLowerLeftX(), rect.getLowerLeftY(), rect.getWidth(), rect.getHeight()); + cs.fill(); + cleanTransparency(cs, color); + } + } + + private void setImageScaledToBox(PDPageContentStream cs, PDDocument doc, + SignatureFieldDimensionAndPosition dimensionAndPosition, DSSDocument image) throws IOException { + if (image == null) { + return; + } + + AnnotationBox annotationBox = dimensionAndPosition.getAnnotationBox(); + float boxWidth = annotationBox.getWidth(); + float boxHeight = annotationBox.getHeight(); + AnnotationBox imageBoundaryBox = ImageUtils.getImageBoundaryBox(image); + float imageWidth = imageBoundaryBox.getWidth(); + float imageHeight = imageBoundaryBox.getHeight(); + if (imageWidth <= 0f || imageHeight <= 0f) { + return; + } + + float imageRatio = imageWidth / imageHeight; + float boxRatio = boxWidth / boxHeight; + float drawWidth; + float drawHeight; + float drawX; + float drawY; + if (imageRatio < boxRatio) { + drawHeight = boxHeight; + drawWidth = boxHeight * imageRatio; + drawX = (boxWidth - drawWidth) / 2f; + drawY = 0f; + } else { + drawWidth = boxWidth; + drawHeight = boxWidth / imageRatio; + drawX = 0f; + drawY = (boxHeight - drawHeight) / 2f; + } + + try (InputStream is = image.openStream()) { + cs.saveGraphicsState(); + byte[] bytes = IOUtils.toByteArray(is); + PDImageXObject imageXObject = PDImageXObject.createFromByteArray(doc, bytes, image.getName()); + cs.drawImage(imageXObject, drawX, drawY, drawWidth, drawHeight); + cs.restoreGraphicsState(); + } + } + + private void setBackgroundImage(PDPageContentStream cs, PDDocument doc, + SignatureFieldDimensionAndPosition dimensionAndPosition, DSSDocument image, float bgScale) + throws IOException { + AnnotationBox annotationBox = dimensionAndPosition.getAnnotationBox(); + float boxWidth = annotationBox.getWidth(); + float boxHeight = annotationBox.getHeight(); + AnnotationBox imageBoundaryBox = ImageUtils.getImageBoundaryBox(image); + float imageWidth = imageBoundaryBox.getWidth(); + float imageHeight = imageBoundaryBox.getHeight(); + if (imageWidth <= 0f || imageHeight <= 0f) { + return; + } + + float drawWidth; + float drawHeight; + float drawX; + float drawY; + + if (bgScale == 0f) { + drawWidth = boxWidth; + drawHeight = boxHeight; + drawX = 0f; + drawY = 0f; + } else { + float scale = bgScale > 0f ? bgScale : Math.min(boxWidth / imageWidth, boxHeight / imageHeight); + drawWidth = imageWidth * scale; + drawHeight = imageHeight * scale; + drawX = (boxWidth - drawWidth) / 2f; + drawY = (boxHeight - drawHeight) / 2f; + } + + try (InputStream is = image.openStream()) { + cs.saveGraphicsState(); + byte[] bytes = IOUtils.toByteArray(is); + PDImageXObject imageXObject = PDImageXObject.createFromByteArray(doc, bytes, image.getName()); + cs.drawImage(imageXObject, drawX, drawY, drawWidth, drawHeight); + cs.restoreGraphicsState(); + } + } + + private void setText(PDPageContentStream cs, SignatureFieldDimensionAndPosition dimensionAndPosition, + SignatureImageParameters parameters) throws IOException { + SignatureImageTextParameters textParameters = parameters.getTextParameters(); + if (!textParameters.isEmpty()) { + setTextBackground(cs, textParameters, dimensionAndPosition); + float fontSize = dimensionAndPosition.getTextSize(); + cs.beginText(); + cs.setFont(pdFont, fontSize); + setNonStrokingColor(cs, textParameters.getTextColor()); + setAlphaChannel(cs, textParameters.getTextColor()); + + PdfBoxDSSFontMetrics pdfBoxFontMetrics = new PdfBoxDSSFontMetrics(pdFont); + + String text = dimensionAndPosition.getText(); + String[] strings = pdfBoxFontMetrics.getLines(text); + + float lineHeight = pdfBoxFontMetrics.getHeight(text, dimensionAndPosition.getTextSize()); + cs.setLeading(lineHeight); + + cs.newLineAtOffset(dimensionAndPosition.getTextX(), + dimensionAndPosition.getTextHeight() + dimensionAndPosition.getTextY() - fontSize); + + float previousOffset = 0; + for (String str : strings) { + float stringWidth = pdfBoxFontMetrics.getWidth(str, fontSize); + float offsetX = 0; + switch (textParameters.getSignerTextHorizontalAlignment()) { + case RIGHT: + offsetX = dimensionAndPosition.getTextWidth() - stringWidth - previousOffset; + break; + case CENTER: + offsetX = (dimensionAndPosition.getTextWidth() - stringWidth) / 2 - previousOffset; + break; + default: + break; + } + previousOffset += offsetX; + cs.newLineAtOffset(offsetX, 0); + cs.showText(str); + cs.newLine(); + } + cs.endText(); + cleanTransparency(cs, textParameters.getTextColor()); + } + } + + private void setTextBackground(PDPageContentStream cs, SignatureImageTextParameters textParameters, + SignatureFieldDimensionAndPosition dimensionAndPosition) throws IOException { + if (textParameters.getBackgroundColor() != null) { + PDRectangle rect = new PDRectangle( + dimensionAndPosition.getTextBoxX(), dimensionAndPosition.getTextBoxY(), + dimensionAndPosition.getTextBoxWidth(), dimensionAndPosition.getTextBoxHeight()); + setBackground(cs, textParameters.getBackgroundColor(), rect); + } + } + + private void setNonStrokingColor(PDPageContentStream cs, Color color) throws IOException { + if (color != null) { + cs.setNonStrokingColor(toPDColor(color)); + } + } + + private PDColor toPDColor(Color color) { + float[] components; + PDColorSpace pdColorSpace; + if (ImageUtils.isGrayscale(color)) { + components = new float[] { color.getRed() / 255f }; + pdColorSpace = PDDeviceGray.INSTANCE; + } else { + components = new float[] { color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f }; + pdColorSpace = PDDeviceRGB.INSTANCE; + } + return new PDColor(components, pdColorSpace); + } + + private void setAlphaChannel(PDPageContentStream cs, Color color) throws IOException { + if (color != null) { + float alpha = color.getAlpha(); + if (alpha < ImageUtils.OPAQUE_VALUE) { + LOG.warn("Transparency detected and enabled (Be aware: not valid with PDF/A !)"); + setAlpha(cs, alpha); + } + } + } + + private void setAlpha(PDPageContentStream cs, float alpha) throws IOException { + PDExtendedGraphicsState gs = new PDExtendedGraphicsState(); + gs.setNonStrokingAlphaConstant(alpha / ImageUtils.OPAQUE_VALUE); + cs.setGraphicsStateParameters(gs); + } + + private void cleanTransparency(PDPageContentStream cs, Color color) throws IOException { + if (color != null) { + float alpha = color.getAlpha(); + if (alpha < ImageUtils.OPAQUE_VALUE) { + setAlpha(cs, ImageUtils.OPAQUE_VALUE); + } + } + } + + private PDRectangle getPdRectangle(SignatureFieldDimensionAndPosition dimensionAndPosition) { + AnnotationBox annotationBox = dimensionAndPosition.getAnnotationBox(); + + PDRectangle pdRectangle = new PDRectangle(); + pdRectangle.setLowerLeftX(annotationBox.getMinX()); + pdRectangle.setLowerLeftY(annotationBox.getMinY()); + pdRectangle.setUpperRightX(annotationBox.getMaxX()); + pdRectangle.setUpperRightY(annotationBox.getMaxY()); + return pdRectangle; + } + + @Override + protected String getExpectedColorSpaceName() throws IOException { + if (parameters.getImage() != null) { + try (InputStream is = parameters.getImage().openStream()) { + byte[] bytes = IOUtils.toByteArray(is); + PDImageXObject imageXObject = PDImageXObject.createFromByteArray(document, bytes, parameters.getImage().getName()); + PDColorSpace colorSpace = imageXObject.getColorSpace(); + return colorSpace.getName(); + } + } + return ImageUtils.containRGBColor(parameters) ? COSName.DEVICERGB.getName() : COSName.DEVICEGRAY.getName(); + } +} diff --git a/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfPdfObjFactory.java b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfPdfObjFactory.java new file mode 100644 index 00000000..9d6fd8dc --- /dev/null +++ b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfPdfObjFactory.java @@ -0,0 +1,29 @@ +package net.sf.jsignpdf.engine.dss.pdfbox; + +import eu.europa.esig.dss.pdf.AbstractPdfObjFactory; +import eu.europa.esig.dss.pdf.PDFServiceMode; +import eu.europa.esig.dss.pdf.PDFSignatureService; +import eu.europa.esig.dss.pdf.pdfbox.PdfBoxSignatureService; + +public class JSignPdfPdfObjFactory extends AbstractPdfObjFactory { + + @Override + public PDFSignatureService newPAdESSignatureService() { + return configure(new PdfBoxSignatureService(PDFServiceMode.SIGNATURE, new JSignPdfSignatureDrawerFactory())); + } + + @Override + public PDFSignatureService newContentTimestampService() { + return configure(new PdfBoxSignatureService(PDFServiceMode.CONTENT_TIMESTAMP, new JSignPdfSignatureDrawerFactory())); + } + + @Override + public PDFSignatureService newSignatureTimestampService() { + return configure(new PdfBoxSignatureService(PDFServiceMode.SIGNATURE_TIMESTAMP, new JSignPdfSignatureDrawerFactory())); + } + + @Override + public PDFSignatureService newArchiveTimestampService() { + return configure(new PdfBoxSignatureService(PDFServiceMode.ARCHIVE_TIMESTAMP, new JSignPdfSignatureDrawerFactory())); + } +} diff --git a/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfSignatureDrawerFactory.java b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfSignatureDrawerFactory.java new file mode 100644 index 00000000..3e77ce67 --- /dev/null +++ b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfSignatureDrawerFactory.java @@ -0,0 +1,13 @@ +package net.sf.jsignpdf.engine.dss.pdfbox; + +import eu.europa.esig.dss.pades.SignatureImageParameters; +import eu.europa.esig.dss.pdf.pdfbox.visible.PdfBoxSignatureDrawer; +import eu.europa.esig.dss.pdf.pdfbox.visible.PdfBoxSignatureDrawerFactory; + +public class JSignPdfSignatureDrawerFactory implements PdfBoxSignatureDrawerFactory { + + @Override + public PdfBoxSignatureDrawer getSignatureDrawer(SignatureImageParameters imageParameters) { + return new JSignPdfOverlaySignatureDrawer(); + } +} diff --git a/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfSignatureImageParameters.java b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfSignatureImageParameters.java new file mode 100644 index 00000000..f5bde115 --- /dev/null +++ b/engines/dss/src/main/java/net/sf/jsignpdf/engine/dss/pdfbox/JSignPdfSignatureImageParameters.java @@ -0,0 +1,33 @@ +package net.sf.jsignpdf.engine.dss.pdfbox; + +import eu.europa.esig.dss.model.DSSDocument; +import eu.europa.esig.dss.pades.SignatureImageParameters; + +public class JSignPdfSignatureImageParameters extends SignatureImageParameters { + + private static final long serialVersionUID = 1L; + + private DSSDocument backgroundImage; + private float backgroundScale = -1f; + + public DSSDocument getBackgroundImage() { + return backgroundImage; + } + + public void setBackgroundImage(DSSDocument backgroundImage) { + this.backgroundImage = backgroundImage; + } + + public float getBackgroundScale() { + return backgroundScale; + } + + public void setBackgroundScale(float backgroundScale) { + this.backgroundScale = backgroundScale; + } + + @Override + public boolean isEmpty() { + return getImage() == null && backgroundImage == null && getTextParameters().isEmpty(); + } +}