Chapter 16: PDF streams

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

10th October 2015
admin-marketing

Switch code for this example

SpecialId.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.chapter16;

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.Rectangle;
import com.itextpdf.text.pdf.PdfImage;
import com.itextpdf.text.pdf.PdfIndirectObject;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfWriter;

public class SpecialId {

    /** The resulting PDF file. */
    public static String RESULT = "results/part4/chapter16/special_id.pdf";
    /** An image file. */
    public static String RESOURCE = "resources/img/bruno.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 {
        Document document = new Document(new Rectangle(400, 300));
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filename));
        document.open();
        Image img = Image.getInstance(RESOURCE);
        img.scaleAbsolute(400, 300);
        img.setAbsolutePosition(0, 0);
        PdfImage stream = new PdfImage(img, "", null);
        stream.put(new PdfName("ITXT_SpecialId"), new PdfName("123456789"));
        PdfIndirectObject ref = writer.addToBody(stream);
        img.setDirectReference(ref.getIndirectReference());
        document.add(img);
        document.close();
    }

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new SpecialId().createPdf(RESULT);
    }
}
ResizeImage.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.chapter16;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfImageObject;

public class ResizeImage {

	/** The resulting PDF file. */
    public static String RESULT = "results/part4/chapter16/resized_image.pdf";
    /** The multiplication factor for the image. */
    public static float FACTOR = 0.5f;
    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException 
     */
    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        PdfName key = new PdfName("ITXT_SpecialId");
        PdfName value = new PdfName("123456789");
        // Read the file
        PdfReader reader = new PdfReader(SpecialId.RESULT);
        int n = reader.getXrefSize();
        PdfObject object;
        PRStream stream;
        // Look for image and manipulate image stream
        for (int i = 0; i < n; i++) {
            object = reader.getPdfObject(i);
            if (object == null || !object.isStream())
                continue;
            stream = (PRStream)object;
            if (value.equals(stream.get(key))) {
                PdfImageObject image = new PdfImageObject(stream);
                BufferedImage bi = image.getBufferedImage();
                if (bi == null) continue;
                int width = (int)(bi.getWidth() * FACTOR);
                int height = (int)(bi.getHeight() * FACTOR);
                BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                AffineTransform at = AffineTransform.getScaleInstance(FACTOR, FACTOR);
                Graphics2D g = img.createGraphics();
                g.drawRenderedImage(bi, at);
                ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
                ImageIO.write(img, "JPG", imgBytes);
                stream.clear();
                stream.setData(imgBytes.toByteArray(), false, PRStream.NO_COMPRESSION);
                stream.put(PdfName.TYPE, PdfName.XOBJECT);
                stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
                stream.put(key, value);
                stream.put(PdfName.FILTER, PdfName.DCTDECODE);
                stream.put(PdfName.WIDTH, new PdfNumber(width));
                stream.put(PdfName.HEIGHT, new PdfNumber(height));
                stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
                stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
            }
        }
        // Save altered PDF
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT));
        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 SpecialId().createPdf(SpecialId.RESULT);
        new ResizeImage().manipulatePdf(SpecialId.RESULT, RESULT);
    }
}
ListUsedFonts.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.chapter16;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;
import java.util.TreeSet;

import part3.chapter11.FontTypes;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;

public class ListUsedFonts {

    /** The resulting PDF file. */
    public static String RESULT
        = "results/part4/chapter16/fonts.txt";

    /**
     * Creates a Set containing information about the fonts in the src PDF file.
     * @param src the path to a PDF file
     * @throws IOException
     */
    public Set listFonts(String src) throws IOException {
        Set set = new TreeSet();
        PdfReader reader = new PdfReader(src);
        PdfDictionary resources;
        for (int k = 1; k <= reader.getNumberOfPages(); ++k) {
            resources = reader.getPageN(k).getAsDict(PdfName.RESOURCES);
            processResource(set, resources);
        }
        reader.close();
        return set;
    }
    
    /**
     * Extracts the font names from page or XObject resources.
     * @param set the set with the font names
     * @param resources the resources dictionary
     */
    public static void processResource(Set set, PdfDictionary resource) {
        if (resource == null)
            return;
        PdfDictionary xobjects = resource.getAsDict(PdfName.XOBJECT);
        if (xobjects != null) {
            for (PdfName key : xobjects.getKeys()) {
                processResource(set, xobjects.getAsDict(key));
            }
        }
        PdfDictionary fonts = resource.getAsDict(PdfName.FONT);
        if (fonts == null)
            return;
        PdfDictionary font;
        for (PdfName key : fonts.getKeys()) {
            font = fonts.getAsDict(key);
            String name = font.getAsName(PdfName.BASEFONT).toString();
            if (name.length() > 8 && name.charAt(7) == '+') {
                name = String.format("%s subset (%s)", name.substring(8), name.substring(1, 7));
            }
            else {
                name = name.substring(1);
                PdfDictionary desc = font.getAsDict(PdfName.FONTDESCRIPTOR);
                if (desc == null)
                    name += " nofontdescriptor";
                else if (desc.get(PdfName.FONTFILE) != null)
                    name += " (Type 1) embedded";
                else if (desc.get(PdfName.FONTFILE2) != null)
                    name += " (TrueType) embedded";
                else if (desc.get(PdfName.FONTFILE3) != null)
                    name += " (" + font.getAsName(PdfName.SUBTYPE).toString().substring(1) + ") embedded";
            }
            set.add(name);
        }
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new FontTypes().createPdf(FontTypes.RESULT);
        Set set = new ListUsedFonts().listFonts(FontTypes.RESULT);
        PrintWriter out = new PrintWriter(new FileOutputStream(RESULT));
        for (String fontname : set)
            out.println(fontname);
        out.flush();
        out.close();
    }
}
EmbedFontPostFacto.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.chapter16;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfIndirectObject;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfStream;
import com.itextpdf.text.pdf.PdfWriter;

public class EmbedFontPostFacto {

    /** The first resulting PDF file. */
    public static String RESULT1 = "results/part4/chapter16/without_font.pdf";
    /** The second resulting PDF file. */
    public static String RESULT2 = "results/part4/chapter16/with_font.pdf";
    /** A special font. */
    public static String FONT = "resources/fonts/wds011402.ttf";
    /** The name of the special font. */
    public static String FONTNAME = "WaltDisneyScriptv4.1";

    /**
     * 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.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4:
        Font font = new Font(BaseFont.createFont(FONT, "", BaseFont.NOT_EMBEDDED), 60);
        document.add(new Paragraph("iText in Action", font));
        // step 5
        document.close();
    }
    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException 
     */
    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        // the font file
        RandomAccessFile raf = new RandomAccessFile(FONT, "r");
        byte fontfile[] = new byte[(int)raf.length()];
        raf.readFully(fontfile);
        raf.close();
        // create a new stream for the font file
        PdfStream stream = new PdfStream(fontfile);
        stream.flateCompress();
        stream.put(PdfName.LENGTH1, new PdfNumber(fontfile.length));
        // create a reader object
        PdfReader reader = new PdfReader(src);
        int n = reader.getXrefSize();
        PdfObject object;
        PdfDictionary font;
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        PdfName fontname = new PdfName(FONTNAME);
        for (int i = 0; i < n; i++) {
            object = reader.getPdfObject(i);
            if (object == null || !object.isDictionary())
                continue;
            font = (PdfDictionary)object;
            if (PdfName.FONTDESCRIPTOR.equals(font.get(PdfName.TYPE))
                && fontname.equals(font.get(PdfName.FONTNAME))) {
                PdfIndirectObject objref = stamper.getWriter().addToBody(stream);
                font.put(PdfName.FONTFILE2, objref.getIndirectReference());
            }
        }
        stamper.close();
        reader.close();
    }

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        EmbedFontPostFacto example = new EmbedFontPostFacto();
        example.createPdf(RESULT1);
        example.manipulatePdf(RESULT1, RESULT2);
    }
}
KubrickDvds.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.chapter16;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Set;
import java.util.TreeSet;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;

/**
 * Creates a PDF listing Stanley Kubrick movies and the corresponding posters.
 * JPGs of the movie posters are added as file attachment annotations.
 * The attachments can be extracted.
 */
public class KubrickDvds {
    
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
    /** The filename of the resulting PDF. */
    public static final String FILENAME = "kubrick_dvds.pdf";
    /** The path to the resulting PDFs */
    public static final String PATH = "results/part4/chapter16/%s";
    /** The filename of the PDF with the movies by Stanley Kubrick. */
    public static final String RESULT = String.format(PATH, FILENAME);
    
    /**
     * Creates a PDF listing Stanley Kubrick movies in my DVD Collection. 
     * @throws IOException 
     * @throws DocumentException 
     * @throws SQLException
     */
    public static void main(String[] args) throws IOException, DocumentException, SQLException {
        KubrickDvds kubrick = new KubrickDvds();
        FileOutputStream os = new FileOutputStream(RESULT);
        os.write(kubrick.createPdf());
        os.flush();
        os.close();
        kubrick.extractAttachments(RESULT);
    }
    
    /**
     * Extracts attachments from an existing PDF.
     * @param src   the path to the existing PDF
     * @param dest  where to put the extracted attachments
     * @throws IOException
     */
    public void extractAttachments(String src) throws IOException {
        PdfReader reader = new PdfReader(src);
        PdfArray array;
        PdfDictionary annot;
        PdfDictionary fs;
        PdfDictionary refs;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            array = reader.getPageN(i).getAsArray(PdfName.ANNOTS);
            if (array == null) continue;
            for (int j = 0; j < array.size(); j++) {
                annot = array.getAsDict(j);
                if (PdfName.FILEATTACHMENT.equals(annot.getAsName(PdfName.SUBTYPE))) {
                    fs = annot.getAsDict(PdfName.FS);
                    refs = fs.getAsDict(PdfName.EF);
                    for (PdfName name : refs.getKeys()) {
                        FileOutputStream fos
                            = new FileOutputStream(String.format(PATH, fs.getAsString(name).toString()));
                        fos.write(PdfReader.getStreamBytes((PRStream)refs.getAsStream(name)));
                        fos.flush();
                        fos.close();
                    }
                }
            }
        }
        reader.close();
    }

    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     * @throws DocumentExcetpion
     * @throws IOException
     * @throws SQLException 
     */
    public byte[] createPdf() throws DocumentException, IOException, SQLException {
        // step 1
        Document document = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph("This is a list of Kubrick movies available in DVD stores."));
        PdfAnnotation annot;
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Set movies = new TreeSet();
        movies.addAll(PojoFactory.getMovies(connection, 1));
        movies.addAll(PojoFactory.getMovies(connection, 4));
        ListItem item;
        Chunk chunk;
        List list = new List();
        for (Movie movie : movies) {
            annot = PdfAnnotation.createFileAttachment(
                    writer, null, movie.getMovieTitle(false), null,
                    String.format(RESOURCE, movie.getImdb()), String.format("%s.jpg", movie.getImdb()));
            item = new ListItem(movie.getMovieTitle(false));
            item.add("\u00a0\u00a0");
            chunk = new Chunk("\u00a0\u00a0\u00a0\u00a0");
            chunk.setAnnotation(annot);
            item.add(chunk);
            list.add(item);
        }
        document.add(list);
        // step 5
        document.close();
        connection.close();
        return baos.toByteArray();
    }
}
KubrickDocumentary.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.chapter16;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.xml.XMLUtil;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;

public class KubrickDocumentary {
    /** The filename of the PDF. */
    public static final String FILENAME = "kubrick_documentary.pdf";
    /** The path to the resulting PDFs */
    public static final String PATH = "results/part4/chapter16/%s";
    /** The filename of the PDF with the movies by Stanley Kubrick. */
    public static final String RESULT = String.format(PATH, FILENAME);
    
    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     * @throws DocumentExcetpion
     * @throws IOException
     * @throws SQLException 
     */
    public byte[] createPdf() throws DocumentException, IOException, SQLException {
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        java.util.List movies = PojoFactory.getMovies(connection, 1);
        connection.close();
        // step 1
        Document document = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph(
            "'Stanley Kubrick: A Life in Pictures' is a documentary about Stanley Kubrick and his films:"));

        ByteArrayOutputStream txt = new ByteArrayOutputStream();
        PrintStream out = new PrintStream(txt);
        out.println("");
        List list = new List(List.UNORDERED, 20);
        ListItem item;
        for (Movie movie : movies) {
            out.println("");
            out.println(
                String.format("%s", XMLUtil.escapeXML(movie.getMovieTitle(), true)));
            out.println(String.format("%s", movie.getYear()));
            out.println(String.format("%s", movie.getDuration()));
            out.println("");
            item = new ListItem(movie.getMovieTitle());
            list.add(item);
        }
        document.add(list);
        out.print("");
        out.flush();
        out.close();
        PdfFileSpecification fs
          = PdfFileSpecification.fileEmbedded(writer,
                  null, "kubrick.xml", txt.toByteArray());
        writer.addFileAttachment(fs);
        // step 5
        document.close();
        return baos.toByteArray();
    }
    
    /**
     * Extracts document level attachments
     * @param filename     a file from which document level attachments will be extracted
     * @throws IOException
     */
    public void extractDocLevelAttachments(String filename) throws IOException {
        PdfReader reader = new PdfReader(filename);
        PdfDictionary root = reader.getCatalog();
        PdfDictionary documentnames = root.getAsDict(PdfName.NAMES);
        PdfDictionary embeddedfiles = documentnames.getAsDict(PdfName.EMBEDDEDFILES);
        PdfArray filespecs = embeddedfiles.getAsArray(PdfName.NAMES);
        PdfDictionary filespec;
        PdfDictionary refs;
        FileOutputStream fos;
        PRStream stream;
        for (int i = 0; i < filespecs.size(); ) {
          filespecs.getAsString(i++);
          filespec = filespecs.getAsDict(i++);
          refs = filespec.getAsDict(PdfName.EF);
          for (PdfName key : refs.getKeys()) {
            fos = new FileOutputStream(String.format(PATH, filespec.getAsString(key).toString()));
            stream = (PRStream) PdfReader.getPdfObject(refs.getAsIndirectObject(key));
            fos.write(PdfReader.getStreamBytes(stream));
            fos.flush();
            fos.close();
          }
        }
        reader.close();
    }

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args) throws IOException, DocumentException, SQLException {
        KubrickDocumentary kubrick = new KubrickDocumentary();
        FileOutputStream os = new FileOutputStream(RESULT);
        os.write(kubrick.createPdf());
        os.flush();
        os.close();
        kubrick.extractDocLevelAttachments(RESULT);
    }
}
KubrickBox.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.chapter16;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Set;
import java.util.TreeSet;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.collection.PdfTargetDictionary;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;

/**
 * This example explains the use of portable collections,
 * a new feature introduced in PDF 1.7
 */
public class KubrickBox {

    /** The resulting PDF. */
    public static final String RESULT = "results/part4/chapter16/kubrick_box.pdf";
    /** The path to an image used in the example. */
    public static final String IMG_BOX = "resources/img/kubrick_box.jpg";
    /** Path to the resources. */
    public static final String RESOURCE = "resources/posters/%s.jpg";
    /** The relative widths of the PdfPTable columns. */
    public static final float[] WIDTHS = { 1 , 7 };

    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     * @throws DocumentException
     * @throws IOException
     * @throws SQLException 
     */
    public void createPdf(String filename) throws DocumentException, IOException, SQLException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        Image img = Image.getInstance(IMG_BOX);
        document.add(img);
        List list = new List(List.UNORDERED, 20);
        PdfDestination dest = new PdfDestination(PdfDestination.FIT);
        dest.addFirst(new PdfNumber(1));
        PdfTargetDictionary target;
        Chunk chunk;
        ListItem item;
        PdfAction action = null;
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Set box = new TreeSet();
        box.addAll(PojoFactory.getMovies(connection, 1));
        box.addAll(PojoFactory.getMovies(connection, 4));
        connection.close();
        PdfFileSpecification fs;
        for (Movie movie : box) {
            if (movie.getYear() > 1960) {
                fs = PdfFileSpecification.fileEmbedded(writer, null,
                        String.format("kubrick_%s.pdf", movie.getImdb()),
                        createMoviePage(movie));
                fs.addDescription(movie.getTitle(), false);
                writer.addFileAttachment(fs);
                item = new ListItem(movie.getMovieTitle());
                target = new PdfTargetDictionary(true);
                target.setEmbeddedFileName(movie.getTitle());
                action = PdfAction.gotoEmbedded(null, target, dest, true);
                chunk = new Chunk(" (see info)");
                chunk.setAction(action);
                item.add(chunk);
                list.add(item);
            }
        }
        document.add(list);
        // step 5
        document.close();
    }

    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     * @throws DocumentExcetpion
     * @throws IOException
     * @throws SQLException 
     */
    public byte[] createMoviePage(Movie movie) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        Paragraph p = new Paragraph(movie.getMovieTitle(),
                FontFactory.getFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED, 16));
        document.add(p);
        document.add(Chunk.NEWLINE);
        PdfPTable table = new PdfPTable(WIDTHS);
        table.addCell(Image.getInstance(String.format(RESOURCE, movie.getImdb())));
        PdfPCell cell = new PdfPCell();
        cell.addElement(new Paragraph("Year: " + movie.getYear()));
        cell.addElement(new Paragraph("Duration: " + movie.getDuration()));
        table.addCell(cell);
        document.add(table);
        PdfDestination dest = new PdfDestination(PdfDestination.FIT);
        dest.addFirst(new PdfNumber(1));
        PdfTargetDictionary target = new PdfTargetDictionary(false);
        Chunk chunk = new Chunk("Go to original document");
        PdfAction action = PdfAction.gotoEmbedded(null, target, dest, false);
        chunk.setAction(action);
        document.add(chunk);
        // step 5
        document.close();
        return baos.toByteArray();
    }

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args) throws DocumentException, IOException, SQLException {
        new KubrickBox().createPdf(RESULT);
    }
}
KubrickMovies.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.chapter16;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.collection.PdfCollection;
import com.itextpdf.text.pdf.collection.PdfCollectionField;
import com.itextpdf.text.pdf.collection.PdfCollectionItem;
import com.itextpdf.text.pdf.collection.PdfCollectionSchema;
import com.itextpdf.text.pdf.collection.PdfCollectionSort;
import com.itextpdf.text.pdf.collection.PdfTargetDictionary;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;

public class KubrickMovies {

    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
    /** The relative widths of the PdfPTable columns. */
    public static final float[] WIDTHS = { 1 , 7 };
    
    /** The filename of the PDF. */
    public static final String FILENAME = "kubrick_movies.pdf";
    /** The filename of the PDF with the movies by Stanley Kubrick. */
    public static final String RESULT = "results/part4/chapter16/" + FILENAME;
    
    /**
     * Creates a Collection schema that can be used to organize the movies of Stanley Kubrick
     * in a collection: year, title, duration, DVD acquisition, filesize (filename is present, but hidden).
     * @return    a collection schema
     */
    private static PdfCollectionSchema getCollectionSchema() {
        PdfCollectionSchema schema = new PdfCollectionSchema();
        
        PdfCollectionField size = new PdfCollectionField("File size", PdfCollectionField.SIZE);
        size.setOrder(4);
        schema.addField("SIZE", size);
        
        PdfCollectionField filename = new PdfCollectionField("File name", PdfCollectionField.FILENAME);
        filename.setVisible(false);
        schema.addField("FILE", filename);
        
        PdfCollectionField title = new PdfCollectionField("Movie title", PdfCollectionField.TEXT);
        title.setOrder(1);
        schema.addField("TITLE", title);
        
        PdfCollectionField duration = new PdfCollectionField("Duration", PdfCollectionField.NUMBER);
        duration.setOrder(2);
        schema.addField("DURATION", duration);
        
        PdfCollectionField year = new PdfCollectionField("Year", PdfCollectionField.NUMBER);
        year.setOrder(0);
        schema.addField("YEAR", year);
        
        return schema;
    }

    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     * @throws SQLException 
     */
    public byte[] createPdf() throws DocumentException, IOException, SQLException {
        // step 1
        Document document = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        document.add(new Paragraph(
            "This document contains a collection of PDFs, one per Stanley Kubrick movie."));
        
        PdfCollection collection = new PdfCollection(PdfCollection.DETAILS);
        PdfCollectionSchema schema = getCollectionSchema(); 
        collection.setSchema(schema);
        PdfCollectionSort sort = new PdfCollectionSort("YEAR");
        sort.setSortOrder(false);
        collection.setSort(sort);
        collection.setInitialDocument("Eyes Wide Shut");
        writer.setCollection(collection);
        
        PdfFileSpecification fs;
        PdfCollectionItem item;
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        java.util.List movies = PojoFactory.getMovies(connection, 1);
        connection.close();
        for (Movie movie : movies) {
            fs = PdfFileSpecification.fileEmbedded(writer, null,
                String.format("kubrick_%s.pdf", movie.getImdb()),
                createMoviePage(movie));
            fs.addDescription(movie.getTitle(), false);

            item = new PdfCollectionItem(schema);
            item.addItem("TITLE", movie.getMovieTitle(false));
            if (movie.getMovieTitle(true) != null) {
                item.setPrefix("TITLE", movie.getMovieTitle(true));
            }
            item.addItem("DURATION", movie.getDuration());
            item.addItem("YEAR", movie.getYear());
            fs.addCollectionItem(item);
            writer.addFileAttachment(fs);
        }
        // step 5
        document.close();
        return baos.toByteArray();
    }

    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     */
    public byte[] createMoviePage(Movie movie) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        Paragraph p = new Paragraph(movie.getMovieTitle(),
            FontFactory.getFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED, 16));
        document.add(p);
        document.add(Chunk.NEWLINE);
        PdfPTable table = new PdfPTable(WIDTHS);
        table.addCell(Image.getInstance(String.format(RESOURCE, movie.getImdb())));
        PdfPCell cell = new PdfPCell();
        cell.addElement(new Paragraph("Year: " + movie.getYear()));
        cell.addElement(new Paragraph("Duration: " + movie.getDuration()));
        table.addCell(cell);
        document.add(table);
        PdfTargetDictionary target = new PdfTargetDictionary(false);
        target.setAdditionalPath(new PdfTargetDictionary(false));
        Chunk chunk = new Chunk("Go to original document");
        PdfAction action = PdfAction.gotoEmbedded(null, target, new PdfString("movies"), false);
        chunk.setAction(action);
        document.add(chunk);
        // step 5
        document.close();
        return baos.toByteArray();
    }

    public static void main(String[] args) throws IOException, DocumentException, SQLException {
        KubrickMovies kubrick = new KubrickMovies();
        FileOutputStream os = new FileOutputStream(RESULT);
        os.write(kubrick.createPdf());
        os.flush();
        os.close();
    }
}
KubrickCollection.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.chapter16;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import java.util.Set;
import java.util.TreeSet;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.collection.PdfCollection;
import com.itextpdf.text.pdf.collection.PdfCollectionField;
import com.itextpdf.text.pdf.collection.PdfCollectionItem;
import com.itextpdf.text.pdf.collection.PdfCollectionSchema;
import com.itextpdf.text.pdf.collection.PdfCollectionSort;
import com.itextpdf.text.pdf.collection.PdfTargetDictionary;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;

/**
 * This example explains the use of portable collections,
 * a new feature introduced in PDF 1.7
 */
public class KubrickCollection {

    /** An image file used in this example */
    public static final String IMG_BOX = "resources/img/kubrick_box.jpg";
    /** An image file used in this example */
    public static final String IMG_KUBRICK = "resources/img/kubrick.jpg";
    /** The resulting PDF file. */
    public static final String RESULT = "results/part4/chapter16/kubrick_collection.pdf";
    /** The name of a field in the collection schema. */
    public static final String TYPE_FIELD        = "TYPE";
    /** A caption of a field in the collection schema. */
    public static final String TYPE_CAPTION        = "File type";
    /** The name of a field in the collection schema. */
    public static final String FILE_FIELD        = "FILE";
    /** A caption of a field in the collection schema. */
    public static final String FILE_CAPTION        = "File name";
    /** Sort order for the keys in the collection. */
    public String[] KEYS = { TYPE_FIELD, FILE_FIELD };
    
    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     * @throws SQLException 
     */
    public void createPdf(String filename) throws DocumentException, IOException, SQLException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfCollection collection = new PdfCollection(PdfCollection.HIDDEN);
        PdfCollectionSchema schema = getCollectionSchema();
        collection.setSchema(schema);
        PdfCollectionSort sort = new PdfCollectionSort(KEYS);
        collection.setSort(sort);
        writer.setCollection(collection);

        PdfCollectionItem collectionitem = new PdfCollectionItem(schema);
        PdfFileSpecification fs;
        fs = PdfFileSpecification.fileEmbedded(writer, IMG_KUBRICK, "kubrick.jpg", null);
        fs.addDescription("Stanley Kubrick", false);
        collectionitem.addItem(TYPE_FIELD, "JPEG");
        fs.addCollectionItem(collectionitem);
        writer.addFileAttachment(fs);
        
        ByteArrayOutputStream txt = new ByteArrayOutputStream();
        PrintStream out = new PrintStream(txt);
        Image img = Image.getInstance(IMG_BOX);
        document.add(img);
        List list = new List(List.UNORDERED, 20);
        PdfDestination dest = new PdfDestination(PdfDestination.FIT);
        dest.addFirst(new PdfNumber(1));
        PdfTargetDictionary intermediate;
        PdfTargetDictionary target;
        Chunk chunk;
        ListItem item;
        PdfAction action = null;
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Set box = new TreeSet();
        java.util.List movies = PojoFactory.getMovies(connection, 1);
        box.addAll(movies);
        box.addAll(PojoFactory.getMovies(connection, 4));
        connection.close();
        for (Movie movie : box) {
            if (movie.getYear() > 1960) {
                out.println(String.format(
                    "%s;%s;%s", movie.getMovieTitle(), movie.getYear(), movie.getDuration()));
                item = new ListItem(movie.getMovieTitle());
                if (!"0278736".equals(movie.getImdb())) {
                    target = new PdfTargetDictionary(true);
                    target.setEmbeddedFileName(movie.getTitle());
                    intermediate = new PdfTargetDictionary(true);
                    intermediate.setFileAttachmentPage(1);
                    intermediate.setFileAttachmentIndex(1);
                    intermediate.setAdditionalPath(target);
                    action = PdfAction.gotoEmbedded(null, intermediate, dest, true);
                    chunk = new Chunk(" (see info)");
                    chunk.setAction(action);
                    item.add(chunk);
                }
                list.add(item);
            }
        }
        out.flush();
        out.close();
        document.add(list);
        fs = PdfFileSpecification.fileEmbedded(writer, null, "kubrick.txt", txt.toByteArray());
        fs.addDescription("Kubrick box: the movies", false);
        collectionitem.addItem(TYPE_FIELD, "TXT");
        fs.addCollectionItem(collectionitem);
        writer.addFileAttachment(fs);

        PdfPTable table = new PdfPTable(1);
        table.setSpacingAfter(10);
        PdfPCell cell = new PdfPCell(new Phrase("All movies by Kubrick"));
        cell.setBorder(PdfPCell.NO_BORDER);
        fs = PdfFileSpecification.fileEmbedded(
            writer, null, KubrickMovies.FILENAME, new KubrickMovies().createPdf());
        collectionitem.addItem(TYPE_FIELD, "PDF");
        fs.addCollectionItem(collectionitem);
        target = new PdfTargetDictionary(true);
        target.setFileAttachmentPagename("movies");
        target.setFileAttachmentName("The movies of Stanley Kubrick");
        cell.setCellEvent(new PdfActionEvent(writer, PdfAction.gotoEmbedded(null, target, dest, true)));
        cell.setCellEvent(new FileAttachmentEvent(writer, fs, "The movies of Stanley Kubrick"));
        cell.setCellEvent(new LocalDestinationEvent(writer, "movies"));
        table.addCell(cell);
        writer.addFileAttachment(fs);

        cell = new PdfPCell(new Phrase("Kubrick DVDs"));
        cell.setBorder(PdfPCell.NO_BORDER);
        fs = PdfFileSpecification.fileEmbedded(
            writer, null, KubrickDvds.FILENAME, new KubrickDvds().createPdf());
        collectionitem.addItem(TYPE_FIELD, "PDF");
        fs.addCollectionItem(collectionitem);
        cell.setCellEvent(new FileAttachmentEvent(writer, fs, "Kubrick DVDs"));
        table.addCell(cell);
        writer.addFileAttachment(fs);
        
        cell = new PdfPCell(new Phrase("Kubrick documentary"));
        cell.setBorder(PdfPCell.NO_BORDER);
        fs = PdfFileSpecification.fileEmbedded(
            writer, null, KubrickDocumentary.FILENAME, new KubrickDocumentary().createPdf());
        collectionitem.addItem(TYPE_FIELD, "PDF");
        fs.addCollectionItem(collectionitem);
        cell.setCellEvent(new FileAttachmentEvent(writer, fs, "Kubrick Documentary"));
        table.addCell(cell);
        writer.addFileAttachment(fs);

        document.newPage();
        document.add(table);
        // step 5
        document.close();
    }
    
    /**
     * Creates a Collection schema that can be used to organize the movies of Stanley Kubrick
     * in a collection: year, title, duration, DVD acquisition, filesize (filename is present, but hidden).
     * @return    a collection schema
     */
    private static PdfCollectionSchema getCollectionSchema() {
        PdfCollectionSchema schema = new PdfCollectionSchema();
        
        PdfCollectionField type = new PdfCollectionField(TYPE_CAPTION, PdfCollectionField.TEXT);
        type.setOrder(0);
        schema.addField(TYPE_FIELD, type);
        
        PdfCollectionField filename = new PdfCollectionField(FILE_FIELD, PdfCollectionField.FILENAME);
        filename.setOrder(1);
        schema.addField(FILE_FIELD, filename);
        
        return schema;
    }

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args) throws DocumentException, IOException, SQLException {
        new KubrickCollection().createPdf(RESULT);
    }
}
FileAttachmentEvent.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.chapter16;

import java.io.IOException;

import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfWriter;

public class FileAttachmentEvent implements PdfPCellEvent {

    /** The PdfWriter to which the file has to be attached. */
    protected PdfWriter writer;
    /** The file specification that will be used to create an annotation. */
    protected PdfFileSpecification fs;
    /** The description that comes with the annotation. */
    protected String description;
    
    /**
     * Creates a FileAttachmentEvent.
     * 
     * @param writer      the writer to which the file attachment has to be added.
     * @param fs          the file specification.
     * @param description a description for the file attachment.
     */
    public FileAttachmentEvent(PdfWriter writer, PdfFileSpecification fs, String description) {
        this.writer = writer;
        this.fs = fs;
        this.description = description;
    }
    
    /**
     * Implementation of the cellLayout method.
     * @see com.itextpdf.text.pdf.PdfPCellEvent#cellLayout(
     *     com.itextpdf.text.pdf.PdfPCell, com.itextpdf.text.Rectangle, com.itextpdf.text.pdf.PdfContentByte[])
     */
    public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
        try {
            PdfAnnotation annotation = PdfAnnotation.createFileAttachment(writer,
                new Rectangle(position.getLeft() - 20, position.getTop() - 15,
                    position.getLeft() - 5, position.getTop() - 5),
                description, fs);
            annotation.setName(description);
            writer.addAnnotation(annotation);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
PdfActionEvent.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.chapter16;

import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfWriter;

public class PdfActionEvent implements PdfPCellEvent {

    /** The writer to which we are going to add the action. */
    protected PdfWriter writer;
    /** The action we're going to add. */
    protected PdfAction action;
    
    /** Creates a new Action event. */
    public PdfActionEvent(PdfWriter writer, PdfAction action) {
        this.writer = writer;
        this.action = action;
    }
    
    /** Implementation of the cellLayout method. */
    public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
        writer.addAnnotation(new PdfAnnotation(writer,
            position.getLeft(), position.getBottom(), position.getRight(), position.getTop(),
            action));
    }
}
LocalDestinationEvent.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.chapter16;

import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfWriter;

public class LocalDestinationEvent implements PdfPCellEvent {

    /** The writer to which the local destination will be added. */
    protected PdfWriter writer;
    /** The name of the local destination. */
    protected String name;
    
    /** Constructs a local destination event. */
    public LocalDestinationEvent(PdfWriter writer, String name) {
        this.writer = writer;
        this.name = name;
    }
    
    /** Implementation of the cellLayout method. */
    public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
        writer.getDirectContent().localDestination(name,
            new PdfDestination(PdfDestination.FITH, position.getTop()));
    }
}
MovieAnnotation.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.chapter16;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfWriter;

public class MovieAnnotation {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part4/chapter16/movie.pdf";
    /** One of the resources. */
    public static final String RESOURCE
        = "resources/img/foxdog.mpg";
    
    /**
     * 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));
        // step 3
        document.open();
        // step 4
        PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(writer,
                RESOURCE, "foxdog.mpg", null);
        writer.addAnnotation(PdfAnnotation.createScreen(writer,
                new Rectangle(200f, 700f, 400f, 800f), "Fox and Dog", fs,
                "video/mpeg", true));
        // step 5
        document.close();
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new MovieAnnotation().createPdf(RESULT);
    }
}
Pdf3D.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.chapter16;

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

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfAppearance;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfIndirectObject;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfStream;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;

public class Pdf3D {

    /** The resulting PDF file. */
    public static String RESULT = "results/part4/chapter16/pdf3d.pdf";
    /** The path to a 3D file. */
    public static String RESOURCE = "resources/img/teapot.u3d";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new Pdf3D().createPdf(RESULT);
    }

    /**
     * Creates the PDF.
     * @param  filename   the path to the resulting PDF file
     * @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));
        // step 3
        document.open();
        // step 4
        Rectangle rect = new Rectangle(100, 400, 500, 800);
        rect.setBorder(Rectangle.BOX);
        rect.setBorderWidth(0.5f);
        rect.setBorderColor(new BaseColor(0xFF, 0x00, 0x00));
        document.add(rect);
            
        PdfStream stream3D = new PdfStream(new FileInputStream(RESOURCE), writer);
        stream3D.put(PdfName.TYPE, new PdfName("3D"));
        stream3D.put(PdfName.SUBTYPE, new PdfName("U3D"));
        stream3D.flateCompress();
        PdfIndirectObject streamObject = writer.addToBody(stream3D);
        stream3D.writeLength();
            
        PdfDictionary dict3D = new PdfDictionary();
        dict3D.put(PdfName.TYPE, new PdfName("3DView"));
        dict3D.put(new PdfName("XN"), new PdfString("Default"));
        dict3D.put(new PdfName("IN"), new PdfString("Unnamed"));
        dict3D.put(new PdfName("MS"), PdfName.M);
        dict3D.put(new PdfName("C2W"),
            new PdfArray(new float[] { 1, 0, 0, 0, 0, -1, 0, 1, 0, 3, -235, 28 } ));
        dict3D.put(PdfName.CO, new PdfNumber(235));

        PdfIndirectObject dictObject = writer.addToBody(dict3D); 
            
        PdfAnnotation annot = new PdfAnnotation(writer, rect);
        annot.put(PdfName.CONTENTS, new PdfString("3D Model"));
        annot.put(PdfName.SUBTYPE, new PdfName("3D"));
        annot.put(PdfName.TYPE, PdfName.ANNOT);
        annot.put(new PdfName("3DD"), streamObject.getIndirectReference());
        annot.put(new PdfName("3DV"), dictObject.getIndirectReference());
        PdfAppearance ap = writer.getDirectContent().createAppearance(rect.getWidth(), rect.getHeight());
        annot.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, ap);
        annot.setPage();

        writer.addAnnotation(annot);
        // step 5
        document.close();
    }
}
FestivalCalendar1.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.chapter16;
import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfDeveloperExtension;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfIndirectReference;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.richmedia.RichMediaActivation;
import com.itextpdf.text.pdf.richmedia.RichMediaAnnotation;
import com.itextpdf.text.pdf.richmedia.RichMediaConfiguration;
import com.itextpdf.text.pdf.richmedia.RichMediaInstance;
import com.itextpdf.text.pdf.richmedia.RichMediaParams;


public class FestivalCalendar1 {
    
    /** The resulting PDF file. */
    public static final String RESULT = "results/part4/chapter16/festival_calendar1.pdf";
    /** The path to a Flash application. */
    public static final String RESOURCE = "resources/swf/FestivalCalendar1.swf";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
        writer.addDeveloperExtension(PdfDeveloperExtension.ADOBE_1_7_EXTENSIONLEVEL3);
        // step 3
        document.open();
        // step 4
        // we prepare a RichMediaAnnotation
        RichMediaAnnotation richMedia = new RichMediaAnnotation(writer, new Rectangle(36, 400, 559,806));
        // we embed the swf file
        PdfFileSpecification fs
            = PdfFileSpecification.fileEmbedded(writer, RESOURCE, "FestivalCalendar1.swf", null);
        // we declare the swf file as an asset
        PdfIndirectReference asset = richMedia.addAsset("FestivalCalendar1.swf", fs);
        // we create a configuration
        RichMediaConfiguration configuration = new RichMediaConfiguration(PdfName.FLASH);
        RichMediaInstance instance = new RichMediaInstance(PdfName.FLASH);
        RichMediaParams flashVars = new RichMediaParams();
        String vars = new String("&day=2011-10-13");
        flashVars.setFlashVars(vars);
        instance.setParams(flashVars);
        instance.setAsset(asset);
        configuration.addInstance(instance);
        // we add the configuration to the annotation
        PdfIndirectReference configurationRef = richMedia.addConfiguration(configuration);
        // activation of the rich media
        RichMediaActivation activation = new RichMediaActivation();
        activation.setConfiguration(configurationRef);
        richMedia.setActivation(activation);
        // we add the annotation
        PdfAnnotation richMediaAnnotation = richMedia.createAnnotation();
        richMediaAnnotation.setFlags(PdfAnnotation.FLAGS_PRINT);
        writer.addAnnotation(richMediaAnnotation);
        // step 5
        document.close();
    }
}
FestivalCalendar2.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.chapter16;
import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfBorderDictionary;
import com.itextpdf.text.pdf.PdfDeveloperExtension;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfIndirectReference;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.PushbuttonField;
import com.itextpdf.text.pdf.TextField;
import com.itextpdf.text.pdf.richmedia.RichMediaActivation;
import com.itextpdf.text.pdf.richmedia.RichMediaAnnotation;
import com.itextpdf.text.pdf.richmedia.RichMediaCommand;
import com.itextpdf.text.pdf.richmedia.RichMediaConfiguration;
import com.itextpdf.text.pdf.richmedia.RichMediaExecuteAction;
import com.itextpdf.text.pdf.richmedia.RichMediaInstance;


public class FestivalCalendar2 {

    /** The resulting PDF file. */
    public static final String RESULT = "results/part4/chapter16/festival_calendar2.pdf";
    /** The path to a Flash application. */
    public static final String RESOURCE = "resources/swf/FestivalCalendar2.swf";
    /** The path to a JavaScript file. */
    public static final String JS = "resources/js/show_date.js";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        // step 1
    	Document document = new Document();
    	// step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
        writer.addDeveloperExtension(PdfDeveloperExtension.ADOBE_1_7_EXTENSIONLEVEL3);
        // step 3
        document.open();
        // step 4
        writer.addJavaScript(Utilities.readFileToString(JS));
        // we prepare a RichMediaAnnotation
        RichMediaAnnotation richMedia = new RichMediaAnnotation(writer, new Rectangle(36, 560, 561, 760));
        // we embed the swf file
        PdfFileSpecification fs
            = PdfFileSpecification.fileEmbedded(writer, RESOURCE, "FestivalCalendar2.swf", null);
        // we declare the swf file as an asset
        PdfIndirectReference asset = richMedia.addAsset("FestivalCalendar2.swf", fs);
        // we create a configuration
        RichMediaConfiguration configuration = new RichMediaConfiguration(PdfName.FLASH);
        RichMediaInstance instance = new RichMediaInstance(PdfName.FLASH);
        instance.setAsset(asset);
        configuration.addInstance(instance);
        // we add the configuration to the annotation
        PdfIndirectReference configurationRef = richMedia.addConfiguration(configuration);
        // activation of the rich media
        RichMediaActivation activation = new RichMediaActivation();
        activation.setConfiguration(configurationRef);
        richMedia.setActivation(activation);
        // we add the annotation
        PdfAnnotation richMediaAnnotation = richMedia.createAnnotation();
        richMediaAnnotation.setFlags(PdfAnnotation.FLAGS_PRINT);
        writer.addAnnotation(richMediaAnnotation);
        
        String[] days = new String[]{"2011-10-12", "2011-10-13", "2011-10-14", "2011-10-15",
                "2011-10-16", "2011-10-17", "2011-10-18", "2011-10-19"};
        for (int i = 0; i < days.length; i++) {
            Rectangle rect = new Rectangle(36 + (65 * i), 765, 100 + (65 * i), 780);
            PushbuttonField button = new PushbuttonField(writer, rect, "button" + i);
            button.setBackgroundColor(new GrayColor(0.75f));
            button.setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
            button.setTextColor(GrayColor.GRAYBLACK);
            button.setFontSize(12);
            button.setText(days[i]);
            button.setLayout(PushbuttonField.LAYOUT_ICON_LEFT_LABEL_RIGHT);
            button.setScaleIcon(PushbuttonField.SCALE_ICON_ALWAYS);
            button.setProportionalIcon(true);
            button.setIconHorizontalAdjustment(0);
            PdfFormField field = button.getField();
            RichMediaCommand command = new RichMediaCommand(new PdfString("getDateInfo"));
            command.setArguments(new PdfString(days[i]));
            RichMediaExecuteAction action
                = new RichMediaExecuteAction(richMediaAnnotation.getIndirectReference(), command);
            field.setAction(action);
            writer.addAnnotation(field);
        }
        TextField text = new TextField(writer, new Rectangle(36, 785, 559, 806), "date");
        text.setOptions(TextField.READ_ONLY);
        writer.addAnnotation(text.getTextField());
        // step 5
        document.close();
    }
}
SpecialId.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;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class SpecialId : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "special_id.pdf";
    /** An image file. */
    public readonly String RESOURCE = Path.Combine(
      Utility.ResourceImage, "bruno.jpg"
    );    
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        zip.AddFile(RESOURCE, "");
        zip.AddEntry(RESULT, new SpecialId().CreatePdf());       
        zip.Save(stream);             
      }
    } 
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        using (Document document = new Document(new Rectangle(400, 300))) {
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          document.Open();
          Image img = Image.GetInstance(
            Path.Combine(Utility.ResourceImage, "bruno.jpg"
          ));
          img.ScaleAbsolute(400, 300);
          img.SetAbsolutePosition(0, 0);
          PdfImage pi = new PdfImage(img, "", null);
          pi.Put(new PdfName("ITXT_SpecialId"), new PdfName("123456789"));
          PdfIndirectObject pio = writer.AddToBody(pi);
          img.DirectReference = pio.IndirectReference;
          document.Add(img);
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
ResizeImage.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.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Collections.Generic;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class ResizeImage : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "resized_image.pdf";
    /** The multiplication factor for the image. */
    public const float FACTOR = 0.5f;
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        SpecialId s = new SpecialId();
        byte[] pdf = s.CreatePdf();
        zip.AddEntry(Utility.ResultFileName(s.ToString() + ".pdf"), pdf);       
        zip.AddEntry(RESULT, new ResizeImage().ManipulatePdf(pdf));       
        zip.Save(stream);             
      }
    } 
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the byte array as result
     */    
    public byte[] ManipulatePdf(byte[] pdf) {
      PdfName key = new PdfName("ITXT_SpecialId");
      PdfName value = new PdfName("123456789");
      // Read the file
      PdfReader reader = new PdfReader(pdf);
      int n = reader.XrefSize;
      PdfObject pdfObject;
      PRStream prStream;
      // Look for image and manipulate image prStream
      for (int i = 0; i < n; i++) {
        pdfObject = reader.GetPdfObject(i);
        if (pdfObject == null || !pdfObject.IsStream()) continue;
        
        prStream = (PRStream) pdfObject;
        byte[] imageBytes;
        if (value.Equals(prStream.Get(key))) {
          PdfImageObject image = new PdfImageObject(prStream);
          using (System.Drawing.Image original = image.GetDrawingImage()) {
            if (original == null) continue;
            int width = (int)(original.Width * FACTOR);
            int height = (int)(original.Height * FACTOR);
            
            using (System.Drawing.Image thumb = new Bitmap(width, height) ) {
              using ( Graphics graphic = Graphics.FromImage(thumb) ) {
                graphic.DrawImage(original, 0, 0, width, height);
                using (MemoryStream ms = new MemoryStream()) {
                  thumb.Save(ms, ImageFormat.Jpeg);
                  imageBytes = ms.ToArray();
                }
              }
            }
            prStream.Clear();
            prStream.SetData(imageBytes, false, PRStream.NO_COMPRESSION);
            prStream.Put(PdfName.TYPE, PdfName.XOBJECT);
            prStream.Put(PdfName.SUBTYPE, PdfName.IMAGE);
            prStream.Put(key, value);
            prStream.Put(PdfName.FILTER, PdfName.DCTDECODE);
            prStream.Put(PdfName.WIDTH, new PdfNumber(width));
            prStream.Put(PdfName.HEIGHT, new PdfNumber(height));
            prStream.Put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
            prStream.Put(PdfName.COLORSPACE, PdfName.DEVICERGB);            
          }
        }
      }
      // Save altered PDF
      using (MemoryStream ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
ListUsedFonts.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using kuujinbo.iTextInAction2Ed.Chapter11;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class ListUsedFonts : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "fonts.txt";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        FontTypes f = new FontTypes();
        byte[] pdf = Utility.PdfBytes(f);
        zip.AddEntry(Utility.ResultFileName(f.ToString() + ".pdf"), pdf);
        IEnumerable set1 = from m 
          in new ListUsedFonts().ListFonts(pdf)
          orderby m select m;
        StringBuilder sb = new StringBuilder();
/*
 * i don't have c:/windows/fonts/ARBLI__.TTF on my system;
 * if you compare to Java example __THIS__ result file will have
 * one __LESS__ font listed!
 */
        foreach (String fontname in set1) {
          sb.AppendLine(fontname);
        }        
        zip.AddEntry(RESULT, sb.ToString());       
        zip.Save(stream);
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a HashSet containing information about the fonts in the src PDF file.
     * @param src the PDF file
     * 
     * HashSet only available in .NET >= 3.5
     */
    public HashSet ListFonts(byte[] src) {
      HashSet set = new HashSet();
      PdfReader reader = new PdfReader(src);
      PdfDictionary resources;
      for (int k = 1; k <= reader.NumberOfPages; ++k) {
        resources = reader.GetPageN(k).GetAsDict(PdfName.RESOURCES);
        ProcessResource(set, resources);
      }
      return set;
    }
// ---------------------------------------------------------------------------    
    /**
     * Extracts the font names from page or XObject resources.
     * @param set the HashSet with the font names
     * @param resources the resources dictionary
     */
    public void ProcessResource(HashSet set, PdfDictionary resource) {
        if (resource == null) return;
        
        PdfDictionary xobjects = resource.GetAsDict(PdfName.XOBJECT);
        if (xobjects != null) {
          foreach (PdfName key in xobjects.Keys) {
            ProcessResource(set, xobjects.GetAsDict(key));
          }
        }
        PdfDictionary fonts = resource.GetAsDict(PdfName.FONT);
        if (fonts == null) return;
        
        PdfDictionary font;
        foreach (PdfName key in fonts.Keys) {
          font = fonts.GetAsDict(key);
          String name = font.GetAsName(PdfName.BASEFONT).ToString();
          if (name.Length > 8 && name.Substring(7, 1) == "+") {
            name = String.Format(
              "{0} subset ({1})", 
              name.Substring(8), name.Substring(1, 7)
            );
          }
          else {
              name = name.Substring(1);
              PdfDictionary desc = font.GetAsDict(PdfName.FONTDESCRIPTOR);
              if (desc == null) {
                name += " nofontdescriptor";
              }
              else if (desc.Get(PdfName.FONTFILE) != null) {
                name += " (Type 1) embedded";
              }
              else if (desc.Get(PdfName.FONTFILE2) != null) {
                name += " (TrueType) embedded";
              }
              else if (desc.Get(PdfName.FONTFILE3) != null) {
                name += " (" + font.GetAsName(PdfName.SUBTYPE).ToString().Substring(1) + ") embedded";
              }
          }
          set.Add(name);
        }
    }
// ===========================================================================  
  }
}
EmbedFontPostFacto.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;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class EmbedFontPostFacto : IWriter {
// ===========================================================================
    /** The first resulting PDF file. */
    public const String RESULT1 = "without_font.pdf";
    /** The second resulting PDF file. */
    public const String RESULT2 = "with_font.pdf";
    /** A special font. */
    public readonly String FONT = Path.Combine(
      Utility.ResourceFonts, "wds011402.ttf"
    );     
    /** The name of the special font. */
    public const String FONTNAME = "WaltDisneyScriptv4.1";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        EmbedFontPostFacto example = new EmbedFontPostFacto();
        byte[] pdf = example.CreatePdf();
        zip.AddEntry(RESULT1, pdf);       
        zip.AddEntry(RESULT2, example.ManipulatePdf(pdf));       
        zip.Save(stream);             
      }
    }     
// --------------------------------------------------------------------------- 
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {    
          // step 2
          PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4:
          Font font = new Font(
            BaseFont.CreateFont(FONT, "", BaseFont.NOT_EMBEDDED), 60
          );
          document.Add(new Paragraph("iText in Action", font));
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------     
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
      // the font file
      byte[] fontfile = null;
      using (FileStream fs = new FileStream(
        FONT, FileMode.Open, FileAccess.Read)) 
      {
        fontfile = new byte[fs.Length];
        fs.Read(fontfile, 0, (int) fs.Length);
      }
      // create a new stream for the font file
      PdfStream stream = new PdfStream(fontfile);
      stream.FlateCompress();
      stream.Put(PdfName.LENGTH1, new PdfNumber(fontfile.Length));
      // create a reader object
      PdfReader reader = new PdfReader(src);
      int n = reader.XrefSize;
      PdfDictionary font;
      using (MemoryStream ms = new MemoryStream()) {      
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          PdfName fontname = new PdfName(FONTNAME);
          for (int i = 0; i < n; i++) {
            PdfObject objectPdf = reader.GetPdfObject(i);
            if (objectPdf == null || !objectPdf.IsDictionary()) {
              continue;
            }
            font = (PdfDictionary)objectPdf;
            if (PdfName.FONTDESCRIPTOR.Equals(font.Get(PdfName.TYPE))
                && fontname.Equals(font.Get(PdfName.FONTNAME))) 
            {
              PdfIndirectObject objref = stamper.Writer.AddToBody(stream);
              font.Put(PdfName.FONTFILE2, objref.IndirectReference);
            }
          }
        }
        return ms.ToArray();
      }
    } 
// ===========================================================================    
  }
}
KubrickDvds.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.Linq;
using System.Collections.Generic;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class KubrickDvds : IWriter {
// ===========================================================================
    /** The filename of the resulting PDF. */
    public const String RESULT = "kubrick_dvds.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        KubrickDvds kubrick = new KubrickDvds();
        byte[] ePdf = kubrick.CreatePdf();
        zip.AddEntry(RESULT, ePdf);
        kubrick.ExtractAttachments(ePdf, zip);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Extracts attachments from an existing PDF.
     * @param src the path to the existing PDF
     * @param zip the ZipFile object to add the extracted images
     */
    public void ExtractAttachments(byte[] src, ZipFile zip) {
      PdfReader reader = new PdfReader(src);
      for (int i = 1; i <= reader.NumberOfPages; i++) {
        PdfArray array = reader.GetPageN(i).GetAsArray(PdfName.ANNOTS);
        if (array == null) continue;
        for (int j = 0; j < array.Size; j++) {
          PdfDictionary annot = array.GetAsDict(j);
          if (PdfName.FILEATTACHMENT.Equals(
              annot.GetAsName(PdfName.SUBTYPE)))
          {
            PdfDictionary fs = annot.GetAsDict(PdfName.FS);
            PdfDictionary refs = fs.GetAsDict(PdfName.EF);
            foreach (PdfName name in refs.Keys) {
              zip.AddEntry(
                fs.GetAsString(name).ToString(), 
                PdfReader.GetStreamBytes((PRStream)refs.GetAsStream(name))
              );
            }
          }
        }
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        using (Document document = new Document()) {
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          document.Open();
          document.Add(new Paragraph(
            "This is a list of Kubrick movies available in DVD stores."
          ));
          IEnumerable movies = PojoFactory.GetMovies(1)
            .Concat(PojoFactory.GetMovies(4))
          ;          
          List list = new List();
          string RESOURCE = Utility.ResourcePosters;
          foreach (Movie movie in movies) {
            PdfAnnotation annot = PdfAnnotation.CreateFileAttachment(
              writer, null, 
              movie.GetMovieTitle(false), null,
              Path.Combine(RESOURCE, movie.Imdb + ".jpg"),
              string.Format("{0}.jpg", movie.Imdb)              
            );
            ListItem item = new ListItem(movie.GetMovieTitle(false));
            item.Add("\u00a0\u00a0");
            Chunk chunk = new Chunk("\u00a0\u00a0\u00a0\u00a0");
            chunk.SetAnnotation(annot);
            item.Add(chunk);
            list.Add(item);
          }
          document.Add(list);
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
	}
}
KubrickDocumentary.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class KubrickDocumentary : IWriter {
// ===========================================================================
    /** The filename of the resulting PDF. */
    public const String RESULT = "kubrick_documentary.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        KubrickDocumentary kubrick = new KubrickDocumentary();
        byte[] ePdf = kubrick.CreatePdf();
        zip.AddEntry(RESULT, ePdf);
        kubrick.ExtractDocLevelAttachments(ePdf, zip);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     */
    public byte[] CreatePdf() {
      IEnumerable movies = PojoFactory.GetMovies(1);
      using (MemoryStream ms = new MemoryStream()) {
        using (Document document = new Document()) {
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          document.Open();
          document.Add(new Paragraph(
            "'Stanley Kubrick: A Life in Pictures'"
            + " is a documentary about Stanley Kubrick and his films:"
          ));
          StringBuilder sb = new StringBuilder();
          sb.AppendLine("");
          List list = new List(List.UNORDERED, 20);
          foreach (Movie movie in movies) {
            sb.AppendLine("");
            sb.AppendLine(String.Format(
              "{0}",
              XMLUtil.EscapeXML(movie.MovieTitle, true)
            ));
            sb.AppendLine(String.Format("{0}", movie.Year));
            sb.AppendLine(String.Format(
              "{0}", movie.Duration
            ));
            sb.AppendLine("");
            ListItem item = new ListItem(movie.MovieTitle);
            list.Add(item);
          }
          document.Add(list);
          sb.Append("");
          PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
            writer, null, "kubrick.xml", Encoding.UTF8.GetBytes(sb.ToString())
            //txt.toByteArray()
          );
          writer.AddFileAttachment(fs);
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Extracts document level attachments
     * @param PDF from which document level attachments will be extracted
     * @param zip the ZipFile object to add the extracted images
     */
    public void ExtractDocLevelAttachments(byte[] pdf, ZipFile zip) {
      PdfReader reader = new PdfReader(pdf);
      PdfDictionary root = reader.Catalog;
      PdfDictionary documentnames = root.GetAsDict(PdfName.NAMES);
      PdfDictionary embeddedfiles = 
          documentnames.GetAsDict(PdfName.EMBEDDEDFILES);
      PdfArray filespecs = embeddedfiles.GetAsArray(PdfName.NAMES);
      for (int i = 0; i < filespecs.Size; ) {
        filespecs.GetAsString(i++);
        PdfDictionary filespec = filespecs.GetAsDict(i++);
        PdfDictionary refs = filespec.GetAsDict(PdfName.EF);
        foreach (PdfName key in refs.Keys) {
          PRStream stream = (PRStream) PdfReader.GetPdfObject(
            refs.GetAsIndirectObject(key)
          );
          zip.AddEntry(
            filespec.GetAsString(key).ToString(), 
            PdfReader.GetStreamBytes(stream)
          );
        }
      }
    }
// ===========================================================================
	}
}
KubrickBox.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.collection;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class KubrickBox : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "kubrick_box.pdf";
    /** The path to an image used in the example. */
    public readonly String IMG_BOX =  Path.Combine(
      Utility.ResourceImage, "kubrick_box.jpg"
    );
    /** Path to the resources. */
    public readonly String RESOURCE =  Path.Combine(
      Utility.ResourcePosters, "{0}.jpg"
    );    
    /** The relative widths of the PdfPTable columns. */
    public readonly float[] WIDTHS = { 1 , 7 };
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        Image img = Image.GetInstance(IMG_BOX);
        document.Add(img);
        List list = new List(List.UNORDERED, 20);
        PdfDestination dest = new PdfDestination(PdfDestination.FIT);
        dest.AddFirst(new PdfNumber(1));
        IEnumerable box = PojoFactory.GetMovies(1)
          .Concat(PojoFactory.GetMovies(4))
        ;
        foreach (Movie movie in box) {
          if (movie.Year > 1960) {
            PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
              writer, null,
              String.Format("kubrick_{0}.pdf", movie.Imdb),
              CreateMoviePage(movie)
            );
            fs.AddDescription(movie.Title, false);
            writer.AddFileAttachment(fs);
            ListItem item = new ListItem(movie.MovieTitle);
            PdfTargetDictionary target = new PdfTargetDictionary(true);
            target.EmbeddedFileName = movie.Title;
            PdfAction action = PdfAction.GotoEmbedded(null, target, dest, true);
            Chunk chunk = new Chunk(" (see info)");
            chunk.SetAction(action);
            item.Add(chunk);
            list.Add(item);
          }
        }
        document.Add(list);
      }
    }
// --------------------------------------------------------------------------- 
    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     */
    public byte[] CreateMoviePage(Movie movie) {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          Paragraph p = new Paragraph(
            movie.MovieTitle,
            FontFactory.GetFont(
              BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED, 16
            )
          );
          document.Add(p);
          document.Add(Chunk.NEWLINE);
          PdfPTable table = new PdfPTable(WIDTHS);
          table.AddCell(Image.GetInstance(
            String.Format(RESOURCE, movie.Imdb)
          ));
          PdfPCell cell = new PdfPCell();
          cell.AddElement(new Paragraph("Year: " + movie.Year.ToString()));
          cell.AddElement(new Paragraph("Duration: " + movie.Duration.ToString()));
          table.AddCell(cell);
          document.Add(table);
          PdfDestination dest = new PdfDestination(PdfDestination.FIT);
          dest.AddFirst(new PdfNumber(1));
          PdfTargetDictionary target = new PdfTargetDictionary(false);
          Chunk chunk = new Chunk("Go to original document");
          PdfAction action = PdfAction.GotoEmbedded(null, target, dest, false);
          chunk.SetAction(action);
          document.Add(chunk);
        }
        return ms.ToArray();
      }
    }
    
// ===========================================================================
  }
}
KubrickMovies.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.collection;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class KubrickMovies : IWriter {
// ===========================================================================
    /** Path to the resources. */
    public readonly String RESOURCE =  Path.Combine(
      Utility.ResourcePosters, "{0}.jpg"
    );    
    /** The relative widths of the PdfPTable columns. */
    public readonly float[] WIDTHS = { 1 , 7 };
    /** The filename of the PDF */
    public const String FILENAME = "kubrick_movies.pdf";    
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        document.Add(new Paragraph(
          "This document contains a collection of PDFs,"
          + " one per Stanley Kubrick movie."
        ));
        
        PdfCollection collection = new PdfCollection(PdfCollection.DETAILS);
        PdfCollectionSchema schema = _collectionSchema(); 
        collection.Schema = schema;
        PdfCollectionSort sort = new PdfCollectionSort("YEAR");
        sort.SetSortOrder(false);
        collection.Sort = sort;
        collection.InitialDocument = "Eyes Wide Shut";
        writer.Collection = collection;
        
        PdfCollectionItem item;
        IEnumerable movies = PojoFactory.GetMovies(1);
        foreach (Movie movie in movies) {
          PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
            writer, null,
            String.Format("kubrick_{0}.pdf", movie.Imdb),
            CreateMoviePage(movie)
          );
          fs.AddDescription(movie.Title, false);

          item = new PdfCollectionItem(schema);
          item.AddItem("TITLE", movie.GetMovieTitle(false));
          if (movie.GetMovieTitle(true) != null) {
            item.SetPrefix("TITLE", movie.GetMovieTitle(true));
          }
          item.AddItem("DURATION", movie.Duration.ToString());
          item.AddItem("YEAR", movie.Year.ToString());
          fs.AddCollectionItem(item);
          writer.AddFileAttachment(fs);
        }
      }
    }
// ---------------------------------------------------------------------------     
    /**
     * Creates a Collection schema that can be used to organize the movies 
     * of Stanley Kubrick in a collection: year, title, duration, DVD 
     * acquisition, filesize (filename is present, but hidden).
     * @return a collection schema
     */
    private PdfCollectionSchema _collectionSchema() {
      PdfCollectionSchema schema = new PdfCollectionSchema();
      PdfCollectionField size = new PdfCollectionField(
        "File size", PdfCollectionField.SIZE
      );
      
      size.Order = 4;
      schema.AddField("SIZE", size);
      
      PdfCollectionField filename = new PdfCollectionField(
        "File name", PdfCollectionField.FILENAME
      );
      filename.Visible = false;
      schema.AddField("FILE", filename);
      
      PdfCollectionField title = new PdfCollectionField(
        "Movie title", PdfCollectionField.TEXT
      );
      title.Order = 1;
      schema.AddField("TITLE", title);
      
      PdfCollectionField duration = new PdfCollectionField(
        "Duration", PdfCollectionField.NUMBER
      );
      duration.Order = 2;
      schema.AddField("DURATION", duration);
      
      PdfCollectionField year = new PdfCollectionField(
        "Year", PdfCollectionField.NUMBER
      );
      year.Order = 0;
      schema.AddField("YEAR", year);
      
      return schema;
    }
// --------------------------------------------------------------------------- 
    /**
     * Creates the PDF.
     * @return the bytes of a PDF file.
     */
    public byte[] CreateMoviePage(Movie movie) {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          Paragraph p = new Paragraph(
            movie.MovieTitle,
            FontFactory.GetFont(
              BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED, 16
            )
          );
          document.Add(p);
          document.Add(Chunk.NEWLINE);
          PdfPTable table = new PdfPTable(WIDTHS);
          table.AddCell(Image.GetInstance(
            String.Format(RESOURCE, movie.Imdb)
          ));
          PdfPCell cell = new PdfPCell();
          cell.AddElement(new Paragraph("Year: " + movie.Year.ToString()));
          cell.AddElement(new Paragraph("Duration: " + movie.Duration.ToString()));
          table.AddCell(cell);
          document.Add(table);
          
          PdfTargetDictionary target = new PdfTargetDictionary(false);
          target.AdditionalPath = new PdfTargetDictionary(false);
          Chunk chunk = new Chunk("Go to original document");
          PdfAction action = PdfAction.GotoEmbedded(
            null, target, new PdfString("movies"), false
          );
          chunk.SetAction(action);
          document.Add(chunk);
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
KubrickCollection.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.collection;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class KubrickCollection : IWriter {
// ===========================================================================
    /** An image file used in this example */
    public readonly String IMG_BOX =  Path.Combine(
      Utility.ResourceImage, "kubrick_box.jpg"
    );
    /** An image file used in this example */
    public readonly String IMG_KUBRICK =  Path.Combine(
      Utility.ResourceImage, "kubrick.jpg"
    );       
    /** The name of a field in the collection schema. */
    public const String TYPE_FIELD = "TYPE";
    /** A caption of a field in the collection schema. */
    public const String TYPE_CAPTION = "File type";
    /** The name of a field in the collection schema. */
    public const String FILE_FIELD = "FILE";
    /** A caption of a field in the collection schema. */
    public const String FILE_CAPTION = "File name";
    /** Sort order for the keys in the collection. */
    public String[] KEYS = { TYPE_FIELD, FILE_FIELD };
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        
        
        // step 4
        PdfCollection collection = new PdfCollection(PdfCollection.HIDDEN);
        PdfCollectionSchema schema = _collectionSchema();
        collection.Schema = schema;
        PdfCollectionSort sort = new PdfCollectionSort(KEYS);
        collection.Sort = sort;
        writer.Collection = collection;

        PdfCollectionItem collectionitem = new PdfCollectionItem(schema);
        PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
          writer, IMG_KUBRICK, "kubrick.jpg", null
        );
        fs.AddDescription("Stanley Kubrick", false);
        collectionitem.AddItem(TYPE_FIELD, "JPEG");
        fs.AddCollectionItem(collectionitem);
        writer.AddFileAttachment(fs);
        
        Image img = Image.GetInstance(IMG_BOX);
        document.Add(img);
        List list = new List(List.UNORDERED, 20);
        PdfDestination dest = new PdfDestination(PdfDestination.FIT);
        dest.AddFirst(new PdfNumber(1));
        PdfTargetDictionary intermediate;
        PdfTargetDictionary target;
        Chunk chunk;
        ListItem item;
        PdfAction action = null;

        IEnumerable box = PojoFactory.GetMovies(1)
          .Concat(PojoFactory.GetMovies(4))
        ;
        StringBuilder sb = new StringBuilder();
        foreach (Movie movie in box) {
          if (movie.Year > 1960) {
            sb.AppendLine(String.Format(
              "{0};{1};{2}", movie.MovieTitle, movie.Year, movie.Duration
            ));
            item = new ListItem(movie.MovieTitle);
            if (!"0278736".Equals(movie.Imdb)) {
              target = new PdfTargetDictionary(true);
              target.EmbeddedFileName = movie.Title;
              intermediate = new PdfTargetDictionary(true);
              intermediate.FileAttachmentPage = 1;
              intermediate.FileAttachmentIndex = 1;
              intermediate.AdditionalPath = target;
              action = PdfAction.GotoEmbedded(null, intermediate, dest, true);
              chunk = new Chunk(" (see info)");
              chunk.SetAction(action);
              item.Add(chunk);
            }
            list.Add(item);
          }
        }
        document.Add(list);
        
        fs = PdfFileSpecification.FileEmbedded(
          writer, null, "kubrick.txt", 
          Encoding.UTF8.GetBytes(sb.ToString())
        );
        fs.AddDescription("Kubrick box: the movies", false);
        collectionitem.AddItem(TYPE_FIELD, "TXT");
        fs.AddCollectionItem(collectionitem);
        writer.AddFileAttachment(fs);

        PdfPTable table = new PdfPTable(1);
        table.SpacingAfter = 10;
        PdfPCell cell = new PdfPCell(new Phrase("All movies by Kubrick"));
        cell.Border = PdfPCell.NO_BORDER;
        fs = PdfFileSpecification.FileEmbedded(
          writer, null, KubrickMovies.FILENAME, 
          Utility.PdfBytes(new KubrickMovies())
          //new KubrickMovies().createPdf()
        );
        collectionitem.AddItem(TYPE_FIELD, "PDF");
        fs.AddCollectionItem(collectionitem);
        target = new PdfTargetDictionary(true);
        target.FileAttachmentPagename = "movies";
        target.FileAttachmentName = "The movies of Stanley Kubrick";
        cell.CellEvent = new PdfActionEvent(
          writer, PdfAction.GotoEmbedded(null, target, dest, true)
        );
        cell.CellEvent = new FileAttachmentEvent(
          writer, fs, "The movies of Stanley Kubrick"
        );
        cell.CellEvent = new LocalDestinationEvent(writer, "movies");
        table.AddCell(cell);
        writer.AddFileAttachment(fs);

        cell = new PdfPCell(new Phrase("Kubrick DVDs"));
        cell.Border = PdfPCell.NO_BORDER;
        fs = PdfFileSpecification.FileEmbedded(
          writer, null, 
          KubrickDvds.RESULT, new KubrickDvds().CreatePdf()
        );
        collectionitem.AddItem(TYPE_FIELD, "PDF");
        fs.AddCollectionItem(collectionitem);
        cell.CellEvent = new FileAttachmentEvent(writer, fs, "Kubrick DVDs");
        table.AddCell(cell);
        writer.AddFileAttachment(fs);
        
        cell = new PdfPCell(new Phrase("Kubrick documentary"));
        cell.Border = PdfPCell.NO_BORDER;
        fs = PdfFileSpecification.FileEmbedded(
          writer, null, 
          KubrickDocumentary.RESULT, new KubrickDocumentary().CreatePdf()
        );
        collectionitem.AddItem(TYPE_FIELD, "PDF");
        fs.AddCollectionItem(collectionitem);
        cell.CellEvent = new FileAttachmentEvent(
          writer, fs, "Kubrick Documentary"
        );
        table.AddCell(cell);
        writer.AddFileAttachment(fs);

        document.NewPage();
        document.Add(table);
      }
    }
// ---------------------------------------------------------------------------     
    /**
     * Creates a Collection schema that can be used to organize the movies
     * of Stanley Kubrick in a collection: year, title, duration, 
     * DVD acquisition, filesize (filename is present, but hidden).
     * @return a collection schema
     */
    private PdfCollectionSchema _collectionSchema() {
      PdfCollectionSchema schema = new PdfCollectionSchema();
      
      PdfCollectionField type = new PdfCollectionField(
        TYPE_CAPTION, PdfCollectionField.TEXT
      );
      type.Order = 0;
      schema.AddField(TYPE_FIELD, type);
      
      PdfCollectionField filename = new PdfCollectionField(
        FILE_FIELD, PdfCollectionField.FILENAME
      );
      filename.Order = 1;
      schema.AddField(FILE_FIELD, filename);
      
      return schema;
    }
// ===========================================================================
  }
}
FileAttachmentEvent.cs
using System;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class FileAttachmentEvent : IPdfPCellEvent {
// ===========================================================================
    /** The writer to which we are going to add the action. */
    protected PdfWriter writer;
    /** The file specification that will be used to create an annotation. */
    protected PdfFileSpecification fs;
    /** The description that comes with the annotation. */
    protected String description;
// ---------------------------------------------------------------------------    
    /**
     * Creates a FileAttachmentEvent.
     * 
     * @param writer      the writer to which the file attachment has to be added.
     * @param fs          the file specification.
     * @param description a description for the file attachment.
     */
    public FileAttachmentEvent(
        PdfWriter writer, PdfFileSpecification fs, String description)
    {
      this.writer = writer;
      this.fs = fs;
      this.description = description;
    }
// ---------------------------------------------------------------------------    
    /**
     * Implementation of the cellLayout method.
     * @see com.itextpdf.text.pdf.PdfPCellEvent#cellLayout(
     * com.itextpdf.text.pdf.PdfPCell, com.itextpdf.text.Rectangle, 
     * com.itextpdf.text.pdf.PdfContentByte[])
     */
    public void CellLayout(
        PdfPCell cell, Rectangle position, PdfContentByte[] canvases) 
    {
      try {
        PdfAnnotation annotation = PdfAnnotation.CreateFileAttachment(
          writer,
          new Rectangle(
            position.Left - 20, position.Top - 15,
            position.Left - 5, position.Top - 5
          ),
          description, fs
        );
        annotation.Name = description;
        writer.AddAnnotation(annotation);
      }
      catch {
        throw;
      }
    }
// ===========================================================================
	}
}
PdfActionEvent.cs
using System;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class PdfActionEvent : IPdfPCellEvent {
// ===========================================================================
    /** The writer to which we are going to add the action. */
    protected PdfWriter writer;
    /** The action we're going to add. */
    protected PdfAction action;
// ---------------------------------------------------------------------------    
    /** Creates a new Action event. */
    public PdfActionEvent(PdfWriter writer, PdfAction action) {
      this.writer = writer;
      this.action = action;
    }
// ---------------------------------------------------------------------------    
    /** Implementation of the cellLayout method. */
    public void CellLayout(
        PdfPCell cell, Rectangle position, PdfContentByte[] canvases) 
    {
      writer.AddAnnotation(new PdfAnnotation(
        writer,
        position.Left, position.Bottom, position.Right, position.Top,
        action
      ));
    }
// ===========================================================================
	}
}
LocalDestinationEvent.cs
using System;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class LocalDestinationEvent : IPdfPCellEvent {
// ===========================================================================
    /** The writer to which we are going to add the action. */
    protected PdfWriter writer;
    /** The name of the local destination. */
    protected String name;
// ---------------------------------------------------------------------------    
    /** Creates a new Action event. */
    public LocalDestinationEvent(PdfWriter writer,  String name) {
      this.writer = writer;
      this.name = name;
    }
// ---------------------------------------------------------------------------    
    /** Implementation of the cellLayout method. */
    public void CellLayout(
        PdfPCell cell, Rectangle position, PdfContentByte[] canvases) 
    {
      writer.DirectContent.LocalDestination(
        name,
        new PdfDestination(PdfDestination.FITH, position.Top)
      );
    }
// ===========================================================================
	}
}
MovieAnnotation.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.Collections.Generic;
using System.IO;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class MovieAnnotation : IWriter {
// ===========================================================================
    /** One of the resources. */
    public readonly String RESOURCE = Path.Combine(
      Utility.ResourceImage, "foxdog.mpg"
    );
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
          writer, RESOURCE, "foxdog.mpg", null
        );
        writer.AddAnnotation(PdfAnnotation.CreateScreen(
          writer,
          new Rectangle(200f, 700f, 400f, 800f), 
          "Fox and Dog", fs,
          "video/mpeg", true
        ));        
      }
    }
// ===========================================================================
	}
}
Pdf3D.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.Collections.Generic;
using System.IO;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class Pdf3D : IWriter {
// ===========================================================================
    public readonly String RESOURCE = Path.Combine(
      Utility.ResourceImage, "teapot.u3d"
    );
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        Rectangle rect = new Rectangle(100, 400, 500, 800);
        rect.Border = Rectangle.BOX;
        rect.BorderWidth = 0.5f;
        rect.BorderColor = new BaseColor(0xFF, 0x00, 0x00);
        document.Add(rect);

        PdfIndirectObject streamObject = null;
        using (FileStream fs = 
          new FileStream(RESOURCE, FileMode.Open, FileAccess.Read))
        {
          PdfStream stream3D = new PdfStream(fs, writer);
          
          stream3D.Put(PdfName.TYPE, new PdfName("3D"));
          stream3D.Put(PdfName.SUBTYPE, new PdfName("U3D"));
          stream3D.FlateCompress();
          streamObject = writer.AddToBody(stream3D);
          stream3D.WriteLength();
        }
            
        PdfDictionary dict3D = new PdfDictionary();
        dict3D.Put(PdfName.TYPE, new PdfName("3DView"));
        dict3D.Put(new PdfName("XN"), new PdfString("Default"));
        dict3D.Put(new PdfName("IN"), new PdfString("Unnamed"));
        dict3D.Put(new PdfName("MS"), PdfName.M);
        dict3D.Put(
          new PdfName("C2W"),
          new PdfArray(
            new float[] { 1, 0, 0, 0, 0, -1, 0, 1, 0, 3, -235, 28 }
          )
        );
        dict3D.Put(PdfName.CO, new PdfNumber(235));

        PdfIndirectObject dictObject = writer.AddToBody(dict3D); 
            
        PdfAnnotation annot = new PdfAnnotation(writer, rect);
        annot.Put(PdfName.CONTENTS, new PdfString("3D Model"));
        annot.Put(PdfName.SUBTYPE, new PdfName("3D"));
        annot.Put(PdfName.TYPE, PdfName.ANNOT);
        annot.Put(new PdfName("3DD"), streamObject.IndirectReference);
        annot.Put(new PdfName("3DV"), dictObject.IndirectReference);
        PdfAppearance ap = writer.DirectContent.CreateAppearance(
          rect.Width, rect.Height
        );
        annot.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, ap);
        annot.SetPage();

        writer.AddAnnotation(annot);      
      }
    }
// ===========================================================================
	}
}
FestivalCalendar1.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.richmedia;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class FestivalCalendar1 : IWriter {
// ===========================================================================
    /** The path to a Flash application. */
    public readonly String RESOURCE = Path.Combine(
      Utility.ResourceSwf, "FestivalCalendar1.swf"
    );
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
        writer.AddDeveloperExtension(
          PdfDeveloperExtension.ADOBE_1_7_EXTENSIONLEVEL3
        );
        // step 3
        document.Open();
        // step 4
        // we prepare a RichMediaAnnotation
        RichMediaAnnotation richMedia = new RichMediaAnnotation(
          writer, new Rectangle(36, 400, 559,806)
        );
        // we embed the swf file
        PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
          writer, RESOURCE, "FestivalCalendar1.swf", null
        );
        // we declare the swf file as an asset
        PdfIndirectReference asset = richMedia.AddAsset(
          "FestivalCalendar1.swf", fs
        );
        // we create a configuration
        RichMediaConfiguration configuration = new RichMediaConfiguration(
          PdfName.FLASH
        );
        RichMediaInstance instance = new RichMediaInstance(PdfName.FLASH);
        RichMediaParams flashVars = new RichMediaParams();
        String vars = "&day=2011-10-13";
        flashVars.FlashVars = vars;
        instance.Params = flashVars;
        instance.Asset = asset;
        configuration.AddInstance(instance);
        // we add the configuration to the annotation
        PdfIndirectReference configurationRef = richMedia.AddConfiguration(
          configuration
        );
        // activation of the rich media
        RichMediaActivation activation = new RichMediaActivation();
        activation.Configuration = configurationRef;
        richMedia.Activation = activation;
        // we add the annotation
        PdfAnnotation richMediaAnnotation = richMedia.CreateAnnotation();
        richMediaAnnotation.Flags = PdfAnnotation.FLAGS_PRINT;
        writer.AddAnnotation(richMediaAnnotation);
      }
    }
// ===========================================================================
	}
}
FestivalCalendar2.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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.richmedia;

namespace kuujinbo.iTextInAction2Ed.Chapter16 {
  public class FestivalCalendar2 : IWriter {
// ===========================================================================
    /** The path to a Flash application. */
    public readonly String RESOURCE = Path.Combine(
      Utility.ResourceSwf, "FestivalCalendar2.swf"
    );
    /** The path to a JavaScript file. */
    public readonly String JS = Path.Combine(
      Utility.ResourceJavaScript, "show_date.js"
    );
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
        writer.AddDeveloperExtension(
          PdfDeveloperExtension.ADOBE_1_7_EXTENSIONLEVEL3
        );
        // step 3
        document.Open();
        // step 4
        writer.AddJavaScript(File.ReadAllText(JS));

        // we prepare a RichMediaAnnotation
        RichMediaAnnotation richMedia = new RichMediaAnnotation(
          writer, new Rectangle(36, 560, 561, 760)
        );
        // we embed the swf file
        PdfFileSpecification fs = PdfFileSpecification.FileEmbedded(
          writer, RESOURCE, "FestivalCalendar2.swf", null
        );
        // we declare the swf file as an asset
        PdfIndirectReference asset = richMedia.AddAsset(
          "FestivalCalendar2.swf", fs
        );
        // we create a configuration
        RichMediaConfiguration configuration = new RichMediaConfiguration(
          PdfName.FLASH
        );
        RichMediaInstance instance = new RichMediaInstance(PdfName.FLASH);
        instance.Asset = asset;
        configuration.AddInstance(instance);
        // we add the configuration to the annotation
        PdfIndirectReference configurationRef = richMedia.AddConfiguration(
          configuration
        );
        // activation of the rich media
        RichMediaActivation activation = new RichMediaActivation();
        activation.Configuration = configurationRef;
        richMedia.Activation = activation;
        // we add the annotation
        PdfAnnotation richMediaAnnotation = richMedia.CreateAnnotation();
        richMediaAnnotation.Flags = PdfAnnotation.FLAGS_PRINT;
        writer.AddAnnotation(richMediaAnnotation);
        
        String[] days = new String[] {
          "2011-10-12", "2011-10-13", "2011-10-14", "2011-10-15",
          "2011-10-16", "2011-10-17", "2011-10-18", "2011-10-19"
        };
        for (int i = 0; i < days.Length; i++) {
          Rectangle rect = new Rectangle(36 + (65 * i), 765, 100 + (65 * i), 780);
          PushbuttonField button = new PushbuttonField(writer, rect, "button" + i);
          button.BackgroundColor = new GrayColor(0.75f);
          button.BorderStyle = PdfBorderDictionary.STYLE_BEVELED;
          button.TextColor = GrayColor.GRAYBLACK;
          button.FontSize = 12;
          button.Text = days[i];
          button.Layout = PushbuttonField.LAYOUT_ICON_LEFT_LABEL_RIGHT;
          button.ScaleIcon = PushbuttonField.SCALE_ICON_ALWAYS;
          button.ProportionalIcon = true;
          button.IconHorizontalAdjustment = 0;
          PdfFormField field = button.Field;
          RichMediaCommand command = new RichMediaCommand(
            new PdfString("getDateInfo")
          );
          command.Arguments = new PdfString(days[i]);
          RichMediaExecuteAction action = new RichMediaExecuteAction(
            richMediaAnnotation.IndirectReference, command
          );
          field.Action = action;
          writer.AddAnnotation(field);
        }
        TextField text = new TextField(
          writer, new Rectangle(36, 785, 559, 806), "date"
        );
        text.Options = TextField.READ_ONLY;
        writer.AddAnnotation(text.GetTextField());
      }
    }
// ===========================================================================
	}
}
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