From 5af1d89ff4f909e73db2aa3d3ef8a013785c9f2f Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Fri, 8 Mar 2024 16:20:12 +0100 Subject: feat(core): add new page position parameter 'last' --- doc/PDFAS4_Dokumentation.docx | Bin 94895 -> 95178 bytes .../at/knowcenter/wag/egov/egiz/pdf/TablePos.java | 361 ++++++++++----------- .../lib/impl/pdfbox2/positioning/Positioning.java | 86 +++-- .../impl/signing/pdfbox2/PADESPDFBOXSigner.java | 2 +- .../POS_AUTO_WITH_NEWPAGE/config.properties | 7 + .../POS_AUTO_WITH_NEWPAGE/example.pdf | Bin 0 -> 41972 bytes .../POS_AUTO_WITH_NEWPAGE/example_ref.png | Bin 0 -> 135525 bytes .../public_pdfbox2/POS_LAST/config.properties | 7 + .../public_pdfbox2/POS_LAST/example.pdf | Bin 0 -> 41972 bytes .../public_pdfbox2/POS_LAST/example_ref.png | Bin 0 -> 308465 bytes .../POS_LAST_WITH_POS/config.properties | 7 + .../public_pdfbox2/POS_LAST_WITH_POS/example.pdf | Bin 0 -> 41972 bytes .../POS_LAST_WITH_POS/example_ref.png | Bin 0 -> 315752 bytes 13 files changed, 227 insertions(+), 243 deletions(-) create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/config.properties create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example.pdf create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example_ref.png create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/config.properties create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example.pdf create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example_ref.png create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/config.properties create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example.pdf create mode 100644 pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example_ref.png diff --git a/doc/PDFAS4_Dokumentation.docx b/doc/PDFAS4_Dokumentation.docx index b1bd82d5..736f7672 100644 Binary files a/doc/PDFAS4_Dokumentation.docx and b/doc/PDFAS4_Dokumentation.docx differ diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java index 86e270d0..33b6cf85 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java @@ -49,8 +49,12 @@ package at.knowcenter.wag.egov.egiz.pdf; import java.io.Serializable; +import java.text.MessageFormat; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; /** * Class that holds the exact position where the table should be written to the @@ -59,9 +63,14 @@ import at.gv.egiz.pdfas.common.exceptions.PdfAsException; * @author wprinz * @author mruhmer */ +@NoArgsConstructor public class TablePos implements Serializable { + public enum PAGE_MODE {AUTO, LAST, EXACT, NEW}; + public enum POS_MODE {AUTO, EXACT}; + + /** * SVUID. */ @@ -71,198 +80,215 @@ public class TablePos implements Serializable * The page on which the block should be displayed. * */ + @Getter private int page = 0; /** * The x position. */ - private float pos_x = 0.0f; + @Getter + private float posX = 0.0f; /** * The y position. */ - private float pos_y = 0.0f; + @Getter + private float posY = 0.0f; /** * The width of the block. */ - public float width = 0.0f; + @Getter + @Setter + private float width = 0.0f; + /** * The top y position of the footer line. */ - public float footer_line = 0.0f; + private float footerLine = 0.0f; /** * The rotation of the signature block */ - public float rotation = 0.0f; - - /** - * The y position. - */ - public String myposstring = ""; + @Getter + private float rotation = 0.0f; - private boolean newpage = false; - private boolean autoX = true; - private boolean autoY = true; - private boolean autoW = true; - private boolean autoP = true; + + @Getter + private PAGE_MODE pageMode = PAGE_MODE.AUTO; + + @Getter + private POS_MODE xMode = POS_MODE.AUTO; + + @Getter + private POS_MODE yMode = POS_MODE.AUTO; + + @Getter + private POS_MODE wMode = POS_MODE.AUTO; + + public boolean isXauto() { + return xMode.equals(POS_MODE.AUTO); - public boolean isXauto() - { - return this.autoX; } - public boolean isYauto() - { - return this.autoY; + + public boolean isYauto() { + return yMode.equals(POS_MODE.AUTO); + } - public boolean isWauto() - { - return this.autoW; + + public boolean isWauto() { + return wMode.equals(POS_MODE.AUTO); } - public boolean isPauto() - { - return this.autoP; + + public float getFooterLine() { + //ignore if newpage and y is not auto + return yMode.equals(POS_MODE.EXACT) || pageMode.equals(PAGE_MODE.NEW) ? 0.0f : footerLine; + + } + + /** + * Constructor. + * + * @param pos_string The pos instruction. + * format : [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo];[r:r_algo] + * x_algo:='auto' ... automatic positioning x + * floatvalue ... absolute x + * y_algo:='auto' ... automatic positioning y + * floatvalue ... absolute y + * w_algo:='auto' ... automatic width + * floatvalue ... absolute width + * p_algo:='auto' ... automatic last page + * 'new' ... new page + * 'last' ... force last page + * intvalue ... pagenumber + * f_algo floatvalue ... consider footerline (only if y_algo is auto and p_algo is not 'new') + * r_algo floatvalue ... rotate the table arround the lower left corner anti clockwise in degree + * @throws PdfAsException + */ + public TablePos(String pos_string) throws PdfAsException { + parsePosString(pos_string); + } - public boolean isNewPage() - { - return this.newpage; + + /** + * Constructor + * @param pos_string The pos instruction. + * format : [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo];[r:r_algo] + * x_algo:='auto' ... automatic positioning x + * floatvalue ... absolute x + * y_algo:='auto' ... automatic positioning y + * floatvalue ... absolute y + * w_algo:='auto' ... automatic width + * floatvalue ... absolute width + * p_algo:='auto' ... automatic position + * 'new' ... new page + * 'last' ... force last page + * intvalue ... pagenumber + * f_algo floatvalue ... consider footerline (only if y_algo is auto and p_algo is not 'new') + * r_algo floatvalue ... rotate the table arround the lower left corner anti clockwise in degree + * @param basePosition The base Table Position these values are the base values + * @throws PdfAsException + */ + public TablePos(String pos_string, TablePos basePosition) throws PdfAsException { + if(basePosition != null) { + readFromPos(basePosition); + + } + parsePosString(pos_string); + } - public int getPage() - { - return this.page; + + public String toString() { + String thatsme = "pos_x:"+this.posX+" pos_y:"+this.posY+" page:"+this.page+" width:"+this.width+" footer:"+this.footerLine+" rotation:"+this.rotation+"\n "+" autoX:"+xMode+" autoY:"+yMode+" autoW:"+wMode+" pageMode:"+pageMode; + return thatsme; + + } + + + private float parseAndCheck(String commandval, int minValue, String errorMsg) + throws PdfAsException, NumberFormatException { + float value= Float.parseFloat(commandval); + if (value < minValue) { + throw new PdfAsException(MessageFormat.format(errorMsg, value)); + + } + return value; + } - public float getFooterLine() - { - //ignore if newpage and y is not auto - if (!this.autoY || this.newpage) - { - return 0.0f; - } - return this.footer_line; - } - public float getPosX() - { - return this.pos_x; - } - public float getPosY() - { - return this.pos_y; - } - public float getWidth() - { - return this.width; - } - public TablePos() - { - //nothing to do --> default - } private void parsePosString(String pos_string) throws PdfAsException { //parse posstring and throw exception //[x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo] String[] strs = pos_string.split(";"); - try - { - for (int cmds = 0;cmds doc_pages) { - log.debug("Document is shorter than requested page for signature block. Adding new page ..."); + log.info("Document is shorter than requested page for signature block. Adding new page ..."); make_new_page = true; page = doc_pages; - } + } } - + make_new_page = checkIfNewPageIsAllowed(make_new_page, numberOfExistingSignatures, settings, profilConfig); - - + final PDPage pdPage = pdfDataSource.getPage(page - 1); - PDRectangle cropBox = pdPage.getCropBox(); - - // fallback to MediaBox if Cropbox not available! - - if (cropBox == null) { - cropBox = pdPage.getCropBox(); - } - - if (cropBox == null) { - cropBox = pdPage.getCropBox(); - } - - // getPagedimensions - // Rectangle psize = reader.getPageSizeWithRotation(page); - // int page_rotation = reader.getPageRotation(page); - - // Integer rotation = pdPage.getRotation(); - // int page_rotation = rotation.intValue(); - - final int rotation = pdPage.getRotation(); - log.debug("Original CropBox: " + cropBox.toString()); - + + final int rotation = pdPage.getRotation(); cropBox = rotateBox(cropBox, rotation); - log.debug("Rotated CropBox: " + cropBox.toString()); final float page_width = cropBox.getWidth(); final float page_height = cropBox.getHeight(); - log.debug("CropBox width: " + page_width); log.debug("CropBox heigth: " + page_height); @@ -161,6 +138,8 @@ public class Positioning { // calculate width // center float pre_width = page_width - 2 * pre_pos_x; + + if (!pos.isWauto()) { // we do have absolute width pre_width = pos.getWidth(); @@ -178,9 +157,19 @@ public class Positioning { pdf_table.fixWidth(); final float table_height = pdf_table.getHeight(); + // now check pos_y - float pos_y = pos.getPosY(); - + + // last page was requested. Use all parameters as they was + if (PAGE_MODE.LAST.equals(pos.getPageMode())) { + log.debug("Positioning on last page was requested. Selecting this and use y-position as requested ... "); + return new PositioningInstruction(make_new_page, page, pos_x, + pos.isYauto() ? page_height - SIGNATURE_MARGIN_VERTICAL : pos.getPosY(), + pos.getRotation()); + + } + + // in case an absolute y position is already given OR // if the table is related to an invisible signature // there is no need for further calculations @@ -190,8 +179,9 @@ public class Positioning { if (make_new_page) { page++; - } - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); + } + + return new PositioningInstruction(make_new_page, page, pos_x, pos.getPosY(), pos.getRotation()); } @@ -199,8 +189,8 @@ public class Positioning { if (make_new_page) { // ignore footer in new page page++; - pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); + return new PositioningInstruction(make_new_page, page, pos_x, + page_height - SIGNATURE_MARGIN_VERTICAL, pos.getRotation()); } @@ -210,16 +200,16 @@ public class Positioning { float pre_page_length = calculatePrePageLength(pdfDataSource, page, pdf_table, pos.getFooterLine(), settings); if (pre_page_length == Float.NEGATIVE_INFINITY) { - // we do have an empty page or nothing in area above footerline - pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; - return buildPostitionInfoOnSubpage(pdfDataSource, make_new_page, page, pos_x, pos_y, pos.rotation, + // we do have an empty page or nothing in area above footerline + return buildPostitionInfoOnSubpage(pdfDataSource, make_new_page, page, pos_x, + page_height - SIGNATURE_MARGIN_VERTICAL, pos.getRotation(), pos.getFooterLine(), table_height, pos, page_height, numberOfExistingSignatures, settings, profilConfig); } else { // we do have text take SIGNATURE_MARGIN - pos_y = page_height - pre_page_length - SIGNATURE_MARGIN_VERTICAL; - return buildPostitionInfoOnSubpage(pdfDataSource, make_new_page, page, pos_x, pos_y, pos.rotation, - pos.getFooterLine(), table_height, pos, page_height, numberOfExistingSignatures, settings, profilConfig); + return buildPostitionInfoOnSubpage(pdfDataSource, make_new_page, page, pos_x, + page_height - pre_page_length - SIGNATURE_MARGIN_VERTICAL, + pos.getRotation(), pos.getFooterLine(), table_height, pos, page_height, numberOfExistingSignatures, settings, profilConfig); } } @@ -274,15 +264,17 @@ public class Positioning { private static PositioningInstruction buildPostitionInfoOnSubpage(PDDocument pdfDataSource, boolean make_new_page, int page, float pos_x, float pos_y, float rotation, float footer_line, float table_height, TablePos pos, float page_height, long numberOfExistingSignatures, ISettings settings, SignatureProfileSettings profilConfig) throws PdfAsException { + if (pos_y - footer_line <= table_height) { + boolean isPageModeAuto = PAGE_MODE.AUTO.equals(pos.getPageMode()); - make_new_page = checkIfNewPageIsAllowed(pos.isPauto(), numberOfExistingSignatures, settings, profilConfig); + make_new_page = checkIfNewPageIsAllowed(isPageModeAuto, numberOfExistingSignatures, settings, profilConfig); if (make_new_page) { page++; } - if (!pos.isPauto()) { + if (!isPageModeAuto) { // we have to correct pagenumber page = pdfDataSource.getNumberOfPages(); @@ -292,7 +284,7 @@ public class Positioning { } - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); + return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.getRotation()); } diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java index 7aa46149..b32935c6 100644 --- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java @@ -598,7 +598,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { TablePos tablePos = nextPlaceholderData.getTablePos(); if (minWidth > 0) { if (tablePos.getWidth() < minWidth) { - tablePos.width = minWidth; + tablePos.setWidth(minWidth); log.debug("Correcting placeholder with to minimum width {}", minWidth); } } diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/config.properties b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/config.properties new file mode 100644 index 00000000..7013bc17 --- /dev/null +++ b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/config.properties @@ -0,0 +1,7 @@ +test.type=position +test.name=POS_AUTO_WITH_NEWPAGE +profile.id=SIGNATURBLOCK_DE +position.positioning_string=p:auto +position.page_number=3 +parent=../auto_pos_example.properties +position.ignored_areas=208,803,142,9 diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example.pdf b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example.pdf new file mode 100644 index 00000000..488e5898 Binary files /dev/null and b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example.pdf differ diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example_ref.png b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example_ref.png new file mode 100644 index 00000000..6f537317 Binary files /dev/null and b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_AUTO_WITH_NEWPAGE/example_ref.png differ diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/config.properties b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/config.properties new file mode 100644 index 00000000..94af6eec --- /dev/null +++ b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/config.properties @@ -0,0 +1,7 @@ +test.type=position +test.name=POS_LAST +profile.id=SIGNATURBLOCK_DE +position.positioning_string=p:last +position.page_number=2 +parent=../auto_pos_example.properties +position.ignored_areas=208,803,142,9 diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example.pdf b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example.pdf new file mode 100644 index 00000000..488e5898 Binary files /dev/null and b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example.pdf differ diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example_ref.png b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example_ref.png new file mode 100644 index 00000000..063bf516 Binary files /dev/null and b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST/example_ref.png differ diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/config.properties b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/config.properties new file mode 100644 index 00000000..def92788 --- /dev/null +++ b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/config.properties @@ -0,0 +1,7 @@ +test.type=position +test.name=POS_LAST_WITH_POS +profile.id=SIGNATURBLOCK_DE +position.positioning_string=y:200;p:last +position.page_number=2 +parent=../auto_pos_example.properties +position.ignored_areas=208,181,142,9 diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example.pdf b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example.pdf new file mode 100644 index 00000000..488e5898 Binary files /dev/null and b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example.pdf differ diff --git a/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example_ref.png b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example_ref.png new file mode 100644 index 00000000..f43f91dc Binary files /dev/null and b/pdf-as-tests/src/test/test-suites/public_pdfbox2/POS_LAST_WITH_POS/example_ref.png differ -- cgit v1.2.3