From dce9a1535236da947d9f866421c4f0b8ae47e527 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Wed, 26 Mar 2014 10:59:51 +0100 Subject: Example Table in AP seems OK --- .../lib/impl/stamping/pdfbox/ImageObject.java | 31 + .../impl/stamping/pdfbox/PDFAsTemplateCreator.java | 9 +- .../pdfbox/PDFAsVisualSignatureBuilder.java | 804 +++++++++++++-------- .../pdfbox/PDFAsVisualSignatureDesigner.java | 34 +- .../pdfbox/PDFAsVisualSignatureProperties.java | 40 +- .../lib/impl/stamping/pdfbox/PDFBoxTable.java | 415 +++++++++++ 6 files changed, 1003 insertions(+), 330 deletions(-) create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/ImageObject.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/ImageObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/ImageObject.java new file mode 100644 index 00000000..db057a2b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/ImageObject.java @@ -0,0 +1,31 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; + +public class ImageObject { + private PDXObjectImage image; + private float size; + + public ImageObject(PDXObjectImage image, float size) { + this.image = image; + this.size = size; + } + + public PDXObjectImage getImage() { + return image; + } + + public void setImage(PDXObjectImage image) { + this.image = image; + } + + public float getSize() { + return size; + } + + public void setSize(float size) { + this.size = size; + } + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java index e952ea73..058b08b0 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java @@ -2,9 +2,11 @@ package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; import java.awt.geom.AffineTransform; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import org.apache.pdfbox.cos.COSDocument; import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -123,7 +125,12 @@ public class PDFAsTemplateCreator extends PDFTemplateCreator { ByteArrayInputStream in = null; try { - in = pdfStructure.getTemplateAppearanceStream(); + //COSDocument doc = pdfStructure.getVisualSignature(); + //doc. + //in = pdfStructure.getTemplateAppearanceStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + template.save(baos); + in = new ByteArrayInputStream(baos.toByteArray()); } catch (COSVisitorException e) { diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java index cd4abdf9..49d7b4bd 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java @@ -1,15 +1,25 @@ package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; +import java.awt.Color; +import java.awt.Image; import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import javax.imageio.ImageIO; import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSStream; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDResources; @@ -19,20 +29,22 @@ import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg; import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm; +import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateStructure; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigBuilder; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner; 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.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.common.settings.ISettings; import at.gv.egiz.pdfas.lib.test.mains.TestPDFBoxTable; import at.knowcenter.wag.egov.egiz.table.Entry; +import at.knowcenter.wag.egov.egiz.table.Style; import at.knowcenter.wag.egov.egiz.table.Table; public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { @@ -40,14 +52,15 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { private static final Logger logger = LoggerFactory .getLogger(TestPDFBoxTable.class); - private static void drawTable(PDPage page, - PDPageContentStream contentStream, float x, float y, - Table abstractTable) throws IOException { + private void drawTable(PDPage page, PDPageContentStream contentStream, + float x, float y, PDFBoxTable abstractTable, PDDocument doc, boolean subtable) + throws IOException, PdfAsException { - final int rows = abstractTable.getRows().size(); - final int cols = abstractTable.getMaxCols(); + final int rows = abstractTable.getRowCount(); + final int cols = abstractTable.getColCount(); float[] colsSizes = abstractTable.getColsRelativeWith(); - int max_cols = abstractTable.getMaxCols(); + int max_cols = abstractTable.getColCount(); + float padding = abstractTable.getPadding(); if (colsSizes == null) { colsSizes = new float[max_cols]; // set the column ratio for all columns to 1 @@ -56,8 +69,13 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { } } - logger.info("TOTAL Col: " + abstractTable.getWidth()); - + logger.info("Drawing Table:"); + abstractTable.dumpTable(); + + contentStream.setNonStrokingColor(Color.blue); + contentStream.fillRect(x, y, abstractTable.getWidth(), abstractTable.getHeight()); + contentStream.setNonStrokingColor(Color.BLACK); + float total = 0; for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { @@ -73,67 +91,143 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]); } - final float cellMargin = 5f; - final float rowHeight = 12f + 2 * cellMargin; - final float tableWidth = abstractTable.getWidth(); - final float tableHeight = rowHeight * rows; + contentStream.setLineWidth(0.1f); + + float tableHeight = abstractTable.getHeight(); + float tableWidth = abstractTable.getWidth(); final float colWidth = tableWidth / (float) cols; - // draw the rows - float nexty = y; - for (int i = 0; i <= rows; i++) { - contentStream.drawLine(x, nexty, x + tableWidth, nexty); - nexty -= rowHeight; - } + // TODO: check boarder width + if (1 != 0) { + + // draw the rows + float nexty = y + tableHeight; + for (int i = 0; i <= rows; i++) { + logger.info("ROW LINE: {} {} {} {}", x, nexty, x + tableWidth, + nexty); + contentStream.drawLine(x, nexty, x + tableWidth, nexty); + if (i < abstractTable.getRowHeights().length) { + nexty -= abstractTable.getRowHeights()[i] + padding * 2; + } + if(subtable && i+1 == abstractTable.getRowHeights().length) { + nexty -= padding; + } + } - // draw the columns - float nextx = x; - for (int i = 0; i <= cols; i++) { - contentStream.drawLine(nextx, y, nextx, y - tableHeight); - if (i < colsSizes.length) { - nextx += (colsSizes != null) ? colsSizes[i] : colWidth; + // draw the columns + float nextx = x; + float ypos = y; + float yheight = y + abstractTable.getHeight(); + if(subtable) { + ypos -= padding; + yheight = y + abstractTable.getHeight(); + } + for (int i = 0; i <= cols; i++) { + logger.info("COL LINE: {} {} {} {}", nextx, ypos, nextx, yheight); + contentStream.drawLine(nextx, ypos, nextx, + yheight); + if (i < colsSizes.length) { + nextx += (colsSizes != null) ? colsSizes[i] : colWidth; + } } } - float textx = x + cellMargin; - float texty = y - 15; - for (int i = 0; i < abstractTable.getRows().size(); i++) { - ArrayList row = (ArrayList) abstractTable.getRows().get(i); + float textx = x + padding; + float texty = y + tableHeight; + for (int i = 0; i < abstractTable.getRowCount(); i++) { + ArrayList row = abstractTable.getRow(i); for (int j = 0; j < row.size(); j++) { Entry cell = (Entry) row.get(j); - String text = cell.toString(); - text = "Hallo"; - COSName name = COSName.getPDFName("ANDI_TAG!"); - contentStream.beginMarkedContentSequence(COSName.ALT, name); - contentStream.beginText(); - logger.info("Writing: " + textx + " : " + texty + " = " + text); - contentStream.moveTextPositionByAmount(textx, texty); - - if (text.contains("\n")) { - String[] lines = text.split("\n"); - contentStream.appendRawCommands(10 + " TL\n"); - for (int k = 0; k < lines.length; k++) { - contentStream.drawString(lines[k]); - if (k < lines.length - 1) { - contentStream.appendRawCommands("T*\n"); + if (cell.getType() == Entry.TYPE_CAPTION + || cell.getType() == Entry.TYPE_VALUE) { + String text = (String) cell.getValue(); + float fontsize = 5.f; + float ttexty = texty - padding - fontsize; + COSName name = COSName.getPDFName("ANDI_TAG!"); + contentStream.beginMarkedContentSequence(COSName.ALT, name); + contentStream.beginText(); + logger.info("Writing: " + textx + " : " + ttexty + " = " + + text); + contentStream.moveTextPositionByAmount(textx, ttexty); + + if (text.contains("\n")) { + String[] lines = text.split("\n"); + contentStream.appendRawCommands(fontsize + " TL\n"); + for (int k = 0; k < lines.length; k++) { + contentStream.drawString(lines[k]); + if (k < lines.length - 1) { + contentStream.appendRawCommands("T*\n"); + } } + } else { + contentStream.drawString(text); + } + contentStream.endText(); + contentStream.endMarkedContentSequence(); + } else if (cell.getType() == Entry.TYPE_IMAGE) { + String img_ref = (String) cell.getValue(); + if(!images.containsKey(img_ref)) { + logger.error("Image not prepared! : " + img_ref); + throw new PdfAsException("Image not prepared! : " + img_ref); } - } else { - contentStream.drawString(text); + ImageObject image = images.get(img_ref); + PDXObjectImage pdImage = image.getImage(); + // text = "Row :" + i + "COL: " + j; + COSName name = COSName.getPDFName("ANDI_TAG!"); + contentStream.beginMarkedContentSequence(COSName.ALT, name); + + float imgy = texty; + if(cell.getStyle().getImageVAlign() != null && + cell.getStyle().getImageVAlign().equals(Style.TOP)) { + imgy = texty - padding - image.getSize(); + } else if(cell.getStyle().getImageVAlign() != null && + cell.getStyle().getImageVAlign().equals(Style.BOTTOM)) { + // Should allready be at bottom ... + imgy = texty - abstractTable.getRowHeights()[i] + padding; + } else { + // default to middle + imgy = texty - padding - abstractTable.getRowHeights()[i] / 2; + imgy = imgy - image.getSize() / 2; + } + logger.info("Image: " + textx + " : " + imgy); + contentStream.drawXObject(pdImage, textx, imgy, + image.getSize(), image.getSize()); + contentStream.endMarkedContentSequence(); + + } else if (cell.getType() == Entry.TYPE_TABLE) { + float tableY = texty - abstractTable.getRowHeights()[i] - padding; + float tableX = textx; + //texty = texty - padding; + tableX = textx - padding; + PDFBoxTable tbl_value = (PDFBoxTable) cell.getValue(); + logger.info("Table: " + tableX + " : " + tableY ); + drawTable(page, contentStream, tableX, tableY, tbl_value, doc, true); } - contentStream.endText(); - contentStream.endMarkedContentSequence(); textx += (colsSizes != null) ? colsSizes[j] : colWidth; } - texty -= rowHeight; - textx = x + cellMargin; + //if (i + 1 < abstractTable.getRowHeights().length) { + logger.info("Row {} from {} - {} - {} = {}", i, texty, + abstractTable.getRowHeights()[i], padding * 2, + texty - (abstractTable.getRowHeights()[i] + padding * 2)); + texty -= abstractTable.getRowHeights()[i] + padding * 2; + //texty = texty - abstractTable.getRowHeights()[i + 1] - padding + // * 2; + //texty = texty - abstractTable.getRowHeights()[i] - padding + // * 2; + //} + textx = x + padding; } } private PDFAsVisualSignatureProperties properties; + private ISettings settings; + private PDResources innerFormResources; + private Map images = new HashMap(); - public PDFAsVisualSignatureBuilder(PDFAsVisualSignatureProperties properties) { + public PDFAsVisualSignatureBuilder( + PDFAsVisualSignatureProperties properties, ISettings settings) { this.properties = properties; + this.settings = settings; } @Override @@ -141,6 +235,9 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { COSArray procSetArr = new COSArray(); procSetArr.add(COSName.getPDFName("PDF")); procSetArr.add(COSName.getPDFName("Text")); + procSetArr.add(COSName.getPDFName("ImageC")); + procSetArr.add(COSName.getPDFName("ImageB")); + procSetArr.add(COSName.getPDFName("ImageI")); getStructure().setProcSet(procSetArr); logger.info("ProcSet array has been created"); } @@ -156,11 +253,99 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { @Override public void createInnerFormStream(PDDocument template) { try { + float[] colsSizes = properties.getMainTable().getColsRelativeWith(); + int max_cols = properties.getMainTable().getColCount(); + float padding = properties.getMainTable().getPadding(); + if (colsSizes == null) { + colsSizes = new float[max_cols]; + // set the column ratio for all columns to 1 + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + colsSizes[cols_idx] = 1; + } + } + + logger.info("TOTAL Width: " + properties.getMainTable().getWidth()); + + float total = 0; + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + total += colsSizes[cols_idx]; + } + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + colsSizes[cols_idx] = (colsSizes[cols_idx] / total) + * properties.getMainTable().getWidth(); + } + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]); + } + + // Hint we have to create all PDXObjectImages before creating the + // PDPageContentStream + // only PDFbox developers know why ... + innerFormResources = new PDResources(); + for (int i = 0; i < properties.getMainTable().getRowCount(); i++) { + ArrayList row = properties.getMainTable().getRow(i); + for (int j = 0; j < row.size(); j++) { + Entry cell = (Entry) row.get(j); + if (cell.getType() == Entry.TYPE_IMAGE) { + String img_ref = (String) cell.getValue(); + if (!images.containsKey(img_ref)) { + File img_file = new File(img_ref); + if (!img_file.isAbsolute()) { + logger.debug("Image file declaration is relative. Prepending path of resources directory."); + logger.debug("Image Location: " + + settings.getWorkingDirectory() + + File.separator + img_ref); + img_file = new File( + settings.getWorkingDirectory() + + File.separator + img_ref); + } else { + logger.debug("Image file declaration is absolute. Skipping file relocation."); + } + + if (!img_file.exists()) { + logger.debug("Image file \"" + + img_file.getCanonicalPath() + + "\" doesn't exist."); + throw new PdfAsException("error.pdf.stamp.04"); + } + + BufferedImage img = null; + try { + img = ImageIO.read(img_file); + } catch (IOException e) { + throw new PdfAsException("error.pdf.stamp.04", + e); + } + + float width = colsSizes[j]; + + int size = (int)Math.floor((double)width); + size -= 2*padding; + logger.debug("Scaling image to: " + size); + + PDXObjectImage pdImage = new PDJpeg(template, + img); + ImageObject image = new ImageObject(pdImage, size); + images.put(img_ref, image); + innerFormResources.addXObject(pdImage, "Im"); + } + } + } + } + + //innerFormResources.getCOSObject().setDirect(true); + // TODO create Fonts caption and Value + innerFormResources.addFont(PDType1Font.COURIER); + PDPageContentStream stream = new PDPageContentStream(template, getStructure().getPage()); - stream.setFont(PDType1Font.HELVETICA_BOLD, 12); - drawTable(getStructure().getPage(), stream, 0, 0, - properties.getMainTable()); + stream.setFont(PDType1Font.COURIER, 5); + + drawTable(getStructure().getPage(), stream, 1, 1, + properties.getMainTable(), template, false); stream.close(); PDStream innterFormStream = getStructure().getPage().getContents(); getStructure().setInnterFormStream(innterFormStream); @@ -180,8 +365,10 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { page.getCOSDictionary().setItem(COSName.PROC_SET, procSet); innerFormResources.getCOSDictionary() .setItem(COSName.PROC_SET, procSet); - /*imageFormResources.getCOSDictionary() - .setItem(COSName.PROC_SET, procSet);*/ + /* + * imageFormResources.getCOSDictionary() .setItem(COSName.PROC_SET, + * procSet); + */ holderFormResources.getCOSDictionary().setItem(COSName.PROC_SET, procSet); logger.info("inserted ProcSet to PDF"); @@ -196,8 +383,10 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { // is 500px, images 100% is 500px. // String imgFormComment = "q "+imageWidthSize+ " 0 0 50 0 0 cm /" + // imageName + " Do Q\n" + builder.toString(); - /*String imgFormComment = "q " + 100 + " 0 0 50 0 0 cm /" + imageName - + " Do Q\n";*/ + /* + * String imgFormComment = "q " + 100 + " 0 0 50 0 0 cm /" + imageName + + * " Do Q\n"; + */ String holderFormComment = "q 1 0 0 1 0 0 cm /" + innerFormName + " Do Q \n"; // String innerFormComment = "q 1 0 0 1 0 0 cm /" + imageObjectName + @@ -219,250 +408,255 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { logger.info("Injected apereance stream to pdf"); } - - public void createPage(PDFAsVisualSignatureDesigner properties) - { - PDPage page = new PDPage(); - page.setMediaBox(new PDRectangle(properties.getPageWidth(), properties.getPageHeight())); - getStructure().setPage(page); - logger.info("PDF page has been created"); - } - - public void createAcroForm(PDDocument template) - { - PDAcroForm theAcroForm = new PDAcroForm(template); - template.getDocumentCatalog().setAcroForm(theAcroForm); - getStructure().setAcroForm(theAcroForm); - logger.info("Acro form page has been created"); - - } - - public void createSignatureField(PDAcroForm acroForm) throws IOException - { - PDSignatureField sf = new PDSignatureField(acroForm); - getStructure().setSignatureField(sf); - logger.info("Signature field has been created"); - } - - public void createSignature(PDSignatureField pdSignatureField, PDPage page, String signatureName) - throws IOException - { - PDSignature pdSignature = new PDSignature(); - pdSignatureField.setSignature(pdSignature); - pdSignatureField.getWidget().setPage(page); - page.getAnnotations().add(pdSignatureField.getWidget()); - pdSignature.setName(signatureName); - pdSignature.setByteRange(new int[] { 0, 0, 0, 0 }); - pdSignature.setContents(new byte[4096]); - getStructure().setPdSignature(pdSignature); - logger.info("PDSignatur has been created"); - } - - public void createAcroFormDictionary(PDAcroForm acroForm, PDSignatureField signatureField) throws IOException - { - @SuppressWarnings("unchecked") - List acroFormFields = acroForm.getFields(); - COSDictionary acroFormDict = acroForm.getDictionary(); - acroFormDict.setDirect(true); - acroFormDict.setInt(COSName.SIG_FLAGS, 3); - acroFormFields.add(signatureField); - acroFormDict.setString(COSName.DA, "/sylfaen 0 Tf 0 g"); - getStructure().setAcroFormFields(acroFormFields); - getStructure().setAcroFormDictionary(acroFormDict); - logger.info("AcroForm dictionary has been created"); - } - - public void createSignatureRectangle(PDSignatureField signatureField, PDFAsVisualSignatureDesigner properties) - throws IOException - { - - PDRectangle rect = new PDRectangle(); - rect.setUpperRightX(properties.getxAxis() + properties.getWidth()); - rect.setUpperRightY(properties.getPageHeight() - properties.getyAxis()); - rect.setLowerLeftY(properties.getPageHeight() - properties.getyAxis() - properties.getHeight()); - rect.setLowerLeftX(properties.getxAxis()); - signatureField.getWidget().setRectangle(rect); - getStructure().setSignatureRectangle(rect); - logger.info("rectangle of signature has been created"); - } - - public void createAffineTransform(byte[] params) - { - AffineTransform transform = new AffineTransform(params[0], params[1], params[2], params[3], params[4], - params[5]); - getStructure().setAffineTransform(transform); - logger.info("Matrix has been added"); - } - - public void createSignatureImage(PDDocument template, InputStream inputStream) throws IOException - { - PDJpeg img = new PDJpeg(template, inputStream); - getStructure().setJpedImage(img); - logger.info("Visible Signature Image has been created"); - // pdfStructure.setTemplate(template); - inputStream.close(); - - } - - public void createFormaterRectangle(byte[] params) - { - - PDRectangle formrect = new PDRectangle(); - formrect.setUpperRightX(params[0]); - formrect.setUpperRightY(params[1]); - formrect.setLowerLeftX(params[2]); - formrect.setLowerLeftY(params[3]); - - getStructure().setFormaterRectangle(formrect); - logger.info("Formater rectangle has been created"); - - } - - public void createHolderFormStream(PDDocument template) - { - PDStream holderForm = new PDStream(template); - getStructure().setHolderFormStream(holderForm); - logger.info("Holder form Stream has been created"); - } - - public void createHolderFormResources() - { - PDResources holderFormResources = new PDResources(); - getStructure().setHolderFormResources(holderFormResources); - logger.info("Holder form resources have been created"); - - } - - public void createHolderForm(PDResources holderFormResources, PDStream holderFormStream, PDRectangle formrect) - { - - PDXObjectForm holderForm = new PDXObjectForm(holderFormStream); - holderForm.setResources(holderFormResources); - holderForm.setBBox(formrect); - holderForm.setFormType(1); - getStructure().setHolderForm(holderForm); - logger.info("Holder form has been created"); - - } - - public void createAppearanceDictionary(PDXObjectForm holderForml, PDSignatureField signatureField) - throws IOException - { - - PDAppearanceDictionary appearance = new PDAppearanceDictionary(); - appearance.getCOSObject().setDirect(true); - - PDAppearanceStream appearanceStream = new PDAppearanceStream(holderForml.getCOSStream()); - - appearance.setNormalAppearance(appearanceStream); - signatureField.getWidget().setAppearance(appearance); - - getStructure().setAppearanceDictionary(appearance); - logger.info("PDF appereance Dictionary has been created"); - - } - - public void createInnerFormResource() - { - PDResources innerFormResources = new PDResources(); - getStructure().setInnerFormResources(innerFormResources); - logger.info("Resources of another form (inner form - it would be inside holder form) have been created"); - } - - public void createInnerForm(PDResources innerFormResources, PDStream innerFormStream, PDRectangle formrect) - { - PDXObjectForm innerForm = new PDXObjectForm(innerFormStream); - innerForm.setResources(innerFormResources); - innerForm.setBBox(formrect); - innerForm.setFormType(1); - getStructure().setInnerForm(innerForm); - logger.info("Another form (inner form - it would be inside holder form) have been created"); - - } - - public void insertInnerFormToHolerResources(PDXObjectForm innerForm, PDResources holderFormResources) - { - String name = holderFormResources.addXObject(innerForm, "FRM"); - getStructure().setInnerFormName(name); - logger.info("Alerady inserted inner form inside holder form"); - } - - public void createImageFormStream(PDDocument template) - { - PDStream imageFormStream = new PDStream(template); - getStructure().setImageFormStream(imageFormStream); - logger.info("Created image form Stream"); - - } - - public void createImageFormResources() - { - PDResources imageFormResources = new PDResources(); - getStructure().setImageFormResources(imageFormResources); - logger.info("Created image form Resources"); - } - - public void createImageForm(PDResources imageFormResources, PDResources innerFormResource, - PDStream imageFormStream, PDRectangle formrect, AffineTransform affineTransform, PDJpeg img) - throws IOException - { - - /* - * if you need text on the visible signature - * - * PDFont font = PDTrueTypeFont.loadTTF(this.pdfStructure.getTemplate(), new File("D:\\arial.ttf")); - * font.setFontEncoding(new WinAnsiEncoding()); - * - * Map fonts = new HashMap(); fonts.put("arial", font); - */ - PDXObjectForm imageForm = new PDXObjectForm(imageFormStream); - imageForm.setBBox(formrect); - imageForm.setMatrix(affineTransform); - imageForm.setResources(imageFormResources); - imageForm.setFormType(1); - /* - * imageForm.getResources().addFont(font); - * imageForm.getResources().setFonts(fonts); - */ - - imageFormResources.getCOSObject().setDirect(true); - String imageFormName = innerFormResource.addXObject(imageForm, "n"); - String imageName = imageFormResources.addXObject(img, "img"); - this.getStructure().setImageForm(imageForm); - this.getStructure().setImageFormName(imageFormName); - this.getStructure().setImageName(imageName); - logger.info("Created image form"); - } - - public void appendRawCommands(OutputStream os, String commands) throws IOException - { - os.write(commands.getBytes("UTF-8")); - os.close(); - } - - public void createVisualSignature(PDDocument template) - { - this.getStructure().setVisualSignature(template.getDocument()); - logger.info("Visible signature has been created"); - - } - - public void createWidgetDictionary(PDSignatureField signatureField, PDResources holderFormResources) - throws IOException - { - - COSDictionary widgetDict = signatureField.getWidget().getDictionary(); - widgetDict.setNeedToBeUpdate(true); - widgetDict.setItem(COSName.DR, holderFormResources.getCOSObject()); - - getStructure().setWidgetDictionary(widgetDict); - logger.info("WidgetDictionary has been crated"); - } - - public void closeTemplate(PDDocument template) throws IOException - { - template.close(); - this.getStructure().getTemplate().close(); - } - + + public void createPage(PDFAsVisualSignatureDesigner properties) { + PDPage page = new PDPage(); + page.setMediaBox(new PDRectangle(properties.getPageWidth(), properties + .getPageHeight())); + getStructure().setPage(page); + logger.info("PDF page has been created"); + } + + public void createAcroForm(PDDocument template) { + PDAcroForm theAcroForm = new PDAcroForm(template); + template.getDocumentCatalog().setAcroForm(theAcroForm); + getStructure().setAcroForm(theAcroForm); + logger.info("Acro form page has been created"); + + } + + public void createSignatureField(PDAcroForm acroForm) throws IOException { + PDSignatureField sf = new PDSignatureField(acroForm); + getStructure().setSignatureField(sf); + logger.info("Signature field has been created"); + } + + public void createSignature(PDSignatureField pdSignatureField, PDPage page, + String signatureName) throws IOException { + PDSignature pdSignature = new PDSignature(); + pdSignatureField.setSignature(pdSignature); + pdSignatureField.getWidget().setPage(page); + page.getAnnotations().add(pdSignatureField.getWidget()); + pdSignature.setName(signatureName); + pdSignature.setByteRange(new int[] { 0, 0, 0, 0 }); + pdSignature.setContents(new byte[4096]); + getStructure().setPdSignature(pdSignature); + logger.info("PDSignatur has been created"); + } + + public void createAcroFormDictionary(PDAcroForm acroForm, + PDSignatureField signatureField) throws IOException { + @SuppressWarnings("unchecked") + List acroFormFields = acroForm.getFields(); + COSDictionary acroFormDict = acroForm.getDictionary(); + acroFormDict.setDirect(true); + acroFormDict.setInt(COSName.SIG_FLAGS, 3); + acroFormFields.add(signatureField); + acroFormDict.setString(COSName.DA, "/sylfaen 0 Tf 0 g"); + getStructure().setAcroFormFields(acroFormFields); + getStructure().setAcroFormDictionary(acroFormDict); + logger.info("AcroForm dictionary has been created"); + } + + public void createSignatureRectangle(PDSignatureField signatureField, + PDFAsVisualSignatureDesigner properties) throws IOException { + + PDRectangle rect = new PDRectangle(); + rect.setUpperRightX(properties.getxAxis() + properties.getWidth() + 10); + rect.setUpperRightY(properties.getPageHeight() - properties.getyAxis()); + rect.setLowerLeftY(properties.getPageHeight() - properties.getyAxis() + - properties.getHeight() - 10); + rect.setLowerLeftX(properties.getxAxis()); + signatureField.getWidget().setRectangle(rect); + getStructure().setSignatureRectangle(rect); + logger.info("rectangle of signature has been created"); + } + + public void createAffineTransform(byte[] params) { + AffineTransform transform = new AffineTransform(params[0], params[1], + params[2], params[3], params[4], params[5]); + getStructure().setAffineTransform(transform); + logger.info("Matrix has been added"); + } + + public void createSignatureImage(PDDocument template, + InputStream inputStream) throws IOException { + PDJpeg img = new PDJpeg(template, inputStream); + getStructure().setJpedImage(img); + logger.info("Visible Signature Image has been created"); + // pdfStructure.setTemplate(template); + inputStream.close(); + + } + + public void createFormaterRectangle(float[] params) { + + PDRectangle formrect = new PDRectangle(); + formrect.setUpperRightX(params[0]); + formrect.setUpperRightY(params[1]); + formrect.setLowerLeftX(params[2]); + formrect.setLowerLeftY(params[3]); + + getStructure().setFormaterRectangle(formrect); + logger.info("Formater rectangle has been created"); + + } + + public void createHolderFormStream(PDDocument template) { + PDStream holderForm = new PDStream(template); + getStructure().setHolderFormStream(holderForm); + logger.info("Holder form Stream has been created"); + } + + public void createHolderFormResources() { + PDResources holderFormResources = new PDResources(); + getStructure().setHolderFormResources(holderFormResources); + logger.info("Holder form resources have been created"); + + } + + public void createHolderForm(PDResources holderFormResources, + PDStream holderFormStream, PDRectangle formrect) { + + PDXObjectForm holderForm = new PDXObjectForm(holderFormStream); + holderForm.setResources(holderFormResources); + holderForm.setBBox(formrect); + holderForm.setFormType(1); + getStructure().setHolderForm(holderForm); + logger.info("Holder form has been created"); + + } + + public void createAppearanceDictionary(PDXObjectForm holderForml, + PDSignatureField signatureField) throws IOException { + + PDAppearanceDictionary appearance = new PDAppearanceDictionary(); + appearance.getCOSObject().setDirect(true); + + PDAppearanceStream appearanceStream = new PDAppearanceStream( + holderForml.getCOSStream()); + + appearance.setNormalAppearance(appearanceStream); + signatureField.getWidget().setAppearance(appearance); + + getStructure().setAppearanceDictionary(appearance); + logger.info("PDF appereance Dictionary has been created"); + + } + + public void createInnerFormResource() { + getStructure().setInnerFormResources(innerFormResources); + logger.info("Resources of another form (inner form - it would be inside holder form) have been created"); + } + + public void createInnerForm(PDResources innerFormResources, + PDStream innerFormStream, PDRectangle formrect) { + PDXObjectForm innerForm = new PDXObjectForm(innerFormStream); + innerForm.setResources(innerFormResources); + innerForm.setBBox(formrect); + innerForm.setFormType(1); + getStructure().setInnerForm(innerForm); + logger.info("Another form (inner form - it would be inside holder form) have been created"); + + } + + public void insertInnerFormToHolerResources(PDXObjectForm innerForm, + PDResources holderFormResources) { + String name = holderFormResources.addXObject(innerForm, "FRM"); + getStructure().setInnerFormName(name); + logger.info("Alerady inserted inner form inside holder form"); + } + + public void createImageFormStream(PDDocument template) { + PDStream imageFormStream = new PDStream(template); + getStructure().setImageFormStream(imageFormStream); + logger.info("Created image form Stream"); + } + + public void createImageFormResources() { + PDResources imageFormResources = new PDResources(); + getStructure().setImageFormResources(imageFormResources); + logger.info("Created image form Resources"); + } + + public void createImageForm(PDResources imageFormResources, + PDResources innerFormResource, PDStream imageFormStream, + PDRectangle formrect, AffineTransform affineTransform, PDJpeg img) + throws IOException { + + /* + * if you need text on the visible signature + * + * PDFont font = PDTrueTypeFont.loadTTF(this.pdfStructure.getTemplate(), + * new File("D:\\arial.ttf")); font.setFontEncoding(new + * WinAnsiEncoding()); + * + * Map fonts = new HashMap(); + * fonts.put("arial", font); + */ + PDXObjectForm imageForm = new PDXObjectForm(imageFormStream); + imageForm.setBBox(formrect); + imageForm.setMatrix(affineTransform); + imageForm.setResources(imageFormResources); + imageForm.setFormType(1); + /* + * imageForm.getResources().addFont(font); + * imageForm.getResources().setFonts(fonts); + */ + + imageFormResources.getCOSObject().setDirect(true); + String imageFormName = innerFormResource.addXObject(imageForm, "n"); + String imageName = imageFormResources.addXObject(img, "img"); + this.getStructure().setImageForm(imageForm); + this.getStructure().setImageFormName(imageFormName); + this.getStructure().setImageName(imageName); + logger.info("Created image form"); + } + + public void appendRawCommands(OutputStream os, String commands) + throws IOException { + os.write(commands.getBytes("UTF-8")); + os.close(); + } + + public void appendCosStreamCommands(OutputStream os, COSStream stream) + throws IOException { + // stream.getScratchFile(); + byte[] data = new byte[1024]; + long i = 0; + long pos = stream.getScratchFile().getPosition(); + stream.getScratchFile().seek(0); + while (i < stream.getScratchFile().length()) { + int read = stream.getScratchFile().read(data, 0, data.length); + i += read; + os.write(data, 0, read); + } + // /byte[] data = + // StreamUtils.inputStreamToByteArray(stream.getFilteredStream()); + // os.write(data); + os.close(); + } + + public void createVisualSignature(PDDocument template) { + this.getStructure().setVisualSignature(template.getDocument()); + logger.info("Visible signature has been created"); + + } + + public void createWidgetDictionary(PDSignatureField signatureField, + PDResources holderFormResources) throws IOException { + + COSDictionary widgetDict = signatureField.getWidget().getDictionary(); + widgetDict.setNeedToBeUpdate(true); + widgetDict.setItem(COSName.DR, holderFormResources.getCOSObject()); + + getStructure().setWidgetDictionary(widgetDict); + logger.info("WidgetDictionary has been crated"); + } + + public void closeTemplate(PDDocument template) throws IOException { + template.close(); + this.getStructure().getTemplate().close(); + } + } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java index 5ad36c62..f9e63a48 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java @@ -14,10 +14,17 @@ import javax.imageio.ImageIO; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.knowcenter.wag.egov.egiz.table.Table; public class PDFAsVisualSignatureDesigner { + private static final Logger logger = LoggerFactory.getLogger(PDFAsVisualSignatureDesigner.class); + private Float sigImgWidth; private Float sigImgHeight; private float xAxis; @@ -26,10 +33,11 @@ public class PDFAsVisualSignatureDesigner { private float pageWidth; private InputStream imgageStream; private String signatureFieldName = "sig"; // default - private byte[] formaterRectangleParams = { 0, 0, 100, 50 }; // default + private float[] formaterRectangleParams = { 0, 0, 100, 50 }; // default private byte[] AffineTransformParams = { 1, 0, 0, 1, 0, 0 }; // default private float imageSizeInPercents; private PDDocument document = null; + PDFAsVisualSignatureProperties properties; /** * @@ -40,8 +48,9 @@ public class PDFAsVisualSignatureDesigner { * @throws IOException * - If we can't read, flush, or can't close stream */ - public PDFAsVisualSignatureDesigner(PDDocument doc, - int page) throws IOException { + public PDFAsVisualSignatureDesigner(PDDocument doc, int page, + PDFAsVisualSignatureProperties properties) throws IOException { + this.properties = properties; calculatePageSize(doc, page); } @@ -69,7 +78,6 @@ public class PDFAsVisualSignatureDesigner { this.pageWidth = this.pageWidth + y; float tPercent = (100 * y / (x + y)); this.imageSizeInPercents = 100 - tPercent; - } /** @@ -79,7 +87,8 @@ public class PDFAsVisualSignatureDesigner { * @return image Stream * @throws IOException */ - public PDFAsVisualSignatureDesigner signatureImage(String path) throws IOException { + public PDFAsVisualSignatureDesigner signatureImage(String path) + throws IOException { InputStream fin = new FileInputStream(path); return signatureImageStream(fin); } @@ -153,7 +162,7 @@ public class PDFAsVisualSignatureDesigner { * @return signature image width */ public float getWidth() { - return 400; + return this.properties.getMainTable().getWidth(); } /** @@ -172,7 +181,7 @@ public class PDFAsVisualSignatureDesigner { * @return signature image height */ public float getHeight() { - return 300; + return this.properties.getMainTable().getHeight(); } /** @@ -217,7 +226,8 @@ public class PDFAsVisualSignatureDesigner { * @param signatureFieldName * @return Visible Signature Configuration Object */ - public PDFAsVisualSignatureDesigner signatureFieldName(String signatureFieldName) { + public PDFAsVisualSignatureDesigner signatureFieldName( + String signatureFieldName) { this.signatureFieldName = signatureFieldName; return this; } @@ -238,8 +248,8 @@ public class PDFAsVisualSignatureDesigner { * @throws IOException * - If we can't read, flush, or close stream of image */ - private PDFAsVisualSignatureDesigner signatureImageStream(InputStream imageStream) - throws IOException { + private PDFAsVisualSignatureDesigner signatureImageStream( + InputStream imageStream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; @@ -308,7 +318,7 @@ public class PDFAsVisualSignatureDesigner { * * @return formatter PDRectanle parameters */ - public byte[] getFormaterRectangleParams() { + public float[] getFormaterRectangleParams() { return formaterRectangleParams; } @@ -319,7 +329,7 @@ public class PDFAsVisualSignatureDesigner { * @return Visible Signature Configuration Object */ public PDFAsVisualSignatureDesigner formaterRectangleParams( - byte[] formaterRectangleParams) { + float[] formaterRectangleParams) { this.formaterRectangleParams = formaterRectangleParams; return this; } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java index 055f035d..24ef3881 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java @@ -7,10 +7,13 @@ import java.io.FileInputStream; import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateBuilder; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateCreator; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.common.settings.ISettings; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; @@ -21,9 +24,12 @@ import at.knowcenter.wag.egov.egiz.table.Table; public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { + private static final Logger logger = LoggerFactory.getLogger(PDFAsVisualSignatureProperties.class); + private ISettings settings; - private Table main; + private PDFBoxTable main; + private PDFont tableFont; private PDFAsVisualSignatureDesigner designer; @@ -31,18 +37,23 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { this.settings = settings; try { SignatureProfileSettings profileSettings = TableFactory - .createProfile("SIGNATURBLOCK_DE", settings); - - X509Certificate cert = new X509Certificate(new FileInputStream( - "/home/andy/certificates/test.crt")); + .createProfile(object.getStatus().getRequestedSignature().getSignatureProfileID(), + settings); + //float width = object.getStatus().getRequestedSignature().getSignaturePosition().getWidth(); + object.getStatus().getRequestedSignature().getCertificate(); + X509Certificate cert = object.getStatus().getRequestedSignature().getCertificate(); CertificateHolderRequest request = new CertificateHolderRequest( cert); - main = TableFactory.createSigTable(profileSettings, "main", + Table mainTable = TableFactory.createSigTable(profileSettings, "main", settings, request); - - main.setWidth(400); + + main = new PDFBoxTable(mainTable, null, 230.f); + + //tableFont = PDFont. + + //main.setWidth(100); } catch (Throwable e) { e.printStackTrace(); } @@ -50,8 +61,11 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { PDDocument origDoc = PDDocument.load(new ByteArrayInputStream( object.getStampedDocument())); - designer = new PDFAsVisualSignatureDesigner(origDoc, 1); - + designer = new PDFAsVisualSignatureDesigner(origDoc, 1, this); + designer.coordinates(100, 100); + float[] form_rect = new float[] {0,0, main.getWidth() + 2, main.getHeight() + 2}; + logger.info("AP Rect: {} {} {} {}", form_rect[0], form_rect[1], form_rect[2], form_rect[3]); + designer.formaterRectangleParams(form_rect); //this.setPdVisibleSignature(designer); } catch (Throwable e) { e.printStackTrace(); @@ -60,14 +74,16 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { @Override public void buildSignature() throws IOException { - PDFAsVisualSignatureBuilder builder = new PDFAsVisualSignatureBuilder(this); + PDFAsVisualSignatureBuilder builder = new PDFAsVisualSignatureBuilder(this, this.settings); PDFAsTemplateCreator creator = new PDFAsTemplateCreator(builder); setVisibleSignature(creator.buildPDF(designer)); } - public Table getMainTable() { + public PDFBoxTable getMainTable() { return main; } + + } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java new file mode 100644 index 00000000..6555b82d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java @@ -0,0 +1,415 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.knowcenter.wag.egov.egiz.table.Entry; +import at.knowcenter.wag.egov.egiz.table.Style; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class PDFBoxTable { + + private static final Logger logger = LoggerFactory + .getLogger(PDFBoxTable.class); + + Table table; + Style style; + PDFont font; + PDFont valueFont; + + float padding; + int positionX = 0; + int positionY = 0; + float tableWidth; + float tableHeight; + float fontSize; + + float[] rowHeights; + float[] colWidths; + + private void initializeStyle(Table abstractTable, PDFBoxTable parent) + throws IOException { + this.table = abstractTable; + + if (abstractTable.getStyle() != null) { + style = abstractTable.getStyle(); + } + + if (style == null && parent != null) { + style = parent.style; + } + + if (style == null) { + throw new IOException("Failed to determine Table style"); + } + + String fontString = style.getFont(); + font = PDType1Font.COURIER; + + String vfontString = style.getValueFont(); + valueFont = font; + + padding = style.getPadding(); + fontSize = 5f; + } + + public PDFBoxTable(Table abstractTable, PDFBoxTable parent, float fixSize) + throws IOException { + initializeStyle(abstractTable, parent); + float[] relativSizes = abstractTable.getColsRelativeWith(); + colWidths = new float[relativSizes.length]; + float totalrel = 0; + + for (int i = 0; i < relativSizes.length; i++) { + totalrel += relativSizes[i]; + } + + float unit = (fixSize / totalrel); + + for (int i = 0; i < relativSizes.length; i++) { + + colWidths[i] = unit * relativSizes[i]; + } + + calculateHeightsBasedOnWidths(); + } + + public PDFBoxTable(Table abstractTable, PDFBoxTable parent) + throws IOException { + initializeStyle(abstractTable, parent); + this.calculateWidthHeight(); + } + + private void calculateHeightsBasedOnWidths() throws IOException { + int rows = this.table.getRows().size(); + rowHeights = new float[rows]; + + for (int i = 0; i < rows; i++) { + rowHeights[i] = 0; + } + + for (int i = 0; i < rows; i++) { + ArrayList row = (ArrayList) this.table.getRows().get(i); + for (int j = 0; j < row.size(); j++) { + Entry cell = (Entry) row.get(j); + + float cellheight = getCellHeight(cell, colWidths[j]); + + if (rowHeights[i] < cellheight) { + rowHeights[i] = cellheight; + } + + logger.debug("ROW: {} COL: {} Width: {} Height: {}", i, j, + cellheight); + + int span = cell.getColSpan() - 1; + j += span; + } + } + + calcTotals(); + } + + private void calculateWidthHeight() throws IOException { + int cols = this.table.getMaxCols(); + colWidths = new float[cols]; + + for (int i = 0; i < cols; i++) { + colWidths[i] = 0; + } + + int rows = this.table.getRows().size(); + rowHeights = new float[rows]; + + for (int i = 0; i < rows; i++) { + rowHeights[i] = 0; + } + + for (int i = 0; i < rows; i++) { + ArrayList row = (ArrayList) this.table.getRows().get(i); + for (int j = 0; j < row.size(); j++) { + Entry cell = (Entry) row.get(j); + float cellWidth = getCellWidth(cell); + + if (colWidths[j] < cellWidth) { + colWidths[j] = cellWidth; + } + + float cellheight = getCellHeight(cell); + + if (rowHeights[i] < cellheight) { + rowHeights[i] = cellheight; + } + + logger.debug("ROW: {} COL: {} Width: {} Height: {}", i, j, + cellWidth, cellheight); + + int span = cell.getColSpan() - 1; + j += span; + } + } + + calcTotals(); + } + + private void calcTotals() { + + this.tableHeight = 0; + + for (int i = 0; i < rowHeights.length; i++) { + this.tableHeight += rowHeights[i] + padding * 2; + } + + this.tableWidth = 0; + + for (int i = 0; i < colWidths.length; i++) { + this.tableWidth += colWidths[i] + padding * 2; + } + } + + private float getCellWidth(Entry cell) throws IOException { + boolean isValue = true; + switch (cell.getType()) { + case Entry.TYPE_CAPTION: + isValue = false; + case Entry.TYPE_VALUE: + PDFont c = null; + String string = (String) cell.getValue(); + if (isValue) { + c = valueFont; + } else { + c = font; + } + + if (string.contains("\n")) { + float maxWidth = 0; + String[] lines = string.split("\n"); + for (int i = 0; i < lines.length; i++) { + float w = c.getStringWidth(lines[i]) / 1000 * fontSize; + if (maxWidth < w) { + maxWidth = w; + } + } + return maxWidth; + } else { + return c.getStringWidth(string) / 1000 * fontSize; + } + case Entry.TYPE_IMAGE: + return 80.f; + case Entry.TYPE_TABLE: + PDFBoxTable pdfBoxTable = null; + if (cell.getValue() instanceof Table) { + pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this); + cell.setValue(pdfBoxTable); + } else if (cell.getValue() instanceof PDFBoxTable) { + pdfBoxTable = (PDFBoxTable) cell.getValue(); + } else { + throw new IOException("Failed to build PDFBox Table"); + } + return pdfBoxTable.getWidth(); + default: + logger.warn("Invalid Cell Entry Type: " + cell.getType()); + // return font.getFontDescriptor().getFontBoundingBox().getHeight() + // / 1000 * fontSize; + } + return 0; + } + + private String concatLines(String[] lines) { + String v = ""; + for (int i = 0; i < lines.length; i++) { + v += lines[i]; + if (i + 1 < lines.length) { + v += "\n"; + } + } + return v; + } + + private String[] breakString(String value, int maxline) { + String[] words = value.split(" "); + List lines = new ArrayList(); + int cLine = 0; + String cLineValue = ""; + for (int i = 0; i < words.length; i++) { + String word = words[i]; + String[] lineBreaks = word.split("\n"); + if (lineBreaks.length > 1) { + for (int j = 0; j < lineBreaks.length; j++) { + String subword = lineBreaks[j]; + //if (cLine + subword.length() > maxline) { + lines.add(cLineValue.trim()); + cLineValue = ""; + cLine = 0; + //} + cLineValue += subword + " "; + cLine += subword.length(); + } + } else { + if (cLine + word.length() > maxline && + cLineValue.length() != 0) { + lines.add(cLineValue.trim()); + cLineValue = ""; + cLine = 0; + } + cLineValue += word + " "; + cLine += word.length(); + } + } + lines.add(cLineValue.trim()); + return lines.toArray(new String[0]); + } + + private float getCellHeight(Entry cell, float width) throws IOException { + boolean isValue = true; + switch (cell.getType()) { + case Entry.TYPE_CAPTION: + isValue = false; + case Entry.TYPE_VALUE: + PDFont c = null; + String string = (String) cell.getValue(); + if (isValue) { + c = valueFont; + } else { + c = font; + } + + float fwidth = c.getFontDescriptor().getFontBoundingBox() + .getWidth() + / 1000 * fontSize; + + int maxcharcount = (int) ((width - padding * 2) / fwidth) - 1; + logger.info("Max {} chars per line!", maxcharcount); + float fheight = c.getFontDescriptor().getFontBoundingBox() + .getHeight() + / 1000 * fontSize; + + String[] lines = breakString(string, maxcharcount); + cell.setValue(concatLines(lines)); + return fheight * lines.length; + case Entry.TYPE_IMAGE: + return width; + case Entry.TYPE_TABLE: + PDFBoxTable pdfBoxTable = null; + if (cell.getValue() instanceof Table) { + pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this, + width - padding); + cell.setValue(pdfBoxTable); + } else if (cell.getValue() instanceof PDFBoxTable) { + pdfBoxTable = (PDFBoxTable) cell.getValue(); + } else { + throw new IOException("Failed to build PDFBox Table"); + } + return pdfBoxTable.getHeight() - padding; + default: + logger.warn("Invalid Cell Entry Type: " + cell.getType()); + } + return 0; + } + + private float getCellHeight(Entry cell) throws IOException { + boolean isValue = true; + switch (cell.getType()) { + case Entry.TYPE_CAPTION: + isValue = false; + case Entry.TYPE_VALUE: + PDFont c = null; + String string = (String) cell.getValue(); + if (isValue) { + c = valueFont; + } else { + c = font; + } + float fheight = c.getFontDescriptor().getFontBoundingBox() + .getHeight() + / 1000 * fontSize; + if (string.contains("\n")) { + String[] lines = string.split("\n"); + + return fheight * lines.length; + } else { + return fheight; + } + case Entry.TYPE_IMAGE: + return 80.f; + case Entry.TYPE_TABLE: + PDFBoxTable pdfBoxTable = null; + if (cell.getValue() instanceof Table) { + pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this); + cell.setValue(pdfBoxTable); + } else if (cell.getValue() instanceof PDFBoxTable) { + pdfBoxTable = (PDFBoxTable) cell.getValue(); + } else { + throw new IOException("Failed to build PDFBox Table"); + } + return pdfBoxTable.getHeight(); + default: + logger.warn("Invalid Cell Entry Type: " + cell.getType()); + } + return 0; + } + + public int getX() { + return this.positionX; + } + + public int getY() { + return this.positionY; + } + + public float getWidth() { + return tableWidth; + } + + public float getHeight() { + return tableHeight; + } + + public float[] getRowHeights() { + return rowHeights; + } + + public int getRowCount() { + return this.table.getRows().size(); + } + + public int getColCount() { + return this.table.getColsRelativeWith().length; + } + + public float[] getColsRelativeWith() { + return this.table.getColsRelativeWith(); + } + + public float getPadding() { + return this.padding; + } + + public void dumpTable() { + logger.info("====================================================================="); + logger.info("Information about: " + this.table.getName()); + logger.info("\tDimensions: {} x {} (W x H)", this.tableWidth, this.tableHeight); + logger.info("\tPadding: {}", padding); + logger.info("\t================================"); + logger.info("\tRow Heights:"); + for (int i = 0; i < rowHeights.length; i++) { + logger.info("\t[{}] : {}", i, this.rowHeights[i]); + } + logger.info("\t================================"); + logger.info("\tCol Widths:"); + for (int i = 0; i < colWidths.length; i++) { + logger.info("\t[{}] : {}", i, this.colWidths[i]); + } + logger.info("====================================================================="); + } + + public ArrayList getRow(int i) { + return (ArrayList) this.table.getRows().get(i); + } +} -- cgit v1.2.3