I've create pdf with pdfbox (using PDResources, PDXObjectForm, PDAppearanceDictionary and so on). I have Visible signature on pdf.
when I see the pdf, I have missed some stream.
4 0 obj
<</Type /XObject//Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]/XObject <</n0 9 0 R/n1 10 0 R>>>>/BBox [0 0 100 100]/FormType 1/Length 11 0 R>>
stream
endstream
endobj
8 0 obj
<</Type /XObject/Subtype /Form/Resources <</XObject <</FRM0 4 0 R >>/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/BBox [0 0 100 100]/Matrix [1 0 0 1 0 0]/FormType 1/Length 13 0 R>>
stream
endstream
endobj
pdf structure (XObjects) is created well. but I don't know what streams should be here. or how to create that? or what streams should there be?
PDDocument template = new PDDocument();
try {
...
PDStream formstream = new PDStream(template);
OutputStream os = formstream.createOutputStream();
PDXObjectForm form = new PDXObjectForm(formstream);
PDResources res = new PDResources();
form.setResources(res);
form.setBBox(formrect);
form.setMatrix(transform);
form.setFormType(1);
PDAppearanceStream dic = new PDAppearanceStream(form.getCOSStream());
PDAppearanceDictionary appearance = new PDAppearanceDictionary();
appearance.setNormalAppearance(dic);
appearance.getCOSObject().setDirect(true);
PDRectangle innerRect = new PDRectangle();
innerRect.setUpperRightX(100);
innerRect.setUpperRightY(100);
innerRect.setLowerLeftX(0);
innerRect.setLowerLeftY(0);
PDStream formStream2 = new PDStream(template);
PDXObjectForm innerForm = new PDXObjectForm(formStream2);
OutputStream os1 = formStream2.createOutputStream();
PDResources innerResources = new PDResources();
innerForm.setResources(innerResources);
innerForm.setBBox(innerRect);
innerForm.setFormType(1);
innerForm.getResources().getCOSDictionary().setItem(COSName.PROC_SET, defaultRes);
res.addXObject(innerForm, "FRM");
PDStream DSStream = new PDStream(template);
OutputStream os2 = DSStream.createOutputStream();
PDXObjectForm dsForm = new PDXObjectForm(DSStream);
dsForm.setBBox(formrect);
dsForm.setMatrix(transform);
PDResources dsRes = new PDResources();
dsForm.setResources(dsRes);
dsForm.setFormType(1);
PDFont firstFont = PDTrueTypeFont.loadTTF(template, new File("/MyFont.ttf"));
PDFont secondFont = PDTrueTypeFont.loadTTF(template, new File("/MyFont.TTF"));
secondFont.setFontEncoding(new WinAnsiEncoding());
firstFont.setFontEncoding(new WinAnsiEncoding());
Map<String, PDFont> fonts = new HashMap<String, PDFont>();
PDStream imageFormStream = new PDStream(template);
OutputStream os3 = imageFormStream.createOutputStream();
PDXObjectForm imageForm = new PDXObjectForm(imageFormStream);
imageForm.setBBox(formrect);
imageForm.setMatrix(transform);
PDResources imgRes = new PDResources();
imgRes.getCOSObject().setDirect(true);
imgRes.addFont(firstFont);
imageForm.setResources(imgRes);
imageForm.setFormType(1);
innerResources.addXObject(dsForm, "n");
innerResources.addXObject(imageForm, "n");
imgRes.addXObject(jpeg, "img");
appendRawCommands(os2, "% DSBlank");
appendRawCommands(os3, "q 101 0 0 24.53 2 12.24 cm /img0 Do Q");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "BT");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "1 0 0 1 2 33 Tm");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "101 0 Td");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "-101 0 Td");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "ET");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "BT");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "1 0 0 1 106 37 Tm");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "/F1 12 Tf");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "(TEXT HERE)Tj");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "1 0 0 1 106 25 Tm");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "(10 11:12:13)Tj");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "1 0 0 1 106 13 Tm");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "(GMT+06:00 2013)Tj");
appendRawCommands(os3, "\n");
appendRawCommands(os3, "ET");
os1.close();
os.close();
os3.close();
os2.close();
sigField.getWidget().setAppearance(appearance);
COSDictionary widgetDict = sigField.getWidget().getDictionary();
widgetDict.setNeedToBeUpdate(true);
defaultRes.setDirect(true);
widgetDict.setItem(COSName.DR, res.getCOSObject());
PDResources resSecondForAcro = new PDResources();
resSecondForAcro.addXObject(innerForm, "FRM");
resSecondForAcro.addFont(secondFont);
COSBase cosBase=resSecondForAcro.getCOSObject();
cosBase.setDirect(true);
acroFormDC.setItem(COSName.DR, cosBase);
COSDocument visualSignature = template.getDocument();
...
COSWriter wr = new COSWriter(new FileOutputStream("/new.pdf"));
wr.write(visualSignature);
wr.close();
template.close();
} finally {
template.close();
}
that's sample:
what should I add to that code? the problem is that , there is no image on Rectangle ( on visible signature).
You add commands to os2
and os3
but neither to os
nor to os1.
You might want to add something along the lines of
appendRawCommands(os, "q 1 0 0 1 0 0 cm /FRM0 Do Q\n");
appendRawCommands(os1, "q 1 0 0 1 0 0 cm /n0 Do Q\n");
appendRawCommands(os1, "q 1 0 0 1 0 0 cm /n1 Do Q\n");
This being said, why do you use such a complicated structure. If you used the xobject names which Adobe used to use when it illustrated the signature state by activating or deactivating such form xobjects (i.e. /FRM, /n0, and /n2; only before Acrobat 6 there were other layers, too), I could understand, but you use different names /FRM0 and /n1, only /n0 is identical. Thus, you could instead immediately use your stream with image and text as normal appearance.
If you want to support the old layered appearances, you should more accurately keep to the notations of Adobe®'s Acrobat® SDK Digital Signature Appearances paper.
PS: It looks like one should not have multiple such PDStream OutputStreams
open simultaneously. Instead one should retrieve such an output stream, write to it, close it, and only then continue with other manipulations of the PDF objects.