________________________________
> Date: Wed, 21 Apr 2010 11:56:00 +0200
> From: [email protected]
> To: [email protected]
> Subject: Re: [iText-questions] performance question
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> Hello Mike,
>
>
>
> I appreciate your interest and will to help. Thank you.
>
>
>
> Mike Marchywka [mailto:[email protected]] wrote:
>
>
>>Forgive the top posting but since this involves statistical modelling
>
>
>>with OP from a financial services company and the "comments" have
>
>
>>already started flying, allow me to throw my two sticks onto the
>
>
>>fire.
>
>
>>
>
>
> I must say that I don't have a strong quantitative background quite yet ... 
> but I am working on that :o)
>

I think I exercized great restraint not going off about PDF
being ideal for a CDO prospsectus or some other innane comments
about modelling in financial companies :) It isn't you,
its just the material is inherently funny at this point...
 
 
>
>
> The fact that I post from this email address only means that I have no access 
> to my private emails from the office so I have no choice.

 
Someone from Lehman posted on another list but now I digress...
 
>
>
>
>>
>
>
>> It may help us here formulate a constructive response
>
>
>> if you could dig a bit deeper into the close method and see who
>
>
>> the big resource hog is. Also, if you can point to the speed limiting
>
>
>> step in your alt package it may be interesting to contemplate. We
>
>
>> really don't know too much about details of your typical use case,
>
>
>> ... snip ...
>
>
>> sometimes IO dominates instead of computation just because no
>
>
>> ... snip ...
>
>
>>
>
>
> Indeed there is quite some IO involved but this is also why I am benchmarking 
> maybe one alternative does more IO than the other for the same use-case or 
> maybe my implementation of the use-case is not optimal which would also be a 
> valid outcome of the experiment :o)
>
>
>
> My assumption is that running the same workload under the same conditions (my 
> development environment) should show if there is a significative performance 
> difference between the two alternatives i.e. compare two means.
>
>
>
> I include the full code for the use-case and workload below.
>
>
>
>> Also, since you went to all the trouble of doing a stats analysis,
>
>
>> and since these things are "supposed to be" deterministic,
>
>
>> it may help to get some idea how the execution time noise appears if
>
>
>> indeed it is a significant fraction of the average. Presumably this
>
>
>> is things like OS, other tasks on machine if you measured "wall clock"
>
>
>> (not cpu time devoted to you) and GC and other "stuff" including
>
>
>> maybe disk and memory cache states. I would point out that depending
>
>
>> on exactly what you are measuring, you could be seeing lots of
>
>
>> caching hot/cold issues that could dominate the results.
>
>
>>
>
>
> I am aware of this, however, I would not seek a lot of isolation because 
> would be like creating a synthetic unrealistic environment for running the 
> benchmarks e.g. if iText did in fact used more memory than the alternative I 
> would not like to hide from the benchmark the consequencing higher GC 
> activity.
>

Again, it depends on what you are measuring. If you just want to
tell management approach X will require time T with distribution
blah ( normal+SD, or whatever you actually find with params to 
describe it ) on server foo with a gazillion bytes or RAM etc then
that's fine. If you want someone here to figure out why itext
is slower, the pointing to a hogging method would help. 
 
 
 
 
 
>
>
> A few notes about the micro-benchmarking I did:
>
>
>
> - I do warm up by running the use-case 1K times

Even here this is ambiguous, if I did this in a simple case
I'd do it from a bash script and the JVM startup time could be
significant and variable. Even running a java program once and putting
a 1k loop inside may or may not warm up caches but it is probably
not realistic for your environment but would be good enough to point
to bottle necks if you use the profiling tools ( see sun.com for
jhat or profiling ). 
 
 
>
>
> - I then benchmark 1K times the elapsed time as shown in the method below 
> "performanceBenchmark"
>
>
> - I do these two points above multiple times
>
>
> - The exact same thing is done for the alternative that generates (almost 
> exactly) the same PDF

This can be an important issue- the final result that people care
about is usually just a bunch of pixels. If you can substitute cheaper
things that look ok, that could be a big deal. 
 
>
>
> - The dynamic allocation of Map of data and similar is emulating what will 
> happen in the real implementation and this is done in the exact same way for 
> the alternative.
>
>
>
> - I use the output 1K elapsed times for both alternatives to do the paired 
> t-test following the recipee [1, 13.4 Comparing two alternatives] which 
> outputs that iText is lagging behind [22.53, 24.18] milliseconds with 95% 
> confidence meaning that one framework perform faster than the other and that 
> the difference of the means is significative and not merely noise.

If you really have paired results and want to compare first-run of
itext with alt great but I guess I'd just find sample stats
for the two groups and see if their mean estimates differ by
more than the noise enough to hit your p value.  But rather than
worry about that too much, I guess if you have a suite of test
pdf's, and you know their parameters, you may be able to say
that the " one with the most fonts is the worst" that may help
( of course if you know that pdf test case n requires m fonts,
maybe you could  fit a linear regression and create and expression
for additional time required per added font LOL).
 
>
>
>
> Running the workload (code below) 9 times for iText and the alternative I get 
> the following elapsed time means (milliseconds):
>
>
>
> (sample means for 9 runs of the workload for each)
>
>
>
> iText Alternative
>
>
> 77.819 54.353
>
>
> 77.976 55.103
>
>
> 77.931 54.951
>
>
> 76.533 54.684
>
>
> 77.713 54.061
>
>
> 77.452 58.662
>
>
> 78.094 52.73
>
>
> 77.438 54.299
>
>
> 77.752 52.344
>
>
>
> [1] The Art of Computer Systems Performance Analysis: Techniques for 
> Experimental Design, Measurement, Simulation, and Modeling 
> http://www.amazon.com/Art-Computer-Systems-Performance-Analysis/dp/0471503363/ref=cm_cr-mr-title
>
>
>
> Best regards,
>
>
> Giovanni
>
>
>
> ==============================================================================
>
>
> Please access the attached hyperlink for an important electronic 
> communications disclaimer:
>
>
>
> http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html
>
>
> ==============================================================================
>
>
>
> Further disclaimer: I could have made mistakes :o)

I'll look later if I get a chance, thanks, but the profile
info may be of more direct help. 
 
>
>
>
> import java.io.*;
>
>
> import java.text.*;
>
>
> import java.util.*;
>
>
> import java.util.List;
>
>
>
> import com.itextpdf.text.*;
>
>
> import com.itextpdf.text.pdf.*;
>
>
> import com.itextpdf.text.pdf.events.*;
>
>
>
> /**
>
>
> * @author F135873
>
>
> */
>
>
> public class LetterIText {
>
>
> private static Font CREDIT_SUISSE_TYPE_LIGHT;
>
>
> private static Font CREDIT_SUISSE_TYPE_BOLD;
>
>
> private static final Rectangle LETTER_SIZE = PageSize.A4;
>
>
> private static final String LINE_BREAK = System.getProperty("line.separator");
>
>
> private static final int FONT_SIZE = 10;
>
>
> private static final Comparator STRING_LENGTH_COMPARATOR = new Comparator() {
>
>
> public int compare(String value1, String value2) {
>
>
> return value1.length() - value2.length();
>
>
> }
>
>
> };
>
>
>
> static {
>
>
> FontFactoryImp factory = new FontFactoryImp();
>
>
> boolean scanSubdirectories = true;
>
>
> factory.registerDirectory("c:/OS/Fonts/", scanSubdirectories);
>
>
> CREDIT_SUISSE_TYPE_LIGHT = factory.getFont("CreditSuisseType-Light", 
> FONT_SIZE);
>
>
> CREDIT_SUISSE_TYPE_BOLD = factory.getFont("CreditSuisseType-Bold", FONT_SIZE);
>
>
> }
>
>
>
> private static final String RESOURCES_DIR = "resources/";
>
>
> private static final String HEADER_PATH = RESOURCES_DIR + "header.pdf";
>
>
> private static final String FOOTER_PATH = RESOURCES_DIR + "footer.pdf";
>
>
>
> public static void main(String[] args) throws Exception {
>
>
> performanceBenchmark("iText");
>
>
> }
>
>
>
> private static void performanceBenchmark(String title) throws Exception {
>
>
> final int REPETITIONS = 1000;
>
>
>
> // warm up
>
>
> for (int i = 0; i < REPETITIONS; i++) {
>
>
> generatePdf();
>
>
> }
>
>
>
> // benchmark
>
>
> double[] elapsedTimes = new double[REPETITIONS];
>
>
> final double oneMillion = 1000000.;
>
>
> double sum = 0;
>
>
> System.out.println("******************************************************");
>
>
> for (int i = 0; i < REPETITIONS; ++i) {
>
>
> elapsedTimes[i] = System.nanoTime();
>
>
> generatePdf();
>
>
> elapsedTimes[i] = (System.nanoTime() - elapsedTimes[i]) / oneMillion;
>
>
> System.out.print(elapsedTimes[i]);
>
>
> System.out.print(",");
>
>
> sum += elapsedTimes[i];
>
>
> }
>
>
> System.out.println("\n******************************************************");
>
>
>
> // calculate sample mean
>
>
> double mean = sum / REPETITIONS;
>
>
>
> // calculate the sample variance
>
>
> double variance = 0;
>
>
> for (int i = 0; i < REPETITIONS; i++) {
>
>
> variance += Math.pow(elapsedTimes[i] - mean, 2);
>
>
> }
>
>
> variance = variance / REPETITIONS;
>
>
>
> System.out.println(MessageFormat.format("{0} sample mean={1}, sample 
> variance={2}",
>
>
> title, mean, variance));
>
>
> }
>
>
>
> private static void generatePdf() throws DocumentException, 
> FileNotFoundException, Exception {
>
>
> Document document = new Document(LETTER_SIZE);
>
>
> document.newPage();
>
>
> PdfWriter writer = PdfWriter.getInstance(document, new 
> FileOutputStream("letter.pdf"));
>
>
> document.open();
>
>
> appendHeader(writer);
>
>
>
> appendSenderAddress(writer);
>
>
> appendRecipientAddress(writer);
>
>
> appendDate(writer);
>
>
> appendLetterSubject(writer);
>
>
> appendPreamble(writer);
>
>
> appendContent(writer);
>
>
> appendFooter(writer);
>
>
> document.close();
>
>
> }
>
>
>
> private static void appendHeader(PdfWriter writer) throws Exception {
>
>
> PdfReader reader = new PdfReader(HEADER_PATH);
>
>
> int pageOne = 1;
>
>
> int xOffset = 200;
>
>
> int yOffset = 0;
>
>
> PdfImportedPage importedPage = writer.getImportedPage(reader, pageOne);
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> content.addTemplate(importedPage, xOffset, yOffset);
>
>
> }
>
>
>
> private static void appendSenderAddress(PdfWriter writer) throws Exception {
>
>
> StringBuilder builder = new StringBuilder();
>
>
> builder.append("Corporate & Institutional Clients");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("XXXXX XXXXX XXXXXXXXXX, XXXX XX");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("XXXXXXXX XXXXXX");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("Assistant Vice President");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("+XX XX XXX XX XX");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("[email protected]");
>
>
>
> float xOffset = 70;
>
>
> float yOffset = 500;
>
>
> float width = 150;
>
>
> float height = 150;
>
>
> float leading = 13;
>
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> ColumnText columnText = new ColumnText(content);
>
>
> columnText.addText(new Phrase(builder.toString(), CREDIT_SUISSE_TYPE_LIGHT));
>
>
> columnText.setSimpleColumn(xOffset, yOffset, xOffset + width, yOffset
>
>
> + height, leading, Element.ALIGN_LEFT);
>
>
> columnText.go();
>
>
> }
>
>
>
> private static void appendRecipientAddress(PdfWriter writer) throws Exception 
> {
>
>
> StringBuilder builder = new StringBuilder();
>
>
> builder.append("XXXXX XX/XX XXXX");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("XXXXXXXXXXXXX XX");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("8001 Zürich");
>
>
>
> float xOffset = 400;
>
>
> float yOffset = 500;
>
>
> float width = 150;
>
>
> float height = 150;
>
>
> float leading = 13;
>
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> ColumnText columnText = new ColumnText(content);
>
>
> columnText.addText(new Phrase(builder.toString(), CREDIT_SUISSE_TYPE_LIGHT));
>
>
> columnText.setSimpleColumn(xOffset, yOffset, xOffset + width, yOffset
>
>
> + height, leading, Element.ALIGN_LEFT);
>
>
> columnText.go();
>
>
> }
>
>
>
> private static void appendDate(PdfWriter writer) {
>
>
> String date = MessageFormat.format("{0,date,dd.MM.yyyy}", new Object[] {new 
> Date()});
>
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> content.beginText();
>
>
> content.setFontAndSize(CREDIT_SUISSE_TYPE_LIGHT.getBaseFont(), FONT_SIZE);
>
>
> float xOffset = 70;
>
>
> float yOffset = 530;
>
>
> content.moveText(xOffset, yOffset);
>
>
> content.showText(date);
>
>
> content.endText();
>
>
> }
>
>
>
> private static void appendLetterSubject(PdfWriter writer) throws Exception {
>
>
> StringBuilder builder = new StringBuilder();
>
>
> builder.append("Bestätigung Ihrer Kontoeröffnung");
>
>
>
> float xOffset = 70;
>
>
> float yOffset = 360;
>
>
> float width = 200;
>
>
> float height = 150;
>
>
> float leading = 13;
>
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> ColumnText columnText = new ColumnText(content);
>
>
> columnText.addText(new Phrase(builder.toString(), CREDIT_SUISSE_TYPE_BOLD));
>
>
> columnText.setSimpleColumn(xOffset, yOffset, xOffset + width, yOffset
>
>
> + height, leading, Element.ALIGN_LEFT);
>
>
> columnText.go();
>
>
> }
>
>
>
> private static void appendPreamble(PdfWriter writer) throws Exception {
>
>
> StringBuilder builder = new StringBuilder();
>
>
> builder.append("Sehr geehrte ");
>
>
> builder.append(LINE_BREAK);
>
>
> builder.append("Gerne bestätigen wir Ihnen die Eröffnung des nachfolgenden 
> Kontos:");
>
>
> builder.append(LINE_BREAK);
>
>
>
> float xOffset = 70;
>
>
> float yOffset = 340;
>
>
> float width = 600;
>
>
> float height = 150;
>
>
> float leading = 13;
>
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> ColumnText columnText = new ColumnText(content);
>
>
> columnText.addText(new Phrase(builder.toString(), CREDIT_SUISSE_TYPE_LIGHT));
>
>
> columnText.setSimpleColumn(xOffset, yOffset, xOffset + width, yOffset
>
>
> + height, leading, Element.ALIGN_LEFT);
>
>
> columnText.go();
>
>
> }
>
>
>
> private static void appendContent(PdfWriter writer) throws Exception {
>
>
> final float TABLE_WIDTH = 500f;
>
>
> final float TABLE_X_OFFSET = 70f;
>
>
> final float TABLE_Y_OFFSET = 450f;
>
>
> final int WIDTH_PER_CHAR = 4;
>
>
> final int WIDTH_THRESHOLD = 350;
>
>
> final float ZERO_BORDER_WIDTH = 0.f;
>
>
> final float ROW_HEIGHT = 20.f;
>
>
> final float MULTI_ROW_HEIGHT = 16.f;
>
>
> final float PADDING_TOP = 0.f;
>
>
>
> // prepare values
>
>
> Map values = new HashMap();
>
>
> values.put("ph0013", "XXXXXXXXX XXXXXXXXXXXXX");
>
>
> values.put("ph0006", "XXXXXX in GBP Nr. XXXXX-XXXXXX-XXXX Salärkonto");
>
>
> values.put("ph0007", "IBAN-Nr. XXXX XXXXX XXXX XXXX XXXXX 0");
>
>
> values.put("ph0008", "Derzeit 1.000% im Jahr abzüglich 35% 
> Verrechnungssteuer");
>
>
> values.put("ph0009", "4835");
>
>
> values.put("ph0010", "CRESCHZZ80A");
>
>
> values.put("ph0011", "Porti und Spesen werden direkt dem Konto belastet");
>
>
> values.put("ph0012", "vierteljährlich");
>
>
> values.put("ph0005", "Ohne Ihren Gegenbericht gilt für dieses Konto die "
>
>
> + "gleiche Verfügungsberechtigung wie für alle bestehenden Konten. Ohne "
>
>
> + "Ihren Gegenbericht gilt für dieses Konto die gleiche 
> Verfügungsberechtigung "
>
>
> + "wie für alle bestehenden Konten.");
>
>
> values.put("ph0014", "Im übrigen gelten die 'Allgemeinen 
> Geschäftsbedingungen' "
>
>
> + "unserer Bank.'");
>
>
>
> // prepare names
>
>
> Map names = new HashMap();
>
>
> names.put("ph0013", "Kunde");
>
>
> names.put("ph0006", "Kontoart");
>
>
> names.put("ph0007", "");
>
>
> names.put("ph0008", "Zinsvergütung");
>
>
> names.put("ph0009", "Clearingnummer");
>
>
> names.put("ph0010", "Swiftadresse");
>
>
> names.put("ph0011", "Porti/ Spesen");
>
>
> names.put("ph0012", "Kontoabschluss");
>
>
> names.put("ph0005", "Verfügungsberechtigung");
>
>
> names.put("ph0014", "Übrige Bestimmungen");
>
>
>
> Map readonly = new HashMap();
>
>
> readonly.put("ph0008", Boolean.TRUE);
>
>
>
> // define row order
>
>
> List rowOrder = new ArrayList(names.keySet());
>
>
> Collections.sort(rowOrder);
>
>
>
> // automatically calculate max column width
>
>
> int leftColumnMaxLength = Collections.max(names.values(),
>
>
> STRING_LENGTH_COMPARATOR).length();
>
>
> int leftColumnWidth = leftColumnMaxLength * WIDTH_PER_CHAR;
>
>
> if (leftColumnWidth> WIDTH_THRESHOLD) {
>
>
> leftColumnWidth = WIDTH_THRESHOLD;
>
>
> }
>
>
>
> int rightColumnMaxLength = Collections.max(values.values(),
>
>
> STRING_LENGTH_COMPARATOR).length();
>
>
> int rightColumnWidth = rightColumnMaxLength * WIDTH_PER_CHAR;
>
>
> if (rightColumnWidth> WIDTH_THRESHOLD) {
>
>
> rightColumnWidth = WIDTH_THRESHOLD;
>
>
> }
>
>
>
> float[] columnWidths = new float[] {leftColumnWidth, rightColumnWidth};
>
>
> PdfPTable table = new PdfPTable(columnWidths);
>
>
> int zeroRows = 0;
>
>
> table.setHeaderRows(zeroRows);
>
>
> table.setFooterRows(zeroRows);
>
>
> table.setTotalWidth(TABLE_WIDTH);
>
>
> table.setLockedWidth(true);
>
>
> table.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
> for (String rowKey : rowOrder) {
>
>
> String name = names.get(rowKey);
>
>
> String value = values.get(rowKey);
>
>
>
> int nameLength = name.length();
>
>
> int valueLength = value.length();
>
>
>
> // calculate row span
>
>
> int rowSpan = Math.max(nameLength * WIDTH_PER_CHAR / WIDTH_THRESHOLD,
>
>
> valueLength * WIDTH_PER_CHAR / WIDTH_THRESHOLD) + 1;
>
>
>
> // in case the number of rows required is only one
>
>
> if (rowSpan == 1) {
>
>
> // calculate the field rectangle to have the precise dimensions
>
>
> Rectangle rectangle = new Rectangle(0, 0, rightColumnWidth, rowSpan * 
> ROW_HEIGHT);
>
>
> rectangle.setBorder(0);
>
>
> TextField field = new TextField(writer, rectangle, value);
>
>
> field.setText(value);
>
>
> field.setFont(CREDIT_SUISSE_TYPE_LIGHT.getBaseFont());
>
>
> field.setOptions(TextField.MULTILINE | TextField.DO_NOT_SCROLL);
>
>
> field.setAlignment(Element.ALIGN_LEFT);
>
>
> field.setFontSize(FONT_SIZE);
>
>
> Boolean isReadoly = readonly.containsKey(name);
>
>
> if (isReadoly != null && isReadoly.booleanValue()) {
>
>
> field.setOptions(TextField.READ_ONLY);
>
>
> }
>
>
>
> PdfPCell leftColumn = new PdfPCell(new Paragraph(new Phrase(name,
>
>
> CREDIT_SUISSE_TYPE_LIGHT)));
>
>
> leftColumn.setVerticalAlignment(Element.ALIGN_TOP);
>
>
> leftColumn.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
> leftColumn.setBorderWidth(ZERO_BORDER_WIDTH);
>
>
> leftColumn.setBorder(PdfPCell.NO_BORDER);
>
>
> leftColumn.setPaddingTop(PADDING_TOP);
>
>
> leftColumn.setFixedHeight(ROW_HEIGHT);
>
>
> PdfPCell rightColumn = new PdfPCell();
>
>
> FieldPositioningEvents events = new FieldPositioningEvents(writer, 
> field.getTextField());
>
>
> rightColumn.setCellEvent(events);
>
>
> rightColumn.setNoWrap(false);
>
>
> rightColumn.setVerticalAlignment(Element.ALIGN_TOP);
>
>
> rightColumn.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
> rightColumn.setBorder(PdfPCell.NO_BORDER);
>
>
> rightColumn.setFixedHeight(ROW_HEIGHT);
>
>
>
> table.addCell(leftColumn);
>
>
> table.addCell(rightColumn);
>
>
> } else {
>
>
> Rectangle rectangle = new Rectangle(0, 0, rightColumnWidth, rowSpan * 
> MULTI_ROW_HEIGHT);
>
>
> rectangle.setBorder(0);
>
>
> TextField field = new TextField(writer, rectangle, value);
>
>
> field.setText(value);
>
>
> field.setFont(CREDIT_SUISSE_TYPE_LIGHT.getBaseFont());
>
>
> field.setOptions(TextField.MULTILINE | TextField.DO_NOT_SCROLL);
>
>
> field.setAlignment(Element.ALIGN_LEFT);
>
>
> field.setFontSize(FONT_SIZE);
>
>
> Boolean isReadoly = readonly.containsKey(name);
>
>
> if (isReadoly != null && isReadoly.booleanValue()) {
>
>
> field.setOptions(TextField.READ_ONLY);
>
>
> }
>
>
>
> // use nested tables
>
>
> int oneColumn = 1;
>
>
> PdfPTable leftNested = new PdfPTable(oneColumn);
>
>
> leftNested.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
>
> PdfPCell leftColumn = new PdfPCell(leftNested);
>
>
> leftColumn.setPhrase(new Paragraph(new Phrase(name, 
> CREDIT_SUISSE_TYPE_LIGHT)));
>
>
> leftColumn.setVerticalAlignment(Element.ALIGN_TOP);
>
>
> leftColumn.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
> leftColumn.setBorderWidth(ZERO_BORDER_WIDTH);
>
>
> leftColumn.setBorder(PdfPCell.NO_BORDER);
>
>
> leftColumn.setPaddingTop(PADDING_TOP);
>
>
> leftColumn.setFixedHeight(rowSpan * MULTI_ROW_HEIGHT);
>
>
>
> PdfPTable rightNested = new PdfPTable(oneColumn);
>
>
> rightNested.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
>
> PdfPCell rightColumn = new PdfPCell(rightNested);
>
>
> FieldPositioningEvents events = new FieldPositioningEvents(writer, 
> field.getTextField());
>
>
> rightColumn.setCellEvent(events);
>
>
> rightColumn.setNoWrap(false);
>
>
> rightColumn.setVerticalAlignment(Element.ALIGN_TOP);
>
>
> rightColumn.setHorizontalAlignment(Element.ALIGN_LEFT);
>
>
> rightColumn.setBorder(PdfPCell.NO_BORDER);
>
>
> rightColumn.setFixedHeight(rowSpan * MULTI_ROW_HEIGHT);
>
>
>
> table.addCell(leftColumn);
>
>
> table.addCell(rightColumn);
>
>
> }
>
>
> }
>
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> table.writeSelectedRows(0, -1, TABLE_X_OFFSET, TABLE_Y_OFFSET, content);
>
>
> }
>
>
>
> private static void appendFooter(PdfWriter writer) throws Exception {
>
>
> Map replacements = new HashMap();
>
>
> replacements.put("ph0001", "XXXXX XXXXX");
>
>
> replacements.put("ph0002", "Head of Customer Acquisition");
>
>
> replacements.put("ph0003", "XXXXXX XXXXXXX");
>
>
> replacements.put("ph0004", "Head of Customer Satisfaction");
>
>
>
> PdfReader footerReader = new PdfReader(FOOTER_PATH);
>
>
> ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
>
>
> PdfStamper stamper = new PdfStamper(footerReader, outputStream);
>
>
> AcroFields form = stamper.getAcroFields();
>
>
> for (Map.Entry entry : replacements.entrySet()) {
>
>
> form.setField(entry.getKey(), entry.getValue());
>
>
> }
>
>
> stamper.setFormFlattening(true);
>
>
> stamper.close();
>
>
>
> int pageOne = 1;
>
>
> int xOffset = 5;
>
>
> int yOffset = -560;
>
>
> PdfReader memoryReader = new PdfReader(outputStream.toByteArray());
>
>
> PdfImportedPage importedPage = writer.getImportedPage(memoryReader, pageOne);
>
>
> PdfContentByte content = writer.getDirectContent();
>
>
> content.addTemplate(importedPage, xOffset, yOffset);
>
>
> }
>
>
> }                                       
_________________________________________________________________
The New Busy is not the too busy. Combine all your e-mail accounts with Hotmail.
http://www.windowslive.com/campaign/thenewbusy?tile=multiaccount&ocid=PID28326::T:WLMTAGL:ON:WL:en-US:WM_HMP:042010_4
------------------------------------------------------------------------------
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions

Buy the iText book: http://www.itextpdf.com/book/
Check the site with examples before you ask questions: 
http://www.1t3xt.info/examples/
You can also search the keywords list: http://1t3xt.info/tutorials/keywords/

Reply via email to