aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2')
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/FontInfoCache.java8
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/IDGenerator.java5
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/ImageObject.java64
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java166
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java659
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureDesigner.java472
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java149
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java299
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxTable.java722
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxStamper.java67
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxVisualObject.java108
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/StamperFactory.java25
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java609
13 files changed, 3353 insertions, 0 deletions
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/FontInfoCache.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/FontInfoCache.java
new file mode 100644
index 00000000..c208820e
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/FontInfoCache.java
@@ -0,0 +1,8 @@
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+public class FontInfoCache {
+ String filename;
+ String fontName;
+ String fontFamily;
+ String fontPath;
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/IDGenerator.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/IDGenerator.java
new file mode 100644
index 00000000..ef898d74
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/IDGenerator.java
@@ -0,0 +1,5 @@
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+public interface IDGenerator {
+ public String createHashedId(String value);
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/ImageObject.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/ImageObject.java
new file mode 100644
index 00000000..16af5cfb
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/ImageObject.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+
+
+public class ImageObject {
+ private PDImageXObject image;
+ private float width;
+ private float height;
+
+ public ImageObject(PDImageXObject image, float width, float height) {
+ this.image = image;
+ this.width = width;
+ this.height = height;
+ }
+
+ public PDImageXObject getImage() {
+ return image;
+ }
+
+ public void setImage(PDImageXObject image) {
+ this.image = image;
+ }
+
+ public float getWidth() {
+ return width;
+ }
+
+ public void setWidth(float width) {
+ this.width = width;
+ }
+
+ public float getHeight() {
+ return height;
+ }
+
+ public void setHeight(float height) {
+ this.height = height;
+ }
+
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java
new file mode 100644
index 00000000..b8c15119
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateCreator;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateStructure;
+import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+
+public class PDFAsTemplateCreator extends PDFTemplateCreator {
+
+ PDFAsVisualSignatureBuilder pdfBuilder;
+ private static final Logger logger = LoggerFactory.getLogger(PDFAsTemplateCreator.class);
+
+ public PDFAsTemplateCreator(PDFAsVisualSignatureBuilder bookBuilder) {
+ super(bookBuilder);
+ this.pdfBuilder = bookBuilder;
+ }
+
+
+ public InputStream buildPDF(PDFAsVisualSignatureDesigner properties, PDDocument originalDocument)
+ throws IOException, PdfAsException {
+ logger.debug("pdf building has been started");
+ PDFTemplateStructure pdfStructure = pdfBuilder.getStructure();
+
+ // we create array of [Text, ImageB, ImageC, ImageI]
+ this.pdfBuilder.createProcSetArray();
+
+ //create page
+ this.pdfBuilder.createPage(properties);
+ PDPage page = pdfStructure.getPage();
+
+ //create template
+ this.pdfBuilder.createTemplate(page);
+ PDDocument template = pdfStructure.getTemplate();
+
+ //create /AcroForm
+ this.pdfBuilder.createAcroForm(template);
+ PDAcroForm acroForm = pdfStructure.getAcroForm();
+
+ // AcroForm contains singature fields
+ this.pdfBuilder.createSignatureField(acroForm);
+ PDSignatureField pdSignatureField = pdfStructure.getSignatureField();
+
+ // create signature
+ this.pdfBuilder.createSignature(pdSignatureField, page, properties.getSignatureFieldName());
+
+ // that is /AcroForm/DR entry
+ this.pdfBuilder.createAcroFormDictionary(acroForm, pdSignatureField);
+
+ // create AffineTransform
+ this.pdfBuilder.createAffineTransform(properties.getAffineTransformParams());
+ //AffineTransform transform = pdfStructure.getAffineTransform();
+
+ // rectangle, formatter, image. /AcroForm/DR/XObject contains that form
+ this.pdfBuilder.createSignatureRectangle(pdSignatureField, properties, properties.getRotation() + properties.getPageRotation());
+ this.pdfBuilder.createFormaterRectangle(properties.getFormaterRectangleParams());
+ PDRectangle formater = pdfStructure.getFormatterRectangle();
+
+ //this.pdfBuilder.createSignatureImage(template, properties.getImageStream());
+
+ // create form stream, form and resource.
+ this.pdfBuilder.createHolderFormStream(template);
+ PDStream holderFormStream = pdfStructure.getHolderFormStream();
+ this.pdfBuilder.createHolderFormResources();
+ PDResources holderFormResources = pdfStructure.getHolderFormResources();
+ this.pdfBuilder.createHolderForm(holderFormResources, holderFormStream, formater);
+
+ // that is /AP entry the appearance dictionary.
+ this.pdfBuilder.createAppearanceDictionary(pdfStructure.getHolderForm(), pdSignatureField,
+ properties.getRotation() + properties.getPageRotation());
+
+ // inner formstream, form and resource (hlder form containts inner form)
+ this.pdfBuilder.createInnerFormStreamPdfAs(template, originalDocument);
+ this.pdfBuilder.createInnerFormResource();
+ PDResources innerFormResource = pdfStructure.getInnerFormResources();
+ this.pdfBuilder.createInnerForm(innerFormResource, pdfStructure.getInnerFormStream(), formater);
+ PDFormXObject innerForm = pdfStructure.getInnerForm();
+
+ // inner form must be in the holder form as we wrote
+ this.pdfBuilder.insertInnerFormToHolerResources(innerForm, holderFormResources);
+
+ // Image form is in this structure: /AcroForm/DR/FRM0/Resources/XObject/n0
+ //this.pdfBuilder.createImageFormStream(template);
+ //PDStream imageFormStream = pdfStructure.getImageFormStream();
+ //this.pdfBuilder.createImageFormResources();
+ //PDResources imageFormResources = pdfStructure.getImageFormResources();
+ //this.pdfBuilder.createImageForm(imageFormResources, innerFormResource, imageFormStream, formater, transform,
+ // pdfStructure.getJpedImage());
+
+ // now inject procSetArray
+ /*this.pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, imageFormResources, holderFormResources,
+ pdfStructure.getProcSet());*/
+ this.pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, null, holderFormResources,
+ pdfStructure.getProcSet());
+
+
+ /*String imgFormName = pdfStructure.getImageFormName();
+ String imgName = pdfStructure.getImageName();*/
+ String innerFormName = pdfStructure.getInnerFormName().getName();
+
+ // now create Streams of AP
+ /*this.pdfBuilder.injectAppearanceStreams(holderFormStream, imageFormStream, imageFormStream, imgFormName,
+ imgName, innerFormName, properties);*/
+ this.pdfBuilder.injectAppearanceStreams(holderFormStream, null, null, null,
+ null, innerFormName, properties);
+ this.pdfBuilder.createVisualSignature(template);
+ this.pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources);
+
+ ByteArrayInputStream in = null;
+
+ //COSDocument doc = pdfStructure.getVisualSignature();
+ //doc.
+ //in = pdfStructure.getTemplateAppearanceStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ template.save(baos);
+ baos.close();
+ in = new ByteArrayInputStream(baos.toByteArray());
+
+
+ logger.debug("stream returning started, size= " + in.available());
+
+ // we must close the document
+ this.pdfBuilder.closeTemplate(template);
+
+ // return result of the stream
+ return in;
+ }
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java
new file mode 100644
index 00000000..30487ead
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java
@@ -0,0 +1,659 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.io.IOUtils;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdfparser.PDFParser;
+import org.apache.pdfbox.pdfparser.PDFStreamParser;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
+import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
+import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+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.PDVisibleSigBuilder;
+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.common.utils.ImageUtils;
+import at.knowcenter.wag.egov.egiz.table.Entry;
+
+public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder implements
+ IDGenerator {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(PDFAsVisualSignatureBuilder.class);
+
+ private PDFAsVisualSignatureProperties properties;
+ private PDFAsVisualSignatureDesigner designer;
+ private ISettings settings;
+ private PDResources innerFormResources;
+ private Map<String, ImageObject> images = new HashMap<String, ImageObject>();
+
+ public PDFAsVisualSignatureBuilder(
+ PDFAsVisualSignatureProperties properties, ISettings settings,
+ PDFAsVisualSignatureDesigner designer) {
+ this.properties = properties;
+ this.settings = settings;
+ this.designer = designer;
+ }
+
+ @Override
+ public void createProcSetArray() {
+ 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.debug("ProcSet array has been created");
+ }
+
+ public void createMyPage(PDFAsVisualSignatureDesigner properties) {
+ PDPage page = properties.getSignaturePage();
+ if (page == null) {
+ page = new PDPage();
+ page.setMediaBox(new PDRectangle(properties.getPageWidth(),
+ properties.getPageHeight()));
+
+ }
+ getStructure().setPage(page);
+ logger.info("PDF page has been created");
+ }
+
+ @Override
+ public void createTemplate(PDPage page) throws IOException {
+ PDDocument template = new PDDocument();
+
+ template.addPage(page);
+ getStructure().setTemplate(template);
+ }
+
+ public String createHashedId(String value) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ md.reset();
+ return Hex.encodeHexString(md.digest(value.getBytes("UTF-8")));
+ } catch (Throwable e) {
+ logger.warn("Failed to generate ID for Image using value", e);
+ return value;
+ }
+ }
+
+ private void readTableResources(PDFBoxTable table, PDDocument template)
+ throws PdfAsException, IOException {
+
+ float[] colsSizes = table.getColsRelativeWith();
+ int max_cols = table.getColCount();
+ float padding = table.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.debug("TOTAL Width: " + table.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)
+ * table.getWidth();
+ }
+
+ for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) {
+ logger.debug("Col: " + cols_idx + " : " + colsSizes[cols_idx]);
+ }
+
+ /*
+ * if(!addedFonts.contains(table.getFont().getFont(null))) { PDFont font
+ * = table.getFont().getFont(template); addedFonts.add(font);
+ * innerFormResources.addFont(font); }
+ *
+ * if(!addedFonts.contains(table.getValueFont().getFont(null))) { PDFont
+ * font = table.getValueFont().getFont(template); addedFonts.add(font);
+ * innerFormResources.addFont(font); }
+ */
+
+ for (int i = 0; i < table.getRowCount(); i++) {
+ ArrayList<Entry> row = table.getRow(i);
+ for (int j = 0; j < row.size(); j++) {
+ Entry cell = (Entry) row.get(j);
+ if (cell.getType() == Entry.TYPE_IMAGE) {
+ String img_value = (String) cell.getValue();
+ String img_ref = createHashedId(img_value);
+ if (!images.containsKey(img_ref)) {
+ BufferedImage img = ImageUtils.getImage(img_value,
+ settings);
+
+ float width = colsSizes[j];
+ float height = table.getRowHeights()[i] + padding * 2;
+
+ float iwidth = (int) Math.floor((double) width);
+ iwidth -= 2 * padding;
+
+ float iheight = (int) Math.floor((double) height);
+ iheight -= 2 * padding;
+
+ float origWidth = (float) img.getWidth();
+ float origHeight = (float) img.getHeight();
+
+ if (table.style != null) {
+ if (table.style.getImageScaleToFit() != null) {
+ iwidth = table.style.getImageScaleToFit()
+ .getWidth();
+ iheight = table.style.getImageScaleToFit()
+ .getHeight();
+ }
+ }
+
+ float wfactor = iwidth / origWidth;
+ float hfactor = iheight / origHeight;
+ float scaleFactor = wfactor;
+ if (hfactor < wfactor) {
+ scaleFactor = hfactor;
+ }
+
+ iwidth = (float) Math
+ .floor((double) (scaleFactor * origWidth));
+ iheight = (float) Math
+ .floor((double) (scaleFactor * origHeight));
+
+ logger.debug("Scaling image to: " + iwidth + " x "
+ + iheight);
+
+ if (this.designer.properties
+ .getSignatureProfileSettings().isPDFA()) {
+ img = ImageUtils.removeAlphaChannel(img);
+ } else {
+ if (img.getAlphaRaster() == null
+ && img.getColorModel().hasAlpha()) {
+ img = ImageUtils.removeAlphaChannel(img);
+ }
+ }
+ // img = ImageUtils.convertRGBAToIndexed(img);
+
+ PDImageXObject pdImage = LosslessFactory.createFromImage(template, img);
+
+
+ ImageObject image = new ImageObject(pdImage, iwidth,
+ iheight);
+ images.put(img_ref, image);
+ innerFormResources.add(pdImage, "Im");
+ }
+ } else if (cell.getType() == Entry.TYPE_TABLE) {
+ PDFBoxTable tbl_value = (PDFBoxTable) cell.getValue();
+ readTableResources(tbl_value, template);
+ }
+ }
+ }
+ }
+
+ public void createInnerFormStreamPdfAs(PDDocument template, PDDocument origDoc)
+ throws PdfAsException {
+ try {
+
+ // Hint we have to create all PDXObjectImages before creating the
+ // PDPageContentStream
+ // only PDFbox developers know why ...
+ // if (getStructure().getPage().getResources() != null) {
+ // innerFormResources = getStructure().getPage().getResources();
+ // } else {
+ innerFormResources = new PDResources();
+ getStructure().getPage().setResources(innerFormResources);
+ // }
+ readTableResources(properties.getMainTable(), template);
+
+ PDPageContentStream stream = new PDPageContentStream(template,
+ getStructure().getPage());
+ // stream.setFont(PDType1Font.COURIER, 5);
+ TableDrawUtils.drawTable(getStructure().getPage(), stream, 1, 1,
+ designer.getWidth(), designer.getHeight(),
+ properties.getMainTable(), template, false,
+ innerFormResources, images, settings, this, properties);
+ stream.close();
+ PDStream innterFormStream = new PDStream(template,getStructure().getPage().getContents());
+
+ getStructure().setInnterFormStream(innterFormStream);
+ logger.debug("Strean of another form (inner form - it would be inside holder form) has been created");
+
+ } catch (Throwable e) {
+ logger.warn("Failed to create visual signature block", e);
+ throw new PdfAsException("Failed to create visual signature block",
+ e);
+ }
+ }
+
+ @Override
+ public void injectProcSetArray(PDFormXObject innerForm, PDPage page,
+ PDResources innerFormResources, PDResources imageFormResources,
+ PDResources holderFormResources, COSArray procSet) {
+ innerForm.getResources().getCOSObject()
+ .setItem(COSName.PROC_SET, procSet); //
+ page.getCOSObject().setItem(COSName.PROC_SET, procSet);
+ innerFormResources.getCOSObject()
+ .setItem(COSName.PROC_SET, procSet);
+ /*
+ * imageFormResources.getCOSDictionary() .setItem(COSName.PROC_SET,
+ * procSet);
+ */
+ holderFormResources.getCOSObject().setItem(COSName.PROC_SET,
+ procSet);
+ logger.debug("inserted ProcSet to PDF");
+ }
+
+ public void injectAppearanceStreams(PDStream holderFormStream,
+ PDStream innterFormStream, PDStream imageFormStream,
+ String imageObjectName, String imageName, String innerFormName,
+ PDFAsVisualSignatureDesigner properties) throws IOException {
+
+ // 100 means that document width is 100% via the rectangle. if rectangle
+ // 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";
+ */
+ double m00 = getStructure().getAffineTransform().getScaleX();
+ double m10 = getStructure().getAffineTransform().getShearY();
+ double m01 = getStructure().getAffineTransform().getShearX();
+ double m11 = getStructure().getAffineTransform().getScaleY();
+ double m02 = getStructure().getAffineTransform().getTranslateX();
+ double m12 = getStructure().getAffineTransform().getTranslateY();
+
+ String holderFormComment = "q " + m00 + " " + m10 + " " + m01 + " "
+ + m11 + " " + m02 + " " + m12 + " cm /" + innerFormName
+ + " Do Q";
+
+ logger.debug("Holder Form Stream: " + holderFormComment);
+
+ // String innerFormComment = "q 1 0 0 1 0 0 cm /" + imageObjectName +
+ // " Do Q\n";
+ String innerFormComment = IOUtils.toString(getStructure().getInnerFormStream().toByteArray());
+
+ // .getInputStreamAsString();//TODO: pdfbox2 - get the string from the stream
+
+ // logger.debug("Inner Form Stream: " + innerFormComment);
+
+ // appendRawCommands(getStructure().getInnterFormStream().createOutputStream(),
+ // getStructure().getInnterFormStream().getInputStreamAsString());
+
+ appendRawCommands(getStructure().getHolderFormStream()
+ .createOutputStream(), holderFormComment.trim().replace("\n", "").replace("\r", ""));
+ appendRawCommands(getStructure().getInnerFormStream()
+ .createOutputStream(), innerFormComment/*.trim().replace("\n", "").replace("\r", "")*/);
+ // appendRawCommands(getStructure().getImageFormStream().createOutputStream(),
+ // imgFormComment);
+ logger.debug("Injected apereance stream to pdf");
+
+ }
+
+ public void createPage(PDFAsVisualSignatureDesigner properties) {
+ PDPage page = new PDPage();
+ page.setMediaBox(new PDRectangle(properties.getPageWidth(), properties
+ .getPageHeight()));
+ page.setRotation(properties.getPageRotation());
+ getStructure().setPage(page);
+ logger.debug("PDF page has been created");
+ }
+
+ public void createAcroForm(PDDocument template) {
+ PDAcroForm theAcroForm = new PDAcroForm(template);
+ template.getDocumentCatalog().setAcroForm(theAcroForm);
+ getStructure().setAcroForm(theAcroForm);
+ logger.debug("Acro form page has been created");
+ }
+
+ public void createSignatureField(PDAcroForm acroForm) throws IOException {
+ PDSignatureField sf = new PDSignatureField(acroForm);
+ getStructure().setSignatureField(sf);
+ logger.debug("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.debug("PDSignatur has been created");
+ }
+
+ public void createAcroFormDictionary(PDAcroForm acroForm,
+ PDSignatureField signatureField) throws IOException {
+ @SuppressWarnings("unchecked")
+ List<PDField> acroFormFields = acroForm.getFields();
+ COSDictionary acroFormDict = acroForm.getCOSObject();
+ 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.debug("AcroForm dictionary has been created");
+ }
+
+ public void createSignatureRectangle(PDSignatureField signatureField,
+ PDFAsVisualSignatureDesigner properties, float degrees)
+ throws IOException {
+
+ PDRectangle rect = new PDRectangle();
+
+ Point2D upSrc = new Point2D.Float();
+ upSrc.setLocation(properties.getxAxis() + properties.getWidth(),
+ properties.getPageHeight() - properties.getyAxis());
+
+ Point2D llSrc = new Point2D.Float();
+ llSrc.setLocation(properties.getxAxis(), properties.getPageHeight()
+ - properties.getyAxis() - properties.getHeight());
+
+ rect.setUpperRightX((float) upSrc.getX());
+ rect.setUpperRightY((float) upSrc.getY());
+ rect.setLowerLeftY((float) llSrc.getY());
+ rect.setLowerLeftX((float) llSrc.getX());
+ logger.debug("orig rectangle of signature has been created: {}",
+ rect.toString());
+
+ AffineTransform transform = new AffineTransform();
+ transform.setToIdentity();
+ if (degrees % 360 != 0) {
+ transform.setToRotation(Math.toRadians(degrees), llSrc.getX(),
+ llSrc.getY());
+ }
+
+ Point2D upDst = new Point2D.Float();
+ transform.transform(upSrc, upDst);
+
+ Point2D llDst = new Point2D.Float();
+ transform.transform(llSrc, llDst);
+
+ float xPos = properties.getxAxis();
+ float yPos = properties.getPageHeight() - properties.getyAxis();
+ logger.debug("POS {} x {}", xPos, yPos);
+ logger.debug("SIZE {} x {}", properties.getWidth(),
+ properties.getHeight());
+ // translate according to page! rotation
+ int pageRotation = properties.getPageRotation();
+ AffineTransform translate = new AffineTransform();
+ switch (pageRotation) {
+ case 90:
+ translate.setToTranslation(
+ properties.getPageHeight()
+ - (properties.getPageHeight() - properties
+ .getyAxis()) - properties.getxAxis()
+ + properties.getHeight(),
+ properties.getxAxis()
+ + properties.getHeight()
+ - (properties.getPageHeight() - properties
+ .getyAxis()));
+ break;
+ case 180:
+ // translate.setToTranslation(properties.getPageWidth() -
+ // properties.getxAxis() - properties.getxAxis(),
+ // properties.getPageHeight() - properties.getyAxis() +
+ // properties.getHeight());
+ translate.setToTranslation(
+ properties.getPageWidth() - 2 * xPos,
+ properties.getPageHeight() - 2
+ * (yPos - properties.getHeight()));
+ break;
+ case 270:
+ translate.setToTranslation(-properties.getHeight() + yPos - xPos,
+ properties.getPageWidth() - (yPos - properties.getHeight())
+ - xPos);
+ break;
+ }
+
+ translate.transform(upDst, upDst);
+ translate.transform(llDst, llDst);
+
+ rect.setUpperRightX((float) upDst.getX());
+ rect.setUpperRightY((float) upDst.getY());
+ rect.setLowerLeftY((float) llDst.getY());
+ rect.setLowerLeftX((float) llDst.getX());
+ logger.debug("rectangle of signature has been created: {}",
+ rect.toString());
+ signatureField.getWidget().setRectangle(rect);
+ getStructure().setSignatureRectangle(rect);
+ logger.debug("rectangle of signature has been created");
+ }
+
+ public void createAffineTransform(float[] params) {
+ AffineTransform transform = new AffineTransform(params[0], params[1],
+ params[2], params[3], params[4], params[5]);
+ // transform.rotate(90);
+ getStructure().setAffineTransform(transform);
+ logger.debug("Matrix has been added");
+ }
+
+ public void createSignatureImage(PDDocument template,
+ InputStream inputStream) throws IOException {
+ PDImageXObject img = JPEGFactory.createFromStream(template, inputStream);
+ getStructure().setImage(img);
+ logger.debug("Visible Signature Image has been created");
+ // pdfStructure.setTemplate(template);
+ inputStream.close();
+
+ }
+
+ public void createFormaterRectangle(float[] params) {
+
+ PDRectangle formrect = new PDRectangle();
+ float[] translated = new float[4];
+ getStructure().getAffineTransform().transform(params, 0, translated, 0,
+ 2);
+
+ formrect.setUpperRightX(translated[0]);
+ formrect.setUpperRightY(translated[1]);
+ formrect.setLowerLeftX(translated[2]);
+ formrect.setLowerLeftY(translated[3]);
+
+ getStructure().setFormatterRectangle(formrect);
+ logger.debug("Formater rectangle has been created");
+
+ }
+
+ public void createHolderFormStream(PDDocument template) {
+ PDStream holderForm = new PDStream(template);
+ getStructure().setHolderFormStream(holderForm);
+ logger.debug("Holder form Stream has been created");
+ }
+
+ public void createHolderFormResources() {
+ PDResources holderFormResources = new PDResources();
+ getStructure().setHolderFormResources(holderFormResources);
+ logger.debug("Holder form resources have been created");
+
+ }
+
+ public void createHolderForm(PDResources holderFormResources,
+ PDStream holderFormStream, PDRectangle formrect) {
+
+ PDFormXObject holderForm = new PDFormXObject(holderFormStream);
+ holderForm.setResources(holderFormResources);
+ holderForm.setBBox(formrect);
+ holderForm.setFormType(1);
+ getStructure().setHolderForm(holderForm);
+ logger.debug("Holder form has been created");
+
+ }
+
+ public void createAppearanceDictionary(PDFormXObject holderForml,
+ PDSignatureField signatureField, float degrees) throws IOException {
+
+ PDAppearanceDictionary appearance = new PDAppearanceDictionary();
+ appearance.getCOSObject().setDirect(true);
+
+ PDAppearanceStream appearanceStream = new PDAppearanceStream(
+ holderForml.getCOSStream());
+ AffineTransform transform = new AffineTransform();
+ transform.setToIdentity();
+ transform.rotate(Math.toRadians(degrees));
+ appearanceStream.setMatrix(transform);
+ appearance.setNormalAppearance(appearanceStream);
+ signatureField.getWidget().setAppearance(appearance);
+
+ getStructure().setAppearanceDictionary(appearance);
+ logger.debug("PDF appereance Dictionary has been created");
+
+ }
+
+ public void createInnerFormResource() {
+ getStructure().setInnerFormResources(innerFormResources);
+ logger.debug("Resources of another form (inner form - it would be inside holder form) have been created");
+ }
+
+ public void createInnerForm(PDResources innerFormResources,
+ PDStream innerFormStream, PDRectangle formrect) {
+ PDFormXObject innerForm = new PDFormXObject(innerFormStream);
+ innerForm.setResources(innerFormResources);
+ innerForm.setBBox(formrect);
+ innerForm.setFormType(1);
+ getStructure().setInnerForm(innerForm);
+ logger.debug("Another form (inner form - it would be inside holder form) have been created");
+
+ }
+
+ public void insertInnerFormToHolerResources(PDFormXObject innerForm,
+ PDResources holderFormResources) {
+ COSName name = holderFormResources.add(innerForm, "FRM");//TODO: pdfbox2 - is this right?
+ getStructure().setInnerFormName(name);
+ logger.debug("Alerady inserted inner form inside holder form");
+ }
+
+ public void createImageFormStream(PDDocument template) {
+ PDStream imageFormStream = new PDStream(template);
+ getStructure().setImageFormStream(imageFormStream);
+ logger.debug("Created image form Stream");
+ }
+
+ public void createImageFormResources() {
+ PDResources imageFormResources = new PDResources();
+ getStructure().setImageFormResources(imageFormResources);
+ logger.debug("Created image form Resources");
+ }
+
+ public void createImageForm(PDResources imageFormResources,
+ PDResources innerFormResource, PDStream imageFormStream,
+ PDRectangle formrect, AffineTransform affineTransform, PDFormXObject 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<String, PDFont> fonts = new HashMap<String, PDFont>();
+ * fonts.put("arial", font);
+ */
+ PDFormXObject imageForm = new PDFormXObject(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);
+ COSName imageFormName = innerFormResource.add(imageForm, "n");//TODO: pdfbox2 - is this right?
+ COSName imageName = imageFormResources.add(img, "img");
+ this.getStructure().setImageForm(imageForm);
+ this.getStructure().setImageFormName(imageFormName);
+ this.getStructure().setImageName(imageName);
+ logger.debug("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.debug("Visible signature has been created");
+
+ }
+
+ public void createWidgetDictionary(PDSignatureField signatureField,
+ PDResources holderFormResources) throws IOException {
+
+ COSDictionary widgetDict = signatureField.getWidgets().get(0).getCOSObject();//TODO: pdfbox2 - is this right was getWidget before?
+ widgetDict.setNeedToBeUpdated(true);
+ widgetDict.setItem(COSName.DR, holderFormResources.getCOSObject());
+
+ getStructure().setWidgetDictionary(widgetDict);
+ logger.debug("WidgetDictionary has been crated");
+ }
+
+ public void closeTemplate(PDDocument template) throws IOException {
+ template.close();
+ this.getStructure().getTemplate().close();
+ }
+
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureDesigner.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureDesigner.java
new file mode 100644
index 00000000..33450b56
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureDesigner.java
@@ -0,0 +1,472 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageTree;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+
+public class PDFAsVisualSignatureDesigner {
+
+// private static final Logger logger = LoggerFactory.getLogger(PDFAsVisualSignatureDesigner.class);
+
+ private Float sigImgWidth;
+ private Float sigImgHeight;
+ private float xAxis;
+ private float yAxis;
+ private float pageHeight;
+ private float pageWidth;
+ private InputStream imgageStream;
+ private String signatureFieldName = "sig"; // default
+ private float[] formaterRectangleParams = { 0, 0, 100, 50 }; // default
+ //private float[] AffineTransformParams = { 0, 1, -1, 0, 0, 0 }; // default
+ private float[] AffineTransformParams = { 1, 0, 0, 1, 0, 0 }; // default
+ private float imageSizeInPercents;
+ private PDDocument document = null;
+ private int page = 0;
+ private int pageRotation = 0;
+ private boolean newpage = false;
+ PDFAsVisualSignatureProperties properties;
+
+ /**
+ *
+ * @param doc
+ * - Already created PDDocument of your PDF document
+ * @param imageStream
+ * @param page
+ * @throws IOException
+ * - If we can't read, flush, or can't close stream
+ */
+ public PDFAsVisualSignatureDesigner(PDDocument doc, int page,
+ PDFAsVisualSignatureProperties properties, boolean newpage) throws IOException {
+ this.properties = properties;
+ calculatePageSize(doc, page, newpage);
+ document = doc;
+ this.page = page;
+ this.newpage = newpage;
+ }
+
+ /**
+ * Each page of document can be different sizes.
+ *
+ * @param document
+ * @param page
+ */
+ private void calculatePageSize(PDDocument document, int page, boolean newpage) {
+
+ if (page < 1) {
+ throw new IllegalArgumentException("First page of pdf is 1, not "
+ + page);
+ }
+
+ PDPageTree pages = document.getDocumentCatalog().getPages();
+ if(newpage) {
+ PDPage lastPage = (PDPage) pages.get(pages.getCount()-1);
+ PDRectangle mediaBox = lastPage.getMediaBox();
+ pageRotation = lastPage.getRotation() % 360;
+ if(pageRotation == 90 || pageRotation == 270) {
+ this.pageHeight(mediaBox.getWidth());
+ this.pageWidth = mediaBox.getHeight();
+ } else {
+ this.pageHeight(mediaBox.getHeight());
+ this.pageWidth = mediaBox.getWidth();
+ }
+ } else {
+ PDPage firstPage = (PDPage) pages.get(page - 1);
+ PDRectangle mediaBox = firstPage.getMediaBox();
+ pageRotation = firstPage.getRotation() % 360;
+ if(pageRotation == 90 || pageRotation == 270) {
+ this.pageHeight(mediaBox.getWidth());
+ this.pageWidth = mediaBox.getHeight();
+ } else {
+ this.pageHeight(mediaBox.getHeight());
+ this.pageWidth = mediaBox.getWidth();
+ }
+ }
+ float x = this.pageWidth;
+ float y = 0;
+ this.pageWidth = this.pageWidth + y;
+ float tPercent = (100 * y / (x + y));
+ this.imageSizeInPercents = 100 - tPercent;
+ }
+
+ /**
+ *
+ * @param path
+ * of image location
+ * @return image Stream
+ * @throws IOException
+ */
+ public PDFAsVisualSignatureDesigner signatureImage(String path)
+ throws IOException {
+ InputStream fin = new FileInputStream(path);
+ return signatureImageStream(fin);
+ }
+
+ /**
+ * zoom signature image with some percent.
+ *
+ * @param percent
+ * - x % increase image with x percent.
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner zoom(float percent) {
+ sigImgHeight = sigImgHeight + (sigImgHeight * percent) / 100;
+ sigImgWidth = sigImgWidth + (sigImgWidth * percent) / 100;
+ return this;
+ }
+
+ /**
+ *
+ * @param xAxis
+ * - x coordinate
+ * @param yAxis
+ * - y coordinate
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner coordinates(float x, float y) {
+ xAxis(x);
+ yAxis(y);
+ return this;
+ }
+
+ /**
+ *
+ * @return xAxis - gets x coordinates
+ */
+ public float getxAxis() {
+ return xAxis;
+ }
+
+ /**
+ *
+ * @param xAxis
+ * - x coordinate
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner xAxis(float xAxis) {
+ this.xAxis = xAxis;
+ return this;
+ }
+
+ /**
+ *
+ * @return yAxis
+ */
+ public float getyAxis() {
+ return yAxis;
+ }
+
+ /**
+ *
+ * @param yAxis
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner yAxis(float yAxis) {
+ this.yAxis = yAxis;
+ return this;
+ }
+
+ /**
+ *
+ * @return signature image width
+ */
+ public float getWidth() {
+ return this.properties.getMainTable().getWidth();
+ }
+
+ /**
+ *
+ * @param sets
+ * signature image width
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner width(float signatureImgWidth) {
+ this.sigImgWidth = signatureImgWidth;
+ return this;
+ }
+
+ /**
+ *
+ * @return signature image height
+ */
+ public float getHeight() {
+ return this.properties.getMainTable().getHeight();
+ }
+
+ /**
+ *
+ * @param set
+ * signature image Height
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner height(float signatureImgHeight) {
+ this.sigImgHeight = signatureImgHeight;
+ return this;
+ }
+
+ /**
+ *
+ * @return template height
+ */
+ protected float getTemplateHeight() {
+ return getPageHeight();
+ }
+
+ /**
+ *
+ * @param templateHeight
+ * @return Visible Signature Configuration Object
+ */
+ private PDFAsVisualSignatureDesigner pageHeight(float templateHeight) {
+ this.pageHeight = templateHeight;
+ return this;
+ }
+
+ /**
+ *
+ * @return signature field name
+ */
+ public String getSignatureFieldName() {
+ return signatureFieldName;
+ }
+
+ /**
+ *
+ * @param signatureFieldName
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner signatureFieldName(
+ String signatureFieldName) {
+ this.signatureFieldName = signatureFieldName;
+ return this;
+ }
+
+ /**
+ *
+ * @return image Stream
+ */
+ public InputStream getImageStream() {
+ return imgageStream;
+ }
+
+ /**
+ *
+ * @param imgageStream
+ * - stream of your visible signature image
+ * @return Visible Signature Configuration Object
+ * @throws IOException
+ * - If we can't read, flush, or close stream of image
+ */
+ private PDFAsVisualSignatureDesigner signatureImageStream(
+ InputStream imageStream) throws IOException {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = imageStream.read(buffer)) > -1) {
+ baos.write(buffer, 0, len);
+ }
+ baos.flush();
+ baos.close();
+
+ byte[] byteArray = baos.toByteArray();
+ byte[] byteArraySecond = byteArray.clone();
+
+ InputStream inputForBufferedImage = new ByteArrayInputStream(byteArray);
+ InputStream revertInputStream = new ByteArrayInputStream(
+ byteArraySecond);
+
+ if (sigImgHeight == null || sigImgWidth == null) {
+ calcualteImageSize(inputForBufferedImage);
+ }
+
+ this.imgageStream = revertInputStream;
+
+ return this;
+ }
+
+ /**
+ * calculates image width and height. sported formats: all
+ *
+ * @param fis
+ * - input stream of image
+ * @throws IOException
+ * - if can't read input stream
+ */
+ private void calcualteImageSize(InputStream fis) throws IOException {
+
+ BufferedImage bimg = ImageIO.read(fis);
+ int width = bimg.getWidth();
+ int height = bimg.getHeight();
+
+ sigImgHeight = (float) height;
+ sigImgWidth = (float) width;
+
+ }
+
+ /**
+ *
+ * @return Affine Transform parameters of for PDF Matrix
+ */
+ public float[] getAffineTransformParams() {
+ return AffineTransformParams;
+ }
+
+ /**
+ *
+ * @param affineTransformParams
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner affineTransformParams(
+ float[] affineTransformParams) {
+ AffineTransformParams = affineTransformParams;
+ return this;
+ }
+
+ /**
+ *
+ * @return formatter PDRectanle parameters
+ */
+ public float[] getFormaterRectangleParams() {
+ return formaterRectangleParams;
+ }
+
+ /**
+ * sets formatter PDRectangle;
+ *
+ * @param formaterRectangleParams
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner formaterRectangleParams(
+ float[] formaterRectangleParams) {
+ this.formaterRectangleParams = formaterRectangleParams;
+ return this;
+ }
+
+ /**
+ *
+ * @return page width
+ */
+ public float getPageWidth() {
+ return pageWidth;
+ }
+
+ public PDPage getSignaturePage() {
+ if (page < 1) {
+ throw new IllegalArgumentException("First page of pdf is 1, not "
+ + page);
+ }
+ PDPage pdPage = null;
+ PDPageTree pages = document.getDocumentCatalog().getPages();
+ if(newpage) {
+ pdPage = new PDPage();
+ } else {
+ pdPage = (PDPage) pages.get(page - 1);
+ }
+
+ return pdPage;
+ }
+
+ /**
+ *
+ * @param sets
+ * pageWidth
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner pageWidth(float pageWidth) {
+ this.pageWidth = pageWidth;
+ return this;
+ }
+
+ /**
+ *
+ * @return page height
+ */
+ public float getPageHeight() {
+ return pageHeight;
+ }
+
+ /**
+ *
+ * @return page height
+ */
+ public int getPageRotation() {
+ return pageRotation;
+ }
+
+ /**
+ * get image size in percents
+ *
+ * @return
+ */
+ public float getImageSizeInPercents() {
+ return imageSizeInPercents;
+ }
+
+ /**
+ *
+ * @param imageSizeInPercents
+ */
+ public void imageSizeInPercents(float imageSizeInPercents) {
+ this.imageSizeInPercents = imageSizeInPercents;
+ }
+
+ /**
+ * returns visible signature text
+ *
+ * @return
+ */
+ public String getSignatureText() {
+ throw new UnsupportedOperationException(
+ "That method is not yet implemented");
+ }
+
+ /**
+ *
+ * @param signatureText
+ * - adds the text on visible signature
+ * @return
+ */
+ public PDFAsVisualSignatureDesigner signatureText(String signatureText) {
+ throw new UnsupportedOperationException(
+ "That method is not yet implemented");
+ }
+
+ public float getRotation() {
+ return this.properties.getRotation();
+ }
+
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java
new file mode 100644
index 00000000..db96767a
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageTree;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException;
+import at.gv.egiz.pdfas.common.settings.ISettings;
+import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;
+import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject;
+import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
+
+public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {
+
+ private static final Logger logger = LoggerFactory.getLogger(PDFAsVisualSignatureProperties.class);
+
+ private ISettings settings;
+
+ private PDFBoxTable main;
+
+ private PDFAsVisualSignatureDesigner designer;
+
+ private float rotationAngle = 0;
+
+ private PDDocument origDoc;
+
+ private SignatureProfileSettings signatureProfileSettings;
+
+ private String alternativeTableCaption="";
+
+ public PDFAsVisualSignatureProperties(ISettings settings, PDFBOXObject object,
+ PdfBoxVisualObject visObj, PositioningInstruction pos, SignatureProfileSettings signatureProfileSettings) {
+ this.settings = settings;
+ this.signatureProfileSettings = signatureProfileSettings;
+ try {
+ main = visObj.getTable();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ this.rotationAngle = pos.getRotation();
+ try {
+ origDoc = object.getDocument();
+
+ designer = new PDFAsVisualSignatureDesigner(origDoc, pos.getPage(), this, pos.isMakeNewPage());
+ PDPageTree pages = origDoc.getDocumentCatalog().getPages();
+ PDPage page = null;
+ if(pos.isMakeNewPage()) {
+ page = (PDPage) pages.get(pages.getCount()-1);
+ } else {
+ page = (PDPage) pages.get(pos.getPage() - 1);
+ }
+ logger.debug("PAGE width {} HEIGHT {}", designer.getPageWidth(), designer.getPageHeight());
+ logger.debug("POS X {} Y {}", pos.getX(), pos.getY());
+ int rot = page.getRotation();
+ float posy = designer.getPageHeight() - pos.getY();
+ float posx = pos.getX();
+ /*switch (rot) {
+ case 90: // CW
+ posx = designer.getPageHeight() - pos.getY();
+ posy = designer.getPageWidth() - main.getWidth();
+ break;
+ case 180:
+ posy = pos.getY();
+ posx = designer.getPageWidth() - pos.getX();
+ break;
+ case 270: // CCW
+ posx = pos.getY();
+ posy = designer.getPageWidth() - pos.getX();
+ break;
+ }*/
+ logger.debug("ROT {}", rot);
+ logger.debug("COORD X {} Y {}", posx, posy);
+ designer.coordinates(posx, posy);
+ float[] form_rect = new float[] {0,0, main.getWidth() + 2, main.getHeight() + 2};
+ logger.debug("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();
+ }
+ }
+
+ @Override
+ public void buildSignature() throws IOException {
+ PDFAsVisualSignatureBuilder builder = new PDFAsVisualSignatureBuilder(this, this.settings, designer);
+ PDFAsTemplateCreator creator = new PDFAsTemplateCreator(builder);
+ try {
+ setVisibleSignature(creator.buildPDF(designer, this.origDoc));
+ } catch (PdfAsException e) {
+ throw new PdfAsWrappedIOException(e);
+ }
+ }
+
+ public PDFBoxTable getMainTable() {
+ return main;
+ }
+
+
+ public float getRotation() {
+ return this.rotationAngle;
+ }
+
+ public PDFAsVisualSignatureDesigner getDesigner() {
+ return designer;
+ }
+
+ public SignatureProfileSettings getSignatureProfileSettings() {
+ return signatureProfileSettings;
+ }
+
+ public String getAlternativeTableCaption() {
+ return alternativeTableCaption;
+ }
+
+ public void setAlternativeTableCaption(String alternativeTableCaption) {
+ this.alternativeTableCaption = alternativeTableCaption;
+ }
+
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java
new file mode 100644
index 00000000..8b46d56a
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.fontbox.ttf.NameRecord;
+import org.apache.fontbox.ttf.NamingTable;
+import org.apache.fontbox.ttf.TTFParser;
+import org.apache.fontbox.ttf.TrueTypeFont;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.pdfas.common.settings.ISettings;
+import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject;
+
+public class PDFBoxFont {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(PDFBoxFont.class);
+
+ private static final String HELVETICA = "HELVETICA";
+ private static final String COURIER = "COURIER";
+ private static final String TIMES_ROMAN = "TIMES_ROMAN";
+ private static final String BOLD = "BOLD";
+ private static final String NORMAL = "NORMAL";
+ private static final String ITALIC = "ITALIC";
+ private static final String SEP = ":";
+
+ public static PDFont defaultFont = PDType1Font.HELVETICA;
+ public static float defaultFontSize = 8;
+
+ private static Map<String, PDFont> fontStyleMap = new HashMap<String, PDFont>();
+
+ private static Map<String, FontInfoCache> fontInfoCache = new HashMap<String, FontInfoCache>();
+
+ static {
+ fontStyleMap.put(HELVETICA + SEP + NORMAL, PDType1Font.HELVETICA);
+ fontStyleMap.put(HELVETICA + SEP + BOLD, PDType1Font.HELVETICA_BOLD);
+
+ fontStyleMap.put(COURIER + SEP + NORMAL, PDType1Font.COURIER);
+ fontStyleMap.put(COURIER + SEP + BOLD, PDType1Font.COURIER_BOLD);
+
+ fontStyleMap.put(TIMES_ROMAN + SEP + NORMAL, PDType1Font.TIMES_ROMAN);
+ fontStyleMap.put(TIMES_ROMAN + SEP + BOLD, PDType1Font.TIMES_BOLD);
+ fontStyleMap.put(TIMES_ROMAN + SEP + ITALIC, PDType1Font.TIMES_ITALIC);
+ }
+
+ public static void showBuildinFonts() {
+ Iterator<String> it = fontStyleMap.keySet().iterator();
+ logger.info("Available Fonts:");
+ while (it.hasNext()) {
+ logger.info(it.next());
+ }
+ }
+
+ PDFont font;
+ PDFont cachedfont = null;
+ float fontSize;
+ String fontDesc;
+ String ttfFontDesc;
+ ISettings settings;
+
+ private FontInfoCache getFontInfo(String pathName) {
+ synchronized (fontInfoCache) {
+
+ if (fontInfoCache.containsKey(pathName)) {
+ return fontInfoCache.get(pathName);
+ } else {
+ try {
+ String fontNameToLoad = null;
+ String fontFamilyToLoad = null;
+ InputStream ttfData = new FileInputStream(pathName);
+ try {
+ TrueTypeFont ttf = null;
+ TTFParser parser = new TTFParser();
+ ttf = parser.parse(ttfData);
+ NamingTable naming = ttf.getNaming();
+ List<NameRecord> records = naming.getNameRecords();
+ for (int i = 0; i < records.size(); i++) {
+ NameRecord nr = records.get(i);
+ if (nr.getNameId() == NameRecord.NAME_POSTSCRIPT_NAME) {
+ fontNameToLoad = nr.getString();
+ } else if (nr.getNameId() == NameRecord.NAME_FONT_FAMILY_NAME) {
+ fontFamilyToLoad = nr.getString();
+ }
+ }
+ } finally {
+ ttfData.close();
+ }
+ FontInfoCache fontInfo = new FontInfoCache();
+ fontInfo.filename = pathName;
+ fontInfo.fontFamily = fontFamilyToLoad;
+ fontInfo.fontName = fontNameToLoad;
+ fontInfo.fontPath = pathName;
+ fontInfoCache.put(pathName, fontInfo);
+ return fontInfo;
+ } catch (Throwable e) {
+ logger.warn("Failed to generate FontInfo from file: {}", pathName);
+ }
+ return null;
+ }
+ }
+ }
+
+ private PDFont findCachedFont(PDFBOXObject pdfObject, FontInfoCache fontInfo) {
+ try {
+ if(pdfObject.getFontCache().containsKey(fontInfo.fontPath)) {
+ return pdfObject.getFontCache().get(fontInfo.fontPath);
+ }
+
+ List<COSObject> cosObjects = pdfObject.getDocument().getDocument().getObjectsByType(
+ COSName.FONT);
+
+ //COSName cosFontName = COSName.getPDFName(fontInfo.fontName);
+ //COSName cosFontFamily = COSName.getPDFName(fontInfo.fontFamily);
+
+ Iterator<COSObject> cosObjectIt = cosObjects.iterator();
+
+ while (cosObjectIt.hasNext()) {
+ COSObject cosObject = cosObjectIt.next();
+ COSDictionary baseObject = (COSDictionary) cosObject
+ .getObject();
+ if (baseObject instanceof COSDictionary) {
+ COSDictionary fontDictionary = (COSDictionary) baseObject;
+ COSBase subType = cosObject.getItem(COSName.SUBTYPE);
+ COSDictionary fontDescriptor = (COSDictionary)cosObject.getDictionaryObject(COSName.FONT_DESC);
+ String fontName = fontDescriptor.getNameAsString(COSName.FONT_NAME);
+ String fontFamily = fontDescriptor.getNameAsString(COSName.FONT_FAMILY);
+ logger.debug("Checking Font {} - {}", fontFamily, fontName);
+ if (COSName.TRUE_TYPE.equals(subType)) {
+ if (fontInfo.fontName != null && fontInfo.fontName.equals(fontName) &&
+ fontInfo.fontFamily != null && fontInfo.fontFamily.equals(fontFamily)) {
+ // Found it! :)
+ logger.info("Found Font {}", fontInfo.fontName);
+ return new PDTrueTypeFont(fontDictionary);
+ } else {
+ logger.debug("Font not found: {} is {}",
+ fontInfo.fontName, fontName);
+ }
+ } else {
+ logger.debug("Font not a TTF");
+ }
+ } else {
+ logger.debug("Font not a COSDictionary");
+ }
+ }
+ } catch (Throwable e) {
+ logger.info("Failed to find existing TTF fonts!", e);
+ }
+ return null;
+ }
+
+ private PDFont generateTTF(String fonttype, PDFBOXObject pdfObject)
+ throws IOException {
+ /*boolean cacheNow = true;
+ if (pdfObject == null) {
+ if (this.doc == null) {
+ this.doc = new PDDocument();
+ }
+ doc = this.doc;
+ } else {
+ cacheNow = true;
+ }*/
+ ttfFontDesc = fonttype;
+ String fontName = fonttype.replaceFirst("TTF:", "");
+ String fontPath = this.settings.getWorkingDirectory() + File.separator
+ + "fonts" + File.separator + fontName;
+
+ logger.debug("Font from: \"" + fontPath + "\".");
+
+ if(fontStyleMap.containsKey(fontPath)) {
+ return fontStyleMap.get(fontPath);
+ }
+
+ FontInfoCache fontInfo = getFontInfo(fontPath);
+
+ if(fontInfo != null) {
+
+ PDFont font = findCachedFont(pdfObject, fontInfo);
+
+ if (font != null) {
+ return font;
+ }
+ }
+
+ logger.debug("Instantiating font.");
+
+ //if (cacheNow) {
+ cachedfont = PDTrueTypeFont.loadTTF(pdfObject.getDocument(), new File(fontPath));
+
+ fontStyleMap.put(fontPath, cachedfont);
+ return cachedfont;
+ //} else {
+ // return PDTrueTypeFont.loadTTF(doc, fontPath);
+ //}
+
+ }
+
+ private PDFont generateFont(String fonttype, String fontder,
+ PDFBOXObject pdfObject) throws IOException {
+ if (fonttype.startsWith("TTF:")) {
+ // Load TTF Font
+ return generateTTF(fonttype, pdfObject);
+ } else {
+ if (fontder == null) {
+ fontder = NORMAL;
+ }
+
+ String fontDesc = fonttype + SEP + fontder;
+ PDFont font = fontStyleMap.get(fontDesc);
+ if (font == null) {
+ showBuildinFonts();
+ throw new IOException("Invalid font descriptor");
+ }
+ return font;
+ }
+ }
+
+ private void setFont(String desc, PDFBOXObject pdfObject)
+ throws IOException {
+ String[] fontArr = desc.split(",");
+
+ if (fontArr.length == 3) {
+ font = generateFont(fontArr[0], fontArr[2], pdfObject);
+ fontSize = Float.parseFloat(fontArr[1]);
+ } else if (fontArr.length == 2 && fontArr[0].startsWith("TTF:")) {
+ font = generateFont(fontArr[0], null, pdfObject);
+ fontSize = Float.parseFloat(fontArr[1]);
+ } else {
+ logger.warn(
+ "Using default font because: {} is not a valid font descriptor.",
+ desc);
+ this.font = defaultFont;
+ this.fontSize = defaultFontSize;
+ }
+
+ }
+
+ public PDFBoxFont(String fontDesc, ISettings settings,
+ PDFBOXObject pdfObject) throws IOException {
+ this.settings = settings;
+ this.fontDesc = fontDesc;
+ logger.debug("Creating Font: " + fontDesc);
+ this.setFont(fontDesc, pdfObject);
+ }
+
+ public PDFont getFont(/*PDFBOXObject pdfObject*/) throws IOException {
+ if (cachedfont != null) {
+ return cachedfont;
+ }
+ return font;
+ /*
+ if (font instanceof PDTrueTypeFont && pdfObject != null) {
+ return generateTTF(ttfFontDesc, pdfObject);
+ } else {
+ return font;
+ }*/
+ }
+
+ public float getFontSize() {
+ return fontSize;
+ }
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxTable.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxTable.java
new file mode 100644
index 00000000..415e1665
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxTable.java
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException;
+import at.gv.egiz.pdfas.common.settings.ISettings;
+import at.gv.egiz.pdfas.common.utils.ImageUtils;
+import at.gv.egiz.pdfas.common.utils.StringUtils;
+import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject;
+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;
+ PDFBoxFont font;
+ PDFBoxFont valueFont;
+ ISettings settings;
+
+ float padding;
+ int positionX = 0;
+ int positionY = 0;
+ float tableWidth;
+ float tableHeight;
+ Color bgColor;
+
+ boolean[] addPadding;
+ float[] rowHeights;
+ float[] colWidths;
+
+ PDDocument originalDoc;
+
+ PDFBOXObject pdfBoxObject;
+
+ private void normalizeContent(Table abstractTable) throws PdfAsException {
+ try {
+ int rows = abstractTable.getRows().size();
+ for (int i = 0; i < rows; i++) {
+ ArrayList<Entry> row = this.table.getRows().get(i);
+ for (int j = 0; j < row.size(); j++) {
+ Entry cell = (Entry) row.get(j);
+
+ switch (cell.getType()) {
+ case Entry.TYPE_CAPTION:
+ case Entry.TYPE_VALUE:
+ String value = (String) cell.getValue();
+ cell.setValue(StringUtils
+ .convertStringToPDFFormat(value));
+ break;
+ }
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ throw new PdfAsException("Unsupported Encoding", e);
+ }
+ }
+
+ private void initializeStyle(Table abstractTable, PDFBoxTable parent,
+ PDFBOXObject pdfBoxObject) throws IOException {
+ this.table = abstractTable;
+ try {
+ normalizeContent(abstractTable);
+ } catch (PdfAsException e) {
+ throw new PdfAsWrappedIOException(e);
+ }
+
+ if (parent != null) {
+ style = Style.doInherit(abstractTable.getStyle(), parent.style);
+ } else {
+ style = abstractTable.getStyle();
+ }
+
+ if (style == null) {
+ throw new IOException("Failed to determine Table style, for table "
+ + abstractTable.getName());
+ }
+
+ String fontString = style.getFont();
+
+ String vfontString = style.getValueFont();
+
+ if (parent != null && style == parent.style) {
+ font = parent.getFont();
+
+ valueFont = parent.getValueFont();
+ } else {
+ if (fontString == null && parent != null && parent.style != null) {
+ fontString = parent.style.getFont();
+ } else if (fontString == null) {
+ throw new IOException(
+ "Failed to determine Table font style, for table "
+ + abstractTable.getName());
+ }
+
+ font = new PDFBoxFont(fontString, settings, pdfBoxObject);
+
+ if (vfontString == null && parent != null && parent.style != null) {
+ vfontString = parent.style.getValueFont();
+ } else if (fontString == null) {
+ throw new IOException(
+ "Failed to determine value Table font style, for table "
+ + abstractTable.getName());
+ }
+
+ valueFont = new PDFBoxFont(vfontString, settings, pdfBoxObject);
+ }
+ padding = style.getPadding();
+
+ bgColor = style.getBgColor();
+ }
+
+ public PDFBoxTable(Table abstractTable, PDFBoxTable parent, float fixSize,
+ ISettings settings, PDFBOXObject pdfBoxObject) throws IOException,
+ PdfAsException {
+ this.settings = settings;
+ this.pdfBoxObject = pdfBoxObject;
+ this.originalDoc = pdfBoxObject.getDocument();
+ initializeStyle(abstractTable, parent, pdfBoxObject);
+ float[] relativSizes = abstractTable.getColsRelativeWith();
+ if (relativSizes != null) {
+ 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];
+ }
+ } else {
+ colWidths = new float[abstractTable.getMaxCols()];
+ float totalrel = abstractTable.getMaxCols();
+ float unit = (fixSize / totalrel);
+ for (int i = 0; i < colWidths.length; i++) {
+
+ colWidths[i] = unit;
+ }
+ }
+ calculateHeightsBasedOnWidths();
+
+ logger.debug("Generating Table with fixed With {} got width {}",
+ fixSize, getWidth());
+ }
+
+ public PDFBoxTable(Table abstractTable, PDFBoxTable parent,
+ ISettings settings, PDFBOXObject pdfBoxObject) throws IOException,
+ PdfAsException {
+ this.settings = settings;
+ this.pdfBoxObject = pdfBoxObject;
+ this.originalDoc = pdfBoxObject.getDocument();
+ initializeStyle(abstractTable, parent, pdfBoxObject);
+ this.calculateWidthHeight();
+ }
+
+ private void calculateHeightsBasedOnWidths() throws IOException,
+ PdfAsException {
+ int rows = this.table.getRows().size();
+ rowHeights = new float[rows];
+ addPadding = new boolean[rows];
+
+ for (int i = 0; i < rows; i++) {
+ rowHeights[i] = 0;
+ }
+
+ for (int i = 0; i < rows; i++) {
+ ArrayList<Entry> row = this.table.getRows().get(i);
+ for (int j = 0; j < row.size(); j++) {
+ Entry cell = (Entry) row.get(j);
+
+ float colWidth = 0;// colWidths[j];
+
+ int colsleft = cell.getColSpan();
+
+ 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,
+ colWidth, cellheight);
+
+ int span = cell.getColSpan() - 1;
+ j += span;
+ }
+ }
+
+ calcTotals();
+ }
+
+ private void calculateWidthHeight() throws IOException, PdfAsException {
+ 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<Entry> row = 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];
+ }
+
+ // Post Process heights for inner Tables ...
+ for (int i = 0; i < rowHeights.length; i++) {
+ ArrayList<Entry> row = this.table.getRows().get(i);
+ for (int j = 0; j < row.size(); j++) {
+ Entry cell = (Entry) row.get(j);
+ if (cell.getType() == Entry.TYPE_TABLE) {
+ PDFBoxTable tbl = (PDFBoxTable) cell.getValue();
+ if (rowHeights[i] != tbl.getHeight()) {
+ tbl.setHeight(rowHeights[i]);
+ }
+ }
+ }
+ }
+
+ this.tableWidth = 0;
+
+ for (int i = 0; i < colWidths.length; i++) {
+ this.tableWidth += colWidths[i];
+ }
+ }
+
+ private float getCellWidth(Entry cell) throws IOException, PdfAsException {
+ boolean isValue = true;
+ switch (cell.getType()) {
+ case Entry.TYPE_CAPTION:
+ isValue = false;
+ case Entry.TYPE_VALUE:
+ PDFont c = null;
+ float fontSize;
+ String string = (String) cell.getValue();
+ if (isValue) {
+ c = valueFont.getFont();//null
+ fontSize = valueFont.getFontSize();
+ } else {
+ c = font.getFont();//null
+ fontSize = font.getFontSize();
+ }
+ if (string == null) {
+ string = "";
+ cell.setValue(string);
+ }
+ 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:
+ if (style != null && style.getImageScaleToFit() != null) {
+ return style.getImageScaleToFit().getWidth();
+ }
+ return 80.f;
+ case Entry.TYPE_TABLE:
+ PDFBoxTable pdfBoxTable = null;
+ if (cell.getValue() instanceof Table) {
+ pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this,
+ this.settings, pdfBoxObject);
+ 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 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, float maxwidth, PDFont font,
+ float fontSize) throws IOException {
+ String[] words = value.split(" ");
+ List<String> lines = new ArrayList<String>();
+ 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) {
+ if (j == 0 && word.startsWith("\n")) {
+ lines.add(cLineValue.trim());
+ cLineValue = "";
+ } else if (j != 0) {
+ lines.add(cLineValue.trim());
+ cLineValue = "";
+ }
+ // }
+ String tmpLine = cLineValue + subword;
+ float size = font.getStringWidth(tmpLine) / 1000.0f
+ * fontSize;
+ if (size > maxwidth && cLineValue.length() != 0) {
+ lines.add(cLineValue.trim());
+ cLineValue = "";
+ }
+ cLineValue += subword + " ";
+ }
+ } else {
+ String tmpLine = cLineValue + word;
+ float size = font.getStringWidth(tmpLine) / 1000.0f * fontSize;
+ if (size > maxwidth && cLineValue.length() != 0) {
+ lines.add(cLineValue.trim());
+ cLineValue = "";
+ }
+ cLineValue += word + " ";
+ }
+ }
+ lines.add(cLineValue.trim());
+ return lines.toArray(new String[0]);
+ }
+
+ private String[] breakString(String value, int maxline) {
+ String[] words = value.split(" ");
+ List<String> lines = new ArrayList<String>();
+ 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 String[] breakString(String value, PDFont f, float maxwidth)
+ // throws IOException {
+ // String[] words = value.split(" ");
+ // List<String> lines = new ArrayList<String>();
+ // 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 (f.getStringWidth(cLineValue + word) > maxwidth && 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[] getStringHeights(String[] lines, PDFont c, float fontSize) {
+ float[] heights = new float[lines.length];
+ for (int i = 0; i < lines.length; i++) {
+ float maxLineHeight = 0;
+ try {
+ byte[] linebytes = StringUtils.applyWinAnsiEncoding(lines[i]);
+ for (int j = 0; j < linebytes.length; j++) {
+ float he = c.getHeight(linebytes[j]) / 1000
+ * fontSize;
+ if (he > maxLineHeight) {
+ maxLineHeight = he;
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ logger.warn("failed to determine String height", e);
+ maxLineHeight = c.getFontDescriptor().getCapHeight() / 1000
+ * fontSize;
+ } catch (IOException e) {
+ logger.warn("failed to determine String height", e);
+ maxLineHeight = c.getFontDescriptor().getCapHeight() / 1000
+ * fontSize;
+ }
+
+ heights[i] = maxLineHeight;
+ }
+
+ return heights;
+ }
+
+ private float getCellHeight(Entry cell, float width) throws IOException,
+ PdfAsException {
+ boolean isValue = true;
+ switch (cell.getType()) {
+ case Entry.TYPE_CAPTION:
+ isValue = false;
+ case Entry.TYPE_VALUE:
+ PDFont c = null;
+ float fontSize;
+ String string = (String) cell.getValue();
+ if (isValue) {
+ c = valueFont.getFont();//null
+ fontSize = valueFont.getFontSize();
+ } else {
+ c = font.getFont();//null
+ fontSize = font.getFontSize();
+ }
+
+ String[] lines = breakString(string, (width - padding * 2.0f), c,
+ fontSize);
+ cell.setValue(concatLines(lines));
+ float[] heights = getStringHeights(lines, c, fontSize);
+ return fontSize * heights.length + padding * 2;
+ case Entry.TYPE_IMAGE:
+ String imageFile = (String) cell.getValue();
+ if (style != null && style.getImageScaleToFit() != null) {
+ // if (style.getImageScaleToFit().getHeight() < width) {
+ return style.getImageScaleToFit().getHeight() + padding * 2;
+ // }
+ }
+ Dimension dim = ImageUtils.getImageDimensions(imageFile, settings);
+ float wfactor = (float) ((width - padding * 2.0f) / dim.getWidth());
+ float scaleFactor = wfactor;
+ float iheight = (float) Math
+ .floor((double) (scaleFactor * dim.getHeight()));
+ //if (dim.getHeight() > 80.0f) {
+ // return width + padding * 2;
+ //}
+ return (float) iheight + padding * 2;
+ case Entry.TYPE_TABLE:
+ PDFBoxTable pdfBoxTable = null;
+ if (cell.getValue() instanceof Table) {
+ pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this,
+ width, this.settings, this.pdfBoxObject);
+ cell.setValue(pdfBoxTable);
+ } else if (cell.getValue() instanceof PDFBoxTable) {
+ // recreate here beacuse of fixed width!
+ pdfBoxTable = (PDFBoxTable) cell.getValue();
+ pdfBoxTable = new PDFBoxTable(pdfBoxTable.table, this, width,
+ this.settings, this.pdfBoxObject);
+ cell.setValue(pdfBoxTable);
+ } else {
+ throw new IOException("Failed to build PDFBox Table");
+ }
+ return pdfBoxTable.getHeight();
+ default:
+ logger.warn("Invalid Cell Entry Type: " + cell.getType());
+ }
+ return 0;
+ }
+
+ private float getCellHeight(Entry cell) throws IOException, PdfAsException {
+ boolean isValue = true;
+ switch (cell.getType()) {
+ case Entry.TYPE_CAPTION:
+ isValue = false;
+ case Entry.TYPE_VALUE:
+ PDFont c = null;
+ float fontSize;
+ String string = (String) cell.getValue();
+ if (isValue) {
+ c = valueFont.getFont();//null
+ fontSize = valueFont.getFontSize();
+ } else {
+ c = font.getFont();//null
+ fontSize = font.getFontSize();
+ }
+
+ if (string.contains("\n")) {
+ String[] lines = string.split("\n");
+
+ return fontSize * lines.length + padding * 2;
+ } else {
+ return fontSize + padding * 2;
+ }
+ case Entry.TYPE_IMAGE:
+ String imageFile = (String) cell.getValue();
+ if (style != null && style.getImageScaleToFit() != null) {
+ return style.getImageScaleToFit().getHeight() + padding * 2;
+ }
+ Dimension dim = ImageUtils.getImageDimensions(imageFile, settings);
+ if (dim.getHeight() > 80.0f) {
+ return 80.0f + padding * 2;
+ }
+ return (float) dim.getHeight() + padding * 2;
+
+ case Entry.TYPE_TABLE:
+ PDFBoxTable pdfBoxTable = null;
+ if (cell.getValue() instanceof Table) {
+ pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this,
+ this.settings, pdfBoxObject);
+ 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 void setHeight(float height) {
+ float diff = height - this.getHeight();
+ if (diff > 0) {
+ this.rowHeights[rowHeights.length - 1] += diff;
+ calcTotals();
+ } else {
+ logger.warn("Table cannot be this small!");
+ }
+ }
+
+ public float[] getRowHeights() {
+ return rowHeights;
+ }
+
+ public int getRowCount() {
+ return this.table.getRows().size();
+ }
+
+ public int getColCount() {
+ return this.table.getMaxCols();// .getColsRelativeWith().length;
+ }
+
+ public float[] getColsRelativeWith() {
+ return this.table.getColsRelativeWith();
+ }
+
+ public float getPadding() {
+ return this.padding;
+ }
+
+ public void dumpTable() {
+ logger.debug("=====================================================================");
+ logger.debug("Information about: " + this.table.getName());
+ logger.debug("\tDimensions: {} x {} (W x H)", this.tableWidth,
+ this.tableHeight);
+ logger.debug("\tPadding: {}", padding);
+ logger.debug("\t================================");
+ logger.debug("\tRow Heights:");
+ for (int i = 0; i < rowHeights.length; i++) {
+ logger.debug("\t[{}] : {}", i, this.rowHeights[i]);
+ }
+ logger.debug("\t================================");
+ logger.debug("\tCol Widths:");
+ 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("=====================================================================");
+ }
+
+ public Table getOrigTable() {
+ return this.table;
+ }
+
+ public ArrayList<Entry> getRow(int i) {
+ return this.table.getRows().get(i);
+ }
+
+ public PDFBoxFont getFont() {
+ return font;
+ }
+
+ public PDFBoxFont getValueFont() {
+ return valueFont;
+ }
+
+ public Color getBGColor() {
+ return this.bgColor;
+ }
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxStamper.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxStamper.java
new file mode 100644
index 00000000..f89d53c5
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxStamper.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.io.IOException;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException;
+import at.gv.egiz.pdfas.common.settings.ISettings;
+import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject;
+import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper;
+import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject;
+import at.gv.egiz.pdfas.lib.impl.status.PDFObject;
+import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
+import at.knowcenter.wag.egov.egiz.table.Table;
+
+public class PdfBoxStamper implements IPDFStamper {
+
+// private static final Logger logger = LoggerFactory.getLogger(PdfBoxStamper.class);
+
+// private PDFTemplateBuilder pdfBuilder;
+
+ public PdfBoxStamper() {
+// this.pdfBuilder = new PDVisibleSigBuilder();
+ }
+
+ public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table) throws IOException {
+ try {
+ PDFBOXObject pdfboxObject = (PDFBOXObject)pdf;
+ return new PdfBoxVisualObject(table, pdf.getStatus().getSettings(), pdfboxObject);
+ } catch (PdfAsException e) {
+ throw new PdfAsWrappedIOException(e);
+ }
+ }
+
+ public byte[] writeVisualObject(IPDFVisualObject visualObject,
+ PositioningInstruction positioningInstruction, byte[] pdfData,
+ String placeholderName) throws PdfAsException {
+ return null;
+ }
+
+ public void setSettings(ISettings settings) {
+ // not needed currently
+ }
+
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxVisualObject.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxVisualObject.java
new file mode 100644
index 00000000..3a4c3957
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PdfBoxVisualObject.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.io.IOException;
+
+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.impl.pdfbox2.PDFBOXObject;
+import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject;
+import at.knowcenter.wag.egov.egiz.table.Table;
+
+public class PdfBoxVisualObject implements IPDFVisualObject {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(PdfBoxVisualObject.class);
+
+ private Table abstractTable;
+ private PDFBoxTable table;
+ private float width;
+ private float x;
+ private float y;
+ private int page;
+ private ISettings settings;
+ private PDFBOXObject pdfBoxObject;
+
+ public PdfBoxVisualObject(Table table, ISettings settings, PDFBOXObject pdfBoxObject)
+ throws IOException, PdfAsException {
+ this.abstractTable = table;
+ this.pdfBoxObject = pdfBoxObject;
+ this.table = new PDFBoxTable(table, null, settings, pdfBoxObject);
+ this.settings = settings;
+ }
+
+ public void setWidth(float width) {
+ this.width = width;
+ }
+
+ public void fixWidth() {
+ try {
+ table = new PDFBoxTable(abstractTable, null, this.width, settings, this.pdfBoxObject);
+ } catch (IOException e) {
+ logger.warn("Failed to fix width of Table!", e);
+ } catch (PdfAsException e) {
+ logger.warn("Failed to fix width of Table!", e);
+ }
+ }
+
+ public float getHeight() {
+ return table.getHeight();
+ }
+
+ public float getWidth() {
+ return table.getWidth();
+ }
+
+ public void setXPos(float x) {
+ this.x = x;
+ }
+
+ public void setYPos(float y) {
+ this.y = y;
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public int getPage() {
+ return page;
+ }
+
+ public void setPage(int page) {
+ this.page = page;
+ }
+
+ public PDFBoxTable getTable() {
+ return this.table;
+ }
+}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/StamperFactory.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/StamperFactory.java
new file mode 100644
index 00000000..90561740
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/StamperFactory.java
@@ -0,0 +1,25 @@
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.common.settings.ISettings;
+import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper;
+
+public class StamperFactory {
+
+ //public static final String DEFAULT_STAMPER_CLASS = "at.gv.egiz.pdfas.stmp.itext.ITextStamper";
+ public static final String DEFAULT_STAMPER_CLASS = "at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2.PdfBoxStamper";
+
+ public static IPDFStamper createDefaultStamper(ISettings settings) throws PdfAsException {
+ try {
+ Class<?> cls = Class.forName(DEFAULT_STAMPER_CLASS);
+ Object st = cls.newInstance();
+ if (!(st instanceof IPDFStamper))
+ throw new ClassCastException();
+ IPDFStamper stamper = (IPDFStamper) st;
+ stamper.setSettings(settings);
+ return stamper;
+ } catch (Throwable e) {
+ throw new PdfAsException("error.pdf.stamp.10", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java
new file mode 100644
index 00000000..aa2a397d
--- /dev/null
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java
@@ -0,0 +1,609 @@
+/*******************************************************************************
+ * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ ******************************************************************************/
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+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.knowcenter.wag.egov.egiz.table.Entry;
+import at.knowcenter.wag.egov.egiz.table.Style;
+
+public class TableDrawUtils {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(TableDrawUtils.class);
+
+ public static final String TABLE_DEBUG = "debug.table";
+
+ public static void drawTable(PDPage page,
+ PDPageContentStream contentStream, float x, float y, float width,
+ float height, PDFBoxTable abstractTable, PDDocument doc,
+ boolean subtable, PDResources formResources,
+ Map<String, ImageObject> images, ISettings settings, IDGenerator generator, PDFAsVisualSignatureProperties properties)
+ throws PdfAsException {
+
+ logger.debug("Drawing Table: X {} Y {} WIDTH {} HEIGHT {} \n{}", x, y,
+ width, height, abstractTable.getOrigTable().toString());
+
+ abstractTable.getOrigTable().setWidth(width);
+
+ drawTableBackground(page, contentStream, x, y, width, height,
+ abstractTable, settings);
+
+ drawBorder(page, contentStream, x, y, width, height, abstractTable,
+ doc, subtable, settings);
+//append strings
+ drawContent(page, contentStream, x, y, width, height, abstractTable,
+ doc, subtable, formResources, images, settings, generator, properties);
+ }
+
+ public static void drawContent(PDPage page,
+ PDPageContentStream contentStream, float x, float y, float width,
+ float height, PDFBoxTable abstractTable, PDDocument doc,
+ boolean subtable, PDResources formResources,
+ Map<String, ImageObject> images, ISettings settings, IDGenerator generator, PDFAsVisualSignatureProperties properties)
+ throws PdfAsException {
+
+ float contentx = x;
+ float contenty = y + height;
+ float padding = abstractTable.getPadding();
+ float[] colsSizes = getColSizes(abstractTable);
+ StringBuilder alternateTableCaption = new StringBuilder();
+ for (int i = 0; i < abstractTable.getRowCount(); i++) {
+ ArrayList<Entry> row = abstractTable.getRow(i);
+ for (int j = 0; j < row.size(); j++) {
+ Entry cell = (Entry) row.get(j);
+
+ // Cell only contains default values so table style is the primary style
+ Style inherit_style = Style.doInherit(abstractTable.style, cell.getStyle());
+ cell.setStyle(inherit_style);
+
+ float colWidth = 0;//colWidths[j];
+
+ int colsleft = cell.getColSpan();
+
+ if (j + colsleft > colsSizes.length) {
+ throw new PdfAsException(
+ "Configuration is wrong. Cannot determine column width!");
+ }
+
+ for (int k = 0; k < colsleft; k++) {
+ colWidth = colWidth + colsSizes[j + k];
+ }
+
+ drawDebugPadding(contentStream, contentx, contenty, padding,
+ colWidth, abstractTable.getRowHeights()[i], settings);
+
+ switch (cell.getType()) {
+ case Entry.TYPE_CAPTION:
+ drawCaption(page, contentStream, contentx, contenty,
+ colWidth, abstractTable.getRowHeights()[i],
+ padding, abstractTable, doc, cell, formResources, settings);
+ addToAlternateTableCaption(cell, alternateTableCaption);
+ break;
+ case Entry.TYPE_VALUE:
+ drawValue(page, contentStream, contentx, contenty,
+ colWidth, abstractTable.getRowHeights()[i],
+ padding, abstractTable, doc, cell, formResources, settings);
+ addToAlternateTableCaption(cell, alternateTableCaption);
+ break;
+ case Entry.TYPE_IMAGE:
+ drawImage(page, contentStream, contentx, contenty,
+ colWidth, abstractTable.getRowHeights()[i],
+ padding, abstractTable, doc, cell, formResources,
+ images, settings, generator);
+ break;
+ case Entry.TYPE_TABLE:
+
+ PDFBoxTable tbl_value = (PDFBoxTable) cell.getValue();
+
+ Style inherit_styletab = Style.doInherit(
+ abstractTable.style, cell.getStyle());
+ tbl_value.table.setStyle(inherit_styletab);
+
+ drawTable(page, contentStream, contentx, contenty
+ - abstractTable.getRowHeights()[i], colWidth,
+ abstractTable.getRowHeights()[i], tbl_value, doc,
+ true, formResources, images, settings, generator,properties);
+ break;
+ default:
+ logger.warn("Unknown Cell entry type: " + cell.getType());
+ break;
+ }
+
+ // Move content pointer
+ contentx += colWidth;
+
+ int span = cell.getColSpan() - 1;
+ j += span;
+ }
+
+ // Move content pointer
+ contenty -= abstractTable.getRowHeights()[i];
+ contentx = x;
+ }
+ properties.setAlternativeTableCaption(alternateTableCaption.toString());
+ }
+
+ private static void drawString(PDPage page,
+ PDPageContentStream contentStream, float contentx, float contenty,
+ float width, float height, float padding,
+ PDFBoxTable abstractTable, PDDocument doc, Entry cell,
+ float fontSize, float textHeight, String valign, String halign,
+ String[] tlines, PDFont textFont, PDResources formResources,
+ ISettings settings) throws PdfAsException {
+ try {
+ float ty = contenty - padding;
+ float tx = contentx + padding;
+ float innerHeight = height - (2 * padding);
+ float innerWidth = width - (2 * padding);
+ if (Style.BOTTOM.equals(valign)) {
+ float bottom_offset = innerHeight - textHeight;
+ ty -= bottom_offset;
+ } else if (Style.MIDDLE.equals(valign)) {
+ float bottom_offset = innerHeight - textHeight;
+ bottom_offset = bottom_offset / 2.0f;
+ ty -= bottom_offset;
+ }
+
+ // calculate the max with of the text content
+ float maxWidth = 0;
+ for (int k = 0; k < tlines.length; k++) {
+ float lineWidth;
+ // if (textFont instanceof PDType1Font) {
+ lineWidth = textFont.getStringWidth(tlines[k]) / 1000.0f
+ * fontSize;
+ /*
+ * } else { float fwidth = textFont
+ * .getStringWidth("abcdefghijklmnopqrstuvwxyz ") / 1000.0f *
+ * fontSize; fwidth = fwidth / (float)
+ * "abcdefghijklmnopqrstuvwxyz" .length(); lineWidth =
+ * tlines[k].length() * fwidth; }
+ */
+ if (maxWidth < lineWidth) {
+ maxWidth = lineWidth;
+ }
+ }
+
+ if (Style.CENTER.equals(halign)) {
+ float offset = innerWidth - maxWidth;
+ if (offset > 0) {
+ offset = offset / 2.0f;
+ tx += offset;
+ }
+ } else if (Style.RIGHT.equals(halign)) {
+ float offset = innerWidth - maxWidth;
+ if (offset > 0) {
+ tx += offset;
+ }
+ }
+ float ascent = textFont.getFontDescriptor().getAscent();
+ float descent = textFont.getFontDescriptor().getDescent();
+
+ ascent = ascent / 1000.0f * fontSize;
+ descent = descent / 1000.0f * fontSize;
+
+ //ty = ty + (descent * (-1));
+
+ logger.debug("Text tx {} ty {} maxWidth {} textHeight {}", tx, ty,
+ maxWidth, textHeight);
+ logger.debug("Text ASCENT {} DESCENT {}", ascent, descent);
+
+ logger.debug("Text TRANSFORMED ASCENT {} DESCENT {}", ascent, descent);
+
+ drawDebugLineString(contentStream, tx, ty, maxWidth, textHeight, descent, settings);
+
+ contentStream.beginText();
+
+
+ if (formResources.getFont(COSName.getPDFName(textFont.getName())) != null) {
+ String fontID = getFontID(textFont, formResources);
+ logger.debug("Using Font: " + fontID);
+ contentStream.appendRawCommands("/" + fontID + " " + fontSize
+ + " Tf\n");
+ } else {
+ contentStream.setFont(textFont, fontSize);
+ }
+
+ logger.debug("Writing: " + tx + " : " + (ty - fontSize + (descent * (-1))) + " as "
+ + cell.getType());
+ contentStream.moveTextPositionByAmount(tx, (ty - fontSize + (descent * (-1))));
+
+ contentStream.appendRawCommands(fontSize + " TL\n");
+ for (int k = 0; k < tlines.length; k++) {
+ contentStream.drawString(tlines[k]);
+ if (k < tlines.length - 1) {
+ contentStream.appendRawCommands("T*\n");
+ }
+ }
+
+ contentStream.endText();
+
+ } catch (IOException e) {
+ logger.warn("IO Exception", e);
+ throw new PdfAsException("Error", e);
+ }
+ }
+
+ public static void drawCaption(PDPage page,
+ PDPageContentStream contentStream, float contentx, float contenty,
+ float width, float height, float padding,
+ PDFBoxTable abstractTable, PDDocument doc, Entry cell,
+ PDResources formResources, ISettings settings)
+ throws PdfAsException {
+
+ logger.debug("Drawing Caption @ X: {} Y: {}", contentx, contenty);
+
+ try {
+ float fontSize = PDFBoxFont.defaultFontSize;
+ PDFont textFont = PDFBoxFont.defaultFont;
+
+ textFont = abstractTable.getFont().getFont();//doc);
+ fontSize = abstractTable.getFont().getFontSize();
+
+ // get the cell Text
+ String text = (String) cell.getValue();
+ String[] tlines = text.split("\n");
+ float textHeight = fontSize * tlines.length;
+
+ Style cellStyle = cell.getStyle();
+ String valign = cellStyle.getVAlign();
+ String halign = cellStyle.getHAlign();
+
+ drawString(page, contentStream, contentx, contenty, width, height,
+ padding, abstractTable, doc, cell, fontSize, textHeight,
+ valign, halign, tlines, textFont, formResources, settings);
+ } catch (IOException e) {
+ logger.warn("IO Exception", e);
+ throw new PdfAsException("Error", e);
+ }
+ }
+
+ public static void drawValue(PDPage page,
+ PDPageContentStream contentStream, float contentx, float contenty,
+ float width, float height, float padding,
+ PDFBoxTable abstractTable, PDDocument doc, Entry cell,
+ PDResources formResources, ISettings settings)
+ throws PdfAsException {
+
+ logger.debug("Drawing Value @ X: {} Y: {}", contentx, contenty);
+
+ try {
+ float fontSize = PDFBoxFont.defaultFontSize;
+ PDFont textFont = PDFBoxFont.defaultFont;
+
+ textFont = abstractTable.getValueFont().getFont();//doc);
+ fontSize = abstractTable.getValueFont().getFontSize();
+
+ // get the cell Text
+ String text = (String) cell.getValue();
+ String[] tlines = text.split("\n");
+ float textHeight = fontSize * tlines.length;
+
+ Style cellStyle = cell.getStyle();
+ String valign = cellStyle.getValueVAlign();
+ String halign = cellStyle.getValueHAlign();
+
+ drawString(page, contentStream, contentx, contenty, width, height,
+ padding, abstractTable, doc, cell, fontSize, textHeight,
+ valign, halign, tlines, textFont, formResources, settings);
+ } catch (IOException e) {
+ logger.warn("IO Exception", e);
+ throw new PdfAsException("Error", e);
+ }
+ }
+
+ public static void drawImage(PDPage page,
+ PDPageContentStream contentStream, float contentx, float contenty,
+ float width, float height, float padding,
+ PDFBoxTable abstractTable, PDDocument doc, Entry cell,
+ PDResources formResources, Map<String, ImageObject> images,
+ ISettings settings, IDGenerator generator) throws PdfAsException {
+ try {
+ float innerHeight = height;
+ float innerWidth = width;
+
+ String img_ref = generator.createHashedId((String) cell.getValue());
+ if (!images.containsKey(img_ref)) {
+ logger.warn("Image not prepared! : " + img_ref);
+ throw new PdfAsException("Image not prepared! : " + img_ref);
+ }
+ ImageObject image = images.get(img_ref);
+ PDImageXObject pdImage = image.getImage();
+
+
+ float imgx = contentx;
+ float hoffset = innerWidth - image.getWidth();
+ if (cell.getStyle().getImageHAlign() != null
+ && cell.getStyle().getImageHAlign().equals(Style.LEFT)) {
+ hoffset = hoffset / 2.0f;
+ imgx += hoffset;
+ } else if (cell.getStyle().getImageHAlign() != null
+ && cell.getStyle().getImageHAlign().equals(Style.RIGHT)) {
+ imgx += hoffset;
+ } else {
+ hoffset = hoffset / 2.0f;
+ imgx += hoffset;
+ }
+
+ float imgy = contenty;
+ float voffset = innerHeight - image.getHeight();
+ if (cell.getStyle().getImageVAlign() != null
+ && cell.getStyle().getImageVAlign().equals(Style.MIDDLE)) {
+ voffset = voffset / 2.0f;
+ imgy -= voffset;
+ } else if (cell.getStyle().getImageVAlign() != null
+ && cell.getStyle().getImageVAlign().equals(Style.BOTTOM)) {
+ imgy -= voffset;
+ }
+
+ drawDebugLine(contentStream, imgx, imgy, image.getWidth(),
+ image.getHeight(), settings);
+
+ // logger.debug("Image: " + imgx + " : " + (imgy -
+ // image.getHeight()));
+ contentStream.drawXObject(pdImage, imgx, imgy - image.getHeight(),
+ image.getWidth(), image.getHeight());
+ } catch (IOException e) {
+ logger.warn("IO Exception", e);
+ throw new PdfAsException("Error", e);
+ }
+
+ }
+
+ public static float[] getColSizes(PDFBoxTable abstractTable) {
+ float[] origcolsSizes = abstractTable.getColsRelativeWith();
+ int max_cols = abstractTable.getColCount();
+ float[] colsSizes = new float[max_cols];
+ if (origcolsSizes == null) {
+ // set the column ratio for all columns to 1
+ for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) {
+ colsSizes[cols_idx] = 1;
+ }
+ } else {
+ // set the column ratio for all columns to 1
+ for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) {
+ colsSizes[cols_idx] = origcolsSizes[cols_idx];
+ }
+ }
+
+ // adapt
+ 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)
+ * abstractTable.getWidth();
+ }
+
+ float sum = 0;
+
+ for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) {
+ sum += colsSizes[cols_idx];
+ }
+
+ logger.debug("Table Col Sizes SUM {} Table Width {}", sum,
+ abstractTable.getWidth());
+ logger.debug("Table Table Height {}", abstractTable.getHeight());
+
+ return colsSizes;
+ }
+
+ public static void drawBorder(PDPage page,
+ PDPageContentStream contentStream, float x, float y, float width,
+ float height, PDFBoxTable abstractTable, PDDocument doc,
+ boolean subtable, ISettings settings) throws PdfAsException {
+ try {
+
+ logger.debug("Drawing Table borders for "
+ + abstractTable.getOrigTable().getName());
+
+ final int rows = abstractTable.getRowCount();
+ float border = abstractTable.style.getBorder();
+ float[] colsSizes = getColSizes(abstractTable);
+
+ if (border > 0) {
+ contentStream.setLineWidth(border);
+
+ float x_from = x;
+ float x_to = x + width;
+ float y_from = y + height;
+ float y_to = y + height;
+
+ // draw first line
+ logger.debug("ROW LINE: {} {} {} {}", x_from, y_from, x_to,
+ y_from);
+ contentStream.drawLine(x, y_from, x_to, y_from);
+
+ // Draw all row borders
+ for (int i = 0; i < rows; i++) {
+ y_from -= abstractTable.getRowHeights()[i];
+
+ // Draw row border!
+ logger.debug("ROW LINE: {} {} {} {}", x_from, y_from, x_to,
+ y_from);
+ contentStream.drawLine(x, y_from, x_to, y_from);
+
+ }
+
+ // reset y for "line feed"
+ y_from = y + height;
+ y_to = y_from - abstractTable.getRowHeights()[0];
+
+ // Draw all column borders
+ for (int i = 0; i < rows; i++) {
+ ArrayList<Entry> row = abstractTable.getRow(i);
+
+ // reset x for "line feed"
+ x_from = x;
+
+ // draw first line
+ logger.debug("COL LINE: {} {} {} {}", x_from, y_from,
+ x_from, y_to);
+
+ contentStream.drawLine(x_from, y_from, x_from, y_to);
+
+ for (int j = 0; j < row.size(); j++) {
+ Entry cell = (Entry) row.get(j);
+
+ for (int k = 0; k < cell.getColSpan(); k++) {
+ if (k + j < colsSizes.length) {
+ x_from += colsSizes[k + j];
+ }
+ }
+ logger.debug("COL LINE: {} {} {} {}", x_from, y_from,
+ x_from, y_to);
+ contentStream.drawLine(x_from, y_from, x_from, y_to);
+ }
+
+ if (i + 1 < rows) {
+ y_from = y_to;
+ y_to = y_from - abstractTable.getRowHeights()[i + 1];
+ }
+ }
+
+ }
+ } catch (Throwable e) {
+ logger.warn("drawing table borders", e);
+ throw new PdfAsException("drawing table borders", e);
+ }
+ }
+
+ public static void drawTableBackground(PDPage page,
+ PDPageContentStream contentStream, float x, float y, float width,
+ float height, PDFBoxTable abstractTable, ISettings settings)
+ throws PdfAsException {
+ try {
+ if (abstractTable.getBGColor() != null) {
+ contentStream.setNonStrokingColor(abstractTable.getBGColor());
+ contentStream.fillRect(x, y, abstractTable.getWidth(),
+ abstractTable.getHeight());
+ contentStream.setNonStrokingColor(Color.BLACK);
+ }
+ } catch (Throwable e) {
+ logger.warn("drawing table borders", e);
+ throw new PdfAsException("drawing table borders", e);
+ }
+ }
+
+ private static void drawDebugLine(PDPageContentStream contentStream,
+ float x, float y, float width, float height, ISettings settings) {
+ if ("true".equals(settings.getValue(TABLE_DEBUG))) {
+ try {
+ contentStream.setStrokingColor(Color.RED);
+ contentStream.drawLine(x, y, x + width, y);
+ contentStream.setStrokingColor(Color.BLUE);
+ contentStream.drawLine(x, y, x, y - height);
+ contentStream.setStrokingColor(Color.GREEN);
+ contentStream.drawLine(x + width, y, x + width, y - height);
+ contentStream.setStrokingColor(Color.ORANGE);
+ contentStream.drawLine(x, y - height, x + width, y - height);
+
+ contentStream.setStrokingColor(Color.BLACK);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void drawDebugLineString(PDPageContentStream contentStream,
+ float x, float y, float width, float height, float descent, ISettings settings) {
+ if ("true".equals(settings.getValue(TABLE_DEBUG))) {
+ try {
+ contentStream.setStrokingColor(Color.RED);
+ contentStream.drawLine(x, y, x + width, y);
+ contentStream.setStrokingColor(Color.BLUE);
+ contentStream.drawLine(x, y, x, y - height);
+ contentStream.setStrokingColor(Color.GREEN);
+ contentStream.drawLine(x + width, y, x + width, y - height);
+ contentStream.setStrokingColor(Color.ORANGE);
+ contentStream.drawLine(x, y - height, x + width, y - height);
+ contentStream.setStrokingColor(Color.MAGENTA);
+ contentStream.drawLine(x, y + (descent * (-1)) - height, x + width, y + (descent * (-1)) - height);
+
+ contentStream.setStrokingColor(Color.BLACK);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void drawDebugPadding(PDPageContentStream contentStream,
+ float x, float y, float padding, float width, float height,
+ ISettings settings) {
+ if ("true".equals(settings.getValue(TABLE_DEBUG))) {
+ try {
+ contentStream.setStrokingColor(Color.RED);
+ contentStream.drawLine(x, y, x + padding, y - padding);
+ contentStream.drawLine(x + width, y, x + width - padding, y
+ - padding);
+ contentStream.drawLine(x + width, y - height, x + width
+ - padding, y - height + padding);
+ contentStream.drawLine(x, y - height, x + padding, y - height
+ + padding);
+ contentStream.setStrokingColor(Color.BLACK);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static String getFontID(PDFont font, PDResources resources) {
+// Iterator<java.util.Map.Entry<String, PDFont>> it = resources.getfon
+// .entrySet().iterator();
+ Iterator<COSName> it = resources.getFontNames().iterator();
+ while (it.hasNext()) {
+ COSName entry = it.next();
+ if (entry.getName().equals(font.getName())) {
+ return entry.getName();
+ }
+ }
+ return "";
+ }
+
+ private static void addToAlternateTableCaption(Entry cell, StringBuilder alternateTableCaption){
+ alternateTableCaption.append(cell.getValue());
+ alternateTableCaption.append("\n");//better for screen reader
+ }
+
+
+}