From 6de4496bc66024471186174c77554ba9804b980a Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Wed, 4 Jun 2014 15:39:57 +0200 Subject: PDF Table Font alignment --- .../lib/impl/signing/pdfbox/PADESPDFBOXSigner.java | 78 ++++++------- .../impl/signing/pdfbox/PdfboxSignerWrapper.java | 2 + .../lib/impl/stamping/CertificateResolver.java | 15 ++- .../gv/egiz/pdfas/lib/impl/stamping/IResolver.java | 3 +- .../egiz/pdfas/lib/impl/stamping/TableFactory.java | 18 +-- .../pdfas/lib/impl/stamping/ValueResolver.java | 15 ++- .../pdfbox/PDFAsVisualSignatureBuilder.java | 125 ++++++++++++++++++++- .../lib/impl/stamping/pdfbox/PDFBoxTable.java | 38 ++++--- .../egiz/pdfas/lib/test/mains/TestPDFBoxTable.java | 6 +- 9 files changed, 226 insertions(+), 74 deletions(-) diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java index 8694017f..b583e48e 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java @@ -30,9 +30,9 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; -import java.util.Iterator; import java.util.List; +import org.apache.pdfbox.cos.COSBase; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.exceptions.COSVisitorException; @@ -42,11 +42,8 @@ import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageNode; import org.apache.pdfbox.pdmodel.PDResources; -import org.apache.pdfbox.pdmodel.graphics.color.PDGamma; import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent; import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions; @@ -56,7 +53,6 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.tools.jar.SignatureFile; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.common.messages.MessageResolver; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; @@ -116,10 +112,11 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { .createProfile(requestedSignature.getSignatureProfileID(), pdfObject.getStatus().getSettings()); - ValueResolver resolver = new ValueResolver(); + ValueResolver resolver = new ValueResolver(requestedSignature, + pdfObject.getStatus()); String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue("SIG_SUBJECT"), - signatureProfileSettings, requestedSignature); + signatureProfileSettings); signature.setName(signerName); signature.setSignDate(Calendar.getInstance()); @@ -128,7 +125,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { if (signerReason == null) { signerReason = "PAdES Signature"; } - + signature.setReason(signerReason); logger.debug("Signing reason: " + signerReason); @@ -139,7 +136,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { signer.setPDSignature(signature); SignatureOptions options = new SignatureOptions(); - + // Is visible Signature if (requestedSignature.isVisual()) { logger.info("Creating visual siganture block"); @@ -192,8 +189,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { // create Table describtion Table main = TableFactory.createSigTable( - signatureProfileSettings, MAIN, pdfObject.getStatus() - .getSettings(), requestedSignature); + signatureProfileSettings, MAIN, pdfObject.getStatus(), + requestedSignature); IPDFStamper stamper = StamperFactory .createDefaultStamper(pdfObject.getStatus() @@ -279,23 +276,26 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { if (signatureProfileSettings.isPDFA()) { PDDocumentCatalog root = doc.getDocumentCatalog(); - InputStream colorProfile = PDDocumentCatalog.class - .getResourceAsStream("/icm/sRGB Color Space Profile.icm"); - try { - PDOutputIntent oi = new PDOutputIntent(doc, - colorProfile); - oi.setInfo("sRGB IEC61966-2.1"); - oi.setOutputCondition("sRGB IEC61966-2.1"); - oi.setOutputConditionIdentifier("sRGB IEC61966-2.1"); - oi.setRegistryName("http://www.color.org"); - - root.addOutputIntent(oi); - root.getCOSObject().setNeedToBeUpdate(true); - logger.info("added Output Intent"); - } catch (Throwable e) { - e.printStackTrace(); - throw new PdfAsException("Failed to add Output Intent", - e); + COSBase base = root.getCOSDictionary().getItem(COSName.OUTPUT_INTENTS); + if(base == null) { + InputStream colorProfile = PDDocumentCatalog.class + .getResourceAsStream("/icm/sRGB Color Space Profile.icm"); + try { + PDOutputIntent oi = new PDOutputIntent(doc, + colorProfile); + oi.setInfo("sRGB IEC61966-2.1"); + oi.setOutputCondition("sRGB IEC61966-2.1"); + oi.setOutputConditionIdentifier("sRGB IEC61966-2.1"); + oi.setRegistryName("http://www.color.org"); + + root.addOutputIntent(oi); + root.getCOSObject().setNeedToBeUpdate(true); + logger.info("added Output Intent"); + } catch (Throwable e) { + e.printStackTrace(); + throw new PdfAsException( + "Failed to add Output Intent", e); + } } } @@ -322,8 +322,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { doc.addSignature(signature, signer, options); String sigFieldName = signatureProfileSettings.getSignFieldValue(); - - if(sigFieldName != null) { + + if (sigFieldName != null) { PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm(); if (acroForm != null) { @SuppressWarnings("unchecked") @@ -333,7 +333,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { if (fields != null) { for (PDField pdField : fields) { if (pdField instanceof PDSignatureField) { - if (((PDSignatureField) pdField).getSignature().getDictionary() + if (((PDSignatureField) pdField).getSignature() + .getDictionary() .equals(signature.getDictionary())) { signatureField = (PDSignatureField) pdField; } @@ -342,15 +343,15 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { } else { logger.warn("Failed to name Signature Field! [Cannot find Field list in acroForm!]"); } - - if(signatureField != null) { + + if (signatureField != null) { signatureField.setPartialName(sigFieldName); } } else { logger.warn("Failed to name Signature Field! [Cannot find acroForm!]"); } } - + if (requestedSignature.isVisual()) { // if(requestedSignature.getSignaturePosition().) @@ -365,7 +366,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { if (fields != null) { for (PDField pdField : fields) { if (pdField instanceof PDSignatureField) { - if (((PDSignatureField) pdField).getSignature().getDictionary() + if (((PDSignatureField) pdField).getSignature() + .getDictionary() .equals(signature.getDictionary())) { signatureField = (PDSignatureField) pdField; } @@ -374,8 +376,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { } else { logger.warn("Failed to apply rotation! [Cannot find Field list in acroForm!]"); } - - if(signatureField != null) { + + if (signatureField != null) { if (signatureField.getWidget() != null) { if (signatureField.getWidget() .getAppearanceCharacteristics() == null) { @@ -432,7 +434,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); throw new PdfAsException("error.pdf.sig.01", e); } finally { - if(doc != null) { + if (doc != null) { try { doc.close(); } catch (IOException e) { diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java index 6c1934ff..0925a646 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java @@ -59,6 +59,8 @@ public class PdfboxSignerWrapper implements PDFASSignatureInterface { IOException { byte[] data = StreamUtils.inputStreamToByteArray(inputStream); byteRange = PDFUtils.extractSignatureByteRange(data); + int[] byteRange2 = signature.getByteRange(); + logger.info("Byte Range 2: " + byteRange2); try { logger.info("Signing with Pdfbox Wrapper"); byte[] signature = signer.sign(data, byteRange); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java index e5b8acd0..5a26974c 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java @@ -25,6 +25,7 @@ package at.gv.egiz.pdfas.lib.impl.stamping; import iaik.x509.X509Certificate; +import java.util.HashMap; import java.util.Map; import javax.naming.InvalidNameException; @@ -38,6 +39,7 @@ import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; import at.gv.egiz.pdfas.common.utils.DNUtils; import at.gv.egiz.pdfas.common.utils.OgnlUtils; import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; +import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; public class CertificateResolver implements IResolver { @@ -45,8 +47,9 @@ public class CertificateResolver implements IResolver { private OgnlContext ctx; private X509Certificate certificate; + private OperationStatus operationStatus; - public CertificateResolver(X509Certificate certificate) { + public CertificateResolver(X509Certificate certificate, OperationStatus operationStatus) { this.certificate = certificate; this.ctx = new OgnlContext(); @@ -66,10 +69,16 @@ public class CertificateResolver implements IResolver { logger.error("Failed to build subject Map", e); } + Map iuiMap = new HashMap(); + try { + iuiMap.put("pdfVersion", String.valueOf(operationStatus.getPdfObject().getDocument().getDocument().getVersion())); + } catch(Throwable e) { + logger.warn("Cannot determine pdfVersion: " + e.getMessage()); + } + this.ctx.put("iui", iuiMap); } - public String resolve(String key, String value, SignatureProfileSettings settings, - ICertificateProvider signature) { + public String resolve(String key, String value, SignatureProfileSettings settings) { return OgnlUtils.resolvsOgnlExpression(value, this.ctx); } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java index 03529d5a..92f80045 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java @@ -34,6 +34,5 @@ import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; * To change this template use File | Settings | File Templates. */ public interface IResolver { - public String resolve(String key, String value, SignatureProfileSettings settings, - ICertificateProvider signature); + public String resolve(String key, String value, SignatureProfileSettings settings); } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java index c3ce8cc8..0ff1dd4e 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java @@ -38,6 +38,7 @@ import at.gv.egiz.pdfas.common.settings.IProfileConstants; import at.gv.egiz.pdfas.common.settings.ISettings; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; +import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; import at.knowcenter.wag.egov.egiz.pdf.sig.SignatureEntry; import at.knowcenter.wag.egov.egiz.table.Entry; import at.knowcenter.wag.egov.egiz.table.Style; @@ -100,11 +101,12 @@ public class TableFactory implements IProfileConstants { * @see at.knowcenter.wag.egov.egiz.table.Table * @see at.knowcenter.wag.egov.egiz.table.Entry */ - public static Table createSigTable(SignatureProfileSettings profile, String tableID, ISettings configuration, + public static Table createSigTable(SignatureProfileSettings profile, String tableID, OperationStatus operationStatus, ICertificateProvider certProvider) { String table_key_prefix = SIG_OBJ + profile.getProfileID() + "." + TABLE; String table_key = table_key_prefix + tableID; + ISettings configuration = operationStatus.getSettings(); // String caption_prefix = SignatureTypes.SIG_OBJ + getSignationType() + // ".key."; // String value_prefix = SignatureTypes.SIG_OBJ + getSignationType() + @@ -165,7 +167,7 @@ public class TableFactory implements IProfileConstants { if (TYPE_TABLE.equals(key)) { // add a table entry - Table table = createSigTable(profile, type, configuration, certProvider); + Table table = createSigTable(profile, type, operationStatus, certProvider); if (table != null) { Entry entry = new Entry(Entry.TYPE_TABLE, table, key); @@ -190,10 +192,10 @@ public class TableFactory implements IProfileConstants { if (TYPE_VALUE.equals(type)) { // add a single value entry - ValueResolver resolver = new ValueResolver(); + ValueResolver resolver = new ValueResolver(certProvider, operationStatus); String value = profile.getValue(key); Entry entry = new Entry(Entry.TYPE_VALUE, - resolver.resolve(key, value, profile, certProvider), key); + resolver.resolve(key, value, profile), key); if (entry != null) { entry.setColSpan(2); @@ -213,9 +215,9 @@ public class TableFactory implements IProfileConstants { Entry c_entry = new Entry(Entry.TYPE_CAPTION, caption, key); c_entry.setNoWrap(true); // dferbas fix bug #331 c_entry.setStyle(defaultCaptionStyle_); - ValueResolver resolver = new ValueResolver(); + ValueResolver resolver = new ValueResolver(certProvider, operationStatus); Entry v_entry = new Entry(Entry.TYPE_VALUE, - resolver.resolve(key, value, profile, certProvider), key); + resolver.resolve(key, value, profile), key); v_entry.setStyle(defaultValueStyle_); if (c_entry != null && v_entry != null) { @@ -228,10 +230,10 @@ public class TableFactory implements IProfileConstants { c_entry.setNoWrap(true); // dferbas fix bug #331 c_entry.setStyle(defaultCaptionStyle_); - ValueResolver resolver = new ValueResolver(); + ValueResolver resolver = new ValueResolver(certProvider, operationStatus); Entry v_entry = new Entry(Entry.TYPE_VALUE, - resolver.resolve(key, value, profile, certProvider), key); + resolver.resolve(key, value, profile), key); v_entry.setStyle(defaultValueStyle_); if (c_entry != null && v_entry != null) { diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java index b05fc52c..16f23759 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java @@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.common.settings.IProfileConstants; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; +import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; /** * Created with IntelliJ IDEA. User: afitzek Date: 9/11/13 Time: 11:11 AM To @@ -51,8 +52,15 @@ public class ValueResolver implements IProfileConstants, IResolver { public static final String EXP_START = "${"; public static final String EXP_END = "}"; + private CertificateResolver certificateResolver; + + public ValueResolver(ICertificateProvider certProvider, OperationStatus operationStatus) { + certificateResolver = new CertificateResolver( + certProvider.getCertificate(), operationStatus); + } + public String resolve(String key, String value, - SignatureProfileSettings settings, ICertificateProvider certProvider) { + SignatureProfileSettings settings) { logger.debug("Resolving value for key: " + key); logger.debug("Resolving value with value: " + value); @@ -71,8 +79,7 @@ public class ValueResolver implements IProfileConstants, IResolver { Pattern pattern = Pattern.compile(PatternRegex); Matcher matcher = pattern.matcher(value); - CertificateResolver certificateResolver = new CertificateResolver( - certProvider.getCertificate()); + String result = ""; int curidx = 0; if (matcher.find()) { @@ -82,7 +89,7 @@ public class ValueResolver implements IProfileConstants, IResolver { result += value.substring(curidx, idx); curidx = idxe; result += certificateResolver.resolve(key, - matcher.group(1), settings, certProvider); + matcher.group(1), settings); } while (matcher.find()); } else { result = value; 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 82116474..3885169b 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 @@ -105,6 +105,52 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { // draw if boarder > 0 if (border != 0) { + float nexty = y + tableHeight; + float lasty = nexty; + for (int i = 0; i < rows; i++) { + ArrayList row = abstractTable.getRow(i); + // Draw row border! + logger.debug("ROW LINE: {} {} {} {}", x, nexty, x + tableWidth, + nexty); + contentStream.drawLine(x, nexty, x + tableWidth, nexty); + lasty = nexty; + if (i < abstractTable.getRowHeights().length) { + nexty -= abstractTable.getRowHeights()[i] + padding * 2; + } + + if (subtable && i + 1 == abstractTable.getRowHeights().length) { + nexty -= padding; + } + + float nextx = x; + float ypos = y; + float yheight = y + abstractTable.getHeight(); + if (subtable) { + ypos -= padding; + yheight = y + abstractTable.getHeight(); + } + + for (int j = 0; j < row.size(); j++) { + Entry cell = (Entry) row.get(j); + + if (subtable && j == cols) { + continue; + } + logger.debug("COL LINE: {} {} {} {}", nextx, ypos, nextx, + yheight); + contentStream.drawLine(nextx, lasty, nextx, nexty); + for(int k = 0; k < cell.getColSpan(); k++) { + if (k + j < colsSizes.length) { + nextx += (colsSizes != null) ? colsSizes[k + j] : colWidth; + } + } + } + contentStream.drawLine(nextx, lasty, nextx, nexty); + } + + contentStream.drawLine(x, nexty, x + tableWidth, nexty); + + /* // draw the rows float nexty = y + tableHeight; for (int i = 0; i <= rows; i++) { @@ -137,7 +183,7 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { if (i < colsSizes.length) { nextx += (colsSizes != null) ? colsSizes[i] : colWidth; } - } + }*/ } float textx = x + padding; @@ -146,6 +192,10 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { ArrayList row = abstractTable.getRow(i); for (int j = 0; j < row.size(); j++) { Entry cell = (Entry) row.get(j); + + Style inherit_style = Style.doInherit(abstractTable.style, cell.getStyle()); + cell.setStyle(inherit_style); + if (cell.getType() == Entry.TYPE_CAPTION || cell.getType() == Entry.TYPE_VALUE) { @@ -175,9 +225,71 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { } else { contentStream.setFont(textFont, fontSize); } - logger.debug("Writing: " + textx + " : " + ttexty + " = " + + // TODO: use halign and valgin + + float fheight = textFont.getFontDescriptor().getFontBoundingBox() + .getHeight() + / 1000 * fontSize; + + String[] tlines = text.split("\n"); + float textHeight = fheight * tlines.length; + + Style cellStyle = cell.getStyle(); + String valign = null; + String halign = null; + + if (cell.getType() == Entry.TYPE_CAPTION && cellStyle != null) { + valign = cellStyle.getVAlign(); + halign = cellStyle.getHAlign(); + } else if (cell.getType() == Entry.TYPE_VALUE && cellStyle != null) { + valign = cellStyle.getValueVAlign(); + halign = cellStyle.getValueHAlign(); + } + float ty = ttexty; + if(Style.BOTTOM.equals(valign)) { + float bottom_offset = abstractTable.getRowHeights()[i] - textHeight; + ty -= bottom_offset; + } else if(Style.MIDDLE.equals(valign)) { + float bottom_offset = abstractTable.getRowHeights()[i] - textHeight; + bottom_offset = bottom_offset / 2.0f; + ty -= bottom_offset; + } + + float columnWidth = (colsSizes != null) ? colsSizes[j] : colWidth; + float maxWidth = 0; + for (int k = 0; k < tlines.length; k++) { + + float fwidth; + if (textFont instanceof PDType1Font) { + fwidth = textFont.getFontDescriptor().getFontBoundingBox().getWidth() + / 1000.0f * fontSize; + } else { + fwidth = textFont.getStringWidth("abcdefghijklmnopqrstuvwxyz ") / 1000.0f * fontSize; + fwidth = fwidth / (float)"abcdefghijklmnopqrstuvwxyz".length(); + } + + float lineWidth = tlines[k].length() * fwidth; + + //float w = textFont.getStringWidth(tlines[k]) / 1000 * fontSize; + if (maxWidth < lineWidth) { + maxWidth = lineWidth; + } + } + + float tx = textx; + if(Style.CENTER.equals(halign)) { + float offset = columnWidth - maxWidth - 2 * padding; + offset = offset / 2.0f; + tx += offset; + } else if(Style.RIGHT.equals(halign)) { + float offset = columnWidth - maxWidth - 2 * padding; + tx += offset; + } + + logger.debug("Writing: " + tx + " : " + ty + " = " + text + " as " + cell.getType() + " w " + fontName); - contentStream.moveTextPositionByAmount(textx, ttexty); + contentStream.moveTextPositionByAmount(tx, ty); if (text.contains("\n")) { String[] lines = text.split("\n"); @@ -207,6 +319,8 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { // contentStream.beginMarkedContentSequence(COSName.ALT, // name); + // TODO: use HAlign + float imgy = texty; if (cell.getStyle().getImageVAlign() != null && cell.getStyle().getImageVAlign() @@ -230,12 +344,17 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { // 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(); + + Style inherit_styletab = Style.doInherit(abstractTable.style, cell.getStyle()); + tbl_value.table.setStyle(inherit_styletab); + logger.debug("Table: " + tableX + " : " + tableY); drawTable(page, contentStream, tableX, tableY, tbl_value, doc, true); 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 index e76c849e..1bbfbe9a 100644 --- 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 @@ -11,6 +11,8 @@ import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.sun.org.apache.bcel.internal.generic.Type; + import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException; import at.gv.egiz.pdfas.common.settings.ISettings; @@ -71,12 +73,11 @@ public class PDFBoxTable { } catch(PdfAsException e) { throw new PdfAsWrappedIOException(e); } - if (abstractTable.getStyle() != null) { - style = abstractTable.getStyle(); - } - if (style == null && parent != null) { - style = parent.style; + if (parent != null) { + style = Style.doInherit(abstractTable.getStyle(), parent.style); + } else { + style = abstractTable.getStyle(); } if (style == null) { @@ -87,10 +88,6 @@ public class PDFBoxTable { String vfontString = style.getValueFont(); - if(fontString == null || vfontString == null) { - - } - if (parent != null && style == parent.style) { font = parent.getFont(); @@ -158,14 +155,26 @@ public class PDFBoxTable { ArrayList row = 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]); + + float colWidth = colWidths[j]; + + int colsleft = cell.getColSpan() - 1; + + if(j + colsleft > colWidths.length) { + throw new IOException("Configuration is wrong. Cannot determine column width!"); + } + + for(int k = 0; k < colsleft; k++) { + colWidth = colWidth + colWidths[j+k]; + } + + float cellheight = getCellHeight(cell, colWidth); if (rowHeights[i] < cellheight) { rowHeights[i] = cellheight; } - logger.debug("ROW: {} COL: {} Width: {} Height: {}", i, j, + logger.debug("ROW: {} COL: {} Width: {} Height: {}", i, j, colWidth, cellheight); int span = cell.getColSpan() - 1; @@ -386,7 +395,7 @@ public class PDFBoxTable { c = font.getFont(null); fontSize = font.getFontSize(); } - + float fwidth; if (c instanceof PDType1Font) { fwidth = c.getFontDescriptor().getFontBoundingBox().getWidth() @@ -536,6 +545,9 @@ public class PDFBoxTable { for (int i = 0; i < colWidths.length; i++) { logger.debug("\t[{}] : {}", i, this.colWidths[i]); } + logger.debug("\t================================"); + logger.debug("\tTable:"); + logger.debug("\t" + this.table.toString()); logger.debug("====================================================================="); } diff --git a/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java index 2c4ea18d..b4f424c2 100644 --- a/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java +++ b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java @@ -167,13 +167,13 @@ public class TestPDFBoxTable { X509Certificate cert = new X509Certificate(new FileInputStream("/home/afitzek/qualified.cer")); CertificateHolderRequest request = new CertificateHolderRequest(cert); - + /* Table main = TableFactory.createSigTable(profileSettings, "main", settings, request); main.setWidth(400); renderTable(main); - + */ // PDStream stream1; PDDocument document = new PDDocument(); @@ -181,7 +181,7 @@ public class TestPDFBoxTable { page.setMediaBox(new PDRectangle()); PDPageContentStream stream = new PDPageContentStream(document, page); stream.setFont(PDType1Font.HELVETICA_BOLD , 12); - drawTable(page, stream, 100, 300, main); + //drawTable(page, stream, 100, 300, main); stream.close(); document.addPage(page); -- cgit v1.2.3