iText - java.lang.RuntimeException: Unbalanced save/restore state operators - itext

I receive the error message "java.lang.RuntimeException: Unbalanced save/restore state Operators", when I try to use setClip(...) several times during drawing with a Graphics2-object, which I got from iText's cb.createGraphics(..).
Additional Information:
single threaded application
error after 10 calls to setClip()
allways a pair setClip(path) and setClip(null)
occurs with version 2.1.4; with Version 2.1.7 the error even appears earlier
without the setClip(...) everything is drawn as expected without errors
Does anybody know a solution for this problem, or has a hint to it?
Does this error appear in Version 5..., too? (Before I buy a licence for version 5 ;-)
Thank you!
FileOutputStream fos = new FileOutputStream("c:\\temp\\test.pdf");
Document document = null;
Rectangle rect=PageSize.A3.rotate();
document = new Document(rect);
PdfWriter writer=PdfWriter.getInstance(document, fos);
document.open();
PdfContentByte cb = writer.getDirectContent();
Graphics2D g =cb.createGraphics(rect.getWidth(), rect.getHeight());
int x[]={10,1000,1000,10};
int y[]={10,10,1000,1000};
Polygon po=new Polygon();
for (int i=0; i<4; i++)
po.addPoint(x[i],y[i]);
g.clip(po);
g.setClip(null);
document.newPage();
g.clip(po);
g.setClip(null);

Related

Error while parsing the PDF Document (Pg Entry of Structure Element with MCIDs not set.)

I am using iTextsharp to create/merge Tagged PDFs.
When I run PDF Accessibility Checker2.0 on the generated PDF, I get following error:
Error while parsing the PDF Document (Pg Entry of Structure Element with MCIDs not set.) under PDF syntax as shown below:
I could not find anything related to this issue online. I checked in : https://taggedpdf.com/508-pdf-help-center/
I need to fix this issue using iTextsharp library but I am not able to fix it manually as well.
Please help me if someone has some idea about how to fix this.
Thanks in advance.
I am adding the code below, I am using to create tagged PDF:
PdfReader reader = new PdfReader(pdfSourceFile);
iTextSharp.text.Document document = new iTextSharp.text.Document();
PdfCopy writer = new PdfSmartCopy(document, new
FileStream(pdfDestinationFile, FileMode.Create));
writer.SetTagged();
document.Open();
for (int j = 1; j <= reader.NumberOfPages; j++)
{
if (reader.GetPageContent(j).Length > 0)
{
var page = writer.GetImportedPage(reader, j, true);
writer.AddPage(page);
}
}
document.Close();
writer.Close();
reader.Close();
I have omitted some lines of logic here.

How to get values and the keys of all the controls in a dynamic pdf using iText?

I've tried to extract all the fields out of a dynamic form. But I've observed that the code worked for some forms while not for others. Worst, the code worked differently for the same form but two different downloaded files. But after digging a lot, I found that those forms which correctly, were freshly processed. Not even a single details were filled from a PDF Software(Adobe Reader). Also, if the form was filled and saved the thumbnail of the form in the explorer would change from. The code snippet is as follows:
PdfDocument pdfDoc;
pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
PdfDictionary perms = pdfDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.Perms);
if (perms != null) {
perms.remove(new PdfName("UR"));
perms.remove(PdfName.UR3);
if (perms.size() == 0) {
pdfDoc.getCatalog().remove(PdfName.Perms);
}
}
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
List<String> result = new ArrayList<String>(form.getFormFields().keySet());
Map<String, PdfFormField> fields = form.getFormFields();
Below is the image for the same form, but downloaded twice. The one with the colorful thumbnail is not filled. Other is filled using Adobe Reader and saved, and on saving the thumbnail vanished.
I suspect a flag might get set on saving the form. Any help is appreciated.Another peculiar observation, there was a mismatch in the number of parameters in the PdfCatalog object for the above two forms. An entry for the property 'NeedsRendering' was present in the faulty PDF and otherwise for the working PDf. I've attached screenshots for the working PDF during a debugging session.
hrsa_working_form:
Update 1
#Browno, apologies for the confusing question from a newbie's mind. I've posted the screenshots from the itext RUPS for the key '/AcroForm'. On exploring the answers for XFAForm, I've learned how to fill them. But flattening them causes an exception. I've used the pdfxfa jar under the license of AGPL. I'm lacking the knowledge of XFAFlattener and it's properties used in the XFAFlattenerProperties class. Below is the code snapshot:
public void fillData2(String src, String xml, String dest, String newDest){
throws IOException, ParserConfigurationException, SAXException, InterruptedException {
PdfReader reader = new PdfReader(src);
reader.setUnethicalReading(true);
PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter(dest), new StampingProperties().useAppendMode());
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
List<String> result = new ArrayList<String>(form.getFormFields().keySet());
System.out.println(result.size());
XfaForm xfa = form.getXfaForm();
xfa.fillXfaForm(new FileInputStream(xml));
xfa.write(pdfDoc);
//form.flattenFields(); throws exception
pdfDoc.close();
FileInputStream fis = new FileInputStream(dest);
FileOutputStream fos = new FileOutputStream(newDest);
XFAFlattener xfaFlattener = new XFAFlattener();
xfaFlattener.setFontSettings(new XFAFontSettings().setEmbedExternalFonts(true));
xfaFlattener.flatten(fis, fos);
fis.close();
fos.close();
}
The encountered exception is:
Exception in thread "main" java.lang.NoSuchFieldError: FONTFAMILY
at com.itextpdf.tool.xml.xtra.xfa.font.XFAFontProvider.addFonts(XFAFontProvider.java:117)
at com.itextpdf.tool.xml.xtra.xfa.font.XFAFontProvider.<init>(XFAFontProvider.java:56)
at com.itextpdf.tool.xml.xtra.xfa.XFAFlattener.initFlattener(XFAFlattener.java:643)
at com.itextpdf.tool.xml.xtra.xfa.XFAFlattener.flatten(XFAFlattener.java:201)
at com.itextpdf.tool.xml.xtra.xfa.XFAFlattener.flatten(XFAFlattener.java:396)
at com.mycompany.kitext.kitext.fillData2(kitext.java:153)
at com.mycompany.kitext.kitext.main(kitext.java:81)
Also, as per #mkl's comment, I've attached the PDF forms:
https://drive.google.com/file/d/0B6w278NcMSCrZDZoZklmVTNuOWc/view?usp=sharing
//iText RUPS /AcroForm Snapshot
https://drive.google.com/file/d/0B6w278NcMSCrZ1Q1VHc5YzY4UG8/view?usp=sharing
//Form filled with fillXfaForm()
//running low on reputation
Form filled with XFA
I've also read the pdfXFA Release notes for developers. But couldn't find a similar example. Thanks for your help and the great work on iText.

maximum page size in itextpdf

I'm creating adf project and generating reports using itextpdf 5.1.3.
For eg:- My table customer has 3000 rows.In my jspx page has customer table & button has file downloader listner there i'm simply calling the report.
Report is generating for only first 50 rows (maximum 4 pages) are only coming.
Why the remaining rows are not coming in reports?
private void generatePDFFile(FacesContext facesContext, java.io.OutputStream outputStream) {
try {
DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding iterBind1 = (DCIteratorBinding)dcBindings.get("CustomerView1Iterator");
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(FILE)); \\file path local disk D:\mywork\customer.pdf
document.open();
Row[] rows= iterBind1.getAllRowsInRange();
for(Row row:rows){
custcode = (String) row.getAttribute("CustomerCode");
custname = (String) row.getAttribute("CustomerNameE");
addgroup(document);
}
document.close();
facesContext = facesContext.getCurrentInstance();
ServletContext context = (ServletContext)facesContext.getExternalContext().getContext();
File file = new File(FILE);
FileInputStream fileInputStream;
byte[] b;
System.out.println(file.getCanonicalPath());
System.out.println(file.getAbsolutePath());
fileInputStream = new FileInputStream(file);
int n = fileInputStream.available();
while (n > 0) {
b = new byte[n];
//b = new byte[8192];
int result = fileInputStream.read(b);
outputStream.write(b, 0, b.length);
if (result == -1)
break;
}
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void addgroup(Document document) throws DocumentException{
Paragraph preface1 = new Paragraph();
Paragraph preface2 = new Paragraph();
preface1.add(new Chunk("\n"));
preface1.add(new Chunk("Customer : "+custcode+" "+custname,BlueFont));
preface1.add(new Chunk("\n"));
document.add(preface1);
document.add(preface2);
}
The maximum size of a page in a PDF document is 14,400 by 14,400 user units. See the blog post Help, I only see blank pages in my PDF. This is not a limitation introduced by iText; it's a limitation that exists in PDF viewers such as Adobe Reader. Other viewers (such as Apple Preview) have no problem displaying PDFs with larger pages.
This answers the question in the Subject-line of your post.
The body of your post contains a completely different question. Maybe you aren't asking about the page size, but rather about the file size. That question has also been answered in the past. See What is the size limit of pdf file?
Allow me to summarize that answer:
The maximum size of a PDF with a version older than PDF 1.5 is about 10 gigabytes.
The maximum size of a PDF with a version PDF 1.5 or higher using a compressed cross-reference stream depends only on the limitations of the software processing the PDF.
The maximum size of a PDF created with iText versions before 5.3 is 2 gigabytes. The maximum size of a PDF created with iText versions 5.3 and higher is 1 terabyte.
Since you are using iText 5.1.3, you can create a PDF of 2 GBytes. It beats me why you are using a version of iText that dates from November 2011 instead of a more recent version, but there is no reason why you wouldn't be able to put a table containing 3000 rows in a PDF that can be as large as 2 GBytes.
Chances are that your code is really bad. Unfortunately, you don't show us your code. Did you read the documentation on how to create Large Tables?
I can't comment on the part where you say:
In my jspx page has customer table & button has file downloader listner there i'm simply calling the report.
That doesn't seem to be relevant in the context of your question.

iTextSharp and Hyphenation

In earlier versions of iTextSharp, I have incorporated hyphenation in the following way (example is for German hyphenation):
HyphenationAuto autoDE = new HyphenationAuto("de", "DR", 3, 3);
BaseFont.AddToResourceSearch(RuntimePath + "itext-hyph-xml.dll");
chunk = new Chunk(text).SetHyphenation(autoDE);
In recent versions of iText, this is no longer possible as the function
BaseFont.AddToResourceSearch()
has been removed from iText. Now how to replace this statement?
When inspecting the 2nd ed. of the iText IN ACTION manual, the statement need not be replaced at all, apparently. When doing so, however, no hyphenation takes place (and no errors occur). I also have taken a newer version of
itext-hyph-xml.dll
and re-referenced it. Same result, no hyphenation. This file resides on the same path as iTextSharp.dll, and I have included the path in the CLASSPATH environment variable. Nothing helps. I'm stuck, please help.
Calling iTextSharp.text.io.StreamUtil.AddToResourceSearch() works for me:
var content = #"
Allein ist besser als mit Schlechten im Verein: mit Guten im Verein, ist besser als allein.
";
var table = new PdfPTable(1);
// make sure .dll is in correct /bin directory
StreamUtil.AddToResourceSearch("itext-hyph-xml.dll");
using (var stream = new MemoryStream())
{
using (var document = new Document(PageSize.A8.Rotate()))
{
PdfWriter.GetInstance(document, stream);
document.Open();
var chunk = new Chunk(content)
.SetHyphenation(new HyphenationAuto("de", "DR", 3, 3));
table.AddCell(new Phrase(chunk));
document.Add(table);
}
File.WriteAllBytes(OUT_FILE, stream.ToArray());
}
Tested with iTextSharp 5.5.11 and itext-hyph-xml 2.0.0.0. Output PDF:

Whats the alternative to copyAcroForm?

We are currently porting our code base from iText 2.1.7 to iText 5.5.0 (yeah I know.. we had a little longer ;-).
Well.. "now" that copyAcroForm has gone the way of the Dodo, I'm struggling to find an alternative to this code:
File outputFile = new File...
Document document = new Document();
FileOutputStream fos = new FileOutputStream(outputFile);
PdfCopy subjobWriter = new PdfCopy(document, fos);
document.open();
PdfReader reader = new PdfReader(generationReader);
for (int i=1; i<=reader.getNumberOfPages(); i++) {
PdfImportedPage page = subjobWriter.getImportedPage(reader, i);
subjobWriter.addPage(page);
}
PRAcroForm form = reader.getAcroForm();
if (form != null)
subjobWriter.copyAcroForm(reader);
subjobWriter.freeReader(reader);
reader.close();
subjobWriter.close();
document.close();
fos.close();
but haven't really found anything. I read in the changelog of 4.34 or so that I apparently should use PdfCopy.addDocument(). I tried that and commented out the other code, such as this:
...
PdfReader reader = new PdfReader(generationReader);
reader.consolidateNamedDestinations();
subjobWriter.addDocument(reader);
subjobWriter.freeReader(reader);
subjobWriter.setOutlines(SimpleBookmark.getBookmark(reader));
...
but that didn't help either.
The problem is, that everything from the original PDF is copied EXCEPT the form (and its fields and content), or rather, it looks like the whole form has been flattened instead.
Since all the samples I could find either used copyAcroForm() which doesn't exist anymore or the PdfCopyFields class which is deprecated and all the samples at itextpdf.com and the "iText in Action, 2nd edition" use copyAcroForm() as well, I'm at loss as to how to solve this. Any idea anyone?
Rog
Please take a look at the MergeForms example:
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
copy.setMergeFields();
document.open();
for (PdfReader reader : readers) {
copy.addDocument(reader);
}
document.close();
for (PdfReader reader : readers) {
reader.close();
}
One line in particular is very important:
copy.setMergeFields();
Did you add that line?