StructuredPDF.java

// $Id: StructuredPDF.java 25211 2017-04-04 10:47:41Z mike $

import java.util.*;
import java.io.*;
import java.awt.color.*;
import java.awt.Color;
import org.faceless.pdf2.*;

/**
 * A worked example showing how to use the beginTag/endTag methods
 * to add structure to a PDF.
 *
 * This example was revised in 2.20 and the resulting file is now
 * both PDF/A-3a and PDF/UA compliant.
 */
public class StructuredPDF {

    public static void main(String[] args) throws IOException {

        // Here's how we create a PDF that meets the requirments of both
        // PDF/A *and* PDF/UA - use the OutputProfile.merge() method.
        ICC_Profile icc = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
        OutputProfile profile = new OutputProfile(OutputProfile.PDFA3a, "sRGB", null, "http://www.color.org", null, icc);
        profile.merge(OutputProfile.PDFUA1);
        PDF pdf = new PDF(profile);

        pdf.setInfo("Title", "An Accessible PDF");              // Title must be set
        pdf.setLocale(Locale.ENGLISH);                          // Locale too - if not we will set a default

        PDFPage page = pdf.newPage("Letter");
        PDFCanvas canvas = new PDFCanvas(612, 792);
        int margin = 36;

        // PDF/A and PDF/UA both require embedded fonts.
        PDFStyle style = new PDFStyle();
        OpenTypeFont font = new OpenTypeFont(new FileInputStream("resources/fonts/bluehigh.ttf"), 2);
        style.setFont(font, 24);
        style.setFillColor(Color.black);

        PDFStyle linkstyle = new PDFStyle(style);
        linkstyle.setFillColor(Color.blue);
        linkstyle.setTextUnderline(true);

        Locale spainlocale = new Locale("es", "ES");
        LayoutBox box = new LayoutBox(page.getWidth() - margin - margin);
        Map<String,Object> atts = new HashMap<String,Object>();

        //--------------------------------------------------------------
        // Here we create the tagged content. The document we're trying to
        // create will have the following psuedo-structure
        //
        // <article>
        //  <p id="para1">
        //   Hello
        //   <span id="span1" class="username">Mr Smith</span>
        //  </p>
        //  <p id="para2" xml:lang="es_ES">
        //   Hola
        //   <span id="span2" class="username">
        //    <a href="http://bfo.com" alt="Página principal de BFO">Señor Smith</a>
        //   </span>
        //  </p>
        // </article>
        //
        // On the left we have the commands for         Here on the right we have
        // the PDF API                                  the analagous HTML-style
        //                                              tags.
        //
        // Of course the HTML equivalents aren't exact - PDF structure tags are
        // not a direct match, but they should help to explain the structure
        //
        page.beginTag("Art", null);                     // <article>

        atts.clear();
        atts.put("id", "para1");
        box.beginTag("P", atts);                        // <p id="para1">

        box.addText("Hello, ", style, null);            // hello

        atts.clear();
        atts.put("id", "span1");
        atts.put("class", "username");
        box.beginTag("Span", atts);                     // <span id="span1" class="username">

        box.addText("Mr Smith", style, null);           // Mr Smith

        box.addLineBreak(style);                        // <br/>
        box.endTag();                                   // </span>
        box.endTag();                                   // </p>

        atts.clear();
        atts.put("id", "para2");
        atts.put("lang", spainlocale);
        box.beginTag("P", atts);                        // <p id="para2" lang="en-ES">

        box.addText("Hola, ", style, null);             // Hola

        atts.clear();
        atts.put("id", "span2");
        atts.put("class", "username");
        box.beginTag("Span", atts);                     // <span id="span2" class="username">

        AnnotationLink link = new AnnotationLink();
        link.setContents("P\u00e1gina principal de BFO");    // Description is required
        link.setAction(PDFAction.goToURL("http://bfo.com"));
        atts.clear();
        atts.put("annotation", link);
        box.beginTag("Link", atts);                     // <a href="http://bfo.com" alt="Página principal de BFO">

        LayoutBox.Text text = box.addText("Se\u00f1or Smith", linkstyle, null);  // Señor Smith

        box.endTag();                                   // </a>
        box.endTag();                                   // </span>
        box.endTag();                                   // </p>
        box.flush();

        page.drawLayoutBox(box, margin, page.getHeight() - margin);

        // After we've drawn the box on the page, set the link annotation position
        // to match our hyperlink
        link.setCorners(text.getCorners(margin, page.getHeight() - margin));
        link.setPage(page);

        // Add an "artifact" - in this case, a page number.
        //
        // Artifacts are parts of the document  that have no meaningful content -
        // this includes incidental text like page numbers, but also graphics: for
        // example, the box drawn around a table.
        //
        // PDF/UA requires that *everything* in a PDF is either actual content marked
        // with tags, or an Artifact. To help you along, we will automatically tag
        // anything not inside a beginTag/endTag as an artifact; but when you want
        // to add an Artifact to the page and you're already inside an existing
        // beginTag/endTag pair, you need to explicitly mark the Artifact, as below.
        //
        // See http://www.w3.org/TR/2014/NOTE-WCAG20-TECHS-20140408/pdf.html#PDF4
        //
        page.beginTag("Artifact", null);                // <artifact>
        box = new LayoutBox(100);
        style.setFont(font, 12);
        box.addText("Page 1", style, null);
        style.setFont(font, 24);
        page.drawLayoutBox(box, page.getWidth() / 2, page.getHeight() - 20);
        page.endTag();                                  // </artifact>

        page.endTag();                                  // </article>

        OutputStream fo = new FileOutputStream("StructuredPDF.pdf");
        pdf.render(fo);
        fo.close();
    }

}