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