Chapter 6: Working with existing PDFs

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

10th October 2015
admin-marketing

Switch code for this example

PageInformation.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 part2.chapter06;

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

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;

import part1.chapter01.HelloWorldLandscape1;
import part1.chapter01.HelloWorldLandscape2;
import part1.chapter03.MovieTemplates;
import part1.chapter05.Hero1;

public class PageInformation {

	/** The resulting text file with info about a PDF. */
    public static final String RESULT
        = "results/part2/chapter06/page_info.txt";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
    	// Use old examples to create PDFs
        HelloWorldLandscape1.main(args);
        HelloWorldLandscape2.main(args);
        MovieTemplates.main(args);
        Hero1.main(args);
        // Inspecting PDFs
        PrintWriter writer = new PrintWriter(new FileOutputStream(RESULT));
        inspect(writer, HelloWorldLandscape1.RESULT);
        inspect(writer, HelloWorldLandscape2.RESULT);
        inspect(writer, MovieTemplates.RESULT);
        inspect(writer, Hero1.RESULT);
        writer.close();
    }
    
    /**
     * Inspect a PDF file and write the info to a txt file
     * @param writer Writer to a text file
     * @param filename Path to the PDF file
     * @throws IOException
     */
    public static void inspect(PrintWriter writer, String filename)
        throws IOException {
        PdfReader reader = new PdfReader(filename);
        writer.println(filename);
        writer.print("Number of pages: ");
        writer.println(reader.getNumberOfPages());
        Rectangle mediabox = reader.getPageSize(1);
        writer.print("Size of page 1: [");
        writer.print(mediabox.getLeft());
        writer.print(',');
        writer.print(mediabox.getBottom());
        writer.print(',');
        writer.print(mediabox.getRight());
        writer.print(',');
        writer.print(mediabox.getTop());
        writer.println("]");
        writer.print("Rotation of page 1: ");
        writer.println(reader.getPageRotation(1));
        writer.print("Page size with rotation of page 1: ");
        writer.println(reader.getPageSizeWithRotation(1));
        writer.print("Is rebuilt? ");
        writer.println(reader.isRebuilt());
        writer.print("Is encrypted? ");
        writer.println(reader.isEncrypted());
        writer.println();
        writer.flush();
        reader.close();
    }
}
MemoryInfo.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 part2.chapter06;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.RandomAccessFileOrArray;
import part1.chapter03.MovieTemplates;

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

public class MemoryInfo {

	/** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/memory_info.txt";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// Use a previous example to create a PDF
        MovieTemplates.main(args);
        // Create a writer for a report file
        PrintWriter writer
            = new PrintWriter(new FileOutputStream(RESULT));
        garbageCollect();
        // Do a full read
        fullRead(writer, MovieTemplates.RESULT);
        // Do a partial read
        partialRead(writer, MovieTemplates.RESULT);
        // Close the text file writer
        writer.close();
    }
    
    /**
     * Do a full read of a PDF file
     * @param writer a writer to a report file
     * @param filename the file to read
     * @throws IOException
     */
    public static void fullRead(PrintWriter writer, String filename)
        throws IOException {
        long before = getMemoryUse();
        PdfReader reader = new PdfReader(filename);
        reader.getNumberOfPages();
        writer.println(String.format("Memory used by full read: %d",
                    getMemoryUse() - before));
        writer.flush();
        reader.close();
    }
    
    /**
     * Do a partial read of a PDF file
     * @param writer a writer to a report file
     * @param filename the file to read
     * @throws IOException
     */
    public static void partialRead(PrintWriter writer, String filename)
        throws IOException {
        long before = getMemoryUse();
        PdfReader reader = new PdfReader(
                new RandomAccessFileOrArray(filename), null);
        reader.getNumberOfPages();
        writer.println(String.format("Memory used by partial read: %d",
                    getMemoryUse() - before));
        writer.flush();
        reader.close();
    }

    /**
     * Returns the current memory use.
     * 
     * @return the current memory use
     */
    public static long getMemoryUse() {
        garbageCollect();
        garbageCollect();
        garbageCollect();
        garbageCollect();
        long totalMemory = Runtime.getRuntime().totalMemory();
        garbageCollect();
        garbageCollect();
        long freeMemory = Runtime.getRuntime().freeMemory();
        return (totalMemory - freeMemory);
    }

    /**
     * Makes sure all garbage is cleared from the memory.
     */
    public static void garbageCollect() {
        try {
            System.gc();
            Thread.sleep(200);
            System.runFinalization();
            Thread.sleep(200);
            System.gc();
            Thread.sleep(200);
            System.runFinalization();
            Thread.sleep(200);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}
SelectPages.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 part2.chapter06;

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

import part1.chapter03.MovieTemplates;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class SelectPages {

	/** A resulting PDF file. */
    public static final String RESULT1 = "results/part2/chapter06/timetable_stamper.pdf";
	/** A resulting PDF file. */
    public static final String RESULT2 = "results/part2/chapter06/timetable_copy.pdf"; 
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) throws IOException, DocumentException {
        new MovieTemplates().createPdf(MovieTemplates.RESULT);
        PdfReader reader = new PdfReader(MovieTemplates.RESULT);
        reader.selectPages("4-8");
        manipulateWithStamper(reader);
        manipulateWithCopy(reader);
        reader.close();
    }

    /**
     * Creates a new PDF based on the one in the reader
     * @param reader a reader with a PDF file
     * @throws IOException
     * @throws DocumentException
     */
    private static void manipulateWithStamper(PdfReader reader)
        throws IOException, DocumentException {
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT1));
        stamper.close();
    }

    /**
     * Creates a new PDF based on the one in the reader
     * @param reader a reader with a PDF file
     * @throws IOException
     * @throws DocumentException
     */
    private static void manipulateWithCopy(PdfReader reader)
        throws IOException, DocumentException {
        int n = reader.getNumberOfPages();
        Document document = new Document();
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT2));
        document.open();
        for (int i = 0; i < n;) {
            copy.addPage(copy.getImportedPage(reader, ++i));
        }
        document.close();
    }
    
    
}
ImportingPages1.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 part2.chapter06;

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

import part1.chapter03.MovieTemplates;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class ImportingPages1 {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/time_table_imported1.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// Use old example to create PDF
        new MovieTemplates().createPdf(MovieTemplates.RESULT);
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfPTable table = new PdfPTable(2);
        PdfReader reader = new PdfReader(MovieTemplates.RESULT);
        int n = reader.getNumberOfPages();
        PdfImportedPage page;
        for (int i = 1; i <= n; i++) {
            page = writer.getImportedPage(reader, i);
            table.addCell(Image.getInstance(page));
        }
        document.add(table);
        // step 5
        document.close();
        reader.close();
    }
}
ImportingPages2.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 part2.chapter06;

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

import part1.chapter03.MovieTemplates;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class ImportingPages2 {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/time_table_imported2.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        // use old example to create PDF
    	new MovieTemplates().createPdf(MovieTemplates.RESULT);
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfReader reader = new PdfReader(MovieTemplates.RESULT);
        int n = reader.getNumberOfPages();
        PdfImportedPage page;
        PdfPTable table = new PdfPTable(2);
        for (int i = 1; i <= n; i++) {
            page = writer.getImportedPage(reader, i);
            table.getDefaultCell().setRotation(-page.getRotation());
            table.addCell(Image.getInstance(page));
        }
        document.add(table);
        // step 5
        document.close();
        reader.close();
    }
}
Layers.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 part2.chapter06;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class Layers {

    /** The resulting PDF. */
    public static final String SOURCE
        = "results/part2/chapter06/layers_orig.pdf";
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter06/layers.pdf";
    /** The movie poster. */
    public static final String RESOURCE
        = "resources/img/loa.jpg";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new Layers().createPdf(SOURCE);
        // Create a reader
        PdfReader reader = new PdfReader(SOURCE);
        // step 1
        Document document = new Document(PageSize.A5.rotate());
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfContentByte canvas = writer.getDirectContent();
        PdfImportedPage page;
        BaseFont bf
            = BaseFont.createFont(BaseFont.ZAPFDINGBATS, "", BaseFont.EMBEDDED);
        for (int i = 0; i < reader.getNumberOfPages(); ) {
            page = writer.getImportedPage(reader, ++i);
            canvas.addTemplate(page, 1f, 0, 0.4f, 0.4f, 72, 50 * i);
            canvas.beginText();
            canvas.setFontAndSize(bf, 20);
            canvas.showTextAligned(Element.ALIGN_CENTER,
                String.valueOf((char)(181 + i)), 496, 150 + 50 * i, 0);
            canvas.endText();
        }
        // step 5
        document.close();
        reader.close();
    }

    /**
     * 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(PageSize.POSTCARD, 30, 30, 30, 30);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfContentByte under = writer.getDirectContentUnder();
        // Page 1: a rectangle
        drawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());
        under.setRGBColorFill(0xFF, 0xD7, 0x00);
        under.rectangle(5, 5, PageSize.POSTCARD.getWidth() - 10, PageSize.POSTCARD.getHeight() - 10);
        under.fill();
        document.newPage();
        // Page 2: an image
        drawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());
        Image img = Image.getInstance(RESOURCE);
        img.setAbsolutePosition((PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
                (PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
        document.add(img);
        document.newPage();
        // Page 3: the words "Foobar Film Festival"
        drawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());;
        Paragraph p = new Paragraph("Foobar Film Festival", new Font(FontFamily.HELVETICA, 22));
        p.setAlignment(Element.ALIGN_CENTER);
        document.add(p);
        document.newPage();
        // Page 4: the words "SOLD OUT"
        drawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());
        PdfContentByte over = writer.getDirectContent();
        over.saveState();
        float sinus = (float)Math.sin(Math.PI / 60);
        float cosinus = (float)Math.cos(Math.PI / 60);
        BaseFont bf = BaseFont.createFont();
        over.beginText();
        over.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
        over.setLineWidth(1.5f);
        over.setRGBColorStroke(0xFF, 0x00, 0x00);
        over.setRGBColorFill(0xFF, 0xFF, 0xFF);
        over.setFontAndSize(bf, 36);
        over.setTextMatrix(cosinus, sinus, -sinus, cosinus, 50, 324);
        over.showText("SOLD OUT");
        over.setTextMatrix(0, 0);
        over.endText();
        over.restoreState();
        // step 5
        document.close();
    }
    
    /**
     * Draws a rectangle
     * @param content the direct content layer
     * @param width the width of the rectangle
     * @param height the height of the rectangle
     */
    public static void drawRectangle(PdfContentByte content, float width, float height) {
        content.saveState();
        PdfGState state = new PdfGState();
        state.setFillOpacity(0.6f);
        content.setGState(state);
        content.setRGBColorFill(0xFF, 0xFF, 0xFF);
        content.setLineWidth(3);
        content.rectangle(0, 0, width, height);
        content.fillStroke();
        content.restoreState();
    }
}
Superimposing.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 part2.chapter06;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class Superimposing {

    /** The resulting PDF. */
    public static final String SOURCE
        = "results/part2/chapter06/opening.pdf";
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter06/festival_opening.pdf";
    /** The movie poster. */
    public static final String RESOURCE
        = "resources/img/loa.jpg";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new Superimposing().createPdf(SOURCE);
        // Create a reader object
        PdfReader reader = new PdfReader(SOURCE);
        // step 1
        Document document = new Document(PageSize.POSTCARD);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfContentByte canvas = writer.getDirectContent();
        PdfImportedPage page;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            page = writer.getImportedPage(reader, i);
            canvas.addTemplate(page, 1f, 0, 0, 1, 0, 0);
        }
        // step 5
        document.close();
        reader.close();
    }

    /**
     * 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(PageSize.POSTCARD, 30, 30, 30, 30);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfContentByte under = writer.getDirectContentUnder();
        // page 1: rectangle
        under.setRGBColorFill(0xFF, 0xD7, 0x00);
        under.rectangle(5, 5,
            PageSize.POSTCARD.getWidth() - 10, PageSize.POSTCARD.getHeight() - 10);
        under.fill();
        document.newPage();
        // page 2: image
        Image img = Image.getInstance(RESOURCE);
        img.setAbsolutePosition(
            (PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
            (PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
        document.add(img);
        document.newPage();
        // page 3: the words "Foobar Film Festival"
        Paragraph p = new Paragraph("Foobar Film Festival", new Font(FontFamily.HELVETICA, 22));
        p.setAlignment(Element.ALIGN_CENTER);
        document.add(p);
        document.newPage();
        // page 4: the words "SOLD OUT"
        PdfContentByte over = writer.getDirectContent();
        over.saveState();
        float sinus = (float)Math.sin(Math.PI / 60);
        float cosinus = (float)Math.cos(Math.PI / 60);
        BaseFont bf = BaseFont.createFont();
        over.beginText();
        over.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
        over.setLineWidth(1.5f);
        over.setRGBColorStroke(0xFF, 0x00, 0x00);
        over.setRGBColorFill(0xFF, 0xFF, 0xFF);
        over.setFontAndSize(bf, 36);
        over.setTextMatrix(cosinus, sinus, -sinus, cosinus, 50, 324);
        over.showText("SOLD OUT");
        over.setTextMatrix(0, 0);
        over.endText();
        over.restoreState();
        // step 5
        document.close();
    }
}
Stationery.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 part2.chapter06;

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

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class Stationery extends PdfPageEventHelper {

    /** The original PDF. */
    public static final String STATIONERY
        = "results/part2/chapter06/stationery.pdf";
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter06/text_on_stationery.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        Stationery stationary = new Stationery();
        createStationary(STATIONERY);
        stationary.createPdf(RESULT);
    }

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws SQLException, IOException, DocumentException {
    	// Create the database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4, 36, 36, 72, 36);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        useStationary(writer);
        // step 3
        document.open();
        // step 4
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT country, id FROM film_country ORDER BY country");
        while (rs.next()) {
            document.add(new Paragraph(rs.getString("country"), FilmFonts.BOLD));
            document.add(Chunk.NEWLINE);
            Set movies = 
                new TreeSet(new MovieComparator(MovieComparator.BY_YEAR));
            movies.addAll(PojoFactory.getMovies(connection, rs.getString("id")));
            for(Movie movie : movies) {
                document.add(new Paragraph(movie.getMovieTitle(), FilmFonts.BOLD));
                if (movie.getOriginalTitle() != null)
                    document.add(new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC));
                document.add(new Paragraph(
                    String.format("Year: %d; run length: %d minutes",
                    movie.getYear(), movie.getDuration()), FilmFonts.NORMAL));
                document.add(PojoToElementFactory.getDirectorList(movie));
            }
            document.newPage();
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /** Imported page with the stationery. */
    protected PdfImportedPage page;

    /**
     * Initialize the imported page.
     * @param writer The PdfWriter
     * @throws IOException
     */
    public void useStationary(PdfWriter writer) throws IOException {
        writer.setPageEvent(this);
        PdfReader reader = new PdfReader(STATIONERY);
        page = writer.getImportedPage(reader, 1);
    }
    
    /**
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
     *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
     */
    public void onEndPage(PdfWriter writer, Document document) {
        writer.getDirectContentUnder().addTemplate(page, 0, 0);
    }

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public static void createStationary(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
        PdfPTable table = new PdfPTable(1);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.addCell(new Phrase("FOOBAR FILM FESTIVAL", FilmFonts.BOLD));
        document.add(table);
        Font font = new Font(FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));
        ColumnText.showTextAligned(writer.getDirectContentUnder(),
                Element.ALIGN_CENTER, new Phrase("FOOBAR FILM FESTIVAL", font),
                297.5f, 421, 45);
        // step 5
        document.close();
    }
}
NUpTool.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 part2.chapter06;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class NUpTool {

    /** Format of the resulting PDF files. */
    public static final String RESULT
        = "results/part2/chapter06/result%dup.pdf";
    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @param pow the PDF will be N-upped with N = Math.pow(2, pow);
     * @throws IOException
     * @throws DocumentException
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest, int pow)
        throws IOException, DocumentException {
    	// reader for the src file
        PdfReader reader = new PdfReader(src);
        // initializations
        Rectangle pageSize = reader.getPageSize(1);
        Rectangle newSize = (pow % 2) == 0 ?
            new Rectangle(pageSize.getWidth(), pageSize.getHeight()) :
            new Rectangle(pageSize.getHeight(), pageSize.getWidth());
        Rectangle unitSize = new Rectangle(pageSize.getWidth(), pageSize.getHeight());
        for (int i = 0; i < pow; i++) {
            unitSize = new Rectangle(unitSize.getHeight() / 2, unitSize.getWidth());
        }
        int n = (int)Math.pow(2, pow);
        int r = (int)Math.pow(2, pow / 2);
        int c = n / r;
        // step 1
        Document document = new Document(newSize, 0, 0, 0, 0);
        // step 2
        PdfWriter writer
           = PdfWriter.getInstance(document, new FileOutputStream(String.format(dest, n)));
        // step 3
        document.open();
        // step 4
        PdfContentByte cb = writer.getDirectContent();
        PdfImportedPage page;
        Rectangle currentSize;
        float offsetX, offsetY, factor;
        int total = reader.getNumberOfPages();
        for (int i = 0; i < total; ) {
            if (i % n == 0) {
                document.newPage();
            }
            currentSize = reader.getPageSize(++i);
            factor = Math.min(
                unitSize.getWidth() / currentSize.getWidth(),
                unitSize.getHeight() / currentSize.getHeight());
            offsetX = unitSize.getWidth() * ((i % n) % c)
              + (unitSize.getWidth() - (currentSize.getWidth() * factor)) / 2f;
            offsetY = newSize.getHeight() - (unitSize.getHeight() * (((i % n) / c) + 1))
              + (unitSize.getHeight() - (currentSize.getHeight() * factor)) / 2f;
            page = writer.getImportedPage(reader, i);
            cb.addTemplate(page, factor, 0, 0, factor, offsetX, offsetY);
        }
        // step 5
        document.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 {
        Stationery.main(args);
        new NUpTool().manipulatePdf(Stationery.RESULT, RESULT, 1);
        new NUpTool().manipulatePdf(Stationery.RESULT, RESULT, 2);
        new NUpTool().manipulatePdf(Stationery.RESULT, RESULT, 3);
        new NUpTool().manipulatePdf(Stationery.RESULT, RESULT, 4);
    }
}
TilingHero.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 part2.chapter06;

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.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class TilingHero {

    /** The original PDF file. */
    public static final String RESOURCE
        = "resources/pdfs/hero.pdf";

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/superman.pdf";
    
    /**
     * 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 {
    	// Creating a reader
        PdfReader reader = new PdfReader(src);
        Rectangle pagesize = reader.getPageSizeWithRotation(1);
        // step 1
        Document document = new Document(pagesize);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(dest));
        // step 3
        document.open();
        // step 4
        PdfContentByte content = writer.getDirectContent();
        PdfImportedPage page = writer.getImportedPage(reader, 1);
        // adding the same page 16 times with a different offset
        float x, y;
        for (int i = 0; i < 16; i++) {
            x = -pagesize.getWidth() * (i % 4);
            y = pagesize.getHeight() * (i / 4 - 3);
            content.addTemplate(page, 4, 0, 0, 4, x, y);
            document.newPage();
        }
        // step 4
        document.close();
        reader.close();
    }

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new TilingHero().manipulatePdf(RESOURCE, RESULT);
    }
}
StampText.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 part2.chapter06;

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

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

import part1.chapter01.HelloWorldLandscape1;
import part1.chapter01.HelloWorldLandscape2;

public class StampText {
    /** A resulting PDF file. */
    public static final String RESULT1
        = "results/part2/chapter06/hello1.pdf";
    /** A resulting PDF file. */
    public static final String RESULT2
        = "results/part2/chapter06/hello2.pdf";
    /** A resulting PDF file. */
    public static final String RESULT3
        = "results/part2/chapter06/hello3.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
        HelloWorldLandscape1.main(args);
        HelloWorldLandscape2.main(args);
        stamp(HelloWorldLandscape1.RESULT, RESULT1);
        stampIgnoreRotation(HelloWorldLandscape1.RESULT, RESULT2);
        stamp(HelloWorldLandscape2.RESULT, RESULT3);
        
    }

    /**
     * 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 static void stamp(String src, String dest)
        throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        PdfContentByte canvas = stamper.getOverContent(1);
        ColumnText.showTextAligned(canvas,
                Element.ALIGN_LEFT, new Phrase("Hello people!"), 36, 540, 0);
        stamper.close();
        reader.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 static void stampIgnoreRotation(String src, String dest)
        throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.setRotateContents(false);
        PdfContentByte canvas = stamper.getOverContent(1);
        ColumnText.showTextAligned(canvas,
                Element.ALIGN_LEFT, new Phrase("Hello people!"), 36, 540, 0);
        stamper.close();
        reader.close();
    }
}
TwoPasses.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 part2.chapter06;

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

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

public class TwoPasses {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/page_x_of_y.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws SQLException, DocumentException, IOException {
    	
    	// FIRST PASS, CREATE THE PDF WITHOUT HEADER
    	
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4, 36, 36, 54, 36);
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, baos);
        // step 3
        document.open();
        // step 4
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT country, id FROM film_country ORDER BY country");
        while (rs.next()) {
            document.add(new Paragraph(rs.getString("country"), FilmFonts.BOLD));
            document.add(Chunk.NEWLINE);
            Set movies = 
                new TreeSet(new MovieComparator(MovieComparator.BY_YEAR));
            movies.addAll(PojoFactory.getMovies(connection, rs.getString("id")));
            for(Movie movie : movies) {
                document.add(new Paragraph(movie.getMovieTitle(), FilmFonts.BOLD));
                if (movie.getOriginalTitle() != null)
                    document.add(
                        new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC));
                document.add(new Paragraph(
                    String.format("Year: %d; run length: %d minutes",
                    movie.getYear(), movie.getDuration()), FilmFonts.NORMAL));
                document.add(PojoToElementFactory.getDirectorList(movie));
            }
            document.newPage();
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
        
        // SECOND PASS, ADD THE HEADER
        
        // Create a reader
        PdfReader reader = new PdfReader(baos.toByteArray());
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(RESULT));
        // Loop over the pages and add a header to each page
        int n = reader.getNumberOfPages();
        for (int i = 1; i <= n; i++) {
            getHeaderTable(i, n).writeSelectedRows(
                    0, -1, 34, 803, stamper.getOverContent(i));
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
    
    /**
     * Create a header table with page X of Y
     * @param x the page number
     * @param y the total number of pages
     * @return a table that can be used as header
     */
    public static PdfPTable getHeaderTable(int x, int y) {
        PdfPTable table = new PdfPTable(2);
        table.setTotalWidth(527);
        table.setLockedWidth(true);
        table.getDefaultCell().setFixedHeight(20);
        table.getDefaultCell().setBorder(Rectangle.BOTTOM);
        table.addCell("FOOBAR FILMFESTIVAL");
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        table.addCell(String.format("Page %d of %d", x, y));
        return table;
    }
}
StampStationery.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 part2.chapter06;

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

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.MovieComparator;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

public class StampStationery {
    /** The original PDF file. */
    public static final String ORIGINAL
        = "results/part2/chapter06/original.pdf";
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter06/stamped_stationary.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        Stationery.createStationary(Stationery.STATIONERY);
        StampStationery stationary = new StampStationery();
        stationary.createPdf(ORIGINAL);
        stationary.manipulatePdf(ORIGINAL, Stationery.STATIONERY, RESULT);
    }
    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param stationery a PDF that will be added as background
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String stationery, String dest)
        throws IOException, DocumentException {
    	// Create readers
        PdfReader reader = new PdfReader(src);
        PdfReader s_reader = new PdfReader(stationery);
        // Create the stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add the stationery to each page
        PdfImportedPage page = stamper.getImportedPage(s_reader, 1);
        int n = reader.getNumberOfPages();
        PdfContentByte background;
        for (int i = 1; i <= n; i++) {
            background = stamper.getUnderContent(i);
            background.addTemplate(page, 0, 0);
        }
        // CLose the stamper
        stamper.close();
        reader.close();
        s_reader.close();
    }

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws SQLException, IOException, DocumentException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4, 36, 36, 72, 36);
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT country, id FROM film_country ORDER BY country");
        while (rs.next()) {
            document.add(new Paragraph(rs.getString("country"), FilmFonts.BOLD));
            document.add(Chunk.NEWLINE);
            Set movies = 
                new TreeSet(new MovieComparator(MovieComparator.BY_YEAR));
            movies.addAll(PojoFactory.getMovies(connection, rs.getString("id")));
            for(Movie movie : movies) {
                document.add(new Paragraph(movie.getMovieTitle(), FilmFonts.BOLD));
                if (movie.getOriginalTitle() != null)
                    document.add(new Paragraph(movie.getOriginalTitle(), FilmFonts.ITALIC));
                document.add(new Paragraph(
                    String.format("Year: %d; run length: %d minutes",
                    movie.getYear(), movie.getDuration()), FilmFonts.NORMAL));
                document.add(PojoToElementFactory.getDirectorList(movie));
            }
            document.newPage();
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
}
InsertPages.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 part2.chapter06;

import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class InsertPages {
    /** A resulting PDF. */
    public static final String RESULT1
        = "results/part2/chapter06/inserted_pages.pdf";
    /** A resulting PDF. */
    public static final String RESULT2
        = "results/part2/chapter06/reordered.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
    	// use a previous example to create a PDF
        StampStationery.main(args);
        // manipulate the PDF
        new InsertPages().manipulatePdf(StampStationery.RESULT, RESULT1);
        // reorder the pages in the PDF
        PdfReader reader = new PdfReader(RESULT1);
        reader.selectPages("3-41,1-2");
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT2));
        stamper.close();
        reader.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
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException, SQLException {
    	// Create a database connection and statement
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Statement stm = connection.createStatement();
        // Fill a ColumnText object with data
        ResultSet rs = stm.executeQuery(
            "SELECT country, id FROM film_country ORDER BY country");
        ColumnText ct = new ColumnText(null);
        while (rs.next()) {
            ct.addElement(new Paragraph(24, new Chunk(rs.getString("country"))));
        }
        // Close the statement and database connection
        stm.close();
        connection.close();
        
        // Create a reader for the original document and for the stationery
        PdfReader reader = new PdfReader(src);
        PdfReader stationery = new PdfReader(Stationery.STATIONERY);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Create an imported page for the stationery
        PdfImportedPage page = stamper.getImportedPage(stationery, 1);
        int i = 0;
        // Add the content of the ColumnText object 
        while(true) {
            // Add a new page
            stamper.insertPage(++i, reader.getPageSize(1));
            // Add the stationary to the new page
            stamper.getUnderContent(i).addTemplate(page, 0, 0);
            // Add as much content of the column as possible
            ct.setCanvas(stamper.getOverContent(i));
            ct.setSimpleColumn(36, 36, 559, 770);
            if (!ColumnText.hasMoreText(ct.go()))
                break;
        }
        // Close the stamper
        stamper.close();
        reader.close();
        stationery.close();
    }
}
FormInformation.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 part2.chapter06;

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

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;

public class FormInformation {

    /** The original PDF file. */
    public static final String DATASHEET
        = "resources/pdfs/datasheet.pdf";
    /** The resulting text file with the field info. */
    public static final String RESULT
        = "results/part2/chapter06/form_info.txt";    
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
        // Create a writer for the report file
        PrintWriter writer
            = new PrintWriter(new FileOutputStream(RESULT));
        // Create a reader to extract info
        PdfReader reader = new PdfReader(DATASHEET);
        // Get the fields from the reader (read-only!!!)
        AcroFields form = reader.getAcroFields();
        // Loop over the fields and get info about them
        Set fields = form.getFields().keySet();
        for (String key : fields) {
            writer.print(key + ": ");
            switch (form.getFieldType(key)) {
            case AcroFields.FIELD_TYPE_CHECKBOX:
                writer.println("Checkbox");
                break;
            case AcroFields.FIELD_TYPE_COMBO:
                writer.println("Combobox");
                break;
            case AcroFields.FIELD_TYPE_LIST:
                writer.println("List");
                break;
            case AcroFields.FIELD_TYPE_NONE:
                writer.println("None");
                break;
            case AcroFields.FIELD_TYPE_PUSHBUTTON:
                writer.println("Pushbutton");
                break;
            case AcroFields.FIELD_TYPE_RADIOBUTTON:
                writer.println("Radiobutton");
                break;
            case AcroFields.FIELD_TYPE_SIGNATURE:
                writer.println("Signature");
                break;
            case AcroFields.FIELD_TYPE_TEXT:
                writer.println("Text");
                break;
            default:
                writer.println("?");
            }
        }
        // Get possible values for field "CP_1"
        writer.println("Possible values for CP_1:");
        String[] states = form.getAppearanceStates("CP_1");
        for (int i = 0; i < states.length; i++) {
            writer.print(" - ");
            writer.println(states[i]);
        }
        // Get possible values for field "category"
        writer.println("Possible values for category:");
        states = form.getAppearanceStates("category");
        for (int i = 0; i < states.length - 1; i++) {
            writer.print(states[i]);
            writer.print(", ");
        }
        writer.println(states[states.length - 1]);
        // flush and close the report file
        writer.flush();
        writer.close();
        reader.close();
    }

}
FillDataSheet.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 part2.chapter06;

import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Director;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class FillDataSheet {

    /** The original PDF file. */
    public static final String DATASHEET
        = "resources/pdfs/datasheet.pdf";
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/imdb%s.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws SQLException, IOException, DocumentException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // Get the movies
        List movies = PojoFactory.getMovies(connection);
        PdfReader reader;
        PdfStamper stamper;
        // Fill out the data sheet form with data
        for (Movie movie : movies) {
            if (movie.getYear() < 2007)
                continue;
            reader = new PdfReader(DATASHEET);
            stamper = new PdfStamper(reader,
                    new FileOutputStream(String.format(RESULT, movie.getImdb())));
            AcroFields fields = stamper.getAcroFields();
            fields.setGenerateAppearances(true);
            fill(fields, movie);
            if (movie.getYear() == 2007)
                stamper.setFormFlattening(true);
            stamper.close();
            reader.close();
        }
        // Close the database connection
        connection.close();
    }
    
    /**
     * Fill out the fields using info from a Movie object.
     * @param form The form object
     * @param movie A movie POJO
     * @throws IOException
     * @throws DocumentException
     */
    public static void fill(AcroFields form, Movie movie)
        throws IOException, DocumentException {
    	form.setField("title", movie.getMovieTitle());
        form.setField("director", getDirectors(movie));
        form.setField("year", String.valueOf(movie.getYear()));
        form.setField("duration", String.valueOf(movie.getDuration()));
        form.setField("category", movie.getEntry().getCategory().getKeyword());
        for (Screening screening : movie.getEntry().getScreenings()) {
            form.setField(screening.getLocation().replace('.', '_'), "Yes");
        }
    }
    
    /**
     * Gets the directors from a Movie object,
     * and concatenates them in a String.
     * @param movie a Movie object
     * @return a String containing director names
     */
    public static String getDirectors(Movie movie) {
        List directors = movie.getDirectors();
        StringBuffer buf = new StringBuffer();
        for (Director director : directors) {
            buf.append(director.getGivenName());
            buf.append(' ');
            buf.append(director.getName());
            buf.append(',');
            buf.append(' ');
        }
        int i = buf.length();
        if (i > 0)
            buf.delete(i - 2, i);
        return buf.toString();
    }
}
Concatenate.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 part2.chapter06;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;

import part1.chapter02.MovieHistory;
import part1.chapter02.MovieLinks1;

public class Concatenate {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/concatenated.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        // using previous examples to create PDFs
    	MovieLinks1.main(args);
        MovieHistory.main(args);
        String[] files = { MovieLinks1.RESULT, MovieHistory.RESULT };
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfReader reader;
        int n;
        // loop over the documents you want to concatenate
        for (int i = 0; i < files.length; i++) {
            reader = new PdfReader(files[i]);
            // loop over the pages in that document
            n = reader.getNumberOfPages();
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(reader, ++page));
            }
            copy.freeReader(reader);
            reader.close();
        }
        // step 5
        document.close();
    }
}
ConcatenateStamp.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 part2.chapter06;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;

import part1.chapter02.MovieHistory;
import part1.chapter02.MovieLinks1;

public class ConcatenateStamp {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/concatenated_stamped.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
    	// use old examples to create PDFs
        MovieLinks1.main(args);
        MovieHistory.main(args);
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        // reader for document 1
        PdfReader reader1 = new PdfReader(MovieLinks1.RESULT);
        int n1 = reader1.getNumberOfPages();
        // reader for document 2
        PdfReader reader2 = new PdfReader(MovieHistory.RESULT);
        int n2 = reader2.getNumberOfPages();
        // initializations
        PdfImportedPage page;
        PdfCopy.PageStamp stamp;
        // Loop over the pages of document 1
        for (int i = 0; i < n1; ) {
            page = copy.getImportedPage(reader1, ++i);
            stamp = copy.createPageStamp(page);
            // add page numbers
            ColumnText.showTextAligned(
                    stamp.getUnderContent(), Element.ALIGN_CENTER,
                    new Phrase(String.format("page %d of %d", i, n1 + n2)),
                    297.5f, 28, 0);
            stamp.alterContents();
            copy.addPage(page);
        }
        // Loop over the pages of document 2
        for (int i = 0; i < n2; ) {
            page = copy.getImportedPage(reader2, ++i);
            stamp = copy.createPageStamp(page);
            // add page numbers
            ColumnText.showTextAligned(
                    stamp.getUnderContent(), Element.ALIGN_CENTER,
                    new Phrase(String.format("page %d of %d", n1 + i, n1 + n2)),
                    297.5f, 28, 0);
            stamp.alterContents();
            copy.addPage(page);
        }
        // step 5
        document.close();
        reader1.close();
        reader2.close();
    }
}
Burst.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 part2.chapter06;

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

import part1.chapter03.MovieTemplates;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;

public class Burst {

    /** Format of the resulting PDF files. */
    public static final String RESULT
        = "results/part2/chapter06/timetable_p%d.pdf";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// use one of the previous examples to create a PDF
        new MovieTemplates().createPdf(MovieTemplates.RESULT);
        // Create a reader
        PdfReader reader = new PdfReader(MovieTemplates.RESULT);
        // We'll create as many new PDFs as there are pages
        Document document;
        PdfCopy copy;
        // loop over all the pages in the original PDF
        int n = reader.getNumberOfPages();
        for (int i = 0; i < n; ) {
        	// step 1
            document = new Document();
            // step 2
            copy = new PdfCopy(document,
                new FileOutputStream(String.format(RESULT, ++i)));
            // step 3
            document.open();
            // step 4
            copy.addPage(copy.getImportedPage(reader, i));
            // step 5
            document.close();
        }
        reader.close();
    }
    
    
}
DataSheets1.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 part2.chapter06;

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

import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class DataSheets1 extends FillDataSheet {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/datasheets1.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        new DataSheets1().createPdf(RESULT);
    }

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfCopy copy
            = new PdfCopy(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        addDataSheets(copy);
        // step 5
        document.close();
    }
    
    /**
     * Fills out a data sheet, flattens it, and adds it to a combined PDF.
     * @param copy the PdfCopy instance (can also be PdfSmartCopy)
     * @throws SQLException
     * @throws IOException
     * @throws DocumentException
     */
    public void addDataSheets(PdfCopy copy)
        throws SQLException, IOException, DocumentException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        List movies = PojoFactory.getMovies(connection);
        PdfReader reader;
        PdfStamper stamper;
        ByteArrayOutputStream baos;
        // Loop over all the movies and fill out the data sheet
        for (Movie movie : movies) {
            reader = new PdfReader(DATASHEET);
            baos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, baos);
            AcroFields fields = stamper.getAcroFields();
            fields.setGenerateAppearances(true);
            fill(fields, movie);
            stamper.setFormFlattening(true);
            stamper.close();
            reader.close();
            
            reader = new PdfReader(baos.toByteArray());
            copy.addPage(copy.getImportedPage(reader, 1));
            copy.freeReader(reader);
            reader.close();
        }
        // Close the database connection
        connection.close();
    }
}
DataSheets2.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 part2.chapter06;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfSmartCopy;

public class DataSheets2 extends DataSheets1 {

    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/datasheets2.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        new DataSheets2().createPdf(RESULT);
    }

    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfSmartCopy copy
            = new PdfSmartCopy(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        addDataSheets(copy);
        // step 5
        document.close();
    }
}
ConcatenateForms1.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 part2.chapter06;

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

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopyFields;
import com.itextpdf.text.pdf.PdfReader;

public class ConcatenateForms1 {

    /** The original PDF file. */
    public static final String DATASHEET
        = "resources/pdfs/datasheet.pdf";
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/concatenated_forms1.pdf";
    
    /**
     * Main method.
     * @param args no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// Create a PdfCopyFields object
        PdfCopyFields copy
            = new PdfCopyFields(new FileOutputStream(RESULT));
        // add a document
        PdfReader reader1 = new PdfReader(DATASHEET);
        copy.addDocument(reader1);
        // add a document
        PdfReader reader2 = new PdfReader(DATASHEET);
        copy.addDocument(reader2);
        // close the PdfCopyFields object
        copy.close();
        reader1.close();
        reader2.close();
    }
}
ConcatenateForms2.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 part2.chapter06;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfCopyFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class ConcatenateForms2 {

    /** The original PDF file. */
    public static final String DATASHEET
        = "resources/pdfs/datasheet.pdf";
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter06/concatenated_forms2.pdf";
    
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// Create a PdfCopyFields object
        PdfCopyFields copy
            = new PdfCopyFields(new FileOutputStream(RESULT));
        // add a document
        PdfReader reader1 = new PdfReader(renameFieldsIn(DATASHEET, 1));
        copy.addDocument(reader1);
        // add a document
        PdfReader reader2 = new PdfReader(renameFieldsIn(DATASHEET, 2));
        copy.addDocument(reader2);
        // Close the PdfCopyFields object
        copy.close();
        reader1.close();
        reader2.close();
    }
    
    /**
     * Renames the fields in an interactive form.
     * @param datasheet the path to the original form
     * @param i a number that needs to be appended to the field names
     * @return a byte[] containing an altered PDF file
     * @throws IOException
     * @throws DocumentException
     */
    private static byte[] renameFieldsIn(String datasheet, int i)
        throws IOException, DocumentException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // Create the stamper
        PdfStamper stamper = new PdfStamper(new PdfReader(datasheet), baos);
        // Get the fields
        AcroFields form = stamper.getAcroFields();
        // Loop over the fields
        Set keys = new HashSet(form.getFields().keySet());
        for (String key : keys) {
            // rename the fields
            form.renameField(key, String.format("%s_%d", key, i));
        }
        // close the stamper
        stamper.close();
        return baos.toByteArray();
    }
}
PageInformation.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.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using Ionic.Zip;
using kuujinbo.iTextInAction2Ed.Chapter01;
using kuujinbo.iTextInAction2Ed.Chapter03;
using kuujinbo.iTextInAction2Ed.Chapter05;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class PageInformation : IWriter {
// ===========================================================================
    public const string RESULT = "page_info.txt";
    public void Write(Stream stream) {
      IWriter[] iw = {
        new HelloWorldLandscape1(), new HelloWorldLandscape2(),
        new MovieTemplates(), new Hero1()
      }; 
      StringBuilder sb = new StringBuilder();       
      using (ZipFile zip = new ZipFile()) {
        foreach (IWriter w in iw) {
          // Create a reader
          byte[] pdf = Utility.PdfBytes(w);
          string fileName = Utility.ResultFileName(w.ToString() + ".pdf");
          Inspect(sb, pdf, fileName); 
          zip.AddEntry(fileName, pdf);  
        }
        zip.AddEntry(RESULT, sb.ToString());
        zip.Save(stream);
      }          
    }   
// ---------------------------------------------------------------------------
    /**
     * Inspect a PDF file and write the info to a txt file
     * @param writer StringBuilder
     * @param pdf PDF file bytes
     * @param fileName PDF filename
     */
    public static void Inspect(StringBuilder sb, byte[] pdf, string fileName) {
      PdfReader reader = new PdfReader(pdf);
      sb.Append(fileName);
      sb.Append(Environment.NewLine);
      sb.Append("Number of pages: ");
      sb.Append(reader.NumberOfPages);
      sb.Append(Environment.NewLine);
      Rectangle mediabox = reader.GetPageSize(1);
      sb.Append("Size of page 1: [");
      sb.Append(mediabox.Left);
      sb.Append(',');
      sb.Append(mediabox.Bottom);
      sb.Append(',');
      sb.Append(mediabox.Right);
      sb.Append(',');
      sb.Append(mediabox.Top);
      sb.Append("]");
      sb.Append(Environment.NewLine);
      sb.Append("Rotation of page 1: ");
      sb.Append(reader.GetPageRotation(1));
      sb.Append(Environment.NewLine);
      sb.Append("Page size with rotation of page 1: ");
      sb.Append(reader.GetPageSizeWithRotation(1));
      sb.Append(Environment.NewLine);
      sb.Append("Is rebuilt? ");
      sb.Append(reader.IsRebuilt().ToString());
      sb.Append(Environment.NewLine);
      sb.Append("Is encrypted? ");
      sb.Append(reader.IsEncrypted().ToString());
      sb.Append(Environment.NewLine);
      sb.Append(Environment.NewLine);
    }    
// ===========================================================================
  }
}
MemoryInfo.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.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter03;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class MemoryInfo : IWriter {

    /** The resulting PDF file. */
    public static readonly String RESULT
        = "memory_info.txt";
    public static readonly String RESULT0
        = "MovieTemplates.pdf";
    
    /**
     * Do a full read of a PDF file
     * @param writer a writer to a report file
     * @param filename the file to read
     * @throws IOException
     */
    public static void fullRead(StreamWriter writer, byte[] file){
        long before = GC.GetTotalMemory(true);
        PdfReader reader = new PdfReader(file);
        int num = reader.NumberOfPages;
        writer.WriteLine(String.Format("Number of pages: {0}", num));
        writer.WriteLine(String.Format("Memory used by full read: {0}",
                    GC.GetTotalMemory(true) - before));
        writer.Flush();
        reader.Close();
    }
    
    /**
     * Do a partial read of a PDF file
     * @param writer a writer to a report file
     * @param filename the file to read
     * @throws IOException
     */
    public static void partialRead(StreamWriter writer, byte[] file) {
        long before = GC.GetTotalMemory(true);
        PdfReader reader = new PdfReader(
                new RandomAccessFileOrArray(file), null);
        int num = reader.NumberOfPages;
        writer.WriteLine(String.Format("Number of pages: {0}", num));
        writer.WriteLine(String.Format("Memory used by partial read: {0}",
                    GC.GetTotalMemory(true) - before));
        writer.Flush();
        reader.Close();
    }
      

    /**
     * Makes sure all garbage is cleared from the memory.
     */
    private static void GarbageCollect()
    {
        try
        {
            GC.Collect();
            Thread.Sleep(200);
            GC.WaitForPendingFinalizers();
            Thread.Sleep(200);
            GC.Collect();
            Thread.Sleep(200);
            GC.WaitForPendingFinalizers();
            Thread.Sleep(200);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }
// ===========================================================================
    public void Write(Stream stream) {
        try
        {
            using (ZipFile zip = new ZipFile())
            {
                using (MemoryStream resultStream = new MemoryStream())
                {
                    using (StreamWriter sw = new StreamWriter(resultStream))
                    {
                        using (MemoryStream movies = new MemoryStream())
                        {
                            // step 1
                            MovieTemplates mt = new MovieTemplates();
                            mt.Write(movies);
                            zip.AddEntry(RESULT0, movies.ToArray());

                            // step 2
                            GarbageCollect();
                            // Do a full read
                            fullRead(sw, movies.ToArray());
                            // Do a partial read
                            partialRead(sw, movies.ToArray());
                            zip.AddEntry(RESULT, resultStream.ToArray());
                        }
                    }
                }
                zip.Save(stream);
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }    
// ===========================================================================
  }
}
SelectPages.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 iTextSharp.text;
using iTextSharp.text.pdf;
using Ionic.Zip;
using kuujinbo.iTextInAction2Ed.Chapter03;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class SelectPages : IWriter {
// ===========================================================================
	/** A resulting PDF file. */
    public const String RESULT1 = "timetable_stamper.pdf";
	/** A resulting PDF file. */
    public const String RESULT2 = "timetable_copy.pdf"; 
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      MovieTemplates mt = new MovieTemplates();
      byte[] pdf = Utility.PdfBytes(mt);
      PdfReader reader = new PdfReader(pdf);
      using (ZipFile zip = new ZipFile()) {
        reader.SelectPages("4-8");
        zip.AddEntry(RESULT1, ManipulateWithStamper(reader));
/*
 * can't figure out __WHY__, but if i don't reset the reader the example
 * will __NOT__ work!
 */
        reader = new PdfReader(pdf);
        reader.SelectPages("4-8"); 
        zip.AddEntry(RESULT2, ManipulateWithCopy(reader));       
        zip.AddEntry(Utility.ResultFileName(mt.ToString() + ".pdf"), pdf);
        zip.Save(stream);
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a new PDF based on the one in the reader
     * @param reader a reader with a PDF file
     */
    private byte[] ManipulateWithStamper(PdfReader reader) {
      using (MemoryStream ms = new MemoryStream()) {
        using ( PdfStamper stamper = new PdfStamper(reader, ms) ) {
        }
        return ms.ToArray();
      }    
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a new PDF based on the one in the reader
     * @param reader a reader with a PDF file
     */
    private byte[] ManipulateWithCopy(PdfReader reader) {
      using (MemoryStream ms = new MemoryStream()) {
        int n = reader.NumberOfPages;
        using (Document document = new Document()) {
          using (PdfCopy copy = new PdfCopy(document, ms)) {
            document.Open();
            for (int i = 0; i < n;) {
              copy.AddPage(copy.GetImportedPage(reader, ++i));
            }
          }
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
  }
}
ImportingPages1.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter03;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class ImportingPages1 : IWriter {
// ===========================================================================
    public const string RESULT = "time_table_imported1.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // Use old example to create PDF
      MovieTemplates mt = new MovieTemplates();
      byte[] pdf = Utility.PdfBytes(mt);
      using (ZipFile zip = new ZipFile()) { 
        using (MemoryStream ms = new MemoryStream()) {
          // step 1
          using (Document document = new Document()) {
            // step 2
            PdfWriter writer = PdfWriter.GetInstance(document, ms);
            // step 3
            document.Open();
            // step 4
            PdfPTable table = new PdfPTable(2);
            PdfReader reader = new PdfReader(pdf);
            int n = reader.NumberOfPages;
            PdfImportedPage page;
            for (int i = 1; i <= n; i++) {
              page = writer.GetImportedPage(reader, i);
              table.AddCell(Image.GetInstance(page));
            }
            document.Add(table);
          }
          zip.AddEntry(RESULT, ms.ToArray());           
        }
        zip.AddEntry(Utility.ResultFileName(mt.ToString() + ".pdf"), pdf);
        zip.Save(stream);
      }
   }
// ===========================================================================
  }
}
ImportingPages2.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter03;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class ImportingPages2 : IWriter {
// ===========================================================================
    public const string RESULT = "time_table_imported2.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // Use old example to create PDF
      MovieTemplates mt = new MovieTemplates();
      byte[] pdf = Utility.PdfBytes(mt);
      using (ZipFile zip = new ZipFile()) { 
        using (MemoryStream ms = new MemoryStream()) {
          // step 1
          using (Document document = new Document()) {
            // step 2
            PdfWriter writer = PdfWriter.GetInstance(document, ms);
            // step 3
            document.Open();
            // step 4
            PdfPTable table = new PdfPTable(2);
            PdfReader reader = new PdfReader(pdf);
            int n = reader.NumberOfPages;
            PdfImportedPage page;
            for (int i = 1; i <= n; i++) {
              page = writer.GetImportedPage(reader, i);
              table.DefaultCell.Rotation = -reader.GetPageRotation(i);
              table.AddCell(Image.GetInstance(page));
            }
            document.Add(table);
          }
          zip.AddEntry(RESULT, ms.ToArray());           
        }
        zip.AddEntry(Utility.ResultFileName(mt.ToString() + ".pdf"), pdf);
        zip.Save(stream);
      }      
    }
// ===========================================================================
  }
}
Layers.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class Layers : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const string SOURCE = "layers_orig.pdf";
    /** The resulting PDF. */
    public const string RESULT = "layers.pdf";    
// ---------------------------------------------------------------------------        
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) { 
        byte[] pdf = new Layers().CreatePdf();        

        // Create a reader
        PdfReader reader = new PdfReader(pdf);
        // step 1
        using (MemoryStream ms = new MemoryStream()) { 
          using (Document document = new Document(PageSize.A5.Rotate())) {
            // step 2
            PdfWriter writer = PdfWriter.GetInstance(document, ms);
            // step 3
            document.Open();
            // step 4
            PdfContentByte canvas = writer.DirectContent;
            PdfImportedPage page;
            BaseFont bf = BaseFont.CreateFont(
              BaseFont.ZAPFDINGBATS, "", BaseFont.EMBEDDED
            );
            for (int i = 0; i < reader.NumberOfPages; ) {
              page = writer.GetImportedPage(reader, ++i);
              canvas.AddTemplate(page, 1f, 0, 0.4f, 0.4f, 72, 50 * i);
              canvas.BeginText();
              canvas.SetFontAndSize(bf, 20);
              canvas.ShowTextAligned(
                Element.ALIGN_CENTER,
                ((char)(181 + i)).ToString(),
                496, 150 + 50 * i, 0
              );
              canvas.EndText();
            }
          }        
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.AddEntry(SOURCE, pdf);
        zip.Save(stream);
      }   
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document for PdfReader.
     */
    public byte[] CreatePdf() {
      // step 1
      using (MemoryStream ms = new MemoryStream()) {
        using (Document document = new Document(PageSize.POSTCARD, 30, 30, 30, 30)) {
        // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          PdfContentByte under = writer.DirectContentUnder;
          // Page 1: a rectangle
          DrawRectangle(
            under, PageSize.POSTCARD.Width, PageSize.POSTCARD.Height
          );
          under.SetRGBColorFill(0xFF, 0xD7, 0x00);
          under.Rectangle(
            5, 5, PageSize.POSTCARD.Width - 10, PageSize.POSTCARD.Height - 10
          );
          under.Fill();
          document.NewPage();
          // Page 2: an image
          DrawRectangle(
            under, PageSize.POSTCARD.Width, PageSize.POSTCARD.Height
          );
          Image img = Image.GetInstance(Path.Combine(
            Utility.ResourceImage, "loa.jpg"
          ));
          img.SetAbsolutePosition(
            (PageSize.POSTCARD.Width - img.ScaledWidth) / 2,
            (PageSize.POSTCARD.Height - img.ScaledHeight) / 2
          );
          document.Add(img);
          document.NewPage();
          // Page 3: the words "Foobar Film Festival"
          DrawRectangle(
            under, PageSize.POSTCARD.Width, PageSize.POSTCARD.Height
          );
          Paragraph p = new Paragraph(
            "Foobar Film Festival", new Font(Font.FontFamily.HELVETICA, 22)
          );
          p.Alignment = Element.ALIGN_CENTER;
          document.Add(p);
          document.NewPage();
          // Page 4: the words "SOLD OUT"
          DrawRectangle(under, PageSize.POSTCARD.Width, PageSize.POSTCARD.Height);
          PdfContentByte over = writer.DirectContent;
          over.SaveState();
          float sinus = (float)Math.Sin(Math.PI / 60);
          float cosinus = (float)Math.Cos(Math.PI / 60);
          BaseFont bf = BaseFont.CreateFont();
          over.BeginText();
          over.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
          over.SetLineWidth(1.5f);
          over.SetRGBColorStroke(0xFF, 0x00, 0x00);
          over.SetRGBColorFill(0xFF, 0xFF, 0xFF);
          over.SetFontAndSize(bf, 36);
          over.SetTextMatrix(cosinus, sinus, -sinus, cosinus, 50, 324);
          over.ShowText("SOLD OUT");
          over.SetTextMatrix(0, 0);
          over.EndText();
          over.RestoreState();
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Draws a rectangle
     * @param content the direct content layer
     * @param width the width of the rectangle
     * @param height the height of the rectangle
     */
    public static void DrawRectangle(
      PdfContentByte content, float width, float height) 
    {
      content.SaveState();
      PdfGState state = new PdfGState();
      state.FillOpacity = 0.6f;
      content.SetGState(state);
      content.SetRGBColorFill(0xFF, 0xFF, 0xFF);
      content.SetLineWidth(3);
      content.Rectangle(0, 0, width, height);
      content.FillStroke();
      content.RestoreState();
    }   
// ===========================================================================
  }
}
Superimposing.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class Superimposing : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const string SOURCE = "opening.pdf";
    /** The resulting PDF. */
    public const string RESULT = "festival_opening.pdf";    
// ---------------------------------------------------------------------------        
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) { 
        byte[] pdf = new Superimposing().CreatePdf();
        // Create a reader
        PdfReader reader = new PdfReader(pdf);
        using (MemoryStream ms = new MemoryStream()) {     
          // step 1
          using (Document document = new Document(PageSize.POSTCARD)) {
            // step 2
            PdfWriter writer = PdfWriter.GetInstance(document, ms);
            // step 3
            document.Open();
            // step 4
            PdfContentByte canvas = writer.DirectContent;
            PdfImportedPage page;
            for (int i = 1; i <= reader.NumberOfPages; i++) {
              page = writer.GetImportedPage(reader, i);
              canvas.AddTemplate(page, 1f, 0, 0, 1, 0, 0);
            }
          } 
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.AddEntry(SOURCE, pdf);
        zip.Save(stream);            
      }        
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document for PdfReader.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document(PageSize.POSTCARD, 30, 30, 30, 30)) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          PdfContentByte under = writer.DirectContentUnder;
          // page 1: rectangle
          under.SetRGBColorFill(0xFF, 0xD7, 0x00);
          under.Rectangle(5, 5,
              PageSize.POSTCARD.Width - 10, PageSize.POSTCARD.Height - 10);
          under.Fill();
          document.NewPage();
          // page 2: image
          Image img = Image.GetInstance(Path.Combine(
            Utility.ResourceImage, "loa.jpg"
          ));
          img.SetAbsolutePosition(
            (PageSize.POSTCARD.Width - img.ScaledWidth) / 2,
            (PageSize.POSTCARD.Height - img.ScaledHeight) / 2
          );
          document.Add(img);
          document.NewPage();
          // page 3: the words "Foobar Film Festival"
          Paragraph p = new Paragraph(
            "Foobar Film Festival", new Font(Font.FontFamily.HELVETICA, 22)
          );
          p.Alignment = Element.ALIGN_CENTER;
          document.Add(p);
          document.NewPage();
          // page 4: the words "SOLD OUT"
          PdfContentByte over = writer.DirectContent;
          over.SaveState();
          float sinus = (float)Math.Sin(Math.PI / 60);
          float cosinus = (float)Math.Cos(Math.PI / 60);
          BaseFont bf = BaseFont.CreateFont();
          over.BeginText();
          over.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
          over.SetLineWidth(1.5f);
          over.SetRGBColorStroke(0xFF, 0x00, 0x00);
          over.SetRGBColorFill(0xFF, 0xFF, 0xFF);
          over.SetFontAndSize(bf, 36);
          over.SetTextMatrix(cosinus, sinus, -sinus, cosinus, 50, 324);
          over.ShowText("SOLD OUT");
          over.SetTextMatrix(0, 0);
          over.EndText();
          over.RestoreState();
        }
        return ms.ToArray();
      }
    }  
// ===========================================================================
  }
}
Stationery.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.Data;
using System.Data.Common;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class Stationery : IWriter {
// ===========================================================================
    /** The original PDF. */
    public const string STATIONERY = "stationery.pdf";
    /** The resulting PDF. */
    public const string RESULT = "text_on_stationery.pdf";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
// create first PDF        
        byte[] stationary  = CreateStationary();
        zip.AddEntry(STATIONERY, stationary);
        zip.AddEntry(RESULT, CreatePdf(stationary));
        zip.Save(stream);
      }
    }
// --------------------------------------------------------------------------- 
    /**
     * Creates a PDF document.
     * @param stationary byte array of the new PDF document
     */   
    public byte[] CreatePdf(byte[] stationary) {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document(PageSize.A4, 36, 36, 72, 36)) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          //writer.CloseStream = false;
          UseStationary(writer, stationary);
          // step 3
          document.Open();
          // step 4
          string SQL = "SELECT country, id FROM film_country ORDER BY country";
          using (var c =  AdoDB.Provider.CreateConnection()) {
            c.ConnectionString = AdoDB.CS;
            using (DbCommand cmd = c.CreateCommand()) {
              cmd.CommandText = SQL;        
              c.Open();
              using (var r = cmd.ExecuteReader()) {
                while (r.Read()) {
                  document.Add(new Paragraph(
                    r["country"].ToString(), FilmFonts.BOLD
                  ));
                  document.Add(Chunk.NEWLINE);          
                  string id = r["id"].ToString();
                  foreach (Movie movie in PojoFactory.GetMovies(id, true)) {
                    document.Add(new Paragraph(
                      movie.MovieTitle, FilmFonts.BOLD
                    ));
                    if (!string.IsNullOrEmpty(movie.OriginalTitle)) {
                      document.Add(new Paragraph(
                        movie.OriginalTitle, FilmFonts.ITALIC
                      ));
                    }
                    document.Add(new Paragraph(
                      string.Format(
                        "Year: {0}; run length: {0} minutes",
                        movie.Year, movie.Duration
                      ), 
                      FilmFonts.NORMAL
                    ));
                    document.Add(PojoToElementFactory.GetDirectorList(movie));
                  }
                  document.NewPage();              
                }
              }
            }
          }
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------    
    /** Imported page with the stationery. */
    private PdfImportedPage page;

    /**
     * Initialize the imported page.
     * @param writer The PdfWriter
     */
    public void UseStationary(PdfWriter writer, byte[] stationary) {
      writer.PageEvent = new TemplateHelper(this);
      PdfReader reader = new PdfReader(stationary);
      page = writer.GetImportedPage(reader, 1);
    }
/*
 * ###########################################################################
 * Inner class to add template
 * ###########################################################################
*/
    class TemplateHelper : PdfPageEventHelper {
      private Stationery instance;
      public TemplateHelper() { }
      public TemplateHelper(Stationery instance) { 
        this.instance = instance;
      }
      /**
       * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
       *      com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
       */
      public override void OnEndPage(PdfWriter writer, Document document) {
        writer.DirectContentUnder.AddTemplate(instance.page, 0, 0);
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document.
     */
    public byte[] CreateStationary() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          writer.CloseStream = false;
          // step 3
          document.Open();
          // step 4
          PdfPTable table = new PdfPTable(1);
          table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
          table.AddCell(new Phrase("FOOBAR FILM FESTIVAL", FilmFonts.BOLD));
          document.Add(table);
          Font font = new Font(
            Font.FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f)
          );
          ColumnText.ShowTextAligned(
            writer.DirectContentUnder,
            Element.ALIGN_CENTER, new Phrase("FOOBAR FILM FESTIVAL", font),
            297.5f, 421, 45
          );
        }
        return ms.ToArray();
      }      
    }    
// ===========================================================================
  }
}
NUpTool.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class NUpTool : IWriter {
// ===========================================================================
    public const String RESULT = "result{0}up.pdf";
// ---------------------------------------------------------------------------     
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        // previous example
        Stationery s = new Stationery();
        byte[] stationary  = s.CreatePdf(s.CreateStationary());
        // reader for the src file
        PdfReader reader = new PdfReader(stationary);
        // initializations
        int pow = 1;
               
        do {
          Rectangle pageSize = reader.GetPageSize(1); 
          Rectangle newSize = (pow % 2) == 0 
            ? new Rectangle(pageSize.Width, pageSize.Height)
            : new Rectangle(pageSize.Height, pageSize.Width)
          ;
          Rectangle unitSize = new Rectangle(pageSize.Width, pageSize.Height);
          for (int i = 0; i < pow; i++) {
            unitSize = new Rectangle(unitSize.Height / 2, unitSize.Width);
          }
          int n = (int)Math.Pow(2, pow);
          int r = (int)Math.Pow(2, pow / 2);
          int c = n / r;           
          
          using (MemoryStream ms = new MemoryStream()) {
            // step 1
            using (Document document = new Document(newSize, 0, 0, 0, 0)) {
              // step 2
              PdfWriter writer = PdfWriter.GetInstance(document, ms);
              // step 3
              document.Open();
              // step 4
              PdfContentByte cb = writer.DirectContent;
              PdfImportedPage page;
              Rectangle currentSize;
              float offsetX, offsetY, factor;
              int total = reader.NumberOfPages;
              
              for (int i = 0; i < total; ) {
                if (i % n == 0) {
                  document.NewPage();
                }
                currentSize = reader.GetPageSize(++i);
                factor = Math.Min(
                    unitSize.Width / currentSize.Width,
                    unitSize.Height / currentSize.Height
                );
                offsetX = unitSize.Width * ((i % n) % c)
                  + (unitSize.Width - (currentSize.Width * factor)) / 2f
                ;
                offsetY = newSize.Height
                  - (unitSize.Height * (((i % n) / c) + 1))
                  + (unitSize.Height - (currentSize.Height * factor)) / 2f
                ;
                page = writer.GetImportedPage(reader, i);
                cb.AddTemplate(page, factor, 0, 0, factor, offsetX, offsetY);
              }
            }
            zip.AddEntry(string.Format(RESULT, n), ms.ToArray());
            ++pow;
          }
        } while (pow < 5); 
        zip.AddEntry(Utility.ResultFileName(s.ToString() + ".pdf"), stationary);
        zip.Save(stream);
      }
    }
// ===========================================================================
  }
}
TilingHero.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class TilingHero : IWriter {
// ===========================================================================
    public const String RESOURCE = "Hero.pdf";
    public const String RESULT = "superman.pdf";
// ---------------------------------------------------------------------------         
    public void Write(Stream stream) {
      // Creating a reader
      string resource = Path.Combine(Utility.ResourcePdf, RESOURCE);
      PdfReader reader = new PdfReader(resource);
      Rectangle pagesize = reader.GetPageSizeWithRotation(1); 
      using (ZipFile zip = new ZipFile()) {
        // step 1
        using (MemoryStream ms = new MemoryStream()) {
          using (Document document = new Document(pagesize)) {
            // step 2
            PdfWriter writer = PdfWriter.GetInstance(document, ms);
            // step 3
            document.Open();
            // step 4
            PdfContentByte content = writer.DirectContent;
            PdfImportedPage page = writer.GetImportedPage(reader, 1);
            // adding the same page 16 times with a different offset
            float x, y;
            for (int i = 0; i < 16; i++) {
              x = -pagesize.Width * (i % 4);
              y = pagesize.Height * (i / 4 - 3);
              content.AddTemplate(page, 4, 0, 0, 4, x, y);
              document.NewPage();
            }
          }
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.AddFile(resource, "");
        zip.Save(stream);
      }
    }
// ===========================================================================
  }
}
StampText.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter01;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class StampText : IWriter {
// ===========================================================================
  /** A resulting PDF file. */
    public const string RESULT1 = "hello1.pdf";
  /** A resulting PDF file. */
    public const string RESULT2 = "hello2.pdf";
  /** A resulting PDF file. */
    public const string RESULT3 = "hello3.pdf";
// ---------------------------------------------------------------------------        
    public void Write(Stream stream) {
      HelloWorldLandscape1 h1 = new HelloWorldLandscape1();
      byte[] h1b = Utility.PdfBytes(h1);
      HelloWorldLandscape2 h2 = new HelloWorldLandscape2();
      byte[] h2b = Utility.PdfBytes(h2);

      using (ZipFile zip = new ZipFile()) {
        zip.AddEntry(RESULT1, Stamp(h1b));
        zip.AddEntry(RESULT2, StampIgnoreRotation(h1b));
        zip.AddEntry(RESULT3, Stamp(h2b));

        zip.AddEntry(Utility.ResultFileName(h1.ToString() + ".pdf"), h1b);
        zip.AddEntry(Utility.ResultFileName(h2.ToString() + ".pdf"), h2b);
        zip.Save(stream);
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param resource the original PDF
     */
    public static byte[] Stamp(byte[] resource) {
      PdfReader reader = new PdfReader(resource);
      using (var ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          PdfContentByte canvas = stamper.GetOverContent(1);
          ColumnText.ShowTextAligned(
            canvas,
            Element.ALIGN_LEFT, 
            new Phrase("Hello people!"), 
            36, 540, 0
          );
        }
        return ms.ToArray();
      }
    }

    /**
     * Manipulates a PDF file
     * @param resource the original PDF
     */
    public static byte[] StampIgnoreRotation(byte[] resource) {
      PdfReader reader = new PdfReader(resource);
      using (var ms = new MemoryStream()) {
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          stamper.RotateContents = false;
          PdfContentByte canvas = stamper.GetOverContent(1);
          ColumnText.ShowTextAligned(
            canvas,
            Element.ALIGN_LEFT, 
            new Phrase("Hello people!"), 
            36, 540, 0
          );
        }
        return ms.ToArray();
      }    
    }    
// ===========================================================================
  }
}
TwoPasses.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 Ionic.Zip;
using System.Data;
using System.Data.Common;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class TwoPasses : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "page_x_of_y.pdf";
// ---------------------------------------------------------------------------         
    public void Write(Stream stream) {
      string SQL = "SELECT country, id FROM film_country ORDER BY country";
      using (ZipFile zip = new ZipFile()) {
        using (var ms = new MemoryStream()) {
          // FIRST PASS, CREATE THE PDF WITHOUT HEADER
          // step 1
          using (Document document = new Document(PageSize.A4, 36, 36, 54, 36)) {
            // step 2
            PdfWriter.GetInstance(document, ms);
            // step 3
            document.Open();
            // step 4
            using (var c =  AdoDB.Provider.CreateConnection()) {
              c.ConnectionString = AdoDB.CS;
              using (DbCommand cmd = c.CreateCommand()) {
                cmd.CommandText = SQL;          
                c.Open();
                using (var r = cmd.ExecuteReader()) {
                  while (r.Read()) {
                    document.Add(new Paragraph(
                      r["country"].ToString(), FilmFonts.BOLD
                    ));
                    document.Add(Chunk.NEWLINE);          
                    string id = r["id"].ToString();
                    foreach (Movie movie in PojoFactory.GetMovies(id, true)) {
                      document.Add(new Paragraph(
                        movie.MovieTitle, FilmFonts.BOLD
                      ));
                      if (!string.IsNullOrEmpty(movie.OriginalTitle)) {
                        document.Add(new Paragraph(
                          movie.OriginalTitle, FilmFonts.ITALIC
                        ));
                      }
                      document.Add(new Paragraph(string.Format(
                          "Year: {0}; run length: {0} minutes",
                          movie.Year, movie.Duration
                        ), 
                        FilmFonts.NORMAL
                      ));
                      document.Add(PojoToElementFactory.GetDirectorList(movie));
                    }
                    document.NewPage();              
                  }
                }
              }
            }
          }
          byte[] firstPass = ms.ToArray();
          zip.AddEntry("first-pass.pdf", firstPass);

          // SECOND PASS, ADD THE HEADER
          // Create a reader
          PdfReader reader = new PdfReader(firstPass);
          using (MemoryStream ms2 = new MemoryStream()) {
            // Create a stamper
            using (PdfStamper stamper = new PdfStamper(reader, ms2)) {
              // Loop over the pages and add a header to each page
              int n = reader.NumberOfPages;
              for (int i = 1; i <= n; i++) {
                GetHeaderTable(i, n).WriteSelectedRows(
                  0, -1, 34, 803, stamper.GetOverContent(i)
                );
              }
            }
            zip.AddEntry(RESULT, ms2.ToArray());
          }
        }
        zip.Save(stream);
      }        
    }
// ---------------------------------------------------------------------------    
    /**
     * Create a header table with page X of Y
     * @param x the page number
     * @param y the total number of pages
     * @return a table that can be used as header
     */
    public static PdfPTable GetHeaderTable(int x, int y) {
      PdfPTable table = new PdfPTable(2);
      table.TotalWidth = 527;
      table.LockedWidth = true;
      table.DefaultCell.FixedHeight = 20;
      table.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
      table.AddCell("FOOBAR FILMFESTIVAL");
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_RIGHT;
      table.AddCell(string.Format("Page {0} of {1}", x, y));
      return table;
    }    
// ===========================================================================
  }
}
InsertPages.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.Data;
using System.Data.Common;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class InsertPages : IWriter {
// ===========================================================================
    public const string RESULT1 = "inserted_pages.pdf";
    public const string RESULT2 = "reordered.pdf";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        Stationery s = new Stationery();
        StampStationery ss = new StampStationery();
        byte[] stationery  = s.CreateStationary();
        byte[] sStationery = ss.ManipulatePdf(
          ss.CreatePdf(), stationery
        );
        byte[] insertPages = ManipulatePdf(sStationery, stationery);
        zip.AddEntry(RESULT1, insertPages); 
        // reorder the pages in the PDF
        PdfReader reader = new PdfReader(insertPages);
        reader.SelectPages("3-41,1-2");
        using (MemoryStream ms = new MemoryStream()) {
          using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          }
          zip.AddEntry(RESULT2, ms.ToArray());
        }
        zip.AddEntry(Utility.ResultFileName(s.ToString() + ".pdf"), stationery);
        zip.AddEntry(Utility.ResultFileName(ss.ToString() + ".pdf"), sStationery);
        zip.Save(stream);          
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src
     * @param src the original PDF
     * @param stationery the resulting PDF
     */
    public byte[] ManipulatePdf(byte[] src, byte[] stationery) {
      ColumnText ct = new ColumnText(null);
      string SQL = 
@"SELECT country, id FROM film_country 
ORDER BY country
";        
      using (var c =  AdoDB.Provider.CreateConnection()) {
        c.ConnectionString = AdoDB.CS;
        using (DbCommand cmd = c.CreateCommand()) {
          cmd.CommandText = SQL;
          c.Open();
          using (var r = cmd.ExecuteReader()) {
            while (r.Read()) {
              ct.AddElement(new Paragraph(
                24, new Chunk(r["country"].ToString())
              ));
            }
          }
        }
      }
      // Create a reader for the original document and for the stationery
      PdfReader reader = new PdfReader(src);
      PdfReader rStationery = new PdfReader(stationery);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Create an imported page for the stationery
          PdfImportedPage page = stamper.GetImportedPage(rStationery, 1);
          int i = 0;
          // Add the content of the ColumnText object 
          while(true) {
          // Add a new page
            stamper.InsertPage(++i, reader.GetPageSize(1));
            // Add the stationary to the new page
            stamper.GetUnderContent(i).AddTemplate(page, 0, 0);
            // Add as much content of the column as possible
            ct.Canvas = stamper.GetOverContent(i);
            ct.SetSimpleColumn(36, 36, 559, 770);
            if (!ColumnText.HasMoreText(ct.Go()))
                break;
          }
        }
        return ms.ToArray();     
      }
    }    
// ===========================================================================
  }
}
FormInformation.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.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class FormInformation : IWriter {
// ===========================================================================
    public const string RESULT = "form_info.txt";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      string datasheet = Path.Combine(Utility.ResourcePdf, "datasheet.pdf"); 
      using (ZipFile zip = new ZipFile()) { 
        // Create a reader to extract info
        PdfReader reader = new PdfReader(datasheet);
        // Get the fields from the reader (read-only!!!)
        AcroFields form = reader.AcroFields;
        // Loop over the fields and get info about them 
        StringBuilder sb = new StringBuilder();       
        foreach (string key in form.Fields.Keys) {
          sb.Append(key);
          sb.Append(": ");
          switch (form.GetFieldType(key)) {
            case AcroFields.FIELD_TYPE_CHECKBOX:
              sb.Append("Checkbox");
              break;
            case AcroFields.FIELD_TYPE_COMBO:
              sb.Append("Combobox");
              break;
            case AcroFields.FIELD_TYPE_LIST:
              sb.Append("List");
              break;
            case AcroFields.FIELD_TYPE_NONE:
              sb.Append("None");
              break;
            case AcroFields.FIELD_TYPE_PUSHBUTTON:
              sb.Append("Pushbutton");
              break;
            case AcroFields.FIELD_TYPE_RADIOBUTTON:
              sb.Append("Radiobutton");
              break;
            case AcroFields.FIELD_TYPE_SIGNATURE:
              sb.Append("Signature");
              break;
            case AcroFields.FIELD_TYPE_TEXT:
              sb.Append("Text");
              break;
            default:
              sb.Append("?");
              break;
          }
          sb.Append(Environment.NewLine);
        } 
        
        // Get possible values for field "CP_1"
        sb.Append("Possible values for CP_1:");
        sb.Append(Environment.NewLine);
        string[] states = form.GetAppearanceStates("CP_1");
        for (int i = 0; i < states.Length; i++) {
          sb.Append(" - ");
          sb.Append(states[i]);
          sb.Append(Environment.NewLine);
        }

        // Get possible values for field "category"
        sb.Append("Possible values for category:");
        sb.Append(Environment.NewLine);
        states = form.GetAppearanceStates("category");
        for (int i = 0; i < states.Length - 1; i++) {
          sb.Append(states[i]);
          sb.Append(", ");
        }
        sb.Append(states[states.Length - 1]);
        
        zip.AddEntry(RESULT, sb.ToString());
        zip.AddFile(datasheet, "");
        zip.Save(stream);
      }      
    }
// ===========================================================================
  }
}
FillDataSheet.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
/*
 * only run on localhost; requires write permissions
 * to the specified directory on a real web server
*/
namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class FillDataSheet : IWriter {
// ===========================================================================
/** The original PDF file. */
    public const string DATASHEET = "datasheet.pdf";
/** Format for resulting PDF files. */
    public const string RESULT = "imdb{0}.pdf";    
// ---------------------------------------------------------------------------    
    public virtual void Write(Stream stream) {  
      using (ZipFile zip = new ZipFile()) { 
        // Get the movies
        IEnumerable movies = PojoFactory.GetMovies();
        string datasheet = Path.Combine(Utility.ResourcePdf, DATASHEET); 
        string className = this.ToString();            
        // Fill out the data sheet form with data
        foreach (Movie movie in movies) {
          if (movie.Year < 2007) continue;
          PdfReader reader = new PdfReader(datasheet);          
          string dest = string.Format(RESULT, movie.Imdb);
          using (MemoryStream ms = new MemoryStream()) {
            using (PdfStamper stamper = new PdfStamper(reader, ms)) {
              AcroFields fields = stamper.AcroFields;
              fields.GenerateAppearances = true;
              Fill(fields, movie);
              if (movie.Year == 2007) stamper.FormFlattening = true;
            }
            zip.AddEntry(dest, ms.ToArray());
          }         
        }
        zip.AddFile(datasheet, "");
        zip.Save(stream);
      }              
    }
// ---------------------------------------------------------------------------    
    /**
     * Fill out the fields using info from a Movie object.
     * @param form The form object
     * @param movie A movie POJO
     */
    public static void Fill(AcroFields form, Movie movie) {
      form.SetField("title", movie.MovieTitle);
      form.SetField("director", GetDirectors(movie));
      form.SetField("year", movie.Year.ToString());
      form.SetField("duration", movie.Duration.ToString());
      form.SetField("category", movie.entry.category.Keyword);
      foreach (Screening screening in movie.entry.Screenings) {
        form.SetField(screening.Location.Replace('.', '_'), "Yes");
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Gets the directors from a Movie object,
     * and concatenates them in a String.
     * @param movie a Movie object
     * @return a String containing director names
     */
    public static String GetDirectors(Movie movie) {
      List directors = movie.Directors;
      StringBuilder buf = new StringBuilder();
      foreach (Director director in directors) {
        buf.Append(director.GivenName);
        buf.Append(' ');
        buf.Append(director.Name);
        buf.Append(',');
        buf.Append(' ');
      }
      int i = buf.Length;
      if (i > 0) buf.Length = i - 2;
      return buf.ToString();
    }    
// ===========================================================================
  }
}
Concatenate.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 iTextSharp.text;
using iTextSharp.text.pdf;
using Ionic.Zip;
using kuujinbo.iTextInAction2Ed.Chapter02;
using kuujinbo.iTextInAction2Ed.Chapter05;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class Concatenate : IWriter {
// ===========================================================================
    public const string RESULT = "concatenated.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      MovieLinks1 ml = new MovieLinks1();
      MovieHistory mh = new MovieHistory();
      List pdf = new List() {
        Utility.PdfBytes(ml),
        Utility.PdfBytes(mh)
      };
      string[] names = {ml.ToString(), mh.ToString()};
      using (ZipFile zip = new ZipFile()) { 
        using (MemoryStream ms = new MemoryStream()) {
          // step 1
          using (Document document = new Document()) {
            // step 2
            using (PdfCopy copy = new PdfCopy(document, ms)) {
              // step 3
              document.Open();
              // step 4
              for (int i = 0; i < pdf.Count; ++i) {
                zip.AddEntry(Utility.ResultFileName(names[i] + ".pdf"), pdf[i]);
                PdfReader reader = new PdfReader(pdf[i]);
                // loop over the pages in that document
                int n = reader.NumberOfPages;
                for (int page = 0; page < n; ) {
                  copy.AddPage(copy.GetImportedPage(reader, ++page));
                }
              }
            }
          }
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.Save(stream);    
      }
    }
// ===========================================================================
  }
}
ConcatenateStamp.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter02;
using kuujinbo.iTextInAction2Ed.Chapter05;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class ConcatenateStamp : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const string RESULT = "concatenated_stamped.pdf";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {   
      using (ZipFile zip = new ZipFile()) { 
        MovieLinks1 ml = new MovieLinks1();
        byte[] r1 = Utility.PdfBytes(ml);
        MovieHistory mh = new MovieHistory();
        byte[] r2 = Utility.PdfBytes(mh);
        using (MemoryStream ms = new MemoryStream()) {
          // step 1
          using (Document document = new Document()) {
            // step 2
            using (PdfCopy copy = new PdfCopy(document, ms)) {
              // step 3
              document.Open();
              // step 4
              // reader for document 1
              PdfReader reader1 = new PdfReader(r1);
              int n1 = reader1.NumberOfPages;
              // reader for document 2
              PdfReader reader2 = new PdfReader(r2);
              int n2 = reader2.NumberOfPages;
              // initializations
              PdfImportedPage page;
              PdfCopy.PageStamp stamp;
              // Loop over the pages of document 1
              for (int i = 0; i < n1; ) {
                page = copy.GetImportedPage(reader1, ++i);
                stamp = copy.CreatePageStamp(page);
                // add page numbers
                ColumnText.ShowTextAligned(
                  stamp.GetUnderContent(), Element.ALIGN_CENTER,
                  new Phrase(string.Format("page {0} of {1}", i, n1 + n2)),
                  297.5f, 28, 0
                );
                stamp.AlterContents();
                copy.AddPage(page);
              }

              // Loop over the pages of document 2
              for (int i = 0; i < n2; ) {
                page = copy.GetImportedPage(reader2, ++i);
                stamp = copy.CreatePageStamp(page);
                // add page numbers
                ColumnText.ShowTextAligned(
                  stamp.GetUnderContent(), Element.ALIGN_CENTER,
                  new Phrase(string.Format("page {0} of {1}", n1 + i, n1 + n2)),
                  297.5f, 28, 0
                );
                stamp.AlterContents();
                copy.AddPage(page);
              }   
            }   
          }
          zip.AddEntry(RESULT, ms.ToArray());          
          zip.AddEntry(Utility.ResultFileName(ml.ToString() + ".pdf"), r1);       
          zip.AddEntry(Utility.ResultFileName(mh.ToString()+ ".pdf"), r2); 
        }
        zip.Save(stream);
      }       
    }
// ===========================================================================
  }
}
Burst.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 iTextSharp.text;
using iTextSharp.text.pdf;
using Ionic.Zip;
using kuujinbo.iTextInAction2Ed.Chapter03;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class Burst : IWriter {
// ===========================================================================
/** Format of the resulting PDF files. */
    public const string RESULT = "timetable_p{0}.pdf";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // use one of the previous examples to create a PDF
      MovieTemplates mt = new MovieTemplates();
      // Create a reader
      byte[] pdf = Utility.PdfBytes(mt);
      PdfReader reader = new PdfReader(pdf);
      // loop over all the pages in the original PDF
      int n = reader.NumberOfPages;      
      using (ZipFile zip = new ZipFile()) {
        for (int i = 0; i < n; ) {
          string dest = string.Format(RESULT, ++i);
          using (MemoryStream ms = new MemoryStream()) {
// We'll create as many new PDFs as there are pages
            // step 1
            using (Document document = new Document()) {
              // step 2
              using (PdfCopy copy = new PdfCopy(document, ms)) {
                // step 3
                document.Open();
                // step 4
                copy.AddPage(copy.GetImportedPage(reader, i));
              }
            }
            zip.AddEntry(dest, ms.ToArray());
          }
        }
        zip.AddEntry(Utility.ResultFileName(mt.ToString() + ".pdf"), pdf);
        zip.Save(stream);       
      }
    }
// ===========================================================================
  }
}
DataSheets1.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO; 
using System.Collections.Generic; 
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class DataSheets1 : FillDataSheet {
// ===========================================================================
    public new const string RESULT = "datasheets1.pdf";
    public readonly string DATASHEET_PATH = Path.Combine(Utility.ResourcePdf, DATASHEET);
// ---------------------------------------------------------------------------
    public override void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) { 
        using (MemoryStream ms = new MemoryStream()) {
          // step 1
          using (Document document = new Document()) {
            // step 2
            using (PdfCopy copy = new PdfCopy(document, ms)) {
              // step 3
              document.Open();
              // step 4
              AddDataSheets(copy);
            }
          }
          zip.AddEntry(RESULT, ms.ToArray());        
        }
        zip.AddFile(DATASHEET_PATH, "");
        zip.Save(stream);
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Fills out a data sheet, flattens it, and adds it to a combined PDF.
     * @param copy the PdfCopy instance (can also be PdfSmartCopy)
     */
    public void AddDataSheets(PdfCopy copy) {
      IEnumerable movies = PojoFactory.GetMovies();
      // Loop over all the movies and fill out the data sheet
      foreach (Movie movie in movies) {
        PdfReader reader = new PdfReader(DATASHEET_PATH);
        using (var ms = new MemoryStream()) {
          using (PdfStamper stamper = new PdfStamper(reader, ms)) {
            Fill(stamper.AcroFields, movie);
            stamper.FormFlattening = true;
          }
          reader = new PdfReader(ms.ToArray());
          copy.AddPage(copy.GetImportedPage(reader, 1));
        }
      }
    }    
// ===========================================================================
  }
}
DataSheets2.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;
/*
 * this creates a bit of overhead, so we only run on localhost;
*/
namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class DataSheets2 : DataSheets1 {
// ===========================================================================
    public new const string RESULT = "datasheets2.pdf";
// ---------------------------------------------------------------------------
    public override void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) { 
        using (MemoryStream ms = new MemoryStream()) {
          // step 1
          using (Document document = new Document()) {
            // step 2
            using (PdfSmartCopy copy = new PdfSmartCopy(document, ms)) {
              // step 3
              document.Open();
              // step 4
              AddDataSheets(copy);
            }
          }
          zip.AddEntry(RESULT, ms.ToArray());        
        }
        zip.AddFile(DATASHEET_PATH, "");
        zip.Save(stream);
      }    
    } 
// ===========================================================================
  }
}
ConcatenateForms1.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 Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class ConcatenateForms1 : IWriter {
// ===========================================================================
    public const string RESULT = "concatenated_forms1.pdf";
    /** The original PDF file. */
    public const string copyName = "datasheet.pdf";
    public readonly string DATASHEET = Path.Combine(
      Utility.ResourcePdf, copyName
    );
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        using (MemoryStream ms = new MemoryStream()) {
          // Create a PdfCopyFields object
          PdfCopyFields copy = new PdfCopyFields(ms);
          // add a document
          copy.AddDocument(new PdfReader(DATASHEET));
          // add a document
          copy.AddDocument(new PdfReader(DATASHEET));
          // close the PdfCopyFields object
          copy.Close();
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.AddFile(DATASHEET, "");
        zip.Save(stream);
      }
    }
// ===========================================================================
  }
}
ConcatenateForms2.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.Chapter06 {
  public class ConcatenateForms2 : IWriter {
// ===========================================================================
    public const string RESULT = "concatenated_forms2.pdf";
/** The original PDF file. */
    public const string copyName = "datasheet.pdf";
    public readonly string DATASHEET = Path.Combine(
      Utility.ResourcePdf, copyName
    );
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {   
      using (ZipFile zip = new ZipFile()) {
        using (MemoryStream ms = new MemoryStream()) {
          // Create a PdfCopyFields object
          PdfCopyFields copy = new PdfCopyFields(ms);
          // add a document
          copy.AddDocument(new PdfReader(RenameFieldsIn(
            DATASHEET, 1
          )));
          // add a document
          copy.AddDocument(new PdfReader(RenameFieldsIn(
            DATASHEET, 2
          )));
          // close the PdfCopyFields object
          copy.Close();
          zip.AddEntry(RESULT, ms.ToArray());            
        }
        zip.AddFile(DATASHEET, "");
        zip.Save(stream);        
      }     
    }
// ---------------------------------------------------------------------------    
    /**
     * Renames the fields in an interactive form.
     * @param datasheet the path to the original form
     * @param i a number that needs to be appended to the field names
     * @return a byte[] containing an altered PDF file
     */
    private static byte[] RenameFieldsIn(string datasheet, int i) {
      List form_keys = new List();
      using (var ms = new MemoryStream()) {
        // Create the stamper
        using (PdfStamper stamper = new PdfStamper(
          new PdfReader(datasheet), ms)) 
        {
          // Get the fields
          AcroFields form = stamper.AcroFields;
          // so we aren't hit with 'Collection was modified' exception
          foreach (string k in stamper.AcroFields.Fields.Keys) {
            form_keys.Add(k);
          }
          // Loop over the fields
          foreach (string key in form_keys) {
            // rename the fields
            form.RenameField(key, string.Format("{0}_{1}", key, i));
          }
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
  }
}
StampStationery.cs
/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using Ionic.Zip;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;

namespace kuujinbo.iTextInAction2Ed.Chapter06 {
  public class StampStationery : IWriter {
// ===========================================================================
    /** The original PDF file. */
    public const string ORIGINAL = "original.pdf";
    /** The resulting PDF. */
    public const string RESULT = "stamped_stationary.pdf";    
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        // previous example
        Stationery s = new Stationery();
        StampStationery ss = new StampStationery();
        byte[] stationery  = s.CreateStationary();
        byte[] sStationery = ss.CreatePdf();
        
        zip.AddEntry(RESULT, ManipulatePdf(sStationery, stationery));
        zip.AddEntry(ORIGINAL, sStationery); 
        zip.AddEntry(Utility.ResultFileName(s.ToString() + ".pdf"), stationery); 
        zip.Save(stream);
      }      
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param stationery a PDF that will be added as background
     */
    public byte[] ManipulatePdf(byte[] src, byte[] stationery) {
      // Create readers
      PdfReader reader = new PdfReader(src);
      PdfReader s_reader = new PdfReader(stationery);
      using (MemoryStream ms = new MemoryStream()) {
        // Create the stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Add the stationery to each page
          PdfImportedPage page = stamper.GetImportedPage(s_reader, 1);
          int n = reader.NumberOfPages;
          PdfContentByte background;
          for (int i = 1; i <= n; i++) {
            background = stamper.GetUnderContent(i);
            background.AddTemplate(page, 0, 0);
          }
        } 
        return ms.ToArray();   
      }
    }  
// ---------------------------------------------------------------------------
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdf() {
      string SQL = 
@"SELECT country, id FROM film_country 
ORDER BY country
";     
      using (MemoryStream ms = new MemoryStream()) {     
        // step 1
        using (Document document = new Document(PageSize.A4, 36, 36, 72, 36)) {
          // step 2
          PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4 
          using (var c =  AdoDB.Provider.CreateConnection()) {
            c.ConnectionString = AdoDB.CS;
            using (DbCommand cmd = c.CreateCommand()) {
              cmd.CommandText = SQL;           
              c.Open();
              using (var r = cmd.ExecuteReader()) {
                while (r.Read()) {
                  document.Add(new Paragraph(
                    r["country"].ToString(), FilmFonts.BOLD
                  ));
                  document.Add(Chunk.NEWLINE);
                  foreach (Movie movie in 
                      PojoFactory.GetMovies(r["id"].ToString(), true)) 
                  {
                    document.Add(new Paragraph(
                      movie.MovieTitle, FilmFonts.BOLD
                    ));
                    if (!string.IsNullOrEmpty(movie.OriginalTitle))
                        document.Add(
                          new Paragraph(movie.OriginalTitle, FilmFonts.ITALIC
                        ));
                    document.Add(new Paragraph(
                        String.Format(
                          "Year: {0}; run length: {1} minutes",
                          movie.Year, movie.Duration
                        ), 
                        FilmFonts.NORMAL
                    ));
                    document.Add(PojoToElementFactory.GetDirectorList(movie));
                  }
                  document.NewPage();              
                }
              }
            }
          }
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
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