Chapter 15: Page content and structure

This is a code example of iText PDF, discover more.

10th October 2015
admin-marketing

Switch code for this example

PeekABoo.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * This example was written by Bruno Lowagie. It is part of the book 'iText in
 * Action' by Manning Publications. 
 * ISBN: 1932394796
 * http://www.1t3xt.com/docs/book.php 
 * http://www.manning.com/lowagie/
 */

public class PeekABoo {

    /** The first resulting PDF. */
    public static String RESULT1 = "results/part4/chapter15/peek-a-boo1.pdf";
    /** The second resulting PDF. */
    public static String RESULT2 = "results/part4/chapter15/peek-a-boo2.pdf";

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename, boolean on) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document,
            new FileOutputStream(filename));
        writer.setViewerPreferences(PdfWriter.PageModeUseOC);
        writer.setPdfVersion(PdfWriter.VERSION_1_5);
        // step 3
        document.open();
        // step 4
        PdfLayer layer = new PdfLayer("Do you see me?", writer);
        layer.setOn(on);
        BaseFont bf = BaseFont.createFont();
        PdfContentByte cb = writer.getDirectContent();
        cb.beginText();
        cb.setFontAndSize(bf, 18);
        cb.showTextAligned(Element.ALIGN_LEFT, "Do you see me?", 50, 790, 0);
        cb.beginLayer(layer);
        cb.showTextAligned(Element.ALIGN_LEFT, "Peek-a-Boo!!!", 50, 766, 0);
        cb.endLayer();
        cb.endText();
        // step 5
        document.close();
    }
    
    /**
     * A simple example with optional content.
     * 
     * @param args
     *            no arguments needed here
     * @throws IOException 
     * @throws DocumentException 
     */
    public static void main(String[] args) throws DocumentException, IOException {
        PeekABoo peekaboo = new PeekABoo();
        peekaboo.createPdf(RESULT1, true);
        peekaboo.createPdf(RESULT2, false);
    }
}
OptionalContentExample.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfWriter;

public class OptionalContentExample {

    /** The resulting PDF. */
    public static String RESULT = "results/part4/chapter15/layer_structure.pdf";

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename)
        throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer =
            PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setPdfVersion(PdfWriter.VERSION_1_5);
        // step 3
        document.open();
        // step 4
        PdfContentByte cb = writer.getDirectContent();
        PdfLayer nested = new PdfLayer("Nested layers", writer);
        PdfLayer nested_1 = new PdfLayer("Nested layer 1", writer);
        PdfLayer nested_2 = new PdfLayer("Nested layer 2", writer);
        nested.addChild(nested_1);
        nested.addChild(nested_2);
        writer.lockLayer(nested_2);
        cb.beginLayer(nested);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "nested layers"), 50, 775, 0);
        cb.endLayer();
        cb.beginLayer(nested_1);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "nested layer 1"), 100, 800, 0);
        cb.endLayer();
        cb.beginLayer(nested_2);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "nested layer 2"), 100, 750, 0);
        cb.endLayer();

        PdfLayer group = PdfLayer.createTitle("Grouped layers", writer);
        PdfLayer layer1 = new PdfLayer("Group: layer 1", writer);
        PdfLayer layer2 = new PdfLayer("Group: layer 2", writer);
        group.addChild(layer1);
        group.addChild(layer2);
        cb.beginLayer(layer1);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "layer 1 in the group"), 50, 700, 0);
        cb.endLayer();
        cb.beginLayer(layer2);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "layer 2 in the group"), 50, 675, 0);
        cb.endLayer();

        PdfLayer radiogroup = PdfLayer.createTitle("Radio group", writer);
        PdfLayer radio1 = new PdfLayer("Radiogroup: layer 1", writer);
        radio1.setOn(true);
        PdfLayer radio2 = new PdfLayer("Radiogroup: layer 2", writer);
        radio2.setOn(false);
        PdfLayer radio3 = new PdfLayer("Radiogroup: layer 3", writer);
        radio3.setOn(false);
        radiogroup.addChild(radio1);
        radiogroup.addChild(radio2);
        radiogroup.addChild(radio3);
        ArrayList options = new ArrayList();
        options.add(radio1);
        options.add(radio2);
        options.add(radio3);
        writer.addOCGRadioGroup(options);
        cb.beginLayer(radio1);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "option 1"), 50, 600, 0);
        cb.endLayer();
        cb.beginLayer(radio2);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "option 2"), 50, 575, 0);
        cb.endLayer();
        cb.beginLayer(radio3);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "option 3"), 50, 550, 0);
        cb.endLayer();

        PdfLayer not_printed = new PdfLayer("not printed", writer);
        not_printed.setOnPanel(false);
        not_printed.setPrint("Print", false);
        cb.beginLayer(not_printed);
        ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, new Phrase(
                "PRINT THIS PAGE"), 300, 700, 90);
        cb.endLayer();

        PdfLayer zoom = new PdfLayer("Zoom 0.75-1.25", writer);
        zoom.setOnPanel(false);
        zoom.setZoom(0.75f, 1.25f);
        cb.beginLayer(zoom);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase(
                "Only visible if the zoomfactor is between 75 and 125%"), 30,
                530, 90);
        cb.endLayer();

        // step 5
        document.close();
    }

    /**
     * A simple example with optional content.
     * 
     * @param args
     *            no arguments needed here
     * @throws IOException
     * @throws DocumentException
     */
    public static void main(String[] args) throws DocumentException,
            IOException {
        new OptionalContentExample().createPdf(RESULT);
    }
}
LayerMembershipExample1.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfLayerMembership;
import com.itextpdf.text.pdf.PdfWriter;

public class LayerMembershipExample1 {

    /** The resulting PDF. */
    public static String RESULT = "results/part4/chapter15/layer_membership1.pdf";

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(
                document, new FileOutputStream(RESULT));
        writer.setPdfVersion(PdfWriter.VERSION_1_5);
        // step 3
        document.open();
        // step 4
        PdfContentByte cb = writer.getDirectContent();

        PdfLayer dog = new PdfLayer("layer 1", writer);
        PdfLayer tiger = new PdfLayer("layer 2", writer);
        PdfLayer lion = new PdfLayer("layer 3", writer);
        PdfLayerMembership cat = new PdfLayerMembership(writer);
        cat.addMember(tiger);
        cat.addMember(lion);
        PdfLayerMembership no_cat = new PdfLayerMembership(writer);
        no_cat.addMember(tiger);
        no_cat.addMember(lion);
        no_cat.setVisibilityPolicy(PdfLayerMembership.ALLOFF);
        cb.beginLayer(dog);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("dog"),
                50, 775, 0);
        cb.endLayer();
        cb.beginLayer(tiger);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("tiger"),
                50, 750, 0);
        cb.endLayer();
        cb.beginLayer(lion);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("lion"),
                50, 725, 0);
        cb.endLayer();
        cb.beginLayer(cat);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("cat"),
                50, 700, 0);
        cb.endLayer();
        cb.beginLayer(no_cat);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT,
                new Phrase("no cat"), 50, 700, 0);
        cb.endLayer();

        // step 5
        document.close();
    }

    /**
     * A simple example with optional content.
     * 
     * @param args
     *            no arguments needed here
     * @throws IOException
     * @throws DocumentException
     */
    public static void main(String[] args) throws DocumentException,
            IOException {
        new LayerMembershipExample1().createPdf(RESULT);
    }
}
LayerMembershipExample2.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfLayerMembership;
import com.itextpdf.text.pdf.PdfVisibilityExpression;
import com.itextpdf.text.pdf.PdfWriter;

public class LayerMembershipExample2 {

    /** The resulting PDF. */
    public static String RESULT = "results/part4/chapter15/layer_membership2.pdf";

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws DocumentException,
            IOException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(
                document, new FileOutputStream(RESULT));
        writer.setPdfVersion(PdfWriter.VERSION_1_6);
        // step 3
        document.open();
        // step 4
        PdfContentByte cb = writer.getDirectContent();

        PdfLayer dog = new PdfLayer("layer 1", writer);
        PdfLayer tiger = new PdfLayer("layer 2", writer);
        PdfLayer lion = new PdfLayer("layer 3", writer);
        PdfLayerMembership cat = new PdfLayerMembership(writer);
        PdfVisibilityExpression ve1 = new PdfVisibilityExpression(PdfVisibilityExpression.OR);
        ve1.add(tiger);
        ve1.add(lion);
        cat.setVisibilityExpression(ve1);
        PdfLayerMembership no_cat = new PdfLayerMembership(writer);
        PdfVisibilityExpression ve2 = new PdfVisibilityExpression(PdfVisibilityExpression.NOT);
        ve2.add(ve1);
        no_cat.setVisibilityExpression(ve2);
        cb.beginLayer(dog);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("dog"),
                50, 775, 0);
        cb.endLayer();
        cb.beginLayer(tiger);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("tiger"),
                50, 750, 0);
        cb.endLayer();
        cb.beginLayer(lion);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("lion"),
                50, 725, 0);
        cb.endLayer();
        cb.beginLayer(cat);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, new Phrase("cat"),
                50, 700, 0);
        cb.endLayer();
        cb.beginLayer(no_cat);
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT,
                new Phrase("no cat"), 50, 700, 0);
        cb.endLayer();

        // step 5
        document.close();
    }

    /**
     * A simple example with optional content.
     * 
     * @param args
     *            no arguments needed here
     * @throws IOException
     * @throws DocumentException
     */
    public static void main(String[] args) throws DocumentException,
            IOException {
        new LayerMembershipExample2().createPdf(RESULT);
    }
}
OptionalContentActionExample.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfWriter;

public class OptionalContentActionExample {

    /** The resulting PDF. */
    public static String RESULT = "results/part4/chapter15/layer_actions.pdf";

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(
                document, new FileOutputStream(RESULT));
        writer.setPdfVersion(PdfWriter.VERSION_1_5);
        // step 3
        document.open();
        // step 4
        PdfLayer a1 = new PdfLayer("answer 1", writer);
        PdfLayer a2 = new PdfLayer("answer 2", writer);
        PdfLayer a3 = new PdfLayer("answer 3", writer);
        a1.setOn(false);
        a2.setOn(false);
        a3.setOn(false);

        BaseFont bf = BaseFont.createFont();
        PdfContentByte cb = writer.getDirectContent();
        cb.beginText();
        cb.setFontAndSize(bf, 18);
        cb.showTextAligned(Element.ALIGN_LEFT,
            "Q1: Who is the director of the movie 'Paths of Glory'?", 50, 766, 0);
        cb.showTextAligned(Element.ALIGN_LEFT,
            "Q2: Who directed the movie 'Lawrence of Arabia'?", 50, 718, 0);
        cb.showTextAligned(Element.ALIGN_LEFT,
            "Q3: Who is the director of 'House of Flying Daggers'?", 50, 670, 0);
        cb.endText();
        cb.saveState();
        cb.setRGBColorFill(0xFF, 0x00, 0x00);
        cb.beginText();
        cb.beginLayer(a1);
        cb.showTextAligned(Element.ALIGN_LEFT,
                "A1: Stanley Kubrick", 50, 742, 0);
        cb.endLayer();
        cb.beginLayer(a2);
        cb.showTextAligned(Element.ALIGN_LEFT,
                "A2: David Lean", 50, 694, 0);
        cb.endLayer();
        cb.beginLayer(a3);
        cb.showTextAligned(Element.ALIGN_LEFT,
                "A3: Zhang Yimou", 50, 646, 0);
        cb.endLayer();
        cb.endText();
        cb.restoreState();

        ArrayList stateOn = new ArrayList();
        stateOn.add("ON");
        stateOn.add(a1);
        stateOn.add(a2);
        stateOn.add(a3);
        PdfAction actionOn = PdfAction.setOCGstate(stateOn, true);
        ArrayList stateOff = new ArrayList();
        stateOff.add("OFF");
        stateOff.add(a1);
        stateOff.add(a2);
        stateOff.add(a3);
        PdfAction actionOff = PdfAction.setOCGstate(stateOff, true);
        ArrayList stateToggle = new ArrayList();
        stateToggle.add("Toggle");
        stateToggle.add(a1);
        stateToggle.add(a2);
        stateToggle.add(a3);
        PdfAction actionToggle = PdfAction.setOCGstate(stateToggle, true);
        Phrase p = new Phrase("Change the state of the answers:");
        Chunk on = new Chunk(" on ").setAction(actionOn);
        p.add(on);
        Chunk off = new Chunk("/ off ").setAction(actionOff);
        p.add(off);
        Chunk toggle = new Chunk("/ toggle").setAction(actionToggle);
        p.add(toggle);
        document.add(p);
        // step 5
        document.close();
    }

    /**
     * A simple example with optional content.
     * 
     * @param args
     *            no arguments needed here
     * @throws IOException
     * @throws DocumentException
     */
    public static void main(String[] args) throws DocumentException,
            IOException {
        new OptionalContentActionExample().createPdf(RESULT);
    }
}
SvgToPdf.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.awt.Graphics2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.svg.SVGDocument;

import com.itextpdf.awt.PdfGraphics2D;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;

public class SvgToPdf {

    /** The resulting PDF. */
    public static final String RESULT = "results/part4/chapter15/foobar.pdf";
    /** The map (shapes). */
    public static final String CITY = "resources/xml/foobarcity.svg";
    /** The map (text = street names in English). */
    public static final String STREETS = "resources/xml/foobarstreets.svg";
    
    /** The SVG document factory. */
    protected SAXSVGDocumentFactory factory;
    /** The SVG bridge context. */
    protected BridgeContext ctx;
    /** The GVT builder */
    protected GVTBuilder builder;
    
    /** Creates an SvgToPdf object. */
    public SvgToPdf() {
        String parser = XMLResourceDescriptor.getXMLParserClassName();
        factory = new SAXSVGDocumentFactory(parser);
        
        UserAgent userAgent = new UserAgentAdapter();
        DocumentLoader loader = new DocumentLoader(userAgent);
        ctx = new BridgeContext(userAgent, loader);
        ctx.setDynamicState(BridgeContext.DYNAMIC);

        builder = new GVTBuilder();
    }
    
    /**
     * Draws an SVG file to a PdfTemplate.
     * @param map      the template to which the SVG has to be drawn.
     * @param resource the SVG content.
     * @throws IOException
     */
    public void drawSvg(PdfTemplate map, String resource) throws IOException {
        Graphics2D g2d = new PdfGraphics2D(map, 6000, 6000);
        SVGDocument city = factory.createSVGDocument(new File(resource).toURL()
                .toString());
        GraphicsNode mapGraphics = builder.build(ctx, city);
        mapGraphics.paint(g2d);
        g2d.dispose();
    }
    
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
    	Document document = new Document(new Rectangle(6000, 6000));
        // step 2
    	PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
    	document.open();
    	// step 4
        PdfContentByte cb = writer.getDirectContent();
        PdfTemplate map = cb.createTemplate(6000, 6000);
        drawSvg(map, CITY);
        cb.addTemplate(map, 0, 0);
        PdfTemplate streets = cb.createTemplate(6000, 6000);
        drawSvg(streets, STREETS);
        cb.addTemplate(streets, 0, 0);
        // step 5
        document.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new SvgToPdf().createPdf(RESULT);
    }
}
SvgLayers.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;


import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;

public class SvgLayers extends SvgToPdf {

    /** The resulting PDF. */
    public static final String RESULT = "results/part4/chapter15/foobarcity.pdf";
    /** The map. */
    public static final String RUES = "resources/xml/foobarrues.svg";
    /** The map. */
    public static final String STRATEN = "resources/xml/foobarstraten.svg";

    
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
    	Document document = new Document(new Rectangle(6000, 6000));
        // step 2
    	PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setViewerPreferences(PdfWriter.PageModeUseOC | PdfWriter.FitWindow);
        writer.setPdfVersion(PdfWriter.VERSION_1_5);
        // step 3
        document.open();
        // step 4
        // CREATE GRID LAYER
        PdfLayer gridLayer = new PdfLayer("Grid", writer);
        gridLayer.setZoom(0.2f, 1);
        gridLayer.setOnPanel(false);
        // CREATE STREET LAYERS
        PdfLayer streetlayer = PdfLayer.createTitle(
                "Streets / Rues / Straten", writer);
        PdfLayer streetlayer_en = new PdfLayer("English", writer);
        streetlayer_en.setOn(true);
        streetlayer_en.setLanguage("en", true);
        PdfLayer streetlayer_fr = new PdfLayer("Fran\u00e7ais", writer);
        streetlayer_fr.setOn(false);
        streetlayer_fr.setLanguage("fr", false);
        PdfLayer streetlayer_nl = new PdfLayer("Nederlands", writer);
        streetlayer_nl.setOn(false);
        streetlayer_nl.setLanguage("nl", false);
        streetlayer.addChild(streetlayer_en);
        streetlayer.addChild(streetlayer_fr);
        streetlayer.addChild(streetlayer_nl);
        ArrayList radio = new ArrayList();
        radio.add(streetlayer_en);
        radio.add(streetlayer_fr);
        radio.add(streetlayer_nl);
        writer.addOCGRadioGroup(radio);
        // CREATE MAP
        PdfContentByte cb = writer.getDirectContent();
        PdfTemplate map = cb.createTemplate(6000, 6000);
        // DRAW CITY
        drawSvg(map, CITY);
        cb.addTemplate(map, 0, 0);
        PdfTemplate streets = cb.createTemplate(6000, 6000);
        // DRAW STREETS
        drawSvg(streets, STREETS);
        streets.setLayer(streetlayer_en);
        cb.addTemplate(streets, 0, 0);
        PdfTemplate rues = cb.createTemplate(6000, 6000);
        drawSvg(rues, RUES);
        rues.setLayer(streetlayer_fr);
        cb.addTemplate(rues, 0, 0);
        PdfTemplate straten = cb.createTemplate(6000, 6000);
        drawSvg(straten, STRATEN);
        straten.setLayer(streetlayer_nl);
        cb.addTemplate(straten, 0, 0);
        // DRAW GRID
        cb.saveState();
        cb.beginLayer(gridLayer);
        cb.setGrayStroke(0.7f);
        cb.setLineWidth(2);
        for (int i = 0; i < 8; i++) {
            cb.moveTo(1250, 1500 + i * 500);
            cb.lineTo(4750, 1500 + i * 500);
        }
        for (int i = 0; i < 8; i++) {
            cb.moveTo(1250 + i * 500, 1500);
            cb.lineTo(1250 + i * 500, 5000);
        }
        cb.stroke();
        cb.endLayer();
        cb.restoreState();
        
        // CREATE INFO LAYERS
        PdfLayer cityInfoLayer = new PdfLayer("Foobar Info", writer);
        cityInfoLayer.setOn(false);
        PdfLayer hotelLayer = new PdfLayer("Hotel", writer);
        hotelLayer.setOn(false);
        cityInfoLayer.addChild(hotelLayer);
        PdfLayer parkingLayer = new PdfLayer("Parking", writer);
        parkingLayer.setOn(false);
        cityInfoLayer.addChild(parkingLayer);
        PdfLayer businessLayer = new PdfLayer("Industry", writer);
        businessLayer.setOn(false);
        cityInfoLayer.addChild(businessLayer);
        PdfLayer cultureLayer = PdfLayer.createTitle("Leisure and Culture",
                writer);
        PdfLayer goingoutLayer = new PdfLayer("Going out", writer);
        goingoutLayer.setOn(false);
        cultureLayer.addChild(goingoutLayer);
        PdfLayer restoLayer = new PdfLayer("Restaurants", writer);
        restoLayer.setOn(false);
        goingoutLayer.addChild(restoLayer);
        PdfLayer theatreLayer = new PdfLayer("(Movie) Theatres", writer);
        theatreLayer.setOn(false);
        goingoutLayer.addChild(theatreLayer);
        PdfLayer monumentLayer = new PdfLayer("Museums and Monuments",
                writer);
        monumentLayer.setOn(false);
        cultureLayer.addChild(monumentLayer);
        PdfLayer sportsLayer = new PdfLayer("Sports", writer);
        sportsLayer.setOn(false);
        cultureLayer.addChild(sportsLayer);
        // DRAW INFO
        BaseFont font = BaseFont.createFont(
                "c:/windows/fonts/webdings.ttf", BaseFont.WINANSI,
                BaseFont.EMBEDDED);
        cb.saveState();
        cb.beginText();
        cb.setRGBColorFill(0x00, 0x00, 0xFF);
        cb.setFontAndSize(font, 36);
        cb.beginLayer(cityInfoLayer);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x69), 2700, 3100, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x69), 3000, 2050, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x69), 3100, 2550, 0);
        cb.beginLayer(hotelLayer);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2000, 1900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2100, 1950, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2200, 2200, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2700, 3000, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2750, 3050, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2500, 3500, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2300, 2000, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 3250, 2200, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 3300, 2300, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 3400, 3050, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 3250, 3200, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2750, 3800, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2900, 3800, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 3000, 2400, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2000, 2800, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe3), 2600, 3200, 0);
        cb.endLayer(); // hotelLayer
        cb.beginLayer(parkingLayer);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe8), 2400, 2000, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe8), 2100, 2600, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe8), 3300, 2250, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe8), 3000, 3900, 0);
        cb.endLayer(); // parkingLayer
        cb.beginLayer(businessLayer);
        cb.setRGBColorFill(0xC0, 0xC0, 0xC0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3050, 3600, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3200, 3900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3150, 3700, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3260, 3610, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3350, 3750, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3500, 4000, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3500, 3800, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3450, 3700, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x46), 3450, 3600, 0);
        cb.endLayer(); // businessLayer
        cb.endLayer(); // cityInfoLayer
        cb.beginLayer(goingoutLayer);
        cb.beginLayer(restoLayer);
        cb.setRGBColorFill(0xFF, 0x14, 0x93);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2650, 3500, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2400, 1900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2750, 3850, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2700, 3200, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2900, 3100, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2850, 3000, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2800, 2900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 2300, 2900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 1950, 2650, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 1800, 2750, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 3350, 3150, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 3400, 3100, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xe4), 3250, 3450, 0);
        cb.endLayer(); // restoLayer
        cb.beginLayer(theatreLayer);
        cb.setRGBColorFill(0xDC, 0x14, 0x3C);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xae), 2850, 3300, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xae), 3050, 2900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xae), 2650, 2900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xae), 2750, 2600, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xB8), 2800, 3350, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xB8), 2550, 2850, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xB8), 2850, 3300, 0);
        cb.endLayer(); // theatreLayer
        cb.endLayer(); // goingoutLayer
        cb.beginLayer(monumentLayer);
        cb.setRGBColorFill(0x00, 0x00, 0x00);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x47), 3250, 2750, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x47), 2750, 2900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x47), 2850, 3500, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xad), 2150, 3550, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xad), 3300, 2730, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xad), 2200, 2000, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xad), 2900, 3300, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0xad), 2080, 3000, 0);
        cb.endLayer(); // monumentLayer
        cb.beginLayer(sportsLayer);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x53), 2700, 4050, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x53), 2700, 3900, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x53), 2800, 3980, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x53), 1950, 2800, 0);
        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, String
                .valueOf((char) 0x53), 3700, 2450, 0);
        cb.endLayer(); // sportsLayer
        cb.endText();
        cb.restoreState();
        // step 5
        document.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException 
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new SvgLayers().createPdf(RESULT);
    }
}
ObjectData.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfStructureElement;
import com.itextpdf.text.pdf.PdfStructureTreeRoot;
import com.itextpdf.text.pdf.PdfWriter;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Director;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;

public class ObjectData {

    /** The resulting PDF. */
    public static final String RESULT = "results/part4/chapter15/objectdata.pdf";
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
    /** SQL statement to get selected directors */
    public static final String SELECTDIRECTORS =
        "SELECT DISTINCT d.id, d.name, d.given_name, count(*) AS c "
        + "FROM film_director d, film_movie_director md "
        + "WHERE d.id = md.director_id AND d.id < 8 "
        + "GROUP BY d.id, d.name, d.given_name ORDER BY id";
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        writer.setTagged();
        writer.setUserProperties(true);
        // step 3
        document.open();
        // step 4

        PdfStructureTreeRoot root = writer.getStructureTreeRoot();
        root.mapRole(new PdfName("Directors"), PdfName.H);
        for (int i = 1; i < 8; i++) {
        	root.mapRole(new PdfName("director" + i), PdfName.P);
        }
        
        DatabaseConnection connection = new HsqldbConnection("filmfestival");

        PdfStructureTreeRoot tree = writer.getStructureTreeRoot();
        PdfStructureElement top = new PdfStructureElement(tree, new PdfName("Directors"));
        
        Map directors = new HashMap();
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(SELECTDIRECTORS);
        int id;
        Director director;
        PdfStructureElement e;
        while (rs.next()) {
            id = rs.getInt("id");
            director = PojoFactory.getDirector(rs);
            e = new PdfStructureElement(top, new PdfName("director" + id));
            PdfDictionary userproperties = new PdfDictionary();
            userproperties.put(PdfName.O, PdfName.USERPROPERTIES);
            PdfArray properties = new PdfArray();
            PdfDictionary property1 = new PdfDictionary();
            property1.put(PdfName.N, new PdfString("Name"));
            property1.put(PdfName.V, new PdfString(director.getName()));            
            properties.add(property1);
            PdfDictionary property2 = new PdfDictionary();
            property2.put(PdfName.N, new PdfString("Given name"));
            property2.put(PdfName.V, new PdfString(director.getGivenName()));            
            properties.add(property2);
            PdfDictionary property3 = new PdfDictionary();
            property3.put(PdfName.N, new PdfString("Posters"));
            property3.put(PdfName.V, new PdfNumber(rs.getInt("c")));            
            properties.add(property3);
            userproperties.put(PdfName.P, properties);
            e.put(PdfName.A, userproperties);
            directors.put(id, e);
        }
        
        Map map = new TreeMap();
        for (int i = 1; i < 8; i++) {
            List movies = PojoFactory.getMovies(connection, i);
            for (Movie movie : movies) {
                map.put(movie, i);
            }
        }
        
        PdfContentByte canvas = writer.getDirectContent();
        Image img;
        float x = 11.5f;
        float y = 769.7f;
        for (Map.Entry entry : map.entrySet()) {
            img = Image.getInstance(String.format(RESOURCE, entry.getKey().getImdb()));
            img.scaleToFit(1000, 60);
            img.setAbsolutePosition(x + (45 - img.getScaledWidth()) / 2, y);
            canvas.beginMarkedContentSequence(directors.get(entry.getValue()));
            canvas.addImage(img);
            canvas.endMarkedContentSequence();
            x += 48;
            if (x > 578) {
                x = 11.5f;
                y -= 84.2f;
            }
        }
        // step 5
        document.close();

    }


    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        new ObjectData().createPdf(RESULT);
    }
}
ReadOutLoud.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfStructureElement;
import com.itextpdf.text.pdf.PdfStructureTreeRoot;
import com.itextpdf.text.pdf.PdfWriter;

public class ReadOutLoud {

    /** The resulting PDF. */
    public static String RESULT = "results/part4/chapter15/read_out_loud.pdf";
    /** A resource that is used in the PDF document. */
    public static String RESOURCE = "resources/posters/0062622.jpg";

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        // step 1
    	Document document = new Document();
    	// step 2
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filename));
        writer.setTagged();
        // step 3
        document.open();
        // step 4
        PdfContentByte cb = writer.getDirectContent();
        BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
                BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
        BaseFont bf2 = BaseFont.createFont("c:/windows/fonts/msgothic.ttc,1",
                BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

        PdfStructureTreeRoot root = writer.getStructureTreeRoot();
        PdfStructureElement div = new PdfStructureElement(root, new PdfName("Div"));
        PdfDictionary dict;

        cb.beginMarkedContentSequence(div);

        cb.beginText();
        cb.moveText(36, 788);
        cb.setFontAndSize(bf, 12);
        cb.setLeading(18);
        cb.showText("These are some famous movies by Stanley Kubrick: ");
        dict = new PdfDictionary();
        dict.put(PdfName.E, new PdfString("Doctor"));
        cb.beginMarkedContentSequence(new PdfName("Span"), dict, true);
        cb.newlineShowText("Dr.");
        cb.endMarkedContentSequence();
        cb.showText(" Strangelove or: How I Learned to Stop Worrying and Love the Bomb.");
        dict = new PdfDictionary();
        dict.put(PdfName.E, new PdfString("Eyes Wide Shut."));
        cb.beginMarkedContentSequence(new PdfName("Span"), dict, true);
        cb.newlineShowText("EWS");
        cb.endMarkedContentSequence();
        cb.endText();
        dict = new PdfDictionary();
        dict.put(PdfName.LANG, new PdfString("en-us"));
        dict.put(new PdfName("Alt"), new PdfString("2001: A Space Odyssey."));
        cb.beginMarkedContentSequence(new PdfName("Span"), dict, true);
        Image img = Image.getInstance(RESOURCE);
        img.scaleToFit(1000, 100);
        img.setAbsolutePosition(36, 640);
        cb.addImage(img);
        cb.endMarkedContentSequence();

        cb.beginText();
        cb.moveText(36, 620);
        cb.setFontAndSize(bf, 12);
        cb.showText("This is a movie by Akira Kurosawa: ");
        dict = new PdfDictionary();
        dict.put(PdfName.ACTUALTEXT, new PdfString("Seven Samurai."));
        cb.beginMarkedContentSequence(new PdfName("Span"), dict, true);
        cb.setFontAndSize(bf2, 12);
        cb.showText("\u4e03\u4eba\u306e\u4f8d");
        cb.endMarkedContentSequence();
        cb.endText();
        
        cb.endMarkedContentSequence();
        // step 5
        document.close();
    }
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new ReadOutLoud().createPdf(RESULT);
    }
}
StructureParser.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfStructureElement;

public class StructureParser extends DefaultHandler {

    /** The top element in the PDF structure */
    protected PdfStructureElement top;
    /** The list of structure elements */
    protected List elements;

    /** Creates a parser that will parse an XML file into a structure tree. */
    public StructureParser(PdfStructureElement top, List elements) {
        this.top = top;
        this.elements = elements;
    }
    
    /**
     * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
     *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
     */
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if ("chapter".equals(qName)) return;
        elements.add(new PdfStructureElement(top, new PdfName(qName)));
    }
}
ContentParser.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.IOException;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfStructureElement;
import com.itextpdf.text.pdf.PdfWriter;

public class ContentParser extends DefaultHandler {

    /** The StringBuffer that holds the characters. */
    protected StringBuffer buf = new StringBuffer();

    /** The document to which content parsed form XML will be added. */
    protected Document document;
    /** The writer to which PDF syntax will be written. */
    protected PdfWriter writer;
    /** The canvas to which content will be written. */
    protected PdfContentByte canvas;
    /** A list with structure elements. */
    protected List elements;
    /** The current structure element during the parsing process. */
    protected PdfStructureElement current;
    /** The column to which content will be added. */
    protected ColumnText column;
    /** The font used when content elements are created. */
    protected Font font;
    
    /**
     * Creates a new ContentParser
     * @param document
     * @param writer
     * @param elements
     * @throws DocumentException
     * @throws IOException
     */
    public ContentParser(Document document, PdfWriter writer, List elements)
        throws DocumentException, IOException {
        this.document = document;
        this.writer = writer;
        canvas = writer.getDirectContent();
        column = new ColumnText(canvas);
        column.setSimpleColumn(36, 36, 384, 569);
        this.elements = elements;
        font = new Font(
            BaseFont.createFont("c:/windows/fonts/arial.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED), 12);
    }

    /**
     * @see org.xml.sax.ContentHandler#characters(char[], int, int)
     */
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        for (int i = start; i < start + length; i++) {
            if (ch[i] == '\n')
                buf.append(' ');
            else
                buf.append(ch[i]);
        }
    }

    /**
     * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
     *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
     */
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if ("chapter".equals(qName)) return;
        current = elements.get(0);
        elements.remove(0);
        canvas.beginMarkedContentSequence(current);
    }
    
    /**
     * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if ("chapter".equals(qName)) return;
        try {
            String s = buf.toString().trim();
            buf = new StringBuffer();
            if (s.length() > 0) {
                Paragraph p = new Paragraph(s, font);
                p.setAlignment(Element.ALIGN_JUSTIFIED);
                column.addElement(p);
                int status = column.go();
                while (ColumnText.hasMoreText(status)) {
                    canvas.endMarkedContentSequence();
                    document.newPage();
                    canvas.beginMarkedContentSequence(current);
                    column.setSimpleColumn(36, 36, 384, 569);
                    status = column.go();
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        canvas.endMarkedContentSequence();
    }
}
StructuredContent.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfStructureElement;
import com.itextpdf.text.pdf.PdfStructureTreeRoot;
import com.itextpdf.text.pdf.PdfWriter;

public class StructuredContent {

    /** The resulting PDF. */
    public static final String RESULT = "results/part4/chapter15/moby.pdf";
    /** An XML file that will be converted to PDF. */
    public static final String RESOURCE = "resources/xml/moby.xml";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SAXException, ParserConfigurationException {
        Document document = new Document(PageSize.A5);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setTagged();
        document.open();
        PdfStructureTreeRoot root = writer.getStructureTreeRoot();
        root.mapRole(new PdfName("chapter"), PdfName.SECT);
        root.mapRole(new PdfName("title"), PdfName.H);
        root.mapRole(new PdfName("para"), PdfName.P);
        PdfStructureElement top = new PdfStructureElement(root, new PdfName("chapter"));
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        List elements = new ArrayList();
        parser.parse(
            new InputSource(new FileInputStream(RESOURCE)),
            new StructureParser(top, elements));
        parser.parse(
            new InputSource(new FileInputStream(RESOURCE)),
            new ContentParser(document, writer, elements));
        document.close();
    }
}
ParseTaggedPdf.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.TaggedPdfReaderTool;

public class ParseTaggedPdf {

    /** The resulting XML file. */
    public static final String RESULT
        = "results/part4/chapter15/moby_extracted.xml";

    /**
     * Creates a PDF file using a previous example,
     * then parses the document.
     * @param    args    no arguments needed
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SAXException, ParserConfigurationException {
        StructuredContent.main(args);
        TaggedPdfReaderTool readertool = new TaggedPdfReaderTool();
        PdfReader reader = new PdfReader(StructuredContent.RESULT);
        readertool.convertToXml(reader, new FileOutputStream(RESULT));
        reader.close();
    }
}
ParsingHelloWorld.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import part1.chapter01.HelloWorld;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.io.RandomAccessSourceFactory;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PRTokeniser;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.RandomAccessFileOrArray;
import com.itextpdf.text.pdf.parser.ContentByteUtils;
import com.itextpdf.text.pdf.parser.PdfContentStreamProcessor;
import com.itextpdf.text.pdf.parser.RenderListener;

public class ParsingHelloWorld {

    /** The resulting PDF. */
    public static final String PDF = "results/part4/chapter15/hello_reverse.pdf";
    /** A possible resulting after parsing the PDF. */
    public static final String TEXT1 = "results/part4/chapter15/result1.txt";
    /** A possible resulting after parsing the PDF. */
    public static final String TEXT2 = "results/part4/chapter15/result2.txt";
    /** A possible resulting after parsing the PDF. */
    public static final String TEXT3 = "results/part4/chapter15/result3.txt";
    
    /**
     * Generates a PDF file with the text 'Hello World'
     * @throws DocumentException 
     * @throws IOException 
     */
    public void createPdf(String filename) throws DocumentException, IOException {
        // step 1
    	Document document = new Document();
        // step 2
    	PdfWriter writer
          = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
    	document.open();
    	// step 4
        // we add the text to the direct content, but not in the right order
        PdfContentByte cb = writer.getDirectContent();
        BaseFont bf = BaseFont.createFont();
        cb.beginText();
        cb.setFontAndSize(bf, 12);
        cb.moveText(88.66f, 367); 
        cb.showText("ld");
        cb.moveText(-22f, 0); 
        cb.showText("Wor");
        cb.moveText(-15.33f, 0); 
        cb.showText("llo");
        cb.moveText(-15.33f, 0); 
        cb.showText("He");
        cb.endText();
        // we also add text in a form XObject
        PdfTemplate tmp = cb.createTemplate(250, 25);
        tmp.beginText();
        tmp.setFontAndSize(bf, 12);
        tmp.moveText(0, 7);
        tmp.showText("Hello People");
        tmp.endText();
        cb.addTemplate(tmp, 36, 343);
        // step 5
        document.close();
    }
    
    /**
     * Parses the PDF using PRTokeniser
     * @param src  the path to the original PDF file
     * @param dest the path to the resulting text file
     * @throws IOException
     */
    public void parsePdf(String src, String dest) throws IOException {
        PdfReader reader = new PdfReader(src);
        // we can inspect the syntax of the imported page
        byte[] streamBytes = reader.getPageContent(1);
        PRTokeniser tokenizer = new PRTokeniser(new RandomAccessFileOrArray(new RandomAccessSourceFactory().createSource(streamBytes)));
        PrintWriter out = new PrintWriter(new FileOutputStream(dest));
        while (tokenizer.nextToken()) {
            if (tokenizer.getTokenType() == PRTokeniser.TokenType.STRING) {
                out.println(tokenizer.getStringValue());
            }
        }
        out.flush();
        out.close();
        reader.close();
    }
    
    /**
     * Extracts text from a PDF document.
     * @param src  the original PDF document
     * @param dest the resulting text file
     * @throws IOException
     */
    public void extractText(String src, String dest) throws IOException {
        PrintWriter out = new PrintWriter(new FileOutputStream(dest));
        PdfReader reader = new PdfReader(src);
        RenderListener listener = new MyTextRenderListener(out);
        PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
        PdfDictionary pageDic = reader.getPageN(1);
        PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
        processor.processContent(ContentByteUtils.getContentBytesForPage(reader, 1), resourcesDic);
        out.flush();
        out.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws DocumentException, IOException {
        ParsingHelloWorld example = new ParsingHelloWorld();
        HelloWorld.main(args);
        example.createPdf(PDF);
        example.parsePdf(HelloWorld.RESULT, TEXT1);
        example.parsePdf(PDF, TEXT2);
        example.extractText(PDF, TEXT3);
    }
}
MyTextRenderListener.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package part4.chapter15;

import java.io.PrintWriter;

import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;

public class MyTextRenderListener implements RenderListener {

	/** The print writer to which the information will be written. */
    protected PrintWriter out;

    /**
     * Creates a RenderListener that will look for text.
     */
    public MyTextRenderListener(PrintWriter out) {
        this.out = out;
    }
    
    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#beginTextBlock()
     */
    public void beginTextBlock() {
        out.print("<");
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#endTextBlock()
     */
    public void endTextBlock() {
        out.println(">");
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(
     *     com.itextpdf.text.pdf.parser.ImageRenderInfo)
     */
    public void renderImage(ImageRenderInfo renderInfo) {
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderText(
     *     com.itextpdf.text.pdf.parser.TextRenderInfo)
     */
    public void renderText(TextRenderInfo renderInfo) {
        out.print("<");
        out.print(renderInfo.getText());
        out.print(">");
    }
}
InspectPageContent.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import part1.chapter03.MovieTemplates;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.parser.PdfContentReaderTool;

public class InspectPageContent {

    /** Text file containing information about a PDF file. */
    public static final String RESULT = "results/part4/chapter15/calendar_info.txt";
    
    /**
     * Parses object and content information of a PDF into a text file.
     * @param pdf the original PDF
     * @param txt the resulting text
     * @throws IOException
     */
    public void inspectPdf(String pdf, String txt) throws IOException {
        PrintWriter out = new PrintWriter(new FileOutputStream(txt));
        PdfContentReaderTool.listContentStream(new File(pdf), out);
        out.flush();
        out.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new MovieTemplates().createPdf(MovieTemplates.RESULT);
        new InspectPageContent().inspectPdf(MovieTemplates.RESULT, RESULT);
    }
}
ExtractPageContent.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;

public class ExtractPageContent {

    /** The original PDF that will be parsed. */
    public static final String PREFACE = "resources/pdfs/preface.pdf";
    /** The resulting text file. */
    public static final String RESULT = "results/part4/chapter15/preface.txt";
    
    /**
     * Parses a PDF to a plain text file.
     * @param pdf the original PDF
     * @param txt the resulting text
     * @throws IOException
     */
    public void parsePdf(String pdf, String txt) throws IOException {
        PdfReader reader = new PdfReader(pdf);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        PrintWriter out = new PrintWriter(new FileOutputStream(txt));
        TextExtractionStrategy strategy;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            strategy = parser.processContent(i, new SimpleTextExtractionStrategy());
            out.println(strategy.getResultantText());
        }
        out.flush();
        out.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        new ExtractPageContent().parsePdf(PREFACE, RESULT);
    }
}
ExtractPageContentSorted1.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.LocationTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;

public class ExtractPageContentSorted1 {

    /** The original PDF that will be parsed. */
    public static final String PREFACE = "resources/pdfs/preface.pdf";
    /** The resulting text file. */
    public static final String RESULT = "results/part4/chapter15/preface_sorted1.txt";
    
    /**
     * Parses a PDF to a plain text file.
     * @param pdf the original PDF
     * @param txt the resulting text
     * @throws IOException
     */
    public void parsePdf(String pdf, String txt) throws IOException {
        PdfReader reader = new PdfReader(pdf);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        PrintWriter out = new PrintWriter(new FileOutputStream(txt));
        TextExtractionStrategy strategy;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            strategy = parser.processContent(i, new LocationTextExtractionStrategy());
            out.println(strategy.getResultantText());
        }
        out.flush();
        out.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        new ExtractPageContentSorted1().parsePdf(PREFACE, RESULT);
    }
}
ExtractPageContentSorted2.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;

public class ExtractPageContentSorted2 {

    /** The original PDF that will be parsed. */
    public static final String PREFACE = "resources/pdfs/preface.pdf";
    /** The resulting text file. */
    public static final String RESULT = "results/part4/chapter15/preface_sorted2.txt";
    
    /**
     * Parses a specific area of a PDF to a plain text file.
     * @param pdf the original PDF
     * @param txt the resulting text
     * @throws IOException
     */
    public void parsePdf(String pdf, String txt) throws IOException {
        PdfReader reader = new PdfReader(pdf);
        PrintWriter out = new PrintWriter(new FileOutputStream(txt));
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            out.println(PdfTextExtractor.getTextFromPage(reader, i));
        }
        out.flush();
        out.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new ExtractPageContentSorted2().parsePdf(PREFACE, RESULT);
    }
}
ExtractPageContentArea.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.FilteredTextRenderListener;
import com.itextpdf.text.pdf.parser.LocationTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.itextpdf.text.pdf.parser.RegionTextRenderFilter;
import com.itextpdf.text.pdf.parser.RenderFilter;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;

public class ExtractPageContentArea {

    /** The original PDF that will be parsed. */
    public static final String PREFACE = "resources/pdfs/preface.pdf";
    /** The resulting text file. */
    public static final String RESULT = "results/part4/chapter15/preface_clipped.txt";
    
    /**
     * Parses a specific area of a PDF to a plain text file.
     * @param pdf the original PDF
     * @param txt the resulting text
     * @throws IOException
     */
    public void parsePdf(String pdf, String txt) throws IOException {
        PdfReader reader = new PdfReader(pdf);
        PrintWriter out = new PrintWriter(new FileOutputStream(txt));
        Rectangle rect = new Rectangle(70, 80, 490, 580);
        RenderFilter filter = new RegionTextRenderFilter(rect);
        TextExtractionStrategy strategy;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), filter);
            out.println(PdfTextExtractor.getTextFromPage(reader, i, strategy));
        }
        out.flush();
        out.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new ExtractPageContentArea().parsePdf(PREFACE, RESULT);
    }
}
ShowTextMargins.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.TextMarginFinder;

public class ShowTextMargins {

    /** The original document. */
    public static final String PREFACE = "resources/pdfs/preface.pdf";
    /** The new document to which we've added a border rectangle. */
    public static final String RESULT = "results/part4/chapter15/margins.pdf";
    
    /**
     * Parses a PDF and ads a rectangle showing the text margin.
     * @param src the source PDF
     * @param dest the resulting PDF
     */
    public void addMarginRectangle(String src, String dest)
        throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT));
        TextMarginFinder finder;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            finder = parser.processContent(i, new TextMarginFinder());
            PdfContentByte cb = stamper.getOverContent(i);
            cb.rectangle(finder.getLlx(), finder.getLly(),
                finder.getWidth(), finder.getHeight());
            cb.stroke();
        }
        stamper.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new ShowTextMargins().addMarginRectangle(PREFACE, RESULT);
    }
}
MyImageRenderListener.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfImageObject;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;

public class MyImageRenderListener implements RenderListener {

    /** The new document to which we've added a border rectangle. */
    protected String path = "";

    /**
     * Creates a RenderListener that will look for images.
     */
    public MyImageRenderListener(String path) {
        this.path = path;
    }
    
    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#beginTextBlock()
     */
    public void beginTextBlock() {
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#endTextBlock()
     */
    public void endTextBlock() {
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(
     *     com.itextpdf.text.pdf.parser.ImageRenderInfo)
     */
    public void renderImage(ImageRenderInfo renderInfo) {
        try {
            String filename;
            FileOutputStream os;
            PdfImageObject image = renderInfo.getImage();
            if (image == null) return;
            filename = String.format(path, renderInfo.getRef().getNumber(), image.getFileType());
            os = new FileOutputStream(filename);
            os.write(image.getImageAsBytes());
            os.flush();
            os.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderText(
     *     com.itextpdf.text.pdf.parser.TextRenderInfo)
     */
    public void renderText(TextRenderInfo renderInfo) {
    }
}
ExtractImages.java
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part4.chapter15;

import java.io.IOException;

import part3.chapter10.ImageTypes;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;

/**
 * Extracts images from a PDF file.
 */
public class ExtractImages {

    /** The new document to which we've added a border rectangle. */
    public static final String RESULT = "results/part4/chapter15/Img%s.%s";
    
    /**
     * Parses a PDF and extracts all the images.
     * @param src the source PDF
     * @param dest the resulting PDF
     */
    public void extractImages(String filename)
        throws IOException, DocumentException {
        PdfReader reader = new PdfReader(filename);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        MyImageRenderListener listener = new MyImageRenderListener(RESULT);
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            parser.processContent(i, listener);
        }
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new ImageTypes().createPdf(ImageTypes.RESULT);
        new ExtractImages().extractImages(ImageTypes.RESULT);
    }
}
PeekABoo.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class PeekABoo : IWriter {
// ===========================================================================
    /** The first resulting PDF. */
    public const String RESULT1 = "peek-a-boo1.pdf";
    /** The second resulting PDF. */
    public const String RESULT2 = "peek-a-boo2.pdf";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        PeekABoo peekaboo = new PeekABoo();
        zip.AddEntry(RESULT1, peekaboo.CreatePdf(true));       
        zip.AddEntry(RESULT2, peekaboo.CreatePdf(false));       
        zip.Save(stream);             
      }
    }    
// ---------------------------------------------------------------------------    
    public byte[] CreatePdf(bool on) {
      using (MemoryStream ms = new MemoryStream()) {
        using (Document document = new Document()) {    
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          writer.ViewerPreferences = PdfWriter.PageModeUseOC;
          writer.PdfVersion = PdfWriter.VERSION_1_5;        
          // step 3
          document.Open();
          // step 4
          PdfLayer layer = new PdfLayer("Do you see me?", writer);
          layer.On = on;
          BaseFont bf = BaseFont.CreateFont();
          PdfContentByte cb = writer.DirectContent;
          cb.BeginText();
          cb.SetFontAndSize(bf, 18);
          cb.ShowTextAligned(Element.ALIGN_LEFT, "Do you see me?", 50, 790, 0);
          cb.BeginLayer(layer);
          cb.ShowTextAligned(Element.ALIGN_LEFT, "Peek-a-Boo!!!", 50, 766, 0);
          cb.EndLayer();
          cb.EndText();
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
OptionalContentActionExample.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class OptionalContentActionExample : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.PdfVersion = PdfWriter.VERSION_1_5;
        // step 3
        document.Open();
        // step 4
        PdfLayer a1 = new PdfLayer("answer 1", writer);
        PdfLayer a2 = new PdfLayer("answer 2", writer);
        PdfLayer a3 = new PdfLayer("answer 3", writer);
        a1.On = false;
        a2.On = false;
        a3.On = false;

        BaseFont bf = BaseFont.CreateFont();
        PdfContentByte cb = writer.DirectContent;
        cb.BeginText();
        cb.SetFontAndSize(bf, 18);
        cb.ShowTextAligned(Element.ALIGN_LEFT,
            "Q1: Who is the director of the movie 'Paths of Glory'?", 50, 766, 0);
        cb.ShowTextAligned(Element.ALIGN_LEFT,
            "Q2: Who directed the movie 'Lawrence of Arabia'?", 50, 718, 0);
        cb.ShowTextAligned(Element.ALIGN_LEFT,
            "Q3: Who is the director of 'House of Flying Daggers'?", 50, 670, 0);
        cb.EndText();
        cb.SaveState();
        cb.SetRGBColorFill(0xFF, 0x00, 0x00);
        cb.BeginText();
        cb.BeginLayer(a1);
        cb.ShowTextAligned(Element.ALIGN_LEFT,
                "A1: Stanley Kubrick", 50, 742, 0);
        cb.EndLayer();
        cb.BeginLayer(a2);
        cb.ShowTextAligned(Element.ALIGN_LEFT,
                "A2: David Lean", 50, 694, 0);
        cb.EndLayer();
        cb.BeginLayer(a3);
        cb.ShowTextAligned(Element.ALIGN_LEFT,
                "A3: Zhang Yimou", 50, 646, 0);
        cb.EndLayer();
        cb.EndText();
        cb.RestoreState();

        List stateOn = new List();
        stateOn.Add("ON");
        stateOn.Add(a1);
        stateOn.Add(a2);
        stateOn.Add(a3);
        PdfAction actionOn = PdfAction.SetOCGstate(stateOn, true);
        List stateOff = new List();
        stateOff.Add("OFF");
        stateOff.Add(a1);
        stateOff.Add(a2);
        stateOff.Add(a3);
        PdfAction actionOff = PdfAction.SetOCGstate(stateOff, true);
        List stateToggle = new List();
        stateToggle.Add("Toggle");
        stateToggle.Add(a1);
        stateToggle.Add(a2);
        stateToggle.Add(a3);
        PdfAction actionToggle = PdfAction.SetOCGstate(stateToggle, true);
        Phrase p = new Phrase("Change the state of the answers:");
        Chunk on = new Chunk(" on ").SetAction(actionOn);
        p.Add(on);
        Chunk off = new Chunk("/ off ").SetAction(actionOff);
        p.Add(off);
        Chunk toggle = new Chunk("/ toggle").SetAction(actionToggle);
        p.Add(toggle);
        document.Add(p);
      }
    }
// ===========================================================================
  }
}                                 
LayerMembershipExample1.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class LayerMembershipExample1 : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.PdfVersion = PdfWriter.VERSION_1_5;
        // step 3
        document.Open();
        // step 4
        PdfContentByte cb = writer.DirectContent;

        PdfLayer dog = new PdfLayer("layer 1", writer);
        PdfLayer tiger = new PdfLayer("layer 2", writer);
        PdfLayer lion = new PdfLayer("layer 3", writer);
        PdfLayerMembership cat = new PdfLayerMembership(writer);
        cat.AddMember(tiger);
        cat.AddMember(lion);
        PdfLayerMembership no_cat = new PdfLayerMembership(writer);
        no_cat.AddMember(tiger);
        no_cat.AddMember(lion);
        no_cat.VisibilityPolicy = PdfLayerMembership.ALLOFF;
        cb.BeginLayer(dog);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("dog"), 50, 775, 0
        );
        cb.EndLayer();
        cb.BeginLayer(tiger);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("tiger"), 50, 750, 0
        );
        cb.EndLayer();
        cb.BeginLayer(lion);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("lion"), 50, 725, 0
        );
        cb.EndLayer();
        cb.BeginLayer(cat);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("cat"), 50, 700, 0
        );
        cb.EndLayer();
        cb.BeginLayer(no_cat);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT,
          new Phrase("no cat"), 50, 700, 0
        );
        cb.EndLayer();
      }
    }
// ===========================================================================
  }
}
LayerMembershipExample2.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class LayerMembershipExample2 : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.PdfVersion = PdfWriter.VERSION_1_6;
        // step 3
        document.Open();
        // step 4
        PdfContentByte cb = writer.DirectContent;

        PdfLayer dog = new PdfLayer("layer 1", writer);
        PdfLayer tiger = new PdfLayer("layer 2", writer);
        PdfLayer lion = new PdfLayer("layer 3", writer);
        PdfLayerMembership cat = new PdfLayerMembership(writer);
        PdfVisibilityExpression ve1 = new PdfVisibilityExpression(
          PdfVisibilityExpression.OR
        );
        ve1.Add(tiger);
        ve1.Add(lion);
        cat.VisibilityExpression = ve1;
        PdfLayerMembership no_cat = new PdfLayerMembership(writer);
        PdfVisibilityExpression ve2 = new PdfVisibilityExpression(
          PdfVisibilityExpression.NOT
        );
        ve2.Add(ve1);
        no_cat.VisibilityExpression = ve2;
        cb.BeginLayer(dog);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase("dog"),
                50, 775, 0);
        cb.EndLayer();
        cb.BeginLayer(tiger);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase("tiger"),
                50, 750, 0);
        cb.EndLayer();
        cb.BeginLayer(lion);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase("lion"),
                50, 725, 0);
        cb.EndLayer();
        cb.BeginLayer(cat);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase("cat"),
                50, 700, 0);
        cb.EndLayer();
        cb.BeginLayer(no_cat);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT,
                new Phrase("no cat"), 50, 700, 0);
        cb.EndLayer();
      }
    }
// ===========================================================================
  }
}
OptionalContentExample.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class OptionalContentExample : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.PdfVersion = PdfWriter.VERSION_1_5;
        // step 3
        document.Open();
        // step 4
        PdfContentByte cb = writer.DirectContent;
        PdfLayer nested = new PdfLayer("Nested layers", writer);
        PdfLayer nested_1 = new PdfLayer("Nested layer 1", writer);
        PdfLayer nested_2 = new PdfLayer("Nested layer 2", writer);
        nested.AddChild(nested_1);
        nested.AddChild(nested_2);
        writer.LockLayer(nested_2);
        cb.BeginLayer(nested);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT,
          new Phrase("nested layers"), 50, 775, 0
        );
        cb.EndLayer();
        cb.BeginLayer(nested_1);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT,
          new Phrase("nested layer 1"), 100, 800, 0
        );
        cb.EndLayer();
        cb.BeginLayer(nested_2);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("nested layer 2"), 100, 750, 0
        );
        cb.EndLayer();

        PdfLayer group = PdfLayer.CreateTitle("Grouped layers", writer);
        PdfLayer layer1 = new PdfLayer("Group: layer 1", writer);
        PdfLayer layer2 = new PdfLayer("Group: layer 2", writer);
        group.AddChild(layer1);
        group.AddChild(layer2);
        cb.BeginLayer(layer1);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase( "layer 1 in the group"), 50, 700, 0
        );
        cb.EndLayer();
        cb.BeginLayer(layer2);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("layer 2 in the group"), 50, 675, 0
        );
        cb.EndLayer();

        PdfLayer radiogroup = PdfLayer.CreateTitle("Radio group", writer);
        PdfLayer radio1 = new PdfLayer("Radiogroup: layer 1", writer);
        radio1.On = true;
        PdfLayer radio2 = new PdfLayer("Radiogroup: layer 2", writer);
        radio2.On = false;
        PdfLayer radio3 = new PdfLayer("Radiogroup: layer 3", writer);
        radio3.On = false;
        radiogroup.AddChild(radio1);
        radiogroup.AddChild(radio2);
        radiogroup.AddChild(radio3);
        List options = new List();
        options.Add(radio1);
        options.Add(radio2);
        options.Add(radio3);
        writer.AddOCGRadioGroup(options);
        cb.BeginLayer(radio1);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("option 1"), 50, 600, 0
        );
        cb.EndLayer();
        cb.BeginLayer(radio2);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase("option 2"), 50, 575, 0
        );
        cb.EndLayer();
        cb.BeginLayer(radio3);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, 
          new Phrase(
                "option 3"
          ), 50, 550, 0
        );
        cb.EndLayer();

        PdfLayer not_printed = new PdfLayer("not printed", writer);
        not_printed.OnPanel = false;
        not_printed.SetPrint("Print", false);
        cb.BeginLayer(not_printed);
        ColumnText.ShowTextAligned(cb, Element.ALIGN_CENTER, 
          new Phrase(
                "PRINT THIS PAGE"
          ), 300, 700, 90
        );
        cb.EndLayer();

        PdfLayer zoom = new PdfLayer("Zoom 0.75-1.25", writer);
        zoom.OnPanel = false;
        zoom.SetZoom(0.75f, 1.25f);
        cb.BeginLayer(zoom);
        ColumnText.ShowTextAligned(
          cb, Element.ALIGN_LEFT, 
          new Phrase(
            "Only visible if the zoomfactor is between 75 and 125%"
          ), 30, 530, 90
        );
        cb.EndLayer();
      }
    }
// ===========================================================================
  }
}
SvgToPdf.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class SvgToPdf : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      throw new NotImplementedException(
        "Batik SVG toolkit is only implemented in Java"
      );
    }
// ===========================================================================
  }
}
SvgLayers.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class SvgLayers : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      throw new NotImplementedException(
        "Batik SVG toolkit is only implemented in Java"
      );
    }
// ===========================================================================
  }
}
ObjectData.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ObjectData : IWriter {
// ===========================================================================
    /** SQL statement to get selected directors */
    public const string SELECTDIRECTORS =
      @"SELECT DISTINCT d.id, d.name, d.given_name, count(*) AS c 
      FROM film_director d, film_movie_director md
      WHERE d.id = md.director_id AND d.id < 8
      GROUP BY d.id, d.name, d.given_name ORDER BY id";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.SetTagged();
        writer.UserProperties = true;        
        // step 3
        document.Open();
        // step 4
        PdfStructureTreeRoot tree = writer.StructureTreeRoot;
        PdfStructureElement top = new PdfStructureElement(
          tree, new PdfName("Directors")
        );
        
        Dictionary directors = 
          new Dictionary();

        int id;
        Director director;
        PdfStructureElement e;
        DbProviderFactory dbp = AdoDB.Provider;
        using (var c = dbp.CreateConnection()) {
          c.ConnectionString = AdoDB.CS;
          using (DbCommand cmd = c.CreateCommand()) {
            cmd.CommandText = SELECTDIRECTORS;
            c.Open();
            using (var r = cmd.ExecuteReader()) {
              while (r.Read()) {
                id = Convert.ToInt32(r["id"]);
                director = PojoFactory.GetDirector(r);
                e = new PdfStructureElement(top, new PdfName("director" + id));
                PdfDictionary userproperties = new PdfDictionary();
                userproperties.Put(PdfName.O, PdfName.USERPROPERTIES);
                PdfArray properties = new PdfArray();
                PdfDictionary property1 = new PdfDictionary();
                property1.Put(PdfName.N, new PdfString("Name"));
                property1.Put(PdfName.V, new PdfString(director.Name));            
                properties.Add(property1);
                PdfDictionary property2 = new PdfDictionary();
                property2.Put(PdfName.N, new PdfString("Given name"));
                property2.Put(PdfName.V, new PdfString(director.GivenName));            
                properties.Add(property2);
                PdfDictionary property3 = new PdfDictionary();
                property3.Put(PdfName.N, new PdfString("Posters"));
                property3.Put(PdfName.V, new PdfNumber(Convert.ToInt32(r["c"]))); 
                properties.Add(property3);
                userproperties.Put(PdfName.P, properties);
                e.Put(PdfName.A, userproperties);
                directors.Add(id, e);
              }
            }
          }
        }

        Dictionary map = new Dictionary();
        for (int i = 1; i < 8; i++) {
          foreach (Movie movie in PojoFactory.GetMovies(i)) {
            map.Add(movie, i);
          }
        }
        
        PdfContentByte canvas = writer.DirectContent;
        Image img;
        float x = 11.5f;
        float y = 769.7f;
        string RESOURCE = Utility.ResourcePosters;
        foreach (var entry in map.Keys) {
          img = Image.GetInstance(Path.Combine(RESOURCE, entry.Imdb + ".jpg"));
          img.ScaleToFit(1000, 60);
          img.SetAbsolutePosition(x + (45 - img.ScaledWidth) / 2, y);
          canvas.BeginMarkedContentSequence(directors[map[entry]]);
          canvas.AddImage(img);
          canvas.EndMarkedContentSequence();
          x += 48;
          if (x > 578) {
            x = 11.5f;
            y -= 84.2f;
          }
        }
      }
    }
// ===========================================================================
  }
}
ReadOutLoud.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ReadOutLoud : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.SetTagged();
        // step 3
        document.Open();
        // step 4
        PdfContentByte cb = writer.DirectContent;
        BaseFont bf = BaseFont.CreateFont(
          BaseFont.HELVETICA,
          BaseFont.CP1252, BaseFont.NOT_EMBEDDED
        );
        BaseFont bf2 = BaseFont.CreateFont(
          "c:/windows/fonts/msgothic.ttc,1",
          BaseFont.IDENTITY_H, BaseFont.EMBEDDED
        );

        PdfStructureTreeRoot root = writer.StructureTreeRoot;
        PdfStructureElement div = new PdfStructureElement(
          root, new PdfName("Div")
        );
        PdfDictionary dict;

        cb.BeginMarkedContentSequence(div);

        cb.BeginText();
        cb.MoveText(36, 788);
        cb.SetFontAndSize(bf, 12);
        cb.SetLeading(18);
        cb.ShowText("These are some famous movies by Stanley Kubrick: ");
        dict = new PdfDictionary();
        dict.Put(PdfName.E, new PdfString("Doctor"));
        cb.BeginMarkedContentSequence(new PdfName("Span"), dict, true);
        cb.NewlineShowText("Dr.");
        cb.EndMarkedContentSequence();
        cb.ShowText(
          " Strangelove or: How I Learned to Stop Worrying and Love the Bomb."
        );
        dict = new PdfDictionary();
        dict.Put(PdfName.E, new PdfString("Eyes Wide Shut."));
        cb.BeginMarkedContentSequence(new PdfName("Span"), dict, true);
        cb.NewlineShowText("EWS");
        cb.EndMarkedContentSequence();
        cb.EndText();
        dict = new PdfDictionary();
        dict.Put(PdfName.LANG, new PdfString("en-us"));
        dict.Put(new PdfName("Alt"), new PdfString("2001: A Space Odyssey."));
        cb.BeginMarkedContentSequence(new PdfName("Span"), dict, true);
        Image img = Image.GetInstance(Path.Combine(
          Utility.ResourcePosters, "0062622.jpg"
        ));
        img.ScaleToFit(1000, 100);
        img.SetAbsolutePosition(36, 640);
        cb.AddImage(img);
        cb.EndMarkedContentSequence();

        cb.BeginText();
        cb.MoveText(36, 620);
        cb.SetFontAndSize(bf, 12);
        cb.ShowText("This is a movie by Akira Kurosawa: ");
        dict = new PdfDictionary();
        dict.Put(PdfName.ACTUALTEXT, new PdfString("Seven Samurai."));
        cb.BeginMarkedContentSequence(new PdfName("Span"), dict, true);
        cb.SetFontAndSize(bf2, 12);
        cb.ShowText("\u4e03\u4eba\u306e\u4f8d");
        cb.EndMarkedContentSequence();
        cb.EndText();
        
        cb.EndMarkedContentSequence();

      }
    }
// ===========================================================================
  }
}
StructureParser.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;
/* 
 * Java book example uses SAX to parse XML. .NET uses XmlReader class instead of 
 * SAX, so this class is unnecessary.
 * couple of good explanations of the differences between Java and C#:
 * http://www.xml.com/pub/a/2002/03/06/csharpxml.html
 * http://msdn.microsoft.com/en-us/library/aa478996.aspx
*/
namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class StructureParser : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      throw new NotImplementedException(
        ".NET uses XmlReader class instead of SAX"
      );
    }
// ===========================================================================
  }
}
ContentParser.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;
/* 
 * Java book example uses SAX to parse XML. .NET uses XmlReader class instead of 
 * SAX, so this class is unnecessary.
 * couple of good explanations of the differences between Java and C#:
 * http://www.xml.com/pub/a/2002/03/06/csharpxml.html
 * http://msdn.microsoft.com/en-us/library/aa478996.aspx
*/
namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ContentParser : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      throw new NotImplementedException(
        ".NET uses XmlReader class instead of SAX"
      );
    }
// ===========================================================================
  }
}
StructuredContent.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Ionic.Zip;
using System.Xml;
using iTextSharp.text;
using iTextSharp.text.pdf;
/* 
 * Java book example uses SAX to parse XML. .NET uses XmlReader class instead of 
 * SAX; i.e. ContentParser & StructureParser classes from book not needed and 
 * are implemented in __THIS__ class
 * 
 * couple of good explanations of the differences between Java and C#:
 * http://www.xml.com/pub/a/2002/03/06/csharpxml.html
 * http://msdn.microsoft.com/en-us/library/aa478996.aspx
 * 
*/
namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class StructuredContent : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "moby.pdf";
    /** An XML file that will be converted to PDF. */
    public readonly String RESOURCE = Path.Combine(
      Utility.ResourceXml, "moby.xml"
    );
    /** The StringBuffer that holds the characters. */
    protected StringBuilder buf = new StringBuilder();

    /** The document to which content parsed form XML will be added. */
    protected Document document;
    /** The writer to which PDF syntax will be written. */
    protected PdfWriter writer;
    /** The canvas to which content will be written. */
    protected PdfContentByte canvas;

    /** The current structure element during the parsing process. */
    protected PdfStructureElement current;
    /** The column to which content will be added. */
    protected ColumnText column;
    /** The font used when content elements are created. */
    protected Font font;    
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(RESOURCE, ""); 
        StructuredContent s = new StructuredContent();      
        zip.AddEntry(RESULT, s.CreatePdf());       
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------    
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        using (document = new Document(PageSize.A5)) {
          // step 2
          writer = PdfWriter.GetInstance(document, ms);
          writer.SetTagged();
          // step 3
          document.Open();
          // step 4
          PdfStructureTreeRoot root = writer.StructureTreeRoot;
          root.MapRole(new PdfName("chapter"), PdfName.SECT);
          root.MapRole(new PdfName("title"), PdfName.H);
          root.MapRole(new PdfName("para"), PdfName.P);
          top = new PdfStructureElement(
            root, new PdfName("chapter")
          );
          
          canvas = writer.DirectContent;
          column = new ColumnText(canvas);
          column.SetSimpleColumn(36, 36, 384, 569);
          font = new Font( 
            BaseFont.CreateFont(
              "c:/windows/fonts/arial.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED
            ), 12
          );          
          
          using (XmlReader xr = XmlReader.Create(RESOURCE)) {
            xr.MoveToContent();
            while (xr.Read()) {
              switch (xr.NodeType) {
                case XmlNodeType.Element:
                  StartElement(xr.Name);
                  break;
                case XmlNodeType.Text:
                  buf.Append(Regex.Replace(xr.Value.Trim(), "\n", " "));
                  break;
                case XmlNodeType.EndElement:
                  EndElement(xr.Name);
                  break;
              }
            }
          }
        }
        return ms.ToArray();
      }
    }
    
    PdfStructureElement top;
// ---------------------------------------------------------------------------        
// replace [StructureParser|ContentParser].startElement() from Java example
    public void StartElement(string name) {
      switch (name) {
        case "chapter":
          break;
        default:
          current = new PdfStructureElement(top, new PdfName(name));
          canvas.BeginMarkedContentSequence(current);
          break;
      }
    }    
// ---------------------------------------------------------------------------        
// replace ContentParser.endElement() from Java example
    public void EndElement(string name) {   
      if ("chapter".Equals(name)) return;
      
      String s = buf.ToString().Trim();
      buf = new StringBuilder();
      if (s.Length > 0) {
        Paragraph p = new Paragraph(s, font);
        p.Alignment = Element.ALIGN_JUSTIFIED;
        column.AddElement(p);
        int status = column.Go();
        while (ColumnText.HasMoreText(status)) {
          canvas.EndMarkedContentSequence();
          document.NewPage();
          canvas.BeginMarkedContentSequence(current);
          column.SetSimpleColumn(36, 36, 384, 569);
          status = column.Go();
        }
      }
      canvas.EndMarkedContentSequence();    
    }
// ===========================================================================
  }
}
ParseTaggedPdf.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ParseTaggedPdf : IWriter {
// ===========================================================================
    /** The resulting XML file. */
    public const String RESULT = "moby_extracted.xml";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        StructuredContent s = new StructuredContent();
        byte[] pdf = s.CreatePdf();
        zip.AddEntry(Utility.ResultFileName(s.ToString() + ".pdf"), pdf); 
        TaggedPdfReaderTool reader = new TaggedPdfReaderTool();
        using (MemoryStream ms = new MemoryStream()) {
          reader.ConvertToXml(new PdfReader(pdf), ms);
          StringBuilder sb =  new StringBuilder();
          foreach (byte b in ms.ToArray()) {
            sb.Append((char) b);
          }
          zip.AddEntry(RESULT, sb.ToString());
        }
        zip.Save(stream);
      }
    }    
// ===========================================================================
	}
}
ParsingHelloWorld.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.io;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using kuujinbo.iTextInAction2Ed.Chapter01;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ParsingHelloWorld : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String PDF = "hello_reverse.pdf";
    /** A possible resulting after parsing the PDF. */
    public const String TEXT1 = "result1.txt";
    /** A possible resulting after parsing the PDF. */
    public const String TEXT2 = "result2.txt";
    /** A possible resulting after parsing the PDF. */
    public const String TEXT3 = "result3.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        ParsingHelloWorld example = new ParsingHelloWorld();
        byte[] ePdf = example.CreatePdf();
        zip.AddEntry(PDF, ePdf);
        HelloWorld hello = new HelloWorld();
        byte[] hPdf = Utility.PdfBytes(hello);
        zip.AddEntry(Utility.ResultFileName(hello.ToString() + ".pdf"), hPdf);       
        zip.AddEntry(TEXT1, example.ParsePdf(hPdf));
        zip.AddEntry(TEXT2, example.ParsePdf(ePdf));
        zip.AddEntry(TEXT3, example.ExtractText(ePdf));
        zip.Save(stream);             
      }
    }
// --------------------------------------------------------------------------- 
    /**
     * Generates a PDF file with the text 'Hello World'
     */    
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        using (Document document = new Document()) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          // we add the text to the direct content, but not in the right order
          PdfContentByte cb = writer.DirectContent;
          BaseFont bf = BaseFont.CreateFont();
          cb.BeginText();
          cb.SetFontAndSize(bf, 12);
          cb.MoveText(88.66f, 367); 
          cb.ShowText("ld");
          cb.MoveText(-22f, 0); 
          cb.ShowText("Wor");
          cb.MoveText(-15.33f, 0); 
          cb.ShowText("llo");
          cb.MoveText(-15.33f, 0); 
          cb.ShowText("He");
          cb.EndText();
          // we also add text in a form XObject
          PdfTemplate tmp = cb.CreateTemplate(250, 25);
          tmp.BeginText();
          tmp.SetFontAndSize(bf, 12);
          tmp.MoveText(0, 7);
          tmp.ShowText("Hello People");
          tmp.EndText();
          cb.AddTemplate(tmp, 36, 343);
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Parses the PDF using PRTokeniser
     * @param src the ]original PDF file
]     */
    public string ParsePdf(byte[] src) {
      PdfReader reader = new PdfReader(src);
      // we can inspect the syntax of the imported page
      byte[] streamBytes = reader.GetPageContent(1);
      StringBuilder sb = new StringBuilder();
      PRTokeniser tokenizer = new PRTokeniser(new RandomAccessFileOrArray(new RandomAccessSourceFactory().CreateSource(streamBytes)));
      while (tokenizer.NextToken()) {
        if (tokenizer.TokenType == PRTokeniser.TokType.STRING) {
          sb.AppendLine(tokenizer.StringValue);
        }
      }
      return sb.ToString();
    }
// ---------------------------------------------------------------------------    
    /**
     * Extracts text from a PDF document.
     * @param src the original PDF document
     */
    public string ExtractText(byte[] src) {
      PdfReader reader = new PdfReader(src);
      MyTextRenderListener listener = new MyTextRenderListener();
      PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
      PdfDictionary pageDic = reader.GetPageN(1);
      PdfDictionary resourcesDic = pageDic.GetAsDict(PdfName.RESOURCES);
      processor.ProcessContent(
        ContentByteUtils.GetContentBytesForPage(reader, 1), 
        resourcesDic
      );
      return listener.Text.ToString();
    }    
// ===========================================================================
  }
}
MyTextRenderListener.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class MyTextRenderListener : IRenderListener {
// ===========================================================================
    public StringBuilder Text { get; set; }
// ---------------------------------------------------------------------------
    /**
     * Creates a RenderListener that will look for text.
     */
    public MyTextRenderListener() {
      Text = new StringBuilder();
    }
    
    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#beginTextBlock()
     */
    public void BeginTextBlock() {
      Text.Append("<");
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#endTextBlock()
     */
    public void EndTextBlock() {
      Text.AppendLine(">");
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(
     *     com.itextpdf.text.pdf.parser.ImageRenderInfo)
     */
    public void RenderImage(ImageRenderInfo renderInfo) {
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderText(
     *     com.itextpdf.text.pdf.parser.TextRenderInfo)
     */
    public void RenderText(TextRenderInfo renderInfo) {
      Text.Append("<");
      Text.Append(renderInfo.GetText());
      Text.Append(">");
    }    
// ===========================================================================
	}
}
InspectPageContent.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using kuujinbo.iTextInAction2Ed.Chapter03;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class InspectPageContent : IWriter {
// ===========================================================================
    /** Text file containing information about a PDF file. */
    public const String RESULT = "calendar_info.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates();
        byte[] mPdf = Utility.PdfBytes(m);
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), mPdf);
        InspectPageContent i = new InspectPageContent();
        zip.AddEntry(RESULT, i.InspectPdf(mPdf));
        zip.Save(stream);             
      }
    }    
// --------------------------------------------------------------------------- 
    /**
     * Parses object and content information of a PDF into a text file.
     * @param pdf the original PDF
     * 
     * this method uses code from; 
     * PdfContentReaderTool.ListContentStreamForPage()
     * so i can pass in a byte array instead of file path
     * 
     */
    public string InspectPdf(byte[] pdf) {
      PdfReader reader = new PdfReader(pdf);
      int maxPageNum = reader.NumberOfPages;
      StringBuilder sb = new StringBuilder();
      for (int pageNum = 1; pageNum <= maxPageNum; pageNum++){
        sb.AppendLine("==============Page " + pageNum + "====================");
        sb.AppendLine("- - - - - Dictionary - - - - - -");
        PdfDictionary pageDictionary = reader.GetPageN(pageNum);
        sb.AppendLine(
          PdfContentReaderTool.GetDictionaryDetail(pageDictionary)
        );

        sb.AppendLine("- - - - - XObject Summary - - - - - -");
        sb.AppendLine(PdfContentReaderTool.GetXObjectDetail(
          pageDictionary.GetAsDict(PdfName.RESOURCES))
        );
        
        sb.AppendLine("- - - - - Content Stream - - - - - -");
        RandomAccessFileOrArray f = reader.SafeFile;

        byte[] contentBytes = reader.GetPageContent(pageNum, f);
        f.Close();

        foreach (byte b in contentBytes) {
          sb.Append((char)b);
        }
        
        sb.AppendLine("- - - - - Text Extraction - - - - - -");
        String extractedText = PdfTextExtractor.GetTextFromPage(
          reader, pageNum, new LocationTextExtractionStrategy()
        );
        if (extractedText.Length != 0) {
          sb.AppendLine(extractedText);
        }
        else {
          sb.AppendLine("No text found on page " + pageNum);
        }
        sb.AppendLine();      
      }   
      return sb.ToString();   
    }    
// ===========================================================================
	}
}
ExtractPageContent.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ExtractPageContent : IWriter {
// ===========================================================================
    /** The original PDF that will be parsed. */
    public readonly string PREFACE = Path.Combine(
      Utility.ResourcePdf, "preface.pdf"
    );    
    /** The resulting text file. */
    public const String RESULT = "preface.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(PREFACE, "");
        PdfReader reader = new PdfReader(PREFACE);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        StringBuilder sb = new StringBuilder();
        ITextExtractionStrategy strategy;
        for (int i = 1; i <= reader.NumberOfPages; i++) {
          strategy = parser.ProcessContent(i, new SimpleTextExtractionStrategy());
          sb.AppendLine(strategy.GetResultantText());
        }
        zip.AddEntry(RESULT, sb.ToString());
        zip.Save(stream);             
      }
    }
// ===========================================================================
  }
}
ExtractPageContentSorted1.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ExtractPageContentSorted1 : IWriter {
// ===========================================================================
    /** The original PDF that will be parsed. */
    public readonly string PREFACE = Path.Combine(
      Utility.ResourcePdf, "preface.pdf"
    );    
    /** The resulting text file. */
    public const String RESULT = "preface_sorted1.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(PREFACE, "");
        PdfReader reader = new PdfReader(PREFACE);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        StringBuilder sb = new StringBuilder();
        ITextExtractionStrategy strategy;
        for (int i = 1; i <= reader.NumberOfPages; i++) {
          strategy = parser.ProcessContent(i, new LocationTextExtractionStrategy());
          sb.AppendLine(strategy.GetResultantText());
        }
        zip.AddEntry(RESULT, sb.ToString());
        zip.Save(stream);             
      }
    }
// ===========================================================================
  }
}
ExtractPageContentSorted2.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ExtractPageContentSorted2 : IWriter {
// ===========================================================================
    /** The original PDF that will be parsed. */
    public readonly string PREFACE = Path.Combine(
      Utility.ResourcePdf, "preface.pdf"
    );    
    /** The resulting text file. */
    public const String RESULT = "preface_sorted2.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(PREFACE, "");
        PdfReader reader = new PdfReader(PREFACE);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= reader.NumberOfPages; i++) {
          sb.AppendLine(PdfTextExtractor.GetTextFromPage(reader, i));
        }
        zip.AddEntry(RESULT, sb.ToString());
        zip.Save(stream);             
      }
    }
// ===========================================================================
  }
}
ExtractPageContentArea.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ExtractPageContentArea : IWriter {
// ===========================================================================
    /** The original PDF that will be parsed. */
    public readonly string PREFACE = Path.Combine(
      Utility.ResourcePdf, "preface.pdf"
    );    
    /** The resulting text file. */
    public const String RESULT = "preface_clipped.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(PREFACE, "");
        PdfReader reader = new PdfReader(PREFACE);
        System.util.RectangleJ rect = new System.util.RectangleJ(
          70, 80, 420, 500
        );
        RenderFilter[] filter = {new RegionTextRenderFilter(rect)};
        ITextExtractionStrategy strategy;
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= reader.NumberOfPages; i++) {
          strategy = new FilteredTextRenderListener(
            new LocationTextExtractionStrategy(), filter
          );
          sb.AppendLine(
            PdfTextExtractor.GetTextFromPage(reader, i, strategy)
          );
        }        
        zip.AddEntry(RESULT, sb.ToString());
        zip.Save(stream);             
      }
    }
// ===========================================================================
  }
}
ShowTextMargins.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ShowTextMargins : IWriter {
// ===========================================================================
    /** The original PDF that will be parsed. */
    public readonly string PREFACE = Path.Combine(
      Utility.ResourcePdf, "preface.pdf"
    );    
    /** The resulting text file. */
    public const String RESULT = "margins.pdf";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(PREFACE, "");
        PdfReader reader = new PdfReader(PREFACE);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        using (MemoryStream ms = new MemoryStream()) {
          using (PdfStamper stamper = new PdfStamper(reader, ms)) {
            TextMarginFinder finder;
            for (int i = 1; i <= reader.NumberOfPages; i++) {
              finder = parser.ProcessContent(i, new TextMarginFinder());
              PdfContentByte cb = stamper.GetOverContent(i);
              cb.Rectangle(
                finder.GetLlx(), finder.GetLly(),
                finder.GetWidth(), finder.GetHeight()
              );
              cb.Stroke();
            }
          }
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.Save(stream);             
      }
    }
// ===========================================================================
  }
}
MyImageRenderListener.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class MyImageRenderListener : IRenderListener {
// ===========================================================================
    /** the byte array of the extracted images */
    private List _myImages;
    public List MyImages {
      get { return _myImages; }
    }
    /** the file names of the extracted images */
    private List _imageNames;
    public List ImageNames { 
      get { return _imageNames; }
    } 
// ---------------------------------------------------------------------------
    /**
     * Creates a RenderListener that will look for images.
     */
    public MyImageRenderListener() {
      _myImages = new List();
      _imageNames = new List();
    }
// ---------------------------------------------------------------------------
    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#beginTextBlock()
     */
    public void BeginTextBlock() { }
// ---------------------------------------------------------------------------     
    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#endTextBlock()
     */
    public void EndTextBlock() { }
// ---------------------------------------------------------------------------     
    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(
     *     com.itextpdf.text.pdf.parser.ImageRenderInfo)
     */
    public void RenderImage(ImageRenderInfo renderInfo) {
      try {
        PdfImageObject image = renderInfo.GetImage();
        if (image == null 
/*
 * do not attempt to parse => jbig2 decoder not fully implemented.
 * THE JAVA EXAMPLE INCORRECTLY CREATES A CORRUPT JBIG2 IMAGE
 * BECAUSE THERE IS NO EXPLICIT CHECK. I POSTED TWICE TO THE MAILING
 * LIST, SINCE VERSION 5.1.3 BUT THE ERROR HAS NOT BEEN CORRECTED.
 */
          || image.GetImageBytesType() == PdfImageObject.ImageBytesType.JBIG2
        ) 
        return;
        
        _imageNames.Add(string.Format(
          "Image{0}.{1}", 
          renderInfo.GetRef().Number, image.GetFileType()
        ) );
        _myImages.Add(image.GetImageAsBytes());
      }
      catch {
// pass through any other unsupported image types
      }
    }
 // ---------------------------------------------------------------------------     
   /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderText(
     *     com.itextpdf.text.pdf.parser.TextRenderInfo)
     */
    public void RenderText(TextRenderInfo renderInfo) { }
// ===========================================================================
  }
}
ExtractImages.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using kuujinbo.iTextInAction2Ed.Chapter10;

namespace kuujinbo.iTextInAction2Ed.Chapter15 {
  public class ExtractImages : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      ImageTypes it = new ImageTypes();
      using (ZipFile zip = new ZipFile()) {
        byte[] pdf = it.CreatePdf();
        zip.AddEntry(Utility.ResultFileName(it.ToString() + ".pdf"), pdf);
        PdfReader reader = new PdfReader(pdf);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        MyImageRenderListener listener = new MyImageRenderListener();
        for (int i = 1; i <= reader.NumberOfPages; i++) {
          parser.ProcessContent(i, listener);
        } 
        for (int i = 0; i < listener.MyImages.Count; ++i) {
          zip.AddEntry(
            listener.ImageNames[i],
            listener.MyImages[i]
          );
        }         
        zip.Save(stream);
      }
    }
// ===========================================================================
  }
}
Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now