New features in the PDF Library 2.11.25

A quick summary

Our latest PDF Library has a few important aspects to it. The most significant is that this release fixes a security vulnerability relating to JavaScript. If you're a customer we should have emailed you already about this, so if you haven't got this already then please contact sales@bfo.com and they'll give you the details.

You can read the Changelog for the full list, but the main aspects of this release are:

  • support for BarCode fields, which have been in Acrobat since 7.0 but not officially documented until the PDF 2.0 specification, which should be out shortly (we've written a separate article on these).
  • Improvements to the viewer: the multi-page viewport has been rewritten for speed, and we've added the ability to optionally capture handwritten signatures using an Android or iOS device (there's a separate article on that too).
  • Lastly, we've put in some long overdue changes relating to List: specifically lists of annotations, as returned by PDFPage.getAnnotations() and FormElement.getAnnotations().

This last one deserves a bit more of an explanation. Many users of the PDF Library find themselves merging PDF documents in one way or another, in particular when a document has form fields. Quite a common operation is to move all a field's annotations from one page to another, and in previous builds this could lead to a contradiction:

List annots1 = page1.getAnnotations();
List annots2 = page2.getAnnotations();
// Move all annotations from page1 to page2
annots2.getAnnotations().addAll(annots1);

// Contradiction ahead: page 1's annotation not on page 1!
assert annots1.isEmpty(); // fails!
PDFAnnotation annot = (PDFAnnotation)annots1.get(0);
assert annot.getPage() == page1;   // fails!

The problem comes about because while in general, an item in a java.util.List can belong to more than one list, an annotation can only be on one page at a time. Adding all the annotations from page 2 to page 1's list should remove them from page 2, but if you try to do that with a normal list you'll quickly come up against a ConcurrentModificationException. The same problem exists when moving widgets between form fields.

We've finally got a a solution to this in the shape of a new List implementation, which manages the moving of items from one list to another without any ConcurrentModificationExceptions. Your Iterators in the following will work properly:

List annots1 = page1.getAnnotations();
List annots2 = page2.getAnnotations();
for (Iterator i = annots1.iterator();i.hasNext();) {
    annots2.add(i.next());
    i.remove();   // optional - it's going to happen anyway
}
assert annots1.isEmpty();

And if you're just copying the annotation list to a regular java.util.List, everything will work as normal:

List annots1 = page1.getAnnotations();
List temp = new ArrayList();
for (Iterator i = annots1.iterator();i.hasNext();) {
    temp.add(i.next());
}
assert annots1.size() == temp.size();

The result is that your PDF's structure is internally consistent all of the time, which clears the way for us to put out some further improvements in a forthcoming release. Watch this space.