Generating Barcodes in PDFs with Flying-Saucer

Flying-Saucer is a nice library to generate PDF documents from within Java applications. Just generate a bunch of XHTML, throw it into the renderer and let it produce the desired document utilizing iText.

When it comes to barcodes however, Flying-Saucer cannot access the built in barcode functionality of iText (at least I didn’t find any documentation for it).
 
 
 
 
 
 
However, being OpenSource and well designed, one only needs to create one subclass to achieve the task: Flying-Saucer relies on a factory named ReplacedElementFactory, which can replace elements by custom objects. This is also used to embed images, as the class ITextReplacedElementFactory shows. Now we can simply create a subclass, which replaces images with an appropriate barcode:

<img src=’0123456789′ type=’code128′ style=’height: 1cm’ />

One simply needs to override the createReplacedElement method like this (the whole code can be found here: BarcodeReplacedElementFactory.java (GitHub)):

@Override
    public ReplacedElement createReplacedElement(
            LayoutContext c, 
            BlockBox box,
            UserAgentCallback uac, 
            int cssWidth, 
            int cssHeight) 
    {

        Element e = box.getElement();
        if (e == null) {
            return null;
        }

        String nodeName = e.getNodeName();
        if (nodeName.equals("img")) {
            if ("code128".equals(e.getAttribute("type"))) {
                try {
                    Barcode128 code = new Barcode128();
                    code.setCode(e.getAttribute("src"));
                    FSImage fsImage = new ITextFSImage(
                                       Image.getInstance(
                                         code.createAwtImage(
                                           Color.BLACK, 
                                           Color.WHITE
                                         ),
                                         Color.WHITE
                                       ));
                    if (cssWidth != -1 || cssHeight != -1) {
                        fsImage.scale(cssWidth, cssHeight);
                    }
                    return new ITextImageElement(fsImage);
                } catch (Throwable e1) {
                    return null;
                }
            }
        }

        return super.createReplacedElement(
                        c, box, uac, cssWidth, cssHeight);
    }

Granted, ‘type’ is no valid XHTML-Element for <img /> but as you can see in the code above, you could easily replace it with data-type or any other attribute. Flying-Saucer doesn’t seem to care about this anyway.

Note: The code above can only handle Code128-Barcodes, but can easily be extended to handle EAN and the like (iText supports a whole bunch of barcodes by default).

In order to make our factory work, we need to pass it to the renderer – which is pretty darn easy:

ITextRenderer renderer = new ITextRenderer();
        renderer.getSharedContext().setReplacedElementFactory(
                new BarcodeReplacedElementFactory(
                        renderer.getOutputDevice()
                ));
        renderer.setDocumentFromString(inputAsString);
        renderer.layout();
        renderer.createPDF(outputAsStream);

 

Reference: Generating Barcodes in PDFs with Flying-Saucer from our JCG partner Andreas Haufler at the Andy’s Software Engineering Corner blog.

Share and enjoy!


© 2010-2012 Java Code Geeks. Licenced under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.