iText in Action: Chapter 7: Making documents interactive

10th October 2015
admin-marketing

These examples were written in the context of Chapter 7 of the book "iText in Action - Second Edition".

NamedActions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class NamedActions {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/named_actions.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 {
        // Create a table with named actions
        Font symbol = new Font(FontFamily.SYMBOL, 20);
        PdfPTable table = new PdfPTable(4);
        table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        Chunk first = new Chunk(String.valueOf((char)220), symbol);
        first.setAction(new PdfAction(PdfAction.FIRSTPAGE));
        table.addCell(new Phrase(first));
        Chunk previous = new Chunk(String.valueOf((char)172), symbol);
        previous.setAction(new PdfAction(PdfAction.PREVPAGE));
        table.addCell(new Phrase(previous));
        Chunk next = new Chunk(String.valueOf((char)174), symbol);
        next.setAction(new PdfAction(PdfAction.NEXTPAGE));
        table.addCell(new Phrase(next));
        Chunk last = new Chunk(String.valueOf((char)222), symbol);
        last.setAction(new PdfAction(PdfAction.LASTPAGE));
        table.addCell(new Phrase(last));
        table.setTotalWidth(120);
        
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add the table to each page
        PdfContentByte canvas;
        for (int i = 0; i < reader.getNumberOfPages(); ) {
            canvas = stamper.getOverContent(++i);
            table.writeSelectedRows(0, -1, 696, 36, canvas);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new NamedActions().manipulatePdf(MovieTemplates.RESULT, RESULT);
    }
}
LinkActions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
 
import part1.chapter02.MovieLinks1;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.FilmFonts;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.SimpleNamedDestination;
 
public class LinkActions {
 
    /** The resulting PDF file. */
    public static final String RESULT1
        = "results/part2/chapter07/movie_links_1.pdf";
    /** The resulting PDF file. */
    public static final String RESULT2
        = "results/part2/chapter07/movie_links_2.pdf";
    /** The resulting XML file. */
    public static final String RESULT3
        = "results/part2/chapter07/destinations.xml";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLException
     */
    protected void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Open the database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        // Add text with a local destination
        Paragraph p = new Paragraph();
        Chunk top = new Chunk("Country List", FilmFonts.BOLD);
        top.setLocalDestination("top");
        p.add(top);
        document.add(p);
        // Add text with a link to an external URL
        Chunk imdb = new Chunk("Internet Movie Database", FilmFonts.ITALIC);
        imdb.setAction(new PdfAction(new URL("http://www.imdb.com/")));
        p = new Paragraph(
            "Click on a country, and you'll get a list of movies, containing links to the ");
        p.add(imdb);
        p.add(".");
        document.add(p);
        // Add text with a remote goto
        p = new Paragraph("This list can be found in a ");
        Chunk page1 = new Chunk("separate document");
        page1.setAction(new PdfAction("movie_links_1.pdf", 1));
        p.add(page1);
        p.add(".");
        document.add(p);
        document.add(Chunk.NEWLINE);
        // Get a list with countries from the database
        Statement stm = connection.createStatement();
        ResultSet rs = stm.executeQuery(
            "SELECT DISTINCT mc.country_id, c.country, count(*) AS c "
            + "FROM film_country c, film_movie_country mc WHERE c.id = mc.country_id "
            + "GROUP BY mc.country_id, country ORDER BY c DESC");
        // Loop over the countries
        while (rs.next()) {
            Paragraph country = new Paragraph(rs.getString("country"));
            country.add(": ");
            Chunk link = new Chunk(String.format("%d movies", rs.getInt("c")));
            link.setAction(
                PdfAction.gotoRemotePage("movie_links_1.pdf", rs.getString("country_id"), false, true));
            country.add(link);
            document.add(country);
        }
        document.add(Chunk.NEWLINE);
        // Add text with a local goto
        p = new Paragraph("Go to ");
        top = new Chunk("top");
        top.setAction(PdfAction.gotoLocalPage("top", false));
        p.add(top);
        p.add(".");
        document.add(p);
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Create an XML file with named destinations
     * @param src The path to the PDF with the destinations
     * @param dest The path to the XML file
     * @throws IOException
     */
    public void createXml(String src, String dest) throws IOException {
        PdfReader reader = new PdfReader(src);
        HashMap<String,String> map = SimpleNamedDestination.getNamedDestination(reader, false);
        SimpleNamedDestination.exportToXML(map, new FileOutputStream(dest),
                "ISO8859-1", true);
        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 {
        new MovieLinks1().createPdf(RESULT1);
        LinkActions actions = new LinkActions();
        actions.createPdf(RESULT2);
        actions.createXml(RESULT1, RESULT3);
    }
}
ConcatenateNamedDestinations.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
 * 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.chapter07;
 
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 com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.SimpleNamedDestination;
 
import part1.chapter02.MovieLinks1;
 
public class ConcatenateNamedDestinations {
 
    /** The resulting PDF file. */
    public static String RESULT1
        = "results/part2/chapter07/concatenated_links_1.pdf";
    /** The resulting PDF file. */
    public static String RESULT2
         = "results/part2/chapter07/concatenated_links_2.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 previous examples to create PDF files
        new MovieLinks1().createPdf(LinkActions.RESULT1);
        new LinkActions().createPdf(LinkActions.RESULT2);
        // Create readers.
        PdfReader[] readers = {
                new PdfReader(LinkActions.RESULT2),
                new PdfReader(LinkActions.RESULT1) };
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT1));
        // step 3
        document.open();
        // step 4
        int n;
        // copy the pages of the different PDFs into one document
        for (int i = 0; i < readers.length; i++) {
            readers[i].consolidateNamedDestinations();
            n = readers[i].getNumberOfPages();
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(readers[i], ++page));
            }
        }
        // Add named destination  
        copy.addNamedDestinations(
            // from the second document
            SimpleNamedDestination.getNamedDestination(readers[1], false),
            // using the page count of the first document as offset
            readers[0].getNumberOfPages());
        // step 5
        document.close();
        readers[0].close();
        readers[1].close();
        
        // Create a reader
        PdfReader reader = new PdfReader(RESULT1);
        // Convert the remote destinations into local destinations
        reader.makeRemoteNamedDestinationsLocal();
        // Create a new PDF containing the local destinations
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(RESULT2));
        stamper.close();
        reader.close();
    }
}
TimetableDestinations.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableDestinations {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/timetable_destinations.pdf";
    /** The font that is used for the navigation links. */
    public static final Font SYMBOL = new Font(FontFamily.SYMBOL, 20);
    /** A list to cache all the possible actions */
    public List<PdfAction> actions;
 
    /**
     * 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 {
        // Create the reader
        PdfReader reader = new PdfReader(src);
        int n = reader.getNumberOfPages();
        // Create the stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Make a list with all the possible actions
        actions = new ArrayList<PdfAction>();
        PdfDestination d;
        for (int i = 0; i < n; ) {
            d = new PdfDestination(PdfDestination.FIT);
            actions.add(PdfAction.gotoLocalPage(++i, d, stamper.getWriter()));
        }
        // Add a navigation table to every page
        PdfContentByte canvas;
        for (int i = 0; i < n; ) {
            canvas = stamper.getOverContent(++i);
            createNavigationTable(i, n).writeSelectedRows(0, -1, 696, 36, canvas);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
    
    /**
     * Create a table that can be used as a footer
     * @param pagenumber the page that will use the table as footer
     * @param total the total number of pages
     * @return a tabel
     */
    public PdfPTable createNavigationTable(int pagenumber, int total) {
        PdfPTable table = new PdfPTable(4);
        table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        Chunk first = new Chunk(String.valueOf((char)220), SYMBOL);
        first.setAction(actions.get(0));
        table.addCell(new Phrase(first));
        Chunk previous = new Chunk(String.valueOf((char)172), SYMBOL);
        previous.setAction(actions.get(pagenumber - 2 < 0 ? 0 : pagenumber - 2));
        table.addCell(new Phrase(previous));
        Chunk next = new Chunk(String.valueOf((char)174), SYMBOL);
        next.setAction(actions.get(pagenumber >= total ? total - 1 : pagenumber));
        table.addCell(new Phrase(next));
        Chunk last = new Chunk(String.valueOf((char)222), SYMBOL);
        last.setAction(actions.get(total - 1));
        table.addCell(new Phrase(last));
        table.setTotalWidth(120);
        return table;
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */   
    public static void main(String[] args) 
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new TimetableDestinations().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
AddVersionChecker.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import part1.chapter01.HelloWorld;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
public class AddVersionChecker {
 
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/version_checker.pdf";
    /** Path to a resource. */
    public static final String RESOURCE
        = "resources/js/viewer_version.js";
 
    /**
     * 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
        HelloWorld.main(args);
        // Create a reader
        PdfReader reader = new PdfReader(HelloWorld.RESULT);
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(RESULT));
        // Add some javascript
        stamper.addJavaScript(Utilities.readFileToString(RESOURCE));
        // Close the stamper
        stamper.close();
        reader.close();
    }
}
FindDirectors.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * 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.chapter07;
 
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
import part1.chapter04.NestedTables;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
 
public class FindDirectors {
    
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/find_directors.pdf";
 
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/js/find_director.js";
    
    /**
     * Creates a PDF file with director names.
     * @param filename the name of the PDF file that needs to be created.
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection and statement
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        Statement stm = connection.createStatement();
        // step 1
        Document tmp = new Document();
        // step 2
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(tmp, baos);
        // step 3
        tmp.open();
        // step 4
        ResultSet rs = stm.executeQuery(
           "SELECT name, given_name FROM film_director ORDER BY name, given_name");
        while (rs.next()) {
            tmp.add(createDirectorParagraph(writer, rs));
        }
        // step 5
        tmp.close();
        // Close the database connection and statement
        stm.close();
        connection.close();
        
        // Create readers
        PdfReader[] readers = {
                new PdfReader(baos.toByteArray()),
                new PdfReader(NestedTables.RESULT) };
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        copy.addJavaScript(Utilities.readFileToString(RESOURCE));
        int n;
        for (int i = 0; i < readers.length; i++) {
            n = readers[i].getNumberOfPages();
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(readers[i], ++page));
            }
        }
        // step 5
        document.close();
        readers[0].close();
        readers[1].close();
    }
    
    /**
     * Creates a Phrase with the name and given name of a director
     * using different fonts.
     * @param rs the ResultSet containing director records.
     */
    public Paragraph createDirectorParagraph(PdfWriter writer, ResultSet rs)
        throws UnsupportedEncodingException, SQLException {
        String n = new String(rs.getBytes("name"), "UTF-8");
        Chunk name = new Chunk(n);
        name.setAction(PdfAction.javaScript(
                String.format("findDirector('%s');", n), writer));
        name.append(", ");
        name.append(new String(rs.getBytes("given_name"), "UTF-8"));
        return new Paragraph(name);
    }
    
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        NestedTables.main(args);
        new FindDirectors().createPdf(RESULT);
    }
}
LaunchAction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfWriter;
 
public class LaunchAction {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/launch_action.pdf";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
    throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        Paragraph p = new Paragraph(new Chunk(
            "Click to open test.txt in Notepad.")
            .setAction(new PdfAction("c:/windows/notepad.exe",
            "test.txt", "open", "C:\\itext-core\\book\\resources\\txt")));
        document.add(p);
        // step 5
        document.close();
    }
    
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        new LaunchAction().createPdf(RESULT);
    }
}
PrintTimeTable.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import part1.chapter03.MovieTemplates;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
public class PrintTimeTable {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/print_timetable.pdf";
 
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/js/print_page.js";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param resource a resource that will be used as advertisement
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
        // Create the reader
        PdfReader reader = new PdfReader(src);
        int n = reader.getNumberOfPages();
        // Create the stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add JavaScript
        stamper.addJavaScript(Utilities.readFileToString(RESOURCE));
        // Create a Chunk with a chained action
        PdfContentByte canvas;
        Chunk chunk = new Chunk("print this page");
        PdfAction action = PdfAction.javaScript(
            "app.alert('Think before you print!');", stamper.getWriter());
        action.next(PdfAction.javaScript(
            "printCurrentPage(this.pageNum);", stamper.getWriter()));
        action.next(new PdfAction("http://www.panda.org/savepaper/"));
        chunk.setAction(action);
        Phrase phrase = new Phrase(chunk);
        // Add this Chunk to every page
        for (int i = 0; i < n; ) {
            canvas = stamper.getOverContent(++i);
            ColumnText.showTextAligned(
                canvas, Element.ALIGN_RIGHT, phrase, 816, 18, 0);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new PrintTimeTable().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
EventsAndActions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import part1.chapter03.MovieTemplates;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
 
public class EventsAndActions {
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/events_and_actions.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param resource a resource that will be used as advertisement
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader,
                new FileOutputStream(dest));
        // Get the writer (to add actions and annotations)
        PdfWriter writer = stamper.getWriter();
        PdfAction action = PdfAction.gotoLocalPage(2,
            new PdfDestination(PdfDestination.FIT), writer);
        writer.setOpenAction(action);
        action = PdfAction.javaScript(
            "app.alert('Think before you print');", writer);
        writer.setAdditionalAction(PdfWriter.WILL_PRINT, action);
        action = PdfAction.javaScript(
            "app.alert('Think again next time!');", writer);
        writer.setAdditionalAction(PdfWriter.DID_PRINT, action);
        action = PdfAction.javaScript(
            "app.alert('We hope you enjoy the festival');", writer);
        writer.setAdditionalAction(PdfWriter.DOCUMENT_CLOSE, action);
        action = PdfAction.javaScript(
            "app.alert('This day is reserved for people with an accreditation "
            + "or an invitation.');", writer);
        stamper.setPageAction(PdfWriter.PAGE_OPEN, action, 1);
        action = PdfAction.javaScript(
            "app.alert('You can buy tickets for all the other days');", writer);
        stamper.setPageAction(PdfWriter.PAGE_CLOSE, action, 1);
        // Close the stamper
        stamper.close();
        reader.close();
    }
    
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new EventsAndActions().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
CreateOutlineTree.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
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.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfDestination;
import com.itextpdf.text.pdf.PdfOutline;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.pdf.SimpleBookmark;
 
public class CreateOutlineTree {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/outline_tree.pdf";
    /** An XML representing the outline tree */
    public static final String RESULTXML
        = "results/part2/chapter07/outline_tree.xml";
    /** Pattern of the IMDB urls */
    public static final String RESOURCE
        = "http://imdb.com/title/tt%s/";
    /** JavaScript snippet. */
    public static final String INFO
        = "app.alert('Movie produced in %s; run length: %s');";
 
    /**
     * 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 {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filename));
        writer.setViewerPreferences(PdfWriter.PageModeUseOutlines);
        // step 3
        document.open();
        // step 4
        PdfOutline root = writer.getRootOutline();
        PdfOutline movieBookmark;
        PdfOutline link;
        String title;
        List<Movie> movies = PojoFactory.getMovies(connection);
        for (Movie movie : movies) {
            title = movie.getMovieTitle();
            if ("3-Iron".equals(title))
                title = "\ube48\uc9d1";
            movieBookmark = new PdfOutline(root, 
                new PdfDestination(
                    PdfDestination.FITH, writer.getVerticalPosition(true)),
                title, true);
            movieBookmark.setStyle(Font.BOLD);
            link = new PdfOutline(movieBookmark,
                new PdfAction(String.format(RESOURCE, movie.getImdb())),
                "link to IMDB");
            link.setColor(BaseColor.BLUE);
            new PdfOutline(movieBookmark,
                PdfAction.javaScript(
                    String.format(INFO, movie.getYear(), movie.getDuration()), writer),
                    "instant info");
            document.add(new Paragraph(movie.getMovieTitle()));
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Creates an XML file with the bookmarks of a PDF file.
     * @param src the path to the PDF file with the bookmarks
     * @param dest the path to the XML file
     * @throws IOException
     */
    public void createXml(String src, String dest) throws IOException {
        PdfReader reader = new PdfReader(src);
        List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(reader);
        SimpleBookmark.exportToXML(list,
                new FileOutputStream(dest), "ISO8859-1", true);
        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 {
        CreateOutlineTree example = new CreateOutlineTree();
        example.createPdf(RESULT);
        example.createXml(RESULT, RESULTXML);
    }
}
BookmarkedTimeTable.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import part1.chapter03.MovieTemplates;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
public class BookmarkedTimeTable {
    
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/time_table_bookmarks.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
     * @throws SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // Create a list with bookmarks
        ArrayList<HashMap<String, Object>> outlines = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> map = new HashMap<String, Object>();
        outlines.add(map);
        map.put("Title", "Calendar");
        ArrayList<HashMap<String, Object>> kids = new ArrayList<HashMap<String, Object>>();
        map.put("Kids", kids);
        int page = 1;
        List<Date> days = PojoFactory.getDays(connection);
        for (Date day : days) {
            HashMap<String, Object> kid = new HashMap<String, Object>();
            kids.add(kid);
            kid.put("Title", day.toString());
            kid.put("Action", "GoTo");
            kid.put("Page", String.format("%d Fit", page++));
        }
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.setOutlines(outlines);
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Main method creating the PDF.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException 
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new BookmarkedTimeTable().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
ConcatenateBookmarks.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import part1.chapter02.MovieHistory;
 
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.SimpleBookmark;
 
public class ConcatenateBookmarks {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/concatenated_bookmarks.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 {
        // step 1
        Document document = new Document();
        // step 2
        PdfCopy copy
            = new PdfCopy(document, new FileOutputStream(dest));
        // step 3
        document.open();
        // step 4
        PdfReader reader;
        int page_offset = 0;
        int n;
        // Create a list for the bookmarks
        ArrayList<HashMap<String, Object>> bookmarks = new ArrayList<HashMap<String, Object>>();
        List<HashMap<String, Object>> tmp;
        for (int i  = 0; i < src.length; i++) {
            reader = new PdfReader(src[i]);
            // merge the bookmarks
            tmp = SimpleBookmark.getBookmark(reader);
            SimpleBookmark.shiftPageNumbers(tmp, page_offset, null);
            bookmarks.addAll(tmp);
            // add the pages
            n = reader.getNumberOfPages();
            page_offset += n;
            for (int page = 0; page < n; ) {
                copy.addPage(copy.getImportedPage(reader, ++page));
            }
            copy.freeReader(reader);
            reader.close();
        }
        // Add the merged bookmarks
        copy.setOutlines(bookmarks);
        // step 5
        document.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        BookmarkedTimeTable.main(args);
        MovieHistory.main(args);
        new ConcatenateBookmarks().manipulatePdf(
            new String[]{BookmarkedTimeTable.RESULT, MovieHistory.RESULT},
            RESULT);
    }
}
MovieAnnotations1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.PojoToElementFactory;
import com.itextpdf.text.Annotation;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieAnnotations1 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/movie_annotations_1.pdf";
    /** Pattern for an info String. */
    public static final String INFO
        = "Movie produced in %s; run length: %s";
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     * @throws    SQLExcception
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        for (Movie movie : PojoFactory.getMovies(connection)) {
            document.add(new Phrase(movie.getMovieTitle()));
            document.add(new Annotation(movie.getTitle(),
                String.format(INFO, movie.getYear(), movie.getDuration())));
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieAnnotations1 example = new MovieAnnotations1();
        example.createPdf(RESULT);
    }
}
MovieAnnotations2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
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.Phrase;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieAnnotations2 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/movie_annotations_2.pdf";
    /** Pattern for an info String. */
    public static final String INFO
        = "Movie produced in %s; run length: %s";
 
    /**
     * 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 {
        // Open the database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        Phrase phrase;
        Chunk chunk;
        for (Movie movie : PojoFactory.getMovies(connection)) {
            phrase = new Phrase(movie.getMovieTitle());
            chunk = new Chunk("\u00a0");
            chunk.setAnnotation(
                PdfAnnotation.createText(writer, null, movie.getMovieTitle(),
                String.format(INFO, movie.getYear(), movie.getDuration()),
                false, "Comment"));
            phrase.add(chunk);
            document.add(phrase);
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // step 5
        document.close();
        // close the database connection
        connection.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieAnnotations2 example = new MovieAnnotations2();
        example.createPdf(RESULT);
    }
}
GenericAnnotations.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfBoolean;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.VerticalPositionMark;
 
public class GenericAnnotations extends PdfPageEventHelper {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/generic_annotations.pdf";
    /** Possible icons. */
    public static final String[] ICONS = {
        "Comment", "Key", "Note", "Help", "NewParagraph", "Paragraph", "Insert"
    };
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setPageEvent(new GenericAnnotations());
        // step 3
        document.open();
        // step 4
        Paragraph p = new Paragraph();
        Chunk chunk;
        Chunk tab = new Chunk(new VerticalPositionMark());
        for (int i = 0; i < ICONS.length; i++) {
            chunk = new Chunk(ICONS[i]);
            chunk.setGenericTag(ICONS[i]);
            p.add(chunk);
            p.add(tab);
        }
        document.add(p);
        // step 5
        document.close();
    }
 
    /**
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onGenericTag(
     *      com.itextpdf.text.pdf.PdfWriter,
     *      com.itextpdf.text.Document,
     *      com.itextpdf.text.Rectangle, java.lang.String)
     */
    @Override
    public void onGenericTag(PdfWriter writer,
        Document document, Rectangle rect, String text) {
        PdfAnnotation annotation = new PdfAnnotation(writer,
            new Rectangle(
                rect.getRight() + 10, rect.getBottom(),
                rect.getRight() + 30, rect.getTop()));
        annotation.setTitle("Text annotation");
        annotation.put(PdfName.SUBTYPE, PdfName.TEXT);
        annotation.put(PdfName.OPEN, PdfBoolean.PDFFALSE);
        annotation.put(PdfName.CONTENTS,
            new PdfString(String.format("Icon: %s", text)));
        annotation.put(PdfName.NAME, new PdfName(text));
        writer.addAnnotation(annotation);
    }
    
}
TimetableAnnotations1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;
import java.util.TimeZone;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.html.WebColors;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableAnnotations1 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/timetable_help.pdf";
    /** A pattern for an info string. */
    public static final String INFO
        = "Movie produced in %s; run length: %s";
 
    static {
        TimeZone.setDefault(TimeZone.getTimeZone("Europe/Brussels"));
    }
 
    /**
     * 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 SQLException, IOException, DocumentException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        locations = PojoFactory.getLocations(connection);
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add the annotations
        int page = 1;
        Rectangle rect;
        PdfAnnotation annotation;
        Movie movie;
        for (Date day : PojoFactory.getDays(connection)) {
            for (Screening screening : PojoFactory.getScreenings(connection, day)) {
                movie = screening.getMovie();
                rect = getPosition(screening);
                annotation = PdfAnnotation.createText(
                    stamper.getWriter(), rect, movie.getMovieTitle(),
                    String.format(INFO, movie.getYear(), movie.getDuration()),
                    false, "Help");
                annotation.setColor(WebColors.getRGBColor(
                    "#" + movie.getEntry().getCategory().getColor()));
                stamper.addAnnotation(annotation, page);
            }
            page++;
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Calculates the position of a rectangle corresponding with a screening.
     * @param    screening    a screening POJO, contains a movie
     * @return    a Rectangle
     */
    protected Rectangle getPosition(Screening screening) {
        float llx, lly, urx, ury;
        long minutesAfter930 = (screening.getTime().getTime() - TIME930) / 60000l;
        llx = OFFSET_LEFT + (MINUTE * minutesAfter930);
        int location = locations.indexOf(screening.getLocation()) + 1;
        lly = OFFSET_BOTTOM + (LOCATIONS - location) * HEIGHT_LOCATION;
        urx = llx + MINUTE * screening.getMovie().getDuration();
        ury = lly + HEIGHT_LOCATION;
        Rectangle rect = new Rectangle(llx, lly, urx, ury);
        return rect;
    }
 
    /** A list containing all the locations. */
    protected List<String> locations;
    
    /** The number of locations on our time table. */
    public static final int LOCATIONS = 9;
    /** The number of time slots on our time table. */
    public static final int TIMESLOTS = 32;
    /** The "offset time" for our calendar sheets. */
    public static final long TIME930 = 30600000l;
    /** The offset to the left of our time table. */
    public static final float OFFSET_LEFT = 76;
    /** The width of our time table. */
    public static final float WIDTH = 740;
    /** The width of a time slot. */
    public static final float WIDTH_TIMESLOT = WIDTH / TIMESLOTS;
    /** The width of one minute. */
    public static final float MINUTE = WIDTH_TIMESLOT / 30f;
    /** The offset from the bottom of our time table. */
    public static final float OFFSET_BOTTOM = 36;
    /** The height of our time table */
    public static final float HEIGHT = 504;
    /** The height of a bar showing the movies at one specific location. */
    public static final float HEIGHT_LOCATION = HEIGHT / LOCATIONS;
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new TimetableAnnotations1().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
MoviePosters1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.Annotation;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MoviePosters1 {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/movie_posters_1.pdf";
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
    /** Path to IMDB. */
    public static final String IMDB
        = "http://imdb.com/title/tt%s/";
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document(PageSize.A4);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        PdfContentByte canvas = writer.getDirectContent();
        // Create a reusable XObject
        PdfTemplate celluloid = canvas.createTemplate(595, 84.2f);
        celluloid.rectangle(8, 8, 579, 68);
        for (float f = 8.25f; f < 581; f+= 6.5f) {
            celluloid.roundRectangle(f, 8.5f, 6, 3, 1.5f);
            celluloid.roundRectangle(f, 72.5f, 6, 3, 1.5f);
        }
        celluloid.setGrayFill(0.1f);
        celluloid.eoFill();
        writer.releaseTemplate(celluloid);
        // Add the XObject ten times
        for (int i = 0; i < 10; i++) {
            canvas.addTemplate(celluloid, 0, i * 84.2f);
        }
        // Add the movie posters
        Image img;
        Annotation annotation;
        float x = 11.5f;
        float y = 769.7f;
        for (Movie movie : PojoFactory.getMovies(connection)) {
            img = Image.getInstance(String.format(RESOURCE, movie.getImdb()));
            img.scaleToFit(1000, 60);
            img.setAbsolutePosition(x + (45 - img.getScaledWidth()) / 2, y);
            annotation = new Annotation(0, 0, 0, 0,
                String.format(IMDB, movie.getImdb()));
            img.setAnnotation(annotation);
            canvas.addImage(img);
            x += 48;
            if (x > 578) {
                x = 11.5f;
                y -= 84.2f;
            }
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        new MoviePosters1().createPdf(RESULT);
    }
}
TimetableAnnotations2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableAnnotations2 extends TimetableAnnotations1 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/timetable_links.pdf";
    /** Path to IMDB. */
    public static final String IMDB
        = "http://imdb.com/title/tt%s/";
 
    /**
     * 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 SQLException, IOException, DocumentException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        locations = PojoFactory.getLocations(connection);
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Add annotations for every screening
        int page = 1;
        Rectangle rect;
        PdfAnnotation annotation;
        for (Date day : PojoFactory.getDays(connection)) {
            for (Screening screening : PojoFactory.getScreenings(connection, day)) {
                rect = getPosition(screening);
                annotation = PdfAnnotation.createLink(
                    stamper.getWriter(), rect, PdfAnnotation.HIGHLIGHT_INVERT,
                    new PdfAction(String.format(IMDB, screening.getMovie().getImdb())));
                stamper.addAnnotation(annotation, page);
            }
            page++;
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new TimetableAnnotations2().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
MovieAnnotations3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
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.Phrase;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.PdfWriter;
 
public class MovieAnnotations3 {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/movie_annotations_3.pdf";
    /** Path to the resources. */
    public static final String RESOURCE
        = "resources/posters/%s.jpg";
 
    /**
     * 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 {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        // step 4
        Phrase phrase;
        Chunk chunk;
        PdfAnnotation annotation;
        for (Movie movie : PojoFactory.getMovies(connection)) {
            phrase = new Phrase(movie.getMovieTitle());
            chunk = new Chunk("\u00a0\u00a0");
            annotation = PdfAnnotation.createFileAttachment(writer, null,
                    movie.getMovieTitle(), null,
                    String.format(RESOURCE, movie.getImdb()),
                    String.format("img_%s.jpg", movie.getImdb()));
            annotation.put(PdfName.NAME, new PdfString("Paperclip"));
            chunk.setAnnotation(annotation);
            phrase.add(chunk);
            document.add(phrase);
            document.add(PojoToElementFactory.getDirectorList(movie));
            document.add(PojoToElementFactory.getCountryList(movie));
        }
        // step 5
        document.close();
        // Close the database connection
        connection.close();
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, DocumentException, SQLException {
        MovieAnnotations3 example = new MovieAnnotations3();
        example.createPdf(RESULT);
    }
}
TimetableAnnotations3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
 
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.lowagie.filmfestival.Screening;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfBorderArray;
import com.itextpdf.text.pdf.PdfBorderDictionary;
import com.itextpdf.text.pdf.PdfDashPattern;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.BaseColor;
 
import part1.chapter03.MovieTemplates;
 
public class TimetableAnnotations3 extends TimetableAnnotations1 {
    /** The resulting PDF file. */
    public static final String RESULT = "results/part2/chapter07/timetable_tickets.pdf";
    /** Path to IMDB. */
    public static final String IMDB = "http://imdb.com/title/tt%s/";
 
    /**
     * 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 SQLException, IOException, DocumentException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        locations = PojoFactory.getLocations(connection);
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Loop over the days and screenings
        int page = 1;
        Rectangle rect;
        float top;
        PdfAnnotation annotation;
        Movie movie;
        for (Date day : PojoFactory.getDays(connection)) {
            for (Screening screening : PojoFactory.getScreenings(connection, day)) {
                rect = getPosition(screening);
                movie = screening.getMovie();
                // Annotation for press previews
                if (screening.isPress()) {
                    annotation = PdfAnnotation.createStamp(stamper.getWriter(),
                        rect, "Press only", "NotForPublicRelease");
                    annotation.setColor(BaseColor.BLACK);
                    annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
                }
                // Annotation for screenings that are sold out
                else if (isSoldOut(screening)) {
                    top = reader.getPageSizeWithRotation(page).getTop();
                    annotation = PdfAnnotation.createLine(
                        stamper.getWriter(), rect, "SOLD OUT",
                        top - rect.getTop(), rect.getRight(),
                        top - rect.getBottom(), rect.getLeft());
                    annotation.setTitle(movie.getMovieTitle());
                    annotation.setColor(BaseColor.WHITE);
                    annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
                    annotation.setBorderStyle(
                        new PdfBorderDictionary(5, PdfBorderDictionary.STYLE_SOLID));
                }
                // Annotation for screenings with tickets available
                else {
                    annotation = PdfAnnotation.createSquareCircle(
                        stamper.getWriter(), rect, "Tickets available", true);
                    annotation.setTitle(movie.getMovieTitle());
                    annotation.setColor(BaseColor.BLUE);
                    annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
                    annotation.setBorder(new PdfBorderArray(0, 0, 2, new PdfDashPattern()));
                }
                stamper.addAnnotation(annotation, page);
            }
            page++;
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Checks if the screening has been sold out.
     * @param screening a Screening POJO
     * @return true if the screening has been sold out.
     */
    public boolean isSoldOut(Screening screening) {
        if (screening.getMovie().getMovieTitle().startsWith("L"))
            return true;
        return false;
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args) 
        throws IOException, DocumentException, SQLException {
        MovieTemplates.main(args);
        new TimetableAnnotations3().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
ButtonsActions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
import part1.chapter03.MovieTemplates;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
import com.itextpdf.text.BaseColor;
 
public class ButtonsActions {
 
    /** The resulting PDF. */
    public static final String RESULT
        = "results/part2/chapter07/save_mail_timetable.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 {
        // Create a reader
        PdfReader reader = new PdfReader(src);
        int n = reader.getNumberOfPages();
        // Create a stamper
        PdfStamper stamper
            = new PdfStamper(reader, new FileOutputStream(dest));
        // Create pushbutton 1
        PushbuttonField saveAs =
            new PushbuttonField(stamper.getWriter(),
                new Rectangle(636, 10, 716, 30), "Save");
        saveAs.setBorderColor(BaseColor.BLACK);
        saveAs.setText("Save");
        saveAs.setTextColor(BaseColor.RED);
        saveAs.setLayout(PushbuttonField.LAYOUT_LABEL_ONLY);
        saveAs.setRotation(90);
        PdfAnnotation saveAsButton = saveAs.getField();
        saveAsButton.setAction(PdfAction.javaScript(
            "app.execMenuItem('SaveAs')", stamper.getWriter()));
        // Create pushbutton 2
        PushbuttonField mail
            = new PushbuttonField(stamper.getWriter(),
                new Rectangle(736, 10, 816, 30), "Mail");
        mail.setBorderColor(BaseColor.BLACK);
        mail.setText("Mail");
        mail.setTextColor(BaseColor.RED);
        mail.setLayout(PushbuttonField.LAYOUT_LABEL_ONLY);
        mail.setRotation(90);
        PdfAnnotation mailButton = mail.getField();
        mailButton.setAction(PdfAction.javaScript(
            "app.execMenuItem('AcroSendMail:SendMail')", stamper.getWriter()));
        // Add the annotations to every page of the document
        for (int page = 1; page <= n; page++) {
            stamper.addAnnotation(saveAsButton, page);
            stamper.addAnnotation(mailButton, page);
        }
        // Close the stamper
        stamper.close();
        reader.close();
    }
    
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        MovieTemplates.main(args);
        new ButtonsActions().manipulatePdf(
            MovieTemplates.RESULT, RESULT);
    }
}
Advertisement.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
 * 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.chapter07;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
 
import part1.chapter04.NestedTables;
 
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
import com.itextpdf.text.BaseColor;
 
public class Advertisement {
 
    /** Path to a resource. */
    public static final String RESOURCE = "resources/pdfs/hero.pdf";
    /** Path to a resource. */
    public static final String IMAGE = "resources/img/close.png";
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/advertisement.pdf";
 
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param resource a resource that will be used as advertisement
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String resource, String dest)
        throws IOException, DocumentException {
        // Create a reader for the original document
        PdfReader reader = new PdfReader(src);
        // Create a reader for the advertisement resource
        PdfReader ad = new PdfReader(resource);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Create the advertisement annotation for the menubar
        Rectangle rect = new Rectangle(400, 772, 545, 792);
        PushbuttonField button = new PushbuttonField(
            stamper.getWriter(), rect, "click");
        button.setBackgroundColor(BaseColor.RED);
        button.setBorderColor(BaseColor.RED);
        button.setFontSize(10);
        button.setText("Close this advertisement");
        button.setImage(Image.getInstance(IMAGE));
        button.setLayout(PushbuttonField.LAYOUT_LABEL_LEFT_ICON_RIGHT);
        button.setIconHorizontalAdjustment(1);
        PdfFormField menubar = button.getField();
        String js = "var f1 = getField('click'); f1.display = display.hidden;"
            + "var f2 = getField('advertisement'); f2.display = display.hidden;";
        menubar.setAction(PdfAction.javaScript(js, stamper.getWriter()));
        // Add the annotation
        stamper.addAnnotation(menubar, 1);
        // Create the advertisement annotation for the content
        rect = new Rectangle(400, 550, 545, 772);
        button = new PushbuttonField(
            stamper.getWriter(), rect, "advertisement");
        button.setBackgroundColor(BaseColor.WHITE);
        button.setBorderColor(BaseColor.RED);
        button.setText("Buy the book iText in Action 2nd edition");
        button.setTemplate(stamper.getImportedPage(ad, 1));
        button.setLayout(PushbuttonField.LAYOUT_ICON_TOP_LABEL_BOTTOM);
        PdfFormField advertisement = button.getField();
        advertisement.setAction(
            new PdfAction("http://www.1t3xt.com/docs/book.php"));
        // Add the annotation
        stamper.addAnnotation(advertisement, 1);
        // Close the stamper
        stamper.close();
        reader.close();
    }
 
    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException 
     * @throws SQLException
     */
    public static void main(String[] args)
        throws SQLException, DocumentException, IOException {
        NestedTables.main(args);
        new Advertisement().manipulatePdf(
            NestedTables.RESULT, RESOURCE, RESULT);
    }
}
MoviePosters2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * 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.chapter07;
 
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.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
 
public class MoviePosters2 {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/movie_posters_2.pdf";
    /** A pattern for an info string. */
    public static final String INFO = "Movie produced in %s; run length: %s";
    /** A JavaScript snippet */
    public static final String JS1 =
        "var t = this.getAnnot(this.pageNum, 'IMDB%1$s'); t.popupOpen = true; "
        + "var w = this.getField('b%1$s'); w.setFocus();";
    /** A JavaScript snippet */
    public static final String JS2 =
        "var t = this.getAnnot(this.pageNum, 'IMDB%s'); t.popupOpen = false;";
    
    /**
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException, SQLException {
        // Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Loop over all the movies to add a popup annotation
        List<Movie> movies = PojoFactory.getMovies(connection);
        Image img;
        float x = 11.5f;
        float y = 769.7f;
        float llx, lly, urx, ury;
        for (Movie movie : movies) {
            img = Image.getInstance(String.format(MoviePosters1.RESOURCE, movie.getImdb()));
            img.scaleToFit(1000, 60);
            llx = x + (45 - img.getScaledWidth()) / 2;
            lly = y;
            urx = x + img.getScaledWidth();
            ury = y + img.getScaledHeight();
            addPopup(stamper, new Rectangle(llx, lly, urx, ury),
                movie.getMovieTitle(),
                String.format(INFO, movie.getYear(), movie.getDuration()), movie.getImdb());
            x += 48;
            if (x > 578) {
                x = 11.5f;
                y -= 84.2f;
            }
        }
        // Close the stamper
        stamper.close();
        reader.close();
        // Close the database connection
        connection.close();
    }
    
    /**
     * Adds a popup.
     * @param stamper the PdfStamper to which the annotation needs to be added
     * @param rect the position of the annotation
     * @param title the annotation title
     * @param contents the annotation content
     * @param imdb the IMDB number of the movie used as name of the annotation
     * @throws IOException
     * @throws DocumentException
     */
    public void addPopup(PdfStamper stamper, Rectangle rect,
        String title, String contents, String imdb)
        throws IOException, DocumentException {
        // Create the text annotation
        PdfAnnotation text = PdfAnnotation.createText(stamper.getWriter(),
            rect, title, contents, false, "Comment");
        text.setName(String.format("IMDB%s", imdb));
        text.setFlags(PdfAnnotation.FLAGS_READONLY | PdfAnnotation.FLAGS_NOVIEW);
        // Create the popup annotation
        PdfAnnotation popup = PdfAnnotation.createPopup(stamper.getWriter(),
            new Rectangle(rect.getLeft() + 10, rect.getBottom() + 10,
                rect.getLeft() + 200, rect.getBottom() + 100), null, false);
        // Add the text annotation to the popup
        popup.put(PdfName.PARENT, text.getIndirectReference());
        // Declare the popup annotation as popup for the text
        text.put(PdfName.POPUP, popup.getIndirectReference());
        // Add both annotations
        stamper.addAnnotation(text, 1);
        stamper.addAnnotation(popup, 1);
        // Create a button field
        PushbuttonField field = new PushbuttonField(
                stamper.getWriter(), rect,
                String.format("b%s", imdb));
        PdfAnnotation widget = field.getField();
        // Show the popup onMouseEnter
        PdfAction enter = PdfAction.javaScript(
            String.format(JS1, imdb), stamper.getWriter());
        widget.setAdditionalActions(PdfName.E, enter);
        // Hide the popup onMouseExit
        PdfAction exit = PdfAction.javaScript(
            String.format(JS2, imdb), stamper.getWriter());
        widget.setAdditionalActions(PdfName.X, exit);
        // Add the button annotation
        stamper.addAnnotation(widget, 1);
 
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
     */
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        MoviePosters1.main(args);
        new MoviePosters2().manipulatePdf(MoviePosters1.RESULT, RESULT);
    }
}
Calculator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
 * 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.chapter07;
 
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.Rectangle;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfAppearance;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;
 
public class Calculator {
    /** The resulting PDF. */
    public static final String RESULT = "results/part2/chapter07/calculator.pdf";
    /** Path to the resource. */
    public static final String RESOURCE = "resources/js/calculator.js";
    
    /** The font that will be used in the appearances. */
    public BaseFont bf;
    /** Position of the digits */
    Rectangle[] digits = new Rectangle[10];
    /** Position of the operators. */
    Rectangle plus, minus, mult, div, equals;
    /** Position of the other annotations */
    Rectangle clearEntry, clear, result, move;
    
    /**
     * Initializes the font
     * @throws DocumentException
     * @throws IOException
     */
    public void initializeFont() throws DocumentException, IOException {
        bf = BaseFont.createFont();
    }
    
    /**
     * Initializes the rectangles for the calculator keys.
     */
    public void initializeRectangles() {
        digits[0] = createRectangle(3, 1, 1, 1);
        digits[1] = createRectangle(1, 3, 1, 1);
        digits[2] = createRectangle(3, 3, 1, 1);
        digits[3] = createRectangle(5, 3, 1, 1);
        digits[4] = createRectangle(1, 5, 1, 1);
        digits[5] = createRectangle(3, 5, 1, 1);
        digits[6] = createRectangle(5, 5, 1, 1);
        digits[7] = createRectangle(1, 7, 1, 1);
        digits[8] = createRectangle(3, 7, 1, 1);
        digits[9] = createRectangle(5, 7, 1, 1);
        plus = createRectangle(7, 7, 1, 1);
        minus = createRectangle(9, 7, 1, 1);
        mult = createRectangle(7, 5, 1, 1);
        div = createRectangle(9, 5, 1, 1);
        equals = createRectangle(7, 1, 3, 1);
        clearEntry = createRectangle(7, 9, 1, 1);
        clear = createRectangle(9, 9, 1, 1);
        result = createRectangle(1, 9, 5, 1);
        move = createRectangle(8, 3, 1, 1);
    }
 
    /**
     * Creates a PDF document.
     * @param filename the path to the new PDF document
     * @throws    DocumentException 
     * @throws    IOException
     */
    public void createPdf(String filename)
        throws IOException, DocumentException {
        // step 1
        Document document = new Document(new Rectangle(360, 360));
        // step 2
        PdfWriter writer =
            PdfWriter.getInstance(document, new FileOutputStream(filename));
        // step 3
        document.open();
        writer.addJavaScript(Utilities.readFileToString(RESOURCE));
        // step 4
        // add the keys for the digits
        for (int i = 0; i < 10; i++) {
            addPushButton(writer, digits[i],
                String.valueOf(i), "this.augment(" + i + ")");
        }
        // add the keys for the operators
        addPushButton(writer, plus, "+", "this.register('+')");
        addPushButton(writer, minus, "-", "this.register('-')");
        addPushButton(writer, mult, "x", "this.register('*')");
        addPushButton(writer, div, ":", "this.register('/')");
        addPushButton(writer, equals, "=", "this.calculateResult()");
        // add the other keys
        addPushButton(writer, clearEntry, "CE", "this.reset(false)");
        addPushButton(writer, clear, "C", "this.reset(true)");
        addTextField(writer, result, "result");
        addTextField(writer, move, "move");
        // step 5
        document.close();
    }
 
    /**
     * Add a text field.
     * @param writer the PdfWriter
     * @param rect the position of the text field
     * @param name the name of the text field
     */
    public void addTextField(PdfWriter writer, Rectangle rect, String name) {
        PdfFormField field = PdfFormField.createTextField(writer, false, false, 0);
        field.setFieldName(name);
        field.setWidget(rect, PdfAnnotation.HIGHLIGHT_NONE);
        field.setQuadding(PdfFormField.Q_RIGHT);
        field.setFieldFlags(PdfFormField.FF_READ_ONLY);
        writer.addAnnotation(field);
    }
 
    /**
     * Create a pushbutton for a key
     * @param writer the PdfWriter
     * @param rect the position of the key
     * @param btn the label for the key
     * @param script the script to be executed when the button is pushed
     */
    public void addPushButton(PdfWriter writer, Rectangle rect,
        String btn, String script) {
        float w = rect.getWidth();
        float h = rect.getHeight();
        PdfFormField pushbutton = PdfFormField.createPushButton(writer);
        pushbutton.setFieldName("btn_" + btn);
        pushbutton.setWidget(rect, PdfAnnotation.HIGHLIGHT_PUSH);
        PdfContentByte cb = writer.getDirectContent();
        pushbutton.setAppearance(PdfAnnotation.APPEARANCE_NORMAL,
                createAppearance(cb, btn, BaseColor.GRAY, w, h));
        pushbutton.setAppearance(PdfAnnotation.APPEARANCE_ROLLOVER,
                createAppearance(cb, btn, BaseColor.RED, w, h));
        pushbutton.setAppearance(PdfAnnotation.APPEARANCE_DOWN,
                createAppearance(cb, btn, BaseColor.BLUE, w, h));
        pushbutton.setAdditionalActions(PdfName.U,
                PdfAction.javaScript(script, writer));
        pushbutton.setAdditionalActions(PdfName.E, PdfAction.javaScript(
                "this.showMove('" + btn + "');", writer));
        pushbutton.setAdditionalActions(PdfName.X, PdfAction.javaScript(
                "this.showMove(' ');", writer));
        writer.addAnnotation(pushbutton);
    }
 
    /**
     * Creates an appearance for a key
     * @param cb the canvas
     * @param btn the label for the key
     * @param color the color of the key
     * @param w the width
     * @param h the height
     * @return an appearance
     */
    public PdfAppearance createAppearance(
        PdfContentByte cb, String btn, BaseColor color, float w, float h) {
        PdfAppearance app = cb.createAppearance(w, h);
        app.setColorFill(color);
        app.rectangle(2, 2, w - 4, h - 4);
        app.fill();
        app.beginText();
        app.setColorFill(BaseColor.BLACK);
        app.setFontAndSize(bf, h / 2);
        app.showTextAligned(Element.ALIGN_CENTER, btn, w / 2, h / 4, 0);
        app.endText();
        return app;
    }
 
    /**
     * Create a rectangle object for a key.
     * @param column column of the key on the key pad
     * @param row row of the key on the key pad
     * @param width width of the key
     * @param height height of the key
     * @return a rectangle defining the position of a key.
     */
    public Rectangle createRectangle(int column, int row, int width,
            int height) {
        column = column * 36 - 18;
        row = row * 36 - 18;
        return new Rectangle(column, row,
            column + width * 36, row + height * 36);
    }
 
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws DocumentException, IOException {
        Calculator calc = new Calculator();
        calc.initializeFont();
        calc.initializeRectangles();
        calc.createPdf(RESULT);
    }
}
NamedActions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * 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.Chapter07 {
  public class NamedActions : IWriter {
// ===========================================================================
    public const String RESULT = "named_actions.pdf";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) { 
        MovieTemplates m = new MovieTemplates();
        byte[] pdf = Utility.PdfBytes(m); 
        zip.AddEntry(RESULT, new NamedActions().ManipulatePdf(pdf)); 
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
    // Create a table with named actions
      Font symbol = new Font(Font.FontFamily.SYMBOL, 20);
      PdfPTable table = new PdfPTable(4);
      table.DefaultCell.Border = Rectangle.NO_BORDER;
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
      Chunk first = new Chunk( ((char)220).ToString() , symbol);
      first.SetAction(new PdfAction(PdfAction.FIRSTPAGE));
      table.AddCell(new Phrase(first));
      Chunk previous = new Chunk( ((char)172).ToString(), symbol);
      previous.SetAction(new PdfAction(PdfAction.PREVPAGE));
      table.AddCell(new Phrase(previous));
      Chunk next = new Chunk( ((char)174).ToString(), symbol);
      next.SetAction(new PdfAction(PdfAction.NEXTPAGE));
      table.AddCell(new Phrase(next));
      Chunk last = new Chunk( ((char)222).ToString(), symbol);
      last.SetAction(new PdfAction(PdfAction.LASTPAGE));
      table.AddCell(new Phrase(last));
      table.TotalWidth = 120;
      
      // Create a reader
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Add the table to each page
          PdfContentByte canvas;
          for (int i = 0; i < reader.NumberOfPages; ) {
            canvas = stamper.GetOverContent(++i);
            table.WriteSelectedRows(0, -1, 696, 36, canvas);
          }
        }
        return ms.ToArray();
      }    
    }    
// ===========================================================================
  }
}
LinkActions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * 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.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
using kuujinbo.iTextInAction2Ed.Chapter02;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class LinkActions : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const string RESULT1 = "movie_links_1.pdf";
     /** The resulting PDF file. */
    public const string RESULT2 = "movie_links_2.pdf"; 
    /** The resulting XML file. */
    public const string RESULT3 = "destinations.xml";    
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieLinks1 m = new MovieLinks1(); 
        byte[] pdf = Utility.PdfBytes(m);
        LinkActions actions = new LinkActions();
        zip.AddEntry(RESULT2, actions.CreatePdf());
        zip.AddEntry(RESULT3, actions.CreateXml(pdf));
        zip.AddEntry(RESULT1, pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          // Add text with a local destination
          Paragraph p = new Paragraph();
          Chunk top = new Chunk("Country List", FilmFonts.BOLD);
          top.SetLocalDestination("top");
          p.Add(top);
          document.Add(p);
          // Add text with a link to an external URL
          Chunk imdb = new Chunk("Internet Movie Database", FilmFonts.ITALIC);
          imdb.SetAction(new PdfAction(new Uri("http://www.imdb.com/")));
          p = new Paragraph(
            @"Click on a country, and you'll get a list of movies, 
            containing links to the "
          );
          p.Add(imdb);
          p.Add(".");
          document.Add(p);
          // Add text with a remote goto
          p = new Paragraph("This list can be found in a ");
          Chunk page1 = new Chunk("separate document");
          page1.SetAction(new PdfAction(RESULT1, 1));
          
          p.Add(page1);
          p.Add(".");
          document.Add(p);
          document.Add(Chunk.NEWLINE); 
          // Get a list with countries from the database      
          var SQL = 
@"SELECT DISTINCT mc.country_id, c.country, count(*) AS c 
FROM film_country c, film_movie_country mc 
WHERE c.id = mc.country_id
GROUP BY mc.country_id, country 
ORDER BY c DESC";
          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()) {
                  Paragraph country = new Paragraph(r["country"].ToString());
                  country.Add(": ");
                  Chunk link = new Chunk(string.Format(
                    "{0} movies", r["c"].ToString()
                  ));
                  link.SetAction(PdfAction.GotoRemotePage(
                    RESULT1, 
                    r["country_id"].ToString(),
                    false, 
                    true
                  ));
                  country.Add(link);
                  document.Add(country);                
                }         
              }
            }
          }
          document.Add(Chunk.NEWLINE);
          // Add text with a local goto
          p = new Paragraph("Go to ");
          top = new Chunk("top");
          top.SetAction(PdfAction.GotoLocalPage("top", false));
          p.Add(top);
          p.Add(".");
          document.Add(p);        
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Create an XML file with named destinations
     * @param src the PDF with the destinations
     */
    public string CreateXml(byte[] src) {
      PdfReader reader = new PdfReader(src);
      Dictionary<string,string> map = SimpleNamedDestination
          .GetNamedDestination(reader, false);
      using (MemoryStream ms = new MemoryStream()) {
        SimpleNamedDestination.ExportToXML(map, ms, "ISO8859-1", true);
        ms.Position = 0;
        using (StreamReader sr =  new StreamReader(ms)) {
          return sr.ReadToEnd();
        }
      }
    }    
// ===========================================================================
  }
}
ConcatenateNamedDestinations.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
 * 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.Collections;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter02;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class ConcatenateNamedDestinations : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const string RESULT1 = "concatenated_links_1.pdf";  
    /** The resulting PDF file. */
    public const string RESULT2 = "concatenated_links_2.pdf";    
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        // Use previous examples to create PDF files
        MovieLinks1 m = new MovieLinks1(); 
        byte[] pdfM = Utility.PdfBytes(m);
        LinkActions l = new LinkActions();
        byte[] pdfL = l.CreatePdf();
        // Create readers.
        PdfReader[] readers = {
          new PdfReader(pdfL),
          new PdfReader(pdfM)
        };
        
        // step 1
        //Document document = new Document();
        // step 2
        using (var ms = new MemoryStream()) { 
          // step 1
          using (Document document = new Document()) {
            using (PdfCopy copy = new PdfCopy(document, ms)) {
              // step 3
              document.Open();
              // step 4
              int n;
              // copy the pages of the different PDFs into one document
              for (int i = 0; i < readers.Length; i++) {
                readers[i].ConsolidateNamedDestinations();
                n = readers[i].NumberOfPages;
                for (int page = 0; page < n; ) {
                  copy.AddPage(copy.GetImportedPage(readers[i], ++page));
                }
              }
              // Add named destination  
              copy.AddNamedDestinations(
                // from the second document
                SimpleNamedDestination.GetNamedDestination(readers[1], false),
                // using the page count of the first document as offset
                readers[0].NumberOfPages
              );
            }
            zip.AddEntry(RESULT1, ms.ToArray());
          }
          
          // Create a reader
          PdfReader reader = new PdfReader(ms.ToArray());
          // Convert the remote destinations into local destinations
          reader.MakeRemoteNamedDestinationsLocal();
          using (MemoryStream ms2 = new MemoryStream()) {
            // Create a new PDF containing the local destinations
            using (PdfStamper stamper = new PdfStamper(reader, ms2)) {
            }
            zip.AddEntry(RESULT2, ms2.ToArray());
          }
          
        }
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdfM);
        zip.AddEntry(Utility.ResultFileName(l.ToString() + ".pdf"), pdfL);
        zip.Save(stream);             
      }   
   }
// ===========================================================================
  }
}
TimetableDestinations.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * 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.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class TimetableDestinations : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "timetable_destinations.pdf";
    /** The font that is used for the navigation links. */
    public static Font SYMBOL = new Font(Font.FontFamily.SYMBOL, 20);
    /** A list to cache all the possible actions */
    public List<PdfAction> actions;
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        zip.AddEntry(RESULT, new TimetableDestinations().ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
    // Create the reader
      PdfReader reader = new PdfReader(src);
      int n = reader.NumberOfPages;
      using (MemoryStream ms =  new MemoryStream()) {
        // Create the stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Make a list with all the possible actions
          actions = new List<PdfAction>();
          PdfDestination d;
          for (int i = 0; i < n; ) {
            d = new PdfDestination(PdfDestination.FIT);
            actions.Add(PdfAction.GotoLocalPage(++i, d, stamper.Writer));
          }
          // Add a navigation table to every page
          PdfContentByte canvas;
          for (int i = 0; i < n; ) {
            canvas = stamper.GetOverContent(++i);
            CreateNavigationTable(i, n).WriteSelectedRows(0, -1, 696, 36, canvas);
          }
        }
        return ms.ToArray();
      }   
    }    
// ---------------------------------------------------------------------------    
    /**
     * Create a table that can be used as a footer
     * @param pagenumber the page that will use the table as footer
     * @param total the total number of pages
     * @return a tabel
     */
    public PdfPTable CreateNavigationTable(int pagenumber, int total) {
      PdfPTable table = new PdfPTable(4);
      table.DefaultCell.Border = Rectangle.NO_BORDER;
      table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
      Chunk first = new Chunk(((char)220).ToString(), SYMBOL);
      first.SetAction(actions[0]);
      table.AddCell(new Phrase(first));
      Chunk previous = new Chunk(((char)172).ToString(), SYMBOL);
      previous.SetAction(actions[pagenumber - 2 < 0 ? 0 : pagenumber - 2]);
      table.AddCell(new Phrase(previous));
      Chunk next = new Chunk(((char)174).ToString(), SYMBOL);
      next.SetAction(actions[pagenumber >= total ? total - 1 : pagenumber]);
      table.AddCell(new Phrase(next));
      Chunk last = new Chunk(((char)222).ToString(), SYMBOL);
      last.SetAction(actions[total - 1]);
      table.AddCell(new Phrase(last));
      table.TotalWidth = 120;
      return table;
    }    
// ===========================================================================
  }
}
AddVersionChecker.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * 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.Chapter07 {
  public class AddVersionChecker : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "version_checker.pdf";
    /** Path to a resource. */
    public const string RESOURCE = "viewer_version.js";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        HelloWorld h = new HelloWorld(); 
        byte[] pdf = Utility.PdfBytes(h);
        // Create a reader
        PdfReader reader = new PdfReader(pdf);
        string js = File.ReadAllText(
          Path.Combine(Utility.ResourceJavaScript, RESOURCE)
        );        
        using (MemoryStream ms = new MemoryStream()) {
          using (PdfStamper stamper = new PdfStamper(reader, ms)) {
            // Add some javascript
            stamper.JavaScript = js;
          }
          zip.AddEntry(RESULT, ms.ToArray());
        }
        zip.AddEntry(RESOURCE, js);
        zip.AddEntry(Utility.ResultFileName(h.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ===========================================================================
  }
}
FindDirectors.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
using kuujinbo.iTextInAction2Ed.Chapter04;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class FindDirectors : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "find_directors.pdf";
    /** Path to a resource. */
    public const string RESOURCE = "find_director.js";
    protected string jsContents;
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) { 
      NestedTables n = new NestedTables();
      byte[] pdf = Utility.PdfBytes(n);        
      using (ZipFile zip = new ZipFile()) {
        FindDirectors f =  new FindDirectors();
        zip.AddEntry(RESULT, f.CreatePdf(pdf));
        zip.AddEntry(RESOURCE, f.jsContents);
        zip.AddEntry(Utility.ResultFileName(n.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }    
    }
// ---------------------------------------------------------------------------
    /**
     * Creates a PDF file with director names.
     * @param pdf the PDF file to be used as a reader
     */
    public byte[] CreatePdf(byte[] pdf) {
      byte[] tmpDoc = null;
      using ( MemoryStream ms = new MemoryStream() ) {
        using (Document tmp = new Document()) {
          PdfWriter writer = PdfWriter.GetInstance(tmp, ms);
          // step 3
          tmp.Open();
          // step 4
          var SQL = 
  @"SELECT name, given_name 
  FROM film_director 
  ORDER BY name, given_name";
        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() ) {
                  tmp.Add(CreateDirectorParagraph(writer, r));
                }
              }
            }
          }
        }
        tmpDoc = ms.ToArray();
      }
 
      jsContents = File.ReadAllText(
        Path.Combine(Utility.ResourceJavaScript, RESOURCE)
      );
      List<byte[]> readers = new List<byte[]>() {tmpDoc, pdf};
      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
            copy.AddJavaScript(jsContents);
            for (int i = 0; i < readers.Count; ++i) {
              PdfReader reader = new PdfReader(readers[i]);
              int n = reader.NumberOfPages;
              for (int page = 0; page < n; ) {
                copy.AddPage(copy.GetImportedPage(reader, ++page));
              }
            }
          }
        } 
        return ms.ToArray();     
      }
    } 
// ---------------------------------------------------------------------------
    /**
     * Creates a Phrase with the name and given name of a director
     * using different fonts.
     * @param r the DbDataReader containing director records.
     */
    public Paragraph CreateDirectorParagraph(PdfWriter writer, DbDataReader r) {
      string n = r["name"].ToString();
      Chunk name = new Chunk(n);
      name.SetAction(PdfAction.JavaScript(
        string.Format("findDirector('{0}');", n), 
        writer
      ) );
      name.Append(", ");
      name.Append(r["given_name"].ToString());
      return new Paragraph(name);
    }
// ===========================================================================
  }
}
LaunchAction.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * 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.Chapter07 {
  public class LaunchAction : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        Paragraph p = new Paragraph(
          new Chunk( "Click to open test.txt in Notepad.")
          .SetAction(
            new PdfAction(
              "c:/windows/notepad.exe",
              "test.txt", "open",
              Path.Combine(Utility.ResourceText, "")
            )
        ));
        document.Add(p);
      }
    }
// ===========================================================================
  }
}
PrintTimeTable.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*
 * 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.Chapter07 {
  public class PrintTimeTable : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "print_timetable.pdf";
    /** Path to a resource. */
    public const string RESOURCE = "print_page.js";
    protected string jsString;
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        PrintTimeTable p = new PrintTimeTable();
        zip.AddEntry(RESULT, p.ManipulatePdf(pdf));
        zip.AddEntry(RESOURCE, p.jsString);
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }    
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result (localhost)
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
    // Create the reader
      PdfReader reader = new PdfReader(src);
      int n = reader.NumberOfPages;
      using (MemoryStream ms = new MemoryStream()) {
        // Create the stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Add JavaScript
          jsString = File.ReadAllText(
            Path.Combine(Utility.ResourceJavaScript, RESOURCE)
          );
          stamper.JavaScript = jsString; 
          // Create a Chunk with a chained action
          PdfContentByte canvas;
          Chunk chunk = new Chunk("print this page");
          PdfAction action = PdfAction.JavaScript(
            "app.alert('Think before you print!');", 
            stamper.Writer
          );
          action.Next(PdfAction.JavaScript(
            "printCurrentPage(this.pageNum);", 
            stamper.Writer
          ));
          action.Next(new PdfAction("http://www.panda.org/savepaper/"));
          chunk.SetAction(action);
          Phrase phrase = new Phrase(chunk);
          // Add this Chunk to every page
          for (int i = 0; i < n; ) {
            canvas = stamper.GetOverContent(++i);
            ColumnText.ShowTextAligned(
              canvas, Element.ALIGN_RIGHT, phrase, 816, 18, 0
            );
          }
        } 
        return ms.ToArray();     
      }      
    }        
// ===========================================================================
  }
}
EventsAndActions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * 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.Chapter07 {
  public class EventsAndActions : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "events_and_actions.pdf";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        EventsAndActions e = new EventsAndActions();
        zip.AddEntry(RESULT, e.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }           
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result (localhost)
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
    // Create the reader
      PdfReader reader = new PdfReader(src);
      int n = reader.NumberOfPages;
      using (MemoryStream ms = new MemoryStream()) {
        // Create the stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Get the writer (to add actions and annotations)
          PdfWriter writer = stamper.Writer;
          PdfAction action = PdfAction.GotoLocalPage(2,
            new PdfDestination(PdfDestination.FIT), writer
          );
          writer.SetOpenAction(action);
          action = PdfAction.JavaScript(
            "app.alert('Think before you print');", writer
          );
          writer.SetAdditionalAction(PdfWriter.WILL_PRINT, action);
          action = PdfAction.JavaScript(
            "app.alert('Think again next time!');", writer
          );
          writer.SetAdditionalAction(PdfWriter.DID_PRINT, action);
          action = PdfAction.JavaScript(
            "app.alert('We hope you enjoy the festival');", writer
          );
          writer.SetAdditionalAction(PdfWriter.DOCUMENT_CLOSE, action);
          action = PdfAction.JavaScript(
            "app.alert('This day is reserved for people with an accreditation "
            + "or an invitation.');",
            writer
          );
          stamper.SetPageAction(PdfWriter.PAGE_OPEN, action, 1);
          action = PdfAction.JavaScript(
            "app.alert('You can buy tickets for all the other days');", writer
          );
          stamper.SetPageAction(PdfWriter.PAGE_CLOSE, action, 1);      
        }
        return ms.ToArray();       
      }       
    }        
// ===========================================================================
  }
}
CreateOutlineTree.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
 * 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.Collections;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class CreateOutlineTree : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "outline_tree.pdf";
    /** An XML representing the outline tree */
    public const string RESULTXML = "outline_tree.xml";
    /** Pattern of the IMDB urls */
    public const String RESOURCE = "http://imdb.com/title/tt{0}/";    
    /** JavaScript snippet. */
    public const string INFO
        = "app.alert('Movie produced in {0}; run length: {1}');";    
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        CreateOutlineTree example = new CreateOutlineTree();
        byte[] pdf = example.CreatePdf();
        zip.AddEntry(RESULT, pdf);
        zip.AddEntry(RESULTXML, example.CreateXml(pdf));
        zip.Save(stream);             
      }   
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document.
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document()) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);
          // step 3
          document.Open();
          // step 4
          PdfOutline root = writer.RootOutline;
          PdfOutline movieBookmark;
          PdfOutline link;
          String title;
          IEnumerable<Movie> movies = PojoFactory.GetMovies();
          foreach (Movie movie in movies) {
            title = movie.MovieTitle;
            if ("3-Iron".Equals(title))
                title = "\ube48\uc9d1";
            movieBookmark = new PdfOutline(root, 
              new PdfDestination(
                PdfDestination.FITH, writer.GetVerticalPosition(true)
              ),
              title, true
            );
            movieBookmark.Style = Font.BOLD;
            link = new PdfOutline(movieBookmark,
              new PdfAction(String.Format(RESOURCE, movie.Imdb)),
              "link to IMDB"
            );
            link.Color = BaseColor.BLUE;
            new PdfOutline(movieBookmark,
              PdfAction.JavaScript(
                String.Format(INFO, movie.Year, movie.Duration),
                writer
              ),
              "instant info"
            );
            document.Add(new Paragraph(movie.MovieTitle));
            document.Add(PojoToElementFactory.GetDirectorList(movie));
            document.Add(PojoToElementFactory.GetCountryList(movie));
          }
        }
        return ms.ToArray();
      }
    }   
// ---------------------------------------------------------------------------    
    /**
     * Creates an XML file with the bookmarks of a PDF file
     * @param pdfIn the byte array with the document 
     */
    public string CreateXml(byte[] pdfIn) {
      PdfReader reader = new PdfReader(pdfIn);
      var list = SimpleBookmark.GetBookmark(reader);
      using (MemoryStream ms = new MemoryStream()) {
        SimpleBookmark.ExportToXML(list, ms, "ISO8859-1", true); 
        ms.Position = 0;
        using (StreamReader sr =  new StreamReader(ms)) {
          return sr.ReadToEnd();
        }              
      }       
    }
// ===========================================================================
  }
}
BookmarkedTimeTable.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
 * 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.Collections;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class BookmarkedTimeTable : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "time_table_bookmarks.pdf";
// ---------------------------------------------------------------------------            
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates();
        byte[] pdf = Utility.PdfBytes(m);
        BookmarkedTimeTable b = new BookmarkedTimeTable();
        zip.AddEntry(RESULT, b.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------  
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
      // Create a list with bookmarks
      List<Dictionary<string,object>> outlines = 
          new List<Dictionary<string,object>>();
      Dictionary<string, object> map = new Dictionary<string, object>();
      outlines.Add(map);
      map.Add("Title", "Calendar");
      List<Dictionary<string,object>> kids = 
          new List<Dictionary<string,object>>();
      map.Add("Kids", kids);
      int page = 1;
      IEnumerable<string> days = PojoFactory.GetDays();
      foreach (string day in days) {
        Dictionary<string,object> kid = new Dictionary<string,object>();      
        kids.Add(kid);
        kid["Title"] = day;
        kid["Action"] = "GoTo";
        kid["Page"] = String.Format("{0} Fit", page++);
      }      
      // Create a reader
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          stamper.Outlines = outlines;
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
  }
}
ConcatenateBookmarks.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * 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.Collections;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
using kuujinbo.iTextInAction2Ed.Chapter02;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class ConcatenateBookmarks : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "concatenated_bookmarks.pdf";
// ---------------------------------------------------------------------------      
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates();
        byte[] pdf = Utility.PdfBytes(m);
        BookmarkedTimeTable b = new BookmarkedTimeTable();
        byte[] bttBytes = b.ManipulatePdf(pdf);      
        MovieHistory mh = new MovieHistory(); 
        byte[] mhBytes = Utility.PdfBytes(mh);
        List<byte[]> src = new List<byte[]>() {bttBytes, mhBytes};
        ConcatenateBookmarks cb = new ConcatenateBookmarks();
        zip.AddEntry(RESULT, cb.ManipulatePdf(src));
        zip.AddEntry(Utility.ResultFileName(b.ToString() + ".pdf"), bttBytes);
        zip.AddEntry(Utility.ResultFileName(mh.ToString() + ".pdf"), mhBytes);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------  
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(List<byte[]> src) {
      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
            int page_offset = 0;
            // Create a list for the bookmarks
            List<Dictionary<String, Object>> bookmarks = 
                new List<Dictionary<String, Object>>();
                
            for (int i  = 0; i < src.Count; i++) {
              PdfReader reader = new PdfReader(src[i]);
              // merge the bookmarks
              IList<Dictionary<String, Object>> tmp = 
                  SimpleBookmark.GetBookmark(reader);
              SimpleBookmark.ShiftPageNumbers(tmp, page_offset, null);
              foreach (var d in tmp) bookmarks.Add(d);
              
              // add the pages
              int n = reader.NumberOfPages;
              page_offset += n;
              for (int page = 0; page < n; ) {
                copy.AddPage(copy.GetImportedPage(reader, ++page));
              }
            }
            // Add the merged bookmarks
            copy.Outlines = bookmarks;
          }
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
  }
}
MovieAnnotations1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
 * 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.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class MovieAnnotations1 : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "movie_annotations_1.pdf";
    /** Pattern for an info String. */
    public const string INFO = "Movie produced in {0}; run length: {1}";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        foreach (Movie movie in PojoFactory.GetMovies()) {
          document.Add(new Phrase(movie.MovieTitle));
          document.Add(new Annotation(
            movie.Title,
            string.Format(INFO, movie.Year, movie.Duration)
          ));
          document.Add(PojoToElementFactory.GetDirectorList(movie));
          document.Add(PojoToElementFactory.GetCountryList(movie));
        }
      }
    }
// ===========================================================================
  }
}
MovieAnnotations2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
 * 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.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class MovieAnnotations2 : IWriter {
// ===========================================================================
    /** Pattern for an info String. */
    public const string INFO = "Movie produced in {0}; run length: {1}";
// ---------------------------------------------------------------------------          
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        Phrase phrase;
        Chunk chunk;        
        foreach (Movie movie in PojoFactory.GetMovies()) {
          phrase = new Phrase(movie.MovieTitle);
          chunk = new Chunk("\u00a0");
          chunk.SetAnnotation( PdfAnnotation.CreateText(
            writer, null, movie.MovieTitle,
            string.Format(INFO, movie.Year, movie.Duration),
            false, "Comment"
          ));
          phrase.Add(chunk);
          document.Add(phrase);
          document.Add(PojoToElementFactory.GetDirectorList(movie));
          document.Add(PojoToElementFactory.GetCountryList(movie));
        }
      }
    }
// ===========================================================================
  }
}
GenericAnnotations.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * 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 iTextSharp.text.pdf.draw;
/*
 * book example inherits directly from PdfPageEventHelper class, we use
 * nested inner class.
*/
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class GenericAnnotations : IWriter {
// ===========================================================================
    /** Possible icons. */
    public static readonly string[] ICONS = {
      "Comment", "Key", "Note", "Help", "NewParagraph", "Paragraph", "Insert"
    };
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        writer.PageEvent = new AnnotationHelper();
        // step 3
        document.Open();
        // step 4
        Paragraph p = new Paragraph();
        Chunk chunk;
        Chunk tab = new Chunk(new VerticalPositionMark());
        for (int i = 0; i < ICONS.Length; i++) {
          chunk = new Chunk(ICONS[i]);
          chunk.SetGenericTag(ICONS[i]);
          p.Add(chunk);
          p.Add(tab);
        }        
        document.Add(p); 
      }
    }
/*
 * ###########################################################################
 * Inner class to write annotations
 * ###########################################################################
*/
    class AnnotationHelper : PdfPageEventHelper {
    /**
     * @see com.itextpdf.text.pdf.PdfPageEventHelper#onGenericTag(
     *      com.itextpdf.text.pdf.PdfWriter,
     *      com.itextpdf.text.Document,
     *      com.itextpdf.text.Rectangle, java.lang.String)
     */
      public override void OnGenericTag(PdfWriter writer,
        Document document, Rectangle rect, string text) 
      {
        PdfAnnotation annotation = new PdfAnnotation(writer,
          new Rectangle(
            rect.Right+ 10, rect.Bottom,
            rect.Right+ 30, rect.Top
          )
        );
        annotation.Title = "Text annotation";
        annotation.Put(PdfName.SUBTYPE, PdfName.TEXT);
        annotation.Put(PdfName.OPEN, PdfBoolean.PDFFALSE);
        annotation.Put(PdfName.CONTENTS,
          new PdfString(string.Format("Icon: {0}", text))
        );
        annotation.Put(PdfName.NAME, new PdfName(text));
        writer.AddAnnotation(annotation);
      }        
    }
// ===========================================================================
  }
}
TimetableAnnotations1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class TimetableAnnotations1 : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "timetable_help.pdf";
    /** A pattern for an info string. */
    public const string INFO = "Movie produced in {0}; run length: {1}";
    /** A list containing all the locations. */
    protected List<String> locations;
    
    /** The number of locations on our time table. */
    public const int LOCATIONS = 9;
    /** The number of time slots on our time table. */
    public const int TIMESLOTS = 32;
    /** The "offset time" for our calendar sheets. */
    // public static long TIME930 = 30600000L;
    public const long TIME930 = 34200000L;
    /** The offset to the left of our time table. */
    public const float OFFSET_LEFT = 76;
    /** The width of our time table. */
    public const float WIDTH = 740;
    /** The width of a time slot. */
    public static float WIDTH_TIMESLOT = WIDTH / TIMESLOTS;
    /** The width of one minute. */
    public static float MINUTE = WIDTH_TIMESLOT / 30f;
    /** The offset from the bottom of our time table. */
    public const float OFFSET_BOTTOM = 36;
    /** The height of our time table */
    public const float HEIGHT = 504;
    /** The height of a bar showing the movies at one specific location. */
    public static float HEIGHT_LOCATION = HEIGHT / LOCATIONS;
// ---------------------------------------------------------------------------
    public virtual void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        TimetableAnnotations1 t = new TimetableAnnotations1();
        zip.AddEntry(RESULT, t.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }     
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public virtual byte[] ManipulatePdf(byte[] src) {
      locations = PojoFactory.GetLocations();
      // Create a reader
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Add the annotations
          int page = 1;
          Rectangle rect;
          PdfAnnotation annotation;
          Movie movie;
          foreach (string day in PojoFactory.GetDays()) {
            foreach (Screening screening in PojoFactory.GetScreenings(day)) {
              movie = screening.movie;
              rect = GetPosition(screening);
              annotation = PdfAnnotation.CreateText(
                stamper.Writer, rect, movie.MovieTitle,
                string.Format(INFO, movie.Year, movie.Duration),
                false, "Help"
              );
              annotation.Color = WebColors.GetRGBColor(
                "#" + movie.entry.category.color
              );
              stamper.AddAnnotation(annotation, page);
            }
            page++;
          }
        }
        return ms.ToArray();
      }
    }  
// ---------------------------------------------------------------------------
    /**
     * Calculates the position of a rectangle corresponding with a screening.
     * @param    screening    a screening POJO, contains a movie
     * @return    a Rectangle
     */
    protected Rectangle GetPosition(Screening screening) {
      float llx, lly, urx, ury;
      // long minutesAfter930 = (screening.getTime().getTime() - TIME930) / 60000L;
      long minutesAfter930 = (
        Utility.GetMilliseconds(screening.Time) - TIME930
      ) / 60000L;      
      llx = OFFSET_LEFT + (MINUTE * minutesAfter930);
      int location = locations.IndexOf(screening.Location) + 1;
      lly = OFFSET_BOTTOM + (LOCATIONS - location) * HEIGHT_LOCATION;
      urx = llx + MINUTE * screening.movie.Duration;
      ury = lly + HEIGHT_LOCATION;
      Rectangle rect = new Rectangle(llx, lly, urx, ury);
      return rect;
    }
// ===========================================================================
  }
}
MoviePosters1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * 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 kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class MoviePosters1 : IWriter {
// ===========================================================================
    /** Path to IMDB. */
    public const string IMDB = "http://imdb.com/title/tt{0}/";
// ---------------------------------------------------------------------------      
    public void Write(Stream stream) {
      // step 1
      using (Document document = new Document(PageSize.A4)) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        PdfContentByte canvas = writer.DirectContent;
        // Create a reusable XObject
        PdfTemplate celluloid = canvas.CreateTemplate(595, 84.2f);
        celluloid.Rectangle(8, 8, 579, 68);
        for (float f = 8.25f; f < 581; f+= 6.5f) {
          celluloid.RoundRectangle(f, 8.5f, 6, 3, 1.5f);
          celluloid.RoundRectangle(f, 72.5f, 6, 3, 1.5f);
        }
        celluloid.SetGrayFill(0.1f);
        celluloid.EoFill();
        writer.ReleaseTemplate(celluloid);
        // Add the XObject ten times
        for (int i = 0; i < 10; i++) {
          canvas.AddTemplate(celluloid, 0, i * 84.2f);
        }
        // Add the movie posters
        Image img;
        Annotation annotation;
        float x = 11.5f;
        float y = 769.7f;
        string RESOURCE = Utility.ResourcePosters;
        foreach (Movie movie in PojoFactory.GetMovies()) {
          img = Image.GetInstance(Path.Combine(RESOURCE, movie.Imdb + ".jpg"));
          img.ScaleToFit(1000, 60);
          img.SetAbsolutePosition(x + (45 - img.ScaledWidth) / 2, y);
          annotation = new Annotation(
            0, 0, 0, 0,
            string.Format(IMDB, movie.Imdb)
          );
          img.Annotation = annotation;
          canvas.AddImage(img);
          x += 48;
          if (x > 578) {
            x = 11.5f;
            y -= 84.2f;
          }
        }
      }
    }
// ===========================================================================
  }
}
TimetableAnnotations2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class TimetableAnnotations2 : TimetableAnnotations1 {
// ===========================================================================
    /** The resulting PDF. */
    public new const String RESULT = "timetable_links.pdf";
    /** Path to IMDB. */
    public const string IMDB = "http://imdb.com/title/tt{0}/";
// --------------------------------------------------------------------------- 
    public override void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        TimetableAnnotations2 t = new TimetableAnnotations2();
        zip.AddEntry(RESULT, t.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public override byte[] ManipulatePdf(byte[] src) {
      locations = PojoFactory.GetLocations();
      // Create a reader
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Add annotations for every screening
          int page = 1;
          Rectangle rect;
          PdfAnnotation annotation;
          foreach (string day in PojoFactory.GetDays()) {
            foreach (Screening screening in PojoFactory.GetScreenings(day)) {
              rect = GetPosition(screening);
              annotation = PdfAnnotation.CreateLink(
                stamper.Writer, rect, PdfAnnotation.HIGHLIGHT_INVERT,
                new PdfAction(string.Format(IMDB, screening.movie.Imdb))
              );
              stamper.AddAnnotation(annotation, page);
            }
            page++;
          }
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
MovieAnnotations3.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * 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.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class MovieAnnotations3 : IWriter {
// ===========================================================================
    public void Write(Stream stream) {
      MovieAnnotations3 example = new MovieAnnotations3();
      example.CreatePdf(stream);        
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document.
     * @param stream Stream for the new PDF document
     */
    public void CreatePdf(Stream stream) {
      string RESOURCE = Utility.ResourcePosters;
      // step 1
      using (Document document = new Document()) {
        // step 2
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        // step 3
        document.Open();
        // step 4
        Phrase phrase;
        Chunk chunk;
        PdfAnnotation annotation;
        foreach (Movie movie in PojoFactory.GetMovies()) {
          phrase = new Phrase(movie.MovieTitle);
          chunk = new Chunk("\u00a0\u00a0");
          annotation = PdfAnnotation.CreateFileAttachment(
            writer, null,
            movie.MovieTitle, null,
            Path.Combine(RESOURCE, movie.Imdb + ".jpg"),
            string.Format("img_{0}.jpg", movie.Imdb)
          );
          annotation.Put(PdfName.NAME, new PdfString("Paperclip"));
          chunk.SetAnnotation(annotation);
          phrase.Add(chunk);
          document.Add(phrase);
          document.Add(PojoToElementFactory.GetDirectorList(movie));
          document.Add(PojoToElementFactory.GetCountryList(movie));
        }
      }
    }
// ===========================================================================
  }
}
TimetableAnnotations3.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class TimetableAnnotations3 : TimetableAnnotations1 {
// ===========================================================================
    /** The resulting PDF file. */
    public new const String RESULT = "timetable_tickets.pdf";
    /** Path to IMDB. */
    public const string IMDB = "http://imdb.com/title/tt{0}/";
// --------------------------------------------------------------------------- 
    public override void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        TimetableAnnotations3 t = new TimetableAnnotations3();
        zip.AddEntry(RESULT, t.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public override byte[] ManipulatePdf(byte[] src) {
      locations = PojoFactory.GetLocations();
      // Create a reader
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Loop over the days and screenings
          int page = 1;
          Rectangle rect;
          float top;
          PdfAnnotation annotation;
          Movie movie;
          foreach (string day in PojoFactory.GetDays()) {
            foreach (Screening screening in PojoFactory.GetScreenings(day)) {
              rect = GetPosition(screening);
              movie = screening.movie;
              // Annotation for press previews
              if (screening.Press) {
                annotation = PdfAnnotation.CreateStamp(
                  stamper.Writer, rect, "Press only", "NotForPublicRelease"
                );
                annotation.Color = BaseColor.BLACK;
                annotation.Flags = PdfAnnotation.FLAGS_PRINT;
              }
              // Annotation for screenings that are sold out
              else if (IsSoldOut(screening)) {
                top = reader.GetPageSizeWithRotation(page).Top;
                annotation = PdfAnnotation.CreateLine(
                    stamper.Writer, rect, "SOLD OUT",
                    top - rect.Top, rect.Right,
                    top - rect.Bottom, rect.Left
                );
                annotation.Title = movie.MovieTitle;
                annotation.Color = BaseColor.WHITE;
                annotation.Flags = PdfAnnotation.FLAGS_PRINT;
                annotation.BorderStyle = new PdfBorderDictionary(
                  5, PdfBorderDictionary.STYLE_SOLID
                );
              }
              // Annotation for screenings with tickets available
              else {
                annotation = PdfAnnotation.CreateSquareCircle(
                  stamper.Writer, rect, "Tickets available", true
                );
                annotation.Title = movie.MovieTitle;
                annotation.Color = BaseColor.BLUE;
                annotation.Flags = PdfAnnotation.FLAGS_PRINT;
                annotation.Border = new PdfBorderArray(
                  0, 0, 2, new PdfDashPattern()
                );
              }
              stamper.AddAnnotation(annotation, page);
            }
            page++;
          }
        }
        return ms.ToArray();
      }
    }    
// ---------------------------------------------------------------------------
    /**
     * Checks if the screening has been sold out.
     * @param screening a Screening POJO
     * @return true if the screening has been sold out.
     */
    public bool IsSoldOut(Screening screening) {
      return screening.movie.MovieTitle.StartsWith("L")
        ? true : false
      ;
    }    
// ===========================================================================
  }
}
ButtonsActions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Chapter03;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class ButtonsActions : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "save_mail_timetable.pdf";
// ---------------------------------------------------------------------------    
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MovieTemplates m = new MovieTemplates(); 
        byte[] pdf = Utility.PdfBytes(m);
        ButtonsActions b = new ButtonsActions();
        zip.AddEntry(RESULT, b.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);        
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
      // Create a reader
      PdfReader reader = new PdfReader(src);
      int n = reader.NumberOfPages;
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {
          // Create pushbutton 1
          PushbuttonField saveAs = new PushbuttonField(
            stamper.Writer,
            new Rectangle(636, 10, 716, 30), 
            "Save"
          );
          saveAs.BorderColor = BaseColor.BLACK;
          saveAs.Text = "Save";
          saveAs.TextColor = BaseColor.RED;
          saveAs.Layout = PushbuttonField.LAYOUT_LABEL_ONLY;
          saveAs.Rotation = 90;
          PdfAnnotation saveAsButton = saveAs.Field;
          saveAsButton.Action = PdfAction.JavaScript(
            "app.execMenuItem('SaveAs')", stamper.Writer
          );
          // Create pushbutton 2
          PushbuttonField mail = new PushbuttonField(
            stamper.Writer,
            new Rectangle(736, 10, 816, 30),
            "Mail"
          );
          mail.BorderColor = BaseColor.BLACK;
          mail.Text = "Mail";
          mail.TextColor = BaseColor.RED;
          mail.Layout = PushbuttonField.LAYOUT_LABEL_ONLY;
          mail.Rotation = 90;
          PdfAnnotation mailButton = mail.Field;
          mailButton.Action = PdfAction.JavaScript(
            "app.execMenuItem('AcroSendMail:SendMail')", 
            stamper.Writer
          );
          // Add the annotations to every page of the document
          for (int page = 1; page <= n; page++) {
            stamper.AddAnnotation(saveAsButton, page);
            stamper.AddAnnotation(mailButton, page);
          }
        }
        return ms.ToArray();
      }
    }    
// ===========================================================================
  }
}
Advertisement.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Chapter04;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class Advertisement : IWriter {
// ===========================================================================
    /** Path to a resource. */
    public static String RESOURCE = Path.Combine(Utility.ResourcePdf, "hero.pdf");
    /** Path to a resource. */
    /** The resulting PDF file. */
    public const String RESULT = "advertisement.pdf";
    /** Path to a resource. */
    public const string IMAGE = "close.png";
// ---------------------------------------------------------------------------
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        NestedTables n = new NestedTables(); 
        byte[] pdf = Utility.PdfBytes(n);
        Advertisement a = new Advertisement();
        zip.AddEntry(RESULT, a.ManipulatePdf(pdf));       
        zip.AddEntry(Utility.ResultFileName(n.ToString() + ".pdf"), pdf);
        zip.AddFile(RESOURCE, "");
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
      // Create a reader for the original document
      PdfReader reader = new PdfReader(src);
      // Create a reader for the advertisement resource
      PdfReader ad = new PdfReader(RESOURCE); 
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {           
          // Create the advertisement annotation for the menubar
          Rectangle rect = new Rectangle(400, 772, 545, 792);
          PushbuttonField button = new PushbuttonField(
            stamper.Writer, rect, "click"
          );
          button.BackgroundColor = BaseColor.RED;
          button.BorderColor = BaseColor.RED;
          button.FontSize = 10;
          button.Text = "Close this advertisement";
          button.Image = Image.GetInstance(
            Path.Combine(Utility.ResourceImage, IMAGE)
          );
          button.Layout = PushbuttonField.LAYOUT_LABEL_LEFT_ICON_RIGHT;
          button.IconHorizontalAdjustment = 1;
          PdfFormField menubar = button.Field;
          String js = "var f1 = getField('click'); f1.display = display.hidden;"
            + "var f2 = getField('advertisement'); f2.display = display.hidden;"
          ;
          menubar.Action = PdfAction.JavaScript(js, stamper.Writer);
          // Add the annotation
          stamper.AddAnnotation(menubar, 1);
          // Create the advertisement annotation for the content
          rect = new Rectangle(400, 550, 545, 772);
          button = new PushbuttonField(
            stamper.Writer, rect, "advertisement"
          );
          button.BackgroundColor = BaseColor.WHITE;
          button.BorderColor = BaseColor.RED;
          button.Text = "Buy the book iText in Action 2nd edition";
          button.Template = stamper.GetImportedPage(ad, 1);
          button.Layout = PushbuttonField.LAYOUT_ICON_TOP_LABEL_BOTTOM;
          PdfFormField advertisement = button.Field;
          advertisement.Action = new PdfAction(
            "http://www.1t3xt.com/docs/book.php"
          );
          // Add the annotation
          stamper.AddAnnotation(advertisement, 1);      
        }
        return ms.ToArray();
      }
    }
// ===========================================================================
  }
}
MoviePosters2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * 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.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq; 
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using kuujinbo.iTextInAction2Ed.Intro_1_2;
 
namespace kuujinbo.iTextInAction2Ed.Chapter07 {
  public class MoviePosters2 : IWriter {
// ===========================================================================
    /** The resulting PDF file. */
    public const String RESULT = "movie_posters_2.pdf";
    /** A pattern for an info string. */
    public const string INFO = "Movie produced in {0}; run length: {1}";
    /** A JavaScript snippet */
    public const string JS1 =
      "var t = this.getAnnot(this.pageNum, 'IMDB{0}'); t.popupOpen = true; "
    + "var w = this.getField('b{0}'); w.Focus();";
    /** A JavaScript snippet */
    public const string JS2 =
      "var t = this.getAnnot(this.pageNum, 'IMDB{0}'); t.popupOpen = false;";
// --------------------------------------------------------------------------- 
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        MoviePosters1 m = new MoviePosters1(); 
        byte[] pdf = Utility.PdfBytes(m);
        MoviePosters2 m2 = new MoviePosters2();
        zip.AddEntry(RESULT, m2.ManipulatePdf(pdf));
        zip.AddEntry(Utility.ResultFileName(m.ToString() + ".pdf"), pdf);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     */
    public byte[] ManipulatePdf(byte[] src) {
      // Create a reader
      PdfReader reader = new PdfReader(src);
      using (MemoryStream ms = new MemoryStream()) {
        // Create a stamper
        using (PdfStamper stamper = new PdfStamper(reader, ms)) {           
          Image img;
          float x = 11.5f;
          float y = 769.7f;
          float llx, lly, urx, ury;
          string RESOURCE = Utility.ResourcePosters;
          // Loop over all the movies to add a popup annotation
          foreach (Movie movie in PojoFactory.GetMovies()) {
            img = Image.GetInstance(Path.Combine(RESOURCE, movie.Imdb + ".jpg"));
            img.ScaleToFit(1000, 60);
            llx = x + (45 - img.ScaledWidth) / 2;
            lly = y;
            urx = x + img.ScaledWidth;
            ury = y + img.ScaledHeight;
            AddPopup(stamper, new Rectangle(llx, lly, urx, ury),
              movie.MovieTitle, 
              string.Format(INFO, movie.Year, movie.Duration), 
              movie.Imdb
            );
            x += 48;
            if (x > 578) {
              x = 11.5f;
              y -= 84.2f;
            }
          }
        }
        return ms.ToArray();
      }
    }  
// ---------------------------------------------------------------------------
    /**
     * Adds a popup.
     * @param stamper the PdfStamper to which the annotation needs to be added
     * @param rect the position of the annotation
     * @param title the annotation title
     * @param contents the annotation content
     * @param imdb the IMDB number of the movie used as name of the annotation
     */
    public void AddPopup(PdfStamper stamper, Rectangle rect,
      String title, String contents, String imdb)
    {
  // Create the text annotation
      PdfAnnotation text = PdfAnnotation.CreateText(
        stamper.Writer,
        rect, title, contents, false, "Comment"
      );
      text.Name = string.Format("IMDB{0}", imdb);
      text.Flags = PdfAnnotation.FLAGS_READONLY | PdfAnnotation.FLAGS_NOVIEW;
      // Create the popup annotation
      PdfAnnotation popup = PdfAnnotation.CreatePopup(
        stamper.Writer,
        new Rectangle(
          rect.Left + 10, rect.Bottom + 10,
          rect.Left + 200, rect.Bottom + 100
        ), 
        null, false
      );
      // Add the text annotation to the popup
      popup.Put(PdfName.PARENT, text.IndirectReference);
      // Declare the popup annotation as popup for the text
      text.Put(PdfName.POPUP, popup.IndirectReference);
      // Add both annotations
      stamper.AddAnnotation(text, 1);
      stamper.AddAnnotation(popup, 1);
      // Create a button field
      PushbuttonField field = new PushbuttonField(
        stamper.Writer, rect,
        string.Format("b{0}", imdb)
      );
      PdfAnnotation widget = field.Field;
      // Show the popup onMouseEnter
      PdfAction enter = PdfAction.JavaScript(
        string.Format(JS1, imdb), stamper.Writer
      );
      widget.SetAdditionalActions(PdfName.E, enter);
      // Hide the popup onMouseExit
      PdfAction exit = PdfAction.JavaScript(
        string.Format(JS2, imdb), stamper.Writer
      );
      widget.SetAdditionalActions(PdfName.X, exit);
      // Add the button annotation
      stamper.AddAnnotation(widget, 1);
    }
// ===========================================================================
  }
}
Calculator.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * 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.Chapter07 {
  public class Calculator : IWriter {
// ===========================================================================
    /** The resulting PDF. */
    public const String RESULT = "calculator.pdf";
    /** Path to the resource. */
    public const string RESOURCE = "calculator.js";
// ---------------------------------------------------------------------------            
    /** The font that will be used in the appearances. */
    public BaseFont bf;
    /** Position of the digits */
    Rectangle[] digits = new Rectangle[10];
    /** Position of the operators. */
    Rectangle plus, minus, mult, div, equals;
    /** Position of the other annotations */
    Rectangle clearEntry, clear, result, move;
// ---------------------------------------------------------------------------                
    /**
     * Initializes the font
     */
    public void InitializeFont() {
      bf = BaseFont.CreateFont();
    }
// --------------------------------------------------------------------------- 
    protected string jsString;
    public void Write(Stream stream) {
      using (ZipFile zip = new ZipFile()) {
        Calculator calc = new Calculator();
        calc.InitializeFont();
        calc.InitializeRectangles();
        zip.AddEntry(RESULT, calc.CreatePdf());
        zip.AddEntry(RESOURCE, calc.jsString);
        zip.Save(stream);             
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Initializes the rectangles for the calculator keys.
     */
    public void InitializeRectangles() {
      digits[0] = CreateRectangle(3, 1, 1, 1);
      digits[1] = CreateRectangle(1, 3, 1, 1);
      digits[2] = CreateRectangle(3, 3, 1, 1);
      digits[3] = CreateRectangle(5, 3, 1, 1);
      digits[4] = CreateRectangle(1, 5, 1, 1);
      digits[5] = CreateRectangle(3, 5, 1, 1);
      digits[6] = CreateRectangle(5, 5, 1, 1);
      digits[7] = CreateRectangle(1, 7, 1, 1);
      digits[8] = CreateRectangle(3, 7, 1, 1);
      digits[9] = CreateRectangle(5, 7, 1, 1);
      plus = CreateRectangle(7, 7, 1, 1);
      minus = CreateRectangle(9, 7, 1, 1);
      mult = CreateRectangle(7, 5, 1, 1);
      div = CreateRectangle(9, 5, 1, 1);
      equals = CreateRectangle(7, 1, 3, 1);
      clearEntry = CreateRectangle(7, 9, 1, 1);
      clear = CreateRectangle(9, 9, 1, 1);
      result = CreateRectangle(1, 9, 5, 1);
      move = CreateRectangle(8, 3, 1, 1);
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates a PDF document for PdfReader.
     * @param stream the stream to create new PDF document
     */
    public byte[] CreatePdf() {
      using (MemoryStream ms = new MemoryStream()) {
        // step 1
        using (Document document = new Document(new Rectangle(360, 360))) {
          // step 2
          PdfWriter writer = PdfWriter.GetInstance(document, ms);      
          // step 3
          document.Open();
          jsString = File.ReadAllText(
            Path.Combine(Utility.ResourceJavaScript, RESOURCE)
          );
          writer.AddJavaScript(jsString);
          // step 4
          // add the keys for the digits
          for (int i = 0; i < 10; i++) {
            AddPushButton(
              writer, digits[i],
              i.ToString(), "this.augment(" + i + ")"
            );
          }
          // add the keys for the operators
          AddPushButton(writer, plus, "+", "this.register('+')");
          AddPushButton(writer, minus, "-", "this.register('-')");
          AddPushButton(writer, mult, "x", "this.register('*')");
          AddPushButton(writer, div, ":", "this.register('/')");
          AddPushButton(writer, equals, "=", "this.calculateResult()");
          // add the other keys
          AddPushButton(writer, clearEntry, "CE", "this.reset(false)");
          AddPushButton(writer, clear, "C", "this.reset(true)");
          AddTextField(writer, result, "result");
          AddTextField(writer, move, "move");
        }
        return ms.ToArray();
      }
    }
// ---------------------------------------------------------------------------    
    /**
     * Add a text field.
     * @param writer the PdfWriter
     * @param rect the position of the text field
     * @param name the name of the text field
     */
    public void AddTextField(PdfWriter writer, Rectangle rect, String name) {
      PdfFormField field = PdfFormField.CreateTextField(
        writer, false, false, 0
      );
      field.FieldName = name;
      field.SetWidget(rect, PdfAnnotation.HIGHLIGHT_NONE);
      field.Quadding = PdfFormField.Q_RIGHT;
      field.SetFieldFlags(PdfFormField.FF_READ_ONLY);
      writer.AddAnnotation(field);
    }
// ---------------------------------------------------------------------------    
    /**
     * Create a pushbutton for a key
     * @param writer the PdfWriter
     * @param rect the position of the key
     * @param btn the label for the key
     * @param script the script to be executed when the button is pushed
     */
    public void AddPushButton(PdfWriter writer, Rectangle rect,
      String btn, String script)
    {
      float w = rect.Width;
      float h = rect.Height;
      PdfFormField pushbutton = PdfFormField.CreatePushButton(writer);
      pushbutton.FieldName = "btn_" + btn;
      pushbutton.SetWidget(rect, PdfAnnotation.HIGHLIGHT_PUSH);
      PdfContentByte cb = writer.DirectContent;
      pushbutton.SetAppearance(
        PdfAnnotation.APPEARANCE_NORMAL,
        CreateAppearance(cb, btn, BaseColor.GRAY, w, h)
      );
      pushbutton.SetAppearance(
        PdfAnnotation.APPEARANCE_ROLLOVER,
        CreateAppearance(cb, btn, BaseColor.RED, w, h)
      );
      pushbutton.SetAppearance(
        PdfAnnotation.APPEARANCE_DOWN,
        CreateAppearance(cb, btn, BaseColor.BLUE, w, h)
      );
      pushbutton.SetAdditionalActions(
        PdfName.U,
        PdfAction.JavaScript(script, writer)
      );
      pushbutton.SetAdditionalActions(
        PdfName.E, PdfAction.JavaScript(
          "this.showMove('" + btn + "');", writer
        )
      );
      pushbutton.SetAdditionalActions(
        PdfName.X, PdfAction.JavaScript(
          "this.showMove(' ');", writer
        )
      );
      writer.AddAnnotation(pushbutton);
    }
// ---------------------------------------------------------------------------    
    /**
     * Creates an appearance for a key
     * @param cb the canvas
     * @param btn the label for the key
     * @param color the color of the key
     * @param w the width
     * @param h the height
     * @return an appearance
     */
    public PdfAppearance CreateAppearance(
      PdfContentByte cb, String btn, BaseColor color, float w, float h)
    {
      PdfAppearance app = cb.CreateAppearance(w, h);
      app.SetColorFill(color);
      app.Rectangle(2, 2, w - 4, h - 4);
      app.Fill();
      app.BeginText();
      app.SetColorFill(BaseColor.BLACK);
      app.SetFontAndSize(bf, h / 2);
      app.ShowTextAligned(Element.ALIGN_CENTER, btn, w / 2, h / 4, 0);
      app.EndText();
      return app;
    }
// ---------------------------------------------------------------------------    
    /**
     * Create a rectangle object for a key.
     * @param column column of the key on the key pad
     * @param row row of the key on the key pad
     * @param width width of the key
     * @param height height of the key
     * @return a rectangle defining the position of a key.
     */
    public Rectangle CreateRectangle(
      int column, int row, int width, int height) 
    {
      column = column * 36 - 18;
      row = row * 36 - 18;
      return new Rectangle(
        column, row,
        column + width * 36, row + height * 36
      );
    }
// ===========================================================================
  }
}


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