Source Code Cross Referenced for PdfDocument.java in  » PDF » pdf-itext » com » lowagie » text » pdf » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » PDF » pdf itext » com.lowagie.text.pdf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Name$
0003:         * $Id: PdfDocument.java 2903 2007-08-29 14:29:07Z blowagie $
0004:         *
0005:         * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
0006:         *
0007:         * The contents of this file are subject to the Mozilla Public License Version 1.1
0008:         * (the "License"); you may not use this file except in compliance with the License.
0009:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the License.
0014:         *
0015:         * The Original Code is 'iText, a free JAVA-PDF library'.
0016:         *
0017:         * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
0018:         * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
0019:         * All Rights Reserved.
0020:         * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
0021:         * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
0022:         *
0023:         * Contributor(s): all the names of the contributors are added in the source code
0024:         * where applicable.
0025:         *
0026:         * Alternatively, the contents of this file may be used under the terms of the
0027:         * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
0028:         * provisions of LGPL are applicable instead of those above.  If you wish to
0029:         * allow use of your version of this file only under the terms of the LGPL
0030:         * License and not to allow others to use your version of this file under
0031:         * the MPL, indicate your decision by deleting the provisions above and
0032:         * replace them with the notice and other provisions required by the LGPL.
0033:         * If you do not delete the provisions above, a recipient may use your version
0034:         * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
0035:         *
0036:         * This library is free software; you can redistribute it and/or modify it
0037:         * under the terms of the MPL as stated above or under the terms of the GNU
0038:         * Library General Public License as published by the Free Software Foundation;
0039:         * either version 2 of the License, or any later version.
0040:         *
0041:         * This library is distributed in the hope that it will be useful, but WITHOUT
0042:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
0043:         * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
0044:         * details.
0045:         *
0046:         * If you didn't download this code from the following link, you should check if
0047:         * you aren't using an obsolete version:
0048:         * http://www.lowagie.com/iText/
0049:         */
0050:
0051:        package com.lowagie.text.pdf;
0052:
0053:        import java.awt.Color;
0054:        import java.io.IOException;
0055:        import java.util.ArrayList;
0056:        import java.util.HashMap;
0057:        import java.util.HashSet;
0058:        import java.util.Iterator;
0059:        import java.util.LinkedHashMap;
0060:        import java.util.Map;
0061:        import java.util.Set;
0062:        import java.util.TreeMap;
0063:
0064:        import com.lowagie.text.Anchor;
0065:        import com.lowagie.text.Annotation;
0066:        import com.lowagie.text.BadElementException;
0067:        import com.lowagie.text.Chunk;
0068:        import com.lowagie.text.Document;
0069:        import com.lowagie.text.DocumentException;
0070:        import com.lowagie.text.Element;
0071:        import com.lowagie.text.ExceptionConverter;
0072:        import com.lowagie.text.Font;
0073:        import com.lowagie.text.HeaderFooter;
0074:        import com.lowagie.text.Image;
0075:        import com.lowagie.text.List;
0076:        import com.lowagie.text.ListItem;
0077:        import com.lowagie.text.MarkedObject;
0078:        import com.lowagie.text.MarkedSection;
0079:        import com.lowagie.text.Meta;
0080:        import com.lowagie.text.Paragraph;
0081:        import com.lowagie.text.Phrase;
0082:        import com.lowagie.text.Rectangle;
0083:        import com.lowagie.text.Section;
0084:        import com.lowagie.text.SimpleTable;
0085:        import com.lowagie.text.Table;
0086:        import com.lowagie.text.pdf.collection.PdfCollection;
0087:        import com.lowagie.text.pdf.internal.PdfAnnotationsImp;
0088:        import com.lowagie.text.pdf.internal.PdfViewerPreferencesImp;
0089:
0090:        /**
0091:         * <CODE>PdfDocument</CODE> is the class that is used by <CODE>PdfWriter</CODE>
0092:         * to translate a <CODE>Document</CODE> into a PDF with different pages.
0093:         * <P>
0094:         * A <CODE>PdfDocument</CODE> always listens to a <CODE>Document</CODE>
0095:         * and adds the Pdf representation of every <CODE>Element</CODE> that is
0096:         * added to the <CODE>Document</CODE>.
0097:         *
0098:         * @see		com.lowagie.text.Document
0099:         * @see		com.lowagie.text.DocListener
0100:         * @see		PdfWriter
0101:         */
0102:
0103:        class PdfDocument extends Document {
0104:
0105:            /**
0106:             * <CODE>PdfInfo</CODE> is the PDF InfoDictionary.
0107:             * <P>
0108:             * A document's trailer may contain a reference to an Info dictionary that provides information
0109:             * about the document. This optional dictionary may contain one or more keys, whose values
0110:             * should be strings.<BR>
0111:             * This object is described in the 'Portable Document Format Reference Manual version 1.3'
0112:             * section 6.10 (page 120-121)
0113:             */
0114:
0115:            public static class PdfInfo extends PdfDictionary {
0116:
0117:                /**
0118:                 * Construct a <CODE>PdfInfo</CODE>-object.
0119:                 */
0120:
0121:                PdfInfo() {
0122:                    super ();
0123:                    addProducer();
0124:                    addCreationDate();
0125:                }
0126:
0127:                /**
0128:                 * Constructs a <CODE>PdfInfo</CODE>-object.
0129:                 *
0130:                 * @param		author		name of the author of the document
0131:                 * @param		title		title of the document
0132:                 * @param		subject		subject of the document
0133:                 */
0134:
0135:                PdfInfo(String author, String title, String subject) {
0136:                    this ();
0137:                    addTitle(title);
0138:                    addSubject(subject);
0139:                    addAuthor(author);
0140:                }
0141:
0142:                /**
0143:                 * Adds the title of the document.
0144:                 *
0145:                 * @param	title		the title of the document
0146:                 */
0147:
0148:                void addTitle(String title) {
0149:                    put(PdfName.TITLE, new PdfString(title,
0150:                            PdfObject.TEXT_UNICODE));
0151:                }
0152:
0153:                /**
0154:                 * Adds the subject to the document.
0155:                 *
0156:                 * @param	subject		the subject of the document
0157:                 */
0158:
0159:                void addSubject(String subject) {
0160:                    put(PdfName.SUBJECT, new PdfString(subject,
0161:                            PdfObject.TEXT_UNICODE));
0162:                }
0163:
0164:                /**
0165:                 * Adds some keywords to the document.
0166:                 *
0167:                 * @param	keywords		the keywords of the document
0168:                 */
0169:
0170:                void addKeywords(String keywords) {
0171:                    put(PdfName.KEYWORDS, new PdfString(keywords,
0172:                            PdfObject.TEXT_UNICODE));
0173:                }
0174:
0175:                /**
0176:                 * Adds the name of the author to the document.
0177:                 *
0178:                 * @param	author		the name of the author
0179:                 */
0180:
0181:                void addAuthor(String author) {
0182:                    put(PdfName.AUTHOR, new PdfString(author,
0183:                            PdfObject.TEXT_UNICODE));
0184:                }
0185:
0186:                /**
0187:                 * Adds the name of the creator to the document.
0188:                 *
0189:                 * @param	creator		the name of the creator
0190:                 */
0191:
0192:                void addCreator(String creator) {
0193:                    put(PdfName.CREATOR, new PdfString(creator,
0194:                            PdfObject.TEXT_UNICODE));
0195:                }
0196:
0197:                /**
0198:                 * Adds the name of the producer to the document.
0199:                 */
0200:
0201:                void addProducer() {
0202:                    put(PdfName.PRODUCER, new PdfString(getVersion()));
0203:                }
0204:
0205:                /**
0206:                 * Adds the date of creation to the document.
0207:                 */
0208:
0209:                void addCreationDate() {
0210:                    PdfString date = new PdfDate();
0211:                    put(PdfName.CREATIONDATE, date);
0212:                    put(PdfName.MODDATE, date);
0213:                }
0214:
0215:                void addkey(String key, String value) {
0216:                    if (key.equals("Producer") || key.equals("CreationDate"))
0217:                        return;
0218:                    put(new PdfName(key), new PdfString(value,
0219:                            PdfObject.TEXT_UNICODE));
0220:                }
0221:            }
0222:
0223:            /**
0224:             * <CODE>PdfCatalog</CODE> is the PDF Catalog-object.
0225:             * <P>
0226:             * The Catalog is a dictionary that is the root node of the document. It contains a reference
0227:             * to the tree of pages contained in the document, a reference to the tree of objects representing
0228:             * the document's outline, a reference to the document's article threads, and the list of named
0229:             * destinations. In addition, the Catalog indicates whether the document's outline or thumbnail
0230:             * page images should be displayed automatically when the document is viewed and wether some location
0231:             * other than the first page should be shown when the document is opened.<BR>
0232:             * In this class however, only the reference to the tree of pages is implemented.<BR>
0233:             * This object is described in the 'Portable Document Format Reference Manual version 1.3'
0234:             * section 6.2 (page 67-71)
0235:             */
0236:
0237:            static class PdfCatalog extends PdfDictionary {
0238:
0239:                /** The writer writing the PDF for which we are creating this catalog object. */
0240:                PdfWriter writer;
0241:
0242:                /**
0243:                 * Constructs a <CODE>PdfCatalog</CODE>.
0244:                 *
0245:                 * @param		pages		an indirect reference to the root of the document's Pages tree.
0246:                 * @param writer the writer the catalog applies to
0247:                 */
0248:
0249:                PdfCatalog(PdfIndirectReference pages, PdfWriter writer) {
0250:                    super (CATALOG);
0251:                    this .writer = writer;
0252:                    put(PdfName.PAGES, pages);
0253:                }
0254:
0255:                /**
0256:                 * Adds the names of the named destinations to the catalog.
0257:                 * @param localDestinations the local destinations
0258:                 * @param documentLevelJS the javascript used in the document
0259:                 * @param documentFileAttachment	the attached files
0260:                 * @param writer the writer the catalog applies to
0261:                 */
0262:                void addNames(TreeMap localDestinations,
0263:                        LinkedHashMap documentLevelJS,
0264:                        HashMap documentFileAttachment, PdfWriter writer) {
0265:                    if (localDestinations.isEmpty()
0266:                            && documentLevelJS.isEmpty()
0267:                            && documentFileAttachment.isEmpty())
0268:                        return;
0269:                    try {
0270:                        PdfDictionary names = new PdfDictionary();
0271:                        if (!localDestinations.isEmpty()) {
0272:                            PdfArray ar = new PdfArray();
0273:                            for (Iterator i = localDestinations.entrySet()
0274:                                    .iterator(); i.hasNext();) {
0275:                                Map.Entry entry = (Map.Entry) i.next();
0276:                                String name = (String) entry.getKey();
0277:                                Object obj[] = (Object[]) entry.getValue();
0278:                                PdfIndirectReference ref = (PdfIndirectReference) obj[1];
0279:                                ar.add(new PdfString(name, null));
0280:                                ar.add(ref);
0281:                            }
0282:                            PdfDictionary dests = new PdfDictionary();
0283:                            dests.put(PdfName.NAMES, ar);
0284:                            names.put(PdfName.DESTS, writer.addToBody(dests)
0285:                                    .getIndirectReference());
0286:                        }
0287:                        if (!documentLevelJS.isEmpty()) {
0288:                            PdfDictionary tree = PdfNameTree.writeTree(
0289:                                    documentLevelJS, writer);
0290:                            names.put(PdfName.JAVASCRIPT, writer
0291:                                    .addToBody(tree).getIndirectReference());
0292:                        }
0293:                        if (!documentFileAttachment.isEmpty()) {
0294:                            names.put(PdfName.EMBEDDEDFILES, writer.addToBody(
0295:                                    PdfNameTree.writeTree(
0296:                                            documentFileAttachment, writer))
0297:                                    .getIndirectReference());
0298:                        }
0299:                        put(PdfName.NAMES, writer.addToBody(names)
0300:                                .getIndirectReference());
0301:                    } catch (IOException e) {
0302:                        throw new ExceptionConverter(e);
0303:                    }
0304:                }
0305:
0306:                /**
0307:                 * Adds an open action to the catalog.
0308:                 * @param	action	the action that will be triggered upon opening the document
0309:                 */
0310:                void setOpenAction(PdfAction action) {
0311:                    put(PdfName.OPENACTION, action);
0312:                }
0313:
0314:                /**
0315:                 * Sets the document level additional actions.
0316:                 * @param actions   dictionary of actions
0317:                 */
0318:                void setAdditionalActions(PdfDictionary actions) {
0319:                    try {
0320:                        put(PdfName.AA, writer.addToBody(actions)
0321:                                .getIndirectReference());
0322:                    } catch (Exception e) {
0323:                        throw new ExceptionConverter(e);
0324:                    }
0325:                }
0326:            }
0327:
0328:            // CONSTRUCTING A PdfDocument/PdfWriter INSTANCE
0329:
0330:            /**
0331:             * Constructs a new PDF document.
0332:             * @throws DocumentException on error
0333:             */
0334:            public PdfDocument() {
0335:                super ();
0336:                addProducer();
0337:                addCreationDate();
0338:            }
0339:
0340:            /** The <CODE>PdfWriter</CODE>. */
0341:            private PdfWriter writer;
0342:
0343:            /**
0344:             * Adds a <CODE>PdfWriter</CODE> to the <CODE>PdfDocument</CODE>.
0345:             *
0346:             * @param writer the <CODE>PdfWriter</CODE> that writes everything
0347:             *                     what is added to this document to an outputstream.
0348:             * @throws DocumentException on error
0349:             */
0350:            public void addWriter(PdfWriter writer) throws DocumentException {
0351:                if (this .writer == null) {
0352:                    this .writer = writer;
0353:                    annotationsImp = new PdfAnnotationsImp(writer);
0354:                    return;
0355:                }
0356:                throw new DocumentException(
0357:                        "You can only add a writer to a PdfDocument once.");
0358:            }
0359:
0360:            // LISTENER METHODS START
0361:
0362:            //	[L0] ElementListener interface
0363:
0364:            /** This is the PdfContentByte object, containing the text. */
0365:            private PdfContentByte text;
0366:
0367:            /** This is the PdfContentByte object, containing the borders and other Graphics. */
0368:            private PdfContentByte graphics;
0369:
0370:            /** This represents the leading of the lines. */
0371:            private float leading = 0;
0372:
0373:            /** This represents the current alignment of the PDF Elements. */
0374:            private int alignment = Element.ALIGN_LEFT;
0375:
0376:            /** This is the current height of the document. */
0377:            private float currentHeight = 0;
0378:
0379:            /** Signals that onParagraph is valid (to avoid that a Chapter/Section title is treated as a Paragraph). */
0380:            private boolean isParagraph = true;
0381:
0382:            /** The current active <CODE>PdfAction</CODE> when processing an <CODE>Anchor</CODE>. */
0383:            private PdfAction anchorAction = null;
0384:
0385:            /**
0386:             * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
0387:             *
0388:             * @param element the element to add
0389:             * @return <CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
0390:             * @throws DocumentException when a document isn't open yet, or has been closed
0391:             */
0392:            public boolean add(Element element) throws DocumentException {
0393:                if (writer != null && writer.isPaused()) {
0394:                    return false;
0395:                }
0396:                try {
0397:                    switch (element.type()) {
0398:                    // Information (headers)
0399:                    case Element.HEADER:
0400:                        info.addkey(((Meta) element).getName(),
0401:                                ((Meta) element).getContent());
0402:                        break;
0403:                    case Element.TITLE:
0404:                        info.addTitle(((Meta) element).getContent());
0405:                        break;
0406:                    case Element.SUBJECT:
0407:                        info.addSubject(((Meta) element).getContent());
0408:                        break;
0409:                    case Element.KEYWORDS:
0410:                        info.addKeywords(((Meta) element).getContent());
0411:                        break;
0412:                    case Element.AUTHOR:
0413:                        info.addAuthor(((Meta) element).getContent());
0414:                        break;
0415:                    case Element.CREATOR:
0416:                        info.addCreator(((Meta) element).getContent());
0417:                        break;
0418:                    case Element.PRODUCER:
0419:                        // you can not change the name of the producer
0420:                        info.addProducer();
0421:                        break;
0422:                    case Element.CREATIONDATE:
0423:                        // you can not set the creation date, only reset it
0424:                        info.addCreationDate();
0425:                        break;
0426:
0427:                    // content (text)
0428:                    case Element.CHUNK: {
0429:                        // if there isn't a current line available, we make one
0430:                        if (line == null) {
0431:                            carriageReturn();
0432:                        }
0433:
0434:                        // we cast the element to a chunk
0435:                        PdfChunk chunk = new PdfChunk((Chunk) element,
0436:                                anchorAction);
0437:                        // we try to add the chunk to the line, until we succeed
0438:                        {
0439:                            PdfChunk overflow;
0440:                            while ((overflow = line.add(chunk)) != null) {
0441:                                carriageReturn();
0442:                                chunk = overflow;
0443:                                chunk.trimFirstSpace();
0444:                            }
0445:                        }
0446:                        pageEmpty = false;
0447:                        if (chunk.isAttribute(Chunk.NEWPAGE)) {
0448:                            newPage();
0449:                        }
0450:                        break;
0451:                    }
0452:                    case Element.ANCHOR: {
0453:                        Anchor anchor = (Anchor) element;
0454:                        String url = anchor.getReference();
0455:                        leading = anchor.getLeading();
0456:                        if (url != null) {
0457:                            anchorAction = new PdfAction(url);
0458:                        }
0459:                        // we process the element
0460:                        element.process(this );
0461:                        anchorAction = null;
0462:                        break;
0463:                    }
0464:                    case Element.ANNOTATION: {
0465:                        if (line == null) {
0466:                            carriageReturn();
0467:                        }
0468:                        Annotation annot = (Annotation) element;
0469:                        Rectangle rect = new Rectangle(0, 0);
0470:                        if (line != null)
0471:                            rect = new Rectangle(annot.llx(indentRight()
0472:                                    - line.widthLeft()), annot.lly(indentTop()
0473:                                    - currentHeight), annot.urx(indentRight()
0474:                                    - line.widthLeft() + 20), annot
0475:                                    .ury(indentTop() - currentHeight - 20));
0476:                        PdfAnnotation an = PdfAnnotationsImp.convertAnnotation(
0477:                                writer, annot, rect);
0478:                        annotationsImp.addPlainAnnotation(an);
0479:                        pageEmpty = false;
0480:                        break;
0481:                    }
0482:                    case Element.PHRASE: {
0483:                        // we cast the element to a phrase and set the leading of the document
0484:                        leading = ((Phrase) element).getLeading();
0485:                        // we process the element
0486:                        element.process(this );
0487:                        break;
0488:                    }
0489:                    case Element.PARAGRAPH: {
0490:                        // we cast the element to a paragraph
0491:                        Paragraph paragraph = (Paragraph) element;
0492:
0493:                        addSpacing(paragraph.spacingBefore(), leading,
0494:                                paragraph.getFont());
0495:
0496:                        // we adjust the parameters of the document
0497:                        alignment = paragraph.getAlignment();
0498:                        leading = paragraph.getTotalLeading();
0499:                        carriageReturn();
0500:
0501:                        // we don't want to make orphans/widows
0502:                        if (currentHeight + line.height() + leading > indentTop()
0503:                                - indentBottom()) {
0504:                            newPage();
0505:                        }
0506:
0507:                        indentation.indentLeft += paragraph
0508:                                .getIndentationLeft();
0509:                        indentation.indentRight += paragraph
0510:                                .getIndentationRight();
0511:                        carriageReturn();
0512:
0513:                        PdfPageEvent pageEvent = writer.getPageEvent();
0514:                        if (pageEvent != null && isParagraph)
0515:                            pageEvent.onParagraph(writer, this , indentTop()
0516:                                    - currentHeight);
0517:
0518:                        // if a paragraph has to be kept together, we wrap it in a table object
0519:                        if (paragraph.getKeepTogether()) {
0520:                            carriageReturn();
0521:                            PdfPTable table = new PdfPTable(1);
0522:                            table.setWidthPercentage(100f);
0523:                            PdfPCell cell = new PdfPCell();
0524:                            cell.addElement(paragraph);
0525:                            cell.setBorder(Table.NO_BORDER);
0526:                            cell.setPadding(0);
0527:                            table.addCell(cell);
0528:                            indentation.indentLeft -= paragraph
0529:                                    .getIndentationLeft();
0530:                            indentation.indentRight -= paragraph
0531:                                    .getIndentationRight();
0532:                            this .add(table);
0533:                            indentation.indentLeft += paragraph
0534:                                    .getIndentationLeft();
0535:                            indentation.indentRight += paragraph
0536:                                    .getIndentationRight();
0537:                        } else {
0538:                            line.setExtraIndent(paragraph.getFirstLineIndent());
0539:                            element.process(this );
0540:                            carriageReturn();
0541:                            addSpacing(paragraph.spacingAfter(), paragraph
0542:                                    .getTotalLeading(), paragraph.getFont());
0543:                        }
0544:
0545:                        if (pageEvent != null && isParagraph)
0546:                            pageEvent.onParagraphEnd(writer, this , indentTop()
0547:                                    - currentHeight);
0548:
0549:                        alignment = Element.ALIGN_LEFT;
0550:                        indentation.indentLeft -= paragraph
0551:                                .getIndentationLeft();
0552:                        indentation.indentRight -= paragraph
0553:                                .getIndentationRight();
0554:                        carriageReturn();
0555:                        break;
0556:                    }
0557:                    case Element.SECTION:
0558:                    case Element.CHAPTER: {
0559:                        // Chapters and Sections only differ in their constructor
0560:                        // so we cast both to a Section
0561:                        Section section = (Section) element;
0562:
0563:                        boolean hasTitle = section.getTitle() != null;
0564:
0565:                        // if the section is a chapter, we begin a new page
0566:                        if (section.isTriggerNewPage()) {
0567:                            newPage();
0568:                        }
0569:                        // otherwise, we begin a new line
0570:                        else {
0571:                            newLine();
0572:                        }
0573:
0574:                        if (hasTitle) {
0575:                            float fith = indentTop() - currentHeight;
0576:                            int rotation = pageSize.getRotation();
0577:                            if (rotation == 90 || rotation == 180)
0578:                                fith = pageSize.getHeight() - fith;
0579:                            PdfDestination destination = new PdfDestination(
0580:                                    PdfDestination.FITH, fith);
0581:                            while (currentOutline.level() >= section.getDepth()) {
0582:                                currentOutline = currentOutline.parent();
0583:                            }
0584:                            PdfOutline outline = new PdfOutline(currentOutline,
0585:                                    destination, section.getBookmarkTitle(),
0586:                                    section.isBookmarkOpen());
0587:                            currentOutline = outline;
0588:                        }
0589:
0590:                        // some values are set
0591:                        carriageReturn();
0592:                        indentation.sectionIndentLeft += section
0593:                                .getIndentationLeft();
0594:                        indentation.sectionIndentRight += section
0595:                                .getIndentationRight();
0596:
0597:                        PdfPageEvent pageEvent = writer.getPageEvent();
0598:                        if (pageEvent != null)
0599:                            if (element.type() == Element.CHAPTER)
0600:                                pageEvent.onChapter(writer, this , indentTop()
0601:                                        - currentHeight, section.getTitle());
0602:                            else
0603:                                pageEvent.onSection(writer, this , indentTop()
0604:                                        - currentHeight, section.getDepth(),
0605:                                        section.getTitle());
0606:
0607:                        // the title of the section (if any has to be printed)
0608:                        if (hasTitle) {
0609:                            isParagraph = false;
0610:                            add(section.getTitle());
0611:                            isParagraph = true;
0612:                        }
0613:                        indentation.sectionIndentLeft += section
0614:                                .getIndentation();
0615:                        // we process the section
0616:                        element.process(this );
0617:                        flushLines();
0618:                        // some parameters are set back to normal again
0619:                        indentation.sectionIndentLeft -= (section
0620:                                .getIndentationLeft() + section
0621:                                .getIndentation());
0622:                        indentation.sectionIndentRight -= section
0623:                                .getIndentationRight();
0624:
0625:                        if (pageEvent != null)
0626:                            if (element.type() == Element.CHAPTER)
0627:                                pageEvent.onChapterEnd(writer, this ,
0628:                                        indentTop() - currentHeight);
0629:                            else
0630:                                pageEvent.onSectionEnd(writer, this ,
0631:                                        indentTop() - currentHeight);
0632:
0633:                        break;
0634:                    }
0635:                    case Element.LIST: {
0636:                        // we cast the element to a List
0637:                        List list = (List) element;
0638:                        if (list.isAlignindent()) {
0639:                            list.normalizeIndentation();
0640:                        }
0641:                        // we adjust the document
0642:                        indentation.listIndentLeft += list.getIndentationLeft();
0643:                        indentation.indentRight += list.getIndentationRight();
0644:                        // we process the items in the list
0645:                        element.process(this );
0646:                        // some parameters are set back to normal again
0647:                        indentation.listIndentLeft -= list.getIndentationLeft();
0648:                        indentation.indentRight -= list.getIndentationRight();
0649:                        carriageReturn();
0650:                        break;
0651:                    }
0652:                    case Element.LISTITEM: {
0653:                        // we cast the element to a ListItem
0654:                        ListItem listItem = (ListItem) element;
0655:
0656:                        addSpacing(listItem.spacingBefore(), leading, listItem
0657:                                .getFont());
0658:
0659:                        // we adjust the document
0660:                        alignment = listItem.getAlignment();
0661:                        indentation.listIndentLeft += listItem
0662:                                .getIndentationLeft();
0663:                        indentation.indentRight += listItem
0664:                                .getIndentationRight();
0665:                        leading = listItem.getTotalLeading();
0666:                        carriageReturn();
0667:
0668:                        // we prepare the current line to be able to show us the listsymbol
0669:                        line.setListItem(listItem);
0670:                        // we process the item
0671:                        element.process(this );
0672:
0673:                        addSpacing(listItem.spacingAfter(), listItem
0674:                                .getTotalLeading(), listItem.getFont());
0675:
0676:                        // if the last line is justified, it should be aligned to the left
0677:                        if (line.hasToBeJustified()) {
0678:                            line.resetAlignment();
0679:                        }
0680:                        // some parameters are set back to normal again
0681:                        carriageReturn();
0682:                        indentation.listIndentLeft -= listItem
0683:                                .getIndentationLeft();
0684:                        indentation.indentRight -= listItem
0685:                                .getIndentationRight();
0686:                        break;
0687:                    }
0688:                    case Element.RECTANGLE: {
0689:                        Rectangle rectangle = (Rectangle) element;
0690:                        graphics.rectangle(rectangle);
0691:                        pageEmpty = false;
0692:                        break;
0693:                    }
0694:                    case Element.PTABLE: {
0695:                        PdfPTable ptable = (PdfPTable) element;
0696:                        if (ptable.size() <= ptable.getHeaderRows())
0697:                            break; //nothing to do
0698:
0699:                        // before every table, we add a new line and flush all lines
0700:                        ensureNewLine();
0701:                        flushLines();
0702:
0703:                        addPTable(ptable);
0704:                        pageEmpty = false;
0705:                        newLine();
0706:                        break;
0707:                    }
0708:                    case Element.MULTI_COLUMN_TEXT: {
0709:                        ensureNewLine();
0710:                        flushLines();
0711:                        MultiColumnText multiText = (MultiColumnText) element;
0712:                        float height = multiText.write(writer
0713:                                .getDirectContent(), this , indentTop()
0714:                                - currentHeight);
0715:                        currentHeight += height;
0716:                        text.moveText(0, -1f * height);
0717:                        pageEmpty = false;
0718:                        break;
0719:                    }
0720:                    case Element.TABLE: {
0721:                        PdfTable table;
0722:                        if (element instanceof  PdfTable) {
0723:                            // Already pre-rendered
0724:                            table = (PdfTable) element;
0725:                            table.updateRowAdditions();
0726:                        } else if (element instanceof  SimpleTable) {
0727:                            PdfPTable ptable = ((SimpleTable) element)
0728:                                    .createPdfPTable();
0729:                            if (ptable.size() <= ptable.getHeaderRows())
0730:                                break; //nothing to do
0731:
0732:                            // before every table, we add a new line and flush all lines
0733:                            ensureNewLine();
0734:                            flushLines();
0735:                            addPTable(ptable);
0736:                            pageEmpty = false;
0737:                            break;
0738:                        } else if (element instanceof  Table) {
0739:                            try {
0740:                                PdfPTable ptable = ((Table) element)
0741:                                        .createPdfPTable();
0742:                                if (ptable.size() <= ptable.getHeaderRows())
0743:                                    break; //nothing to do
0744:
0745:                                // before every table, we add a new line and flush all lines
0746:                                ensureNewLine();
0747:                                flushLines();
0748:                                addPTable(ptable);
0749:                                pageEmpty = false;
0750:                                break;
0751:                            } catch (BadElementException bee) {
0752:                                // constructing the PdfTable
0753:                                // Before the table, add a blank line using offset or default leading
0754:                                float offset = ((Table) element).getOffset();
0755:                                if (Float.isNaN(offset))
0756:                                    offset = leading;
0757:                                carriageReturn();
0758:                                lines.add(new PdfLine(indentLeft(),
0759:                                        indentRight(), alignment, offset));
0760:                                currentHeight += offset;
0761:                                table = getPdfTable((Table) element, false);
0762:                            }
0763:                        } else {
0764:                            return false;
0765:                        }
0766:                        add(table, false);
0767:                        break;
0768:                    }
0769:                    case Element.JPEG:
0770:                    case Element.IMGRAW:
0771:                    case Element.IMGTEMPLATE: {
0772:                        //carriageReturn(); suggestion by Marc Campforts
0773:                        add((Image) element);
0774:                        break;
0775:                    }
0776:                    case Element.MARKED: {
0777:                        MarkedObject mo;
0778:                        if (element instanceof  MarkedSection) {
0779:                            mo = ((MarkedSection) element).title();
0780:                            if (mo != null) {
0781:                                mo.process(this );
0782:                            }
0783:                        }
0784:                        mo = (MarkedObject) element;
0785:                        mo.process(this );
0786:                        break;
0787:                    }
0788:                    default:
0789:                        return false;
0790:                    }
0791:                    lastElementType = element.type();
0792:                    return true;
0793:                } catch (Exception e) {
0794:                    throw new DocumentException(e);
0795:                }
0796:            }
0797:
0798:            //	[L1] DocListener interface
0799:
0800:            /**
0801:             * Opens the document.
0802:             * <P>
0803:             * You have to open the document before you can begin to add content
0804:             * to the body of the document.
0805:             */
0806:            public void open() {
0807:                if (!open) {
0808:                    super .open();
0809:                    writer.open();
0810:                    rootOutline = new PdfOutline(writer);
0811:                    currentOutline = rootOutline;
0812:                }
0813:                try {
0814:                    initPage();
0815:                } catch (DocumentException de) {
0816:                    throw new ExceptionConverter(de);
0817:                }
0818:            }
0819:
0820:            //	[L2] DocListener interface
0821:
0822:            /**
0823:             * Closes the document.
0824:             * <B>
0825:             * Once all the content has been written in the body, you have to close
0826:             * the body. After that nothing can be written to the body anymore.
0827:             */
0828:            public void close() {
0829:                if (close) {
0830:                    return;
0831:                }
0832:                try {
0833:                    boolean wasImage = (imageWait != null);
0834:                    newPage();
0835:                    if (imageWait != null || wasImage)
0836:                        newPage();
0837:                    if (annotationsImp.hasUnusedAnnotations())
0838:                        throw new RuntimeException(
0839:                                "Not all annotations could be added to the document (the document doesn't have enough pages).");
0840:                    PdfPageEvent pageEvent = writer.getPageEvent();
0841:                    if (pageEvent != null)
0842:                        pageEvent.onCloseDocument(writer, this );
0843:                    super .close();
0844:
0845:                    writer.addLocalDestinations(localDestinations);
0846:                    calculateOutlineCount();
0847:                    writeOutlines();
0848:                } catch (Exception e) {
0849:                    throw new ExceptionConverter(e);
0850:                }
0851:
0852:                writer.close();
0853:            }
0854:
0855:            //	[L3] DocListener interface
0856:            private int textEmptySize;
0857:
0858:            // [C9] Metadata for the page
0859:            /** XMP Metadata for the page. */
0860:            protected byte[] xmpMetadata = null;
0861:
0862:            /**
0863:             * Use this method to set the XMP Metadata.
0864:             * @param xmpMetadata The xmpMetadata to set.
0865:             */
0866:            public void setXmpMetadata(byte[] xmpMetadata) {
0867:                this .xmpMetadata = xmpMetadata;
0868:            }
0869:
0870:            /**
0871:             * Makes a new page and sends it to the <CODE>PdfWriter</CODE>.
0872:             *
0873:             * @return a <CODE>boolean</CODE>
0874:             * @throws DocumentException on error
0875:             */
0876:            public boolean newPage() {
0877:                lastElementType = -1;
0878:                if (writer == null
0879:                        || (writer.getDirectContent().size() == 0
0880:                                && writer.getDirectContentUnder().size() == 0 && (pageEmpty || writer
0881:                                .isPaused()))) {
0882:                    setNewPageSizeAndMargins();
0883:                    return false;
0884:                }
0885:                if (!open || close) {
0886:                    throw new RuntimeException("The document isn't open.");
0887:                }
0888:                PdfPageEvent pageEvent = writer.getPageEvent();
0889:                if (pageEvent != null)
0890:                    pageEvent.onEndPage(writer, this );
0891:
0892:                //Added to inform any listeners that we are moving to a new page (added by David Freels)
0893:                super .newPage();
0894:
0895:                // the following 2 lines were added by Pelikan Stephan
0896:                indentation.imageIndentLeft = 0;
0897:                indentation.imageIndentRight = 0;
0898:
0899:                try {
0900:                    // we flush the arraylist with recently written lines
0901:                    flushLines();
0902:
0903:                    // we prepare the elements of the page dictionary
0904:
0905:                    // [U1] page size and rotation
0906:                    int rotation = pageSize.getRotation();
0907:
0908:                    // [C10]
0909:                    if (writer.isPdfX()) {
0910:                        if (this BoxSize.containsKey("art")
0911:                                && this BoxSize.containsKey("trim"))
0912:                            throw new PdfXConformanceException(
0913:                                    "Only one of ArtBox or TrimBox can exist in the page.");
0914:                        if (!this BoxSize.containsKey("art")
0915:                                && !this BoxSize.containsKey("trim")) {
0916:                            if (this BoxSize.containsKey("crop"))
0917:                                this BoxSize
0918:                                        .put("trim", this BoxSize.get("crop"));
0919:                            else
0920:                                this BoxSize.put("trim", new PdfRectangle(
0921:                                        pageSize, pageSize.getRotation()));
0922:                        }
0923:                    }
0924:
0925:                    // [M1]
0926:                    pageResources.addDefaultColorDiff(writer
0927:                            .getDefaultColorspace());
0928:                    PdfDictionary resources = pageResources.getResources();
0929:
0930:                    // we create the page dictionary
0931:
0932:                    PdfPage page = new PdfPage(new PdfRectangle(pageSize,
0933:                            rotation), this BoxSize, resources, rotation);
0934:
0935:                    // we complete the page dictionary
0936:
0937:                    // [C9] if there is XMP data to add: add it
0938:                    if (xmpMetadata != null) {
0939:                        PdfStream xmp = new PdfStream(xmpMetadata);
0940:                        xmp.put(PdfName.TYPE, PdfName.METADATA);
0941:                        xmp.put(PdfName.SUBTYPE, PdfName.XML);
0942:                        PdfEncryption crypto = writer.getEncryption();
0943:                        if (crypto != null && !crypto.isMetadataEncrypted()) {
0944:                            PdfArray ar = new PdfArray();
0945:                            ar.add(PdfName.CRYPT);
0946:                            xmp.put(PdfName.FILTER, ar);
0947:                        }
0948:                        page.put(PdfName.METADATA, writer.addToBody(xmp)
0949:                                .getIndirectReference());
0950:                    }
0951:
0952:                    // [U3] page actions: transition, duration, additional actions
0953:                    if (this .transition != null) {
0954:                        page.put(PdfName.TRANS, this .transition
0955:                                .getTransitionDictionary());
0956:                        transition = null;
0957:                    }
0958:                    if (this .duration > 0) {
0959:                        page.put(PdfName.DUR, new PdfNumber(this .duration));
0960:                        duration = 0;
0961:                    }
0962:                    if (pageAA != null) {
0963:                        page.put(PdfName.AA, writer.addToBody(pageAA)
0964:                                .getIndirectReference());
0965:                        pageAA = null;
0966:                    }
0967:
0968:                    // [U4] we add the thumbs
0969:                    if (thumb != null) {
0970:                        page.put(PdfName.THUMB, thumb);
0971:                        thumb = null;
0972:                    }
0973:
0974:                    // [U8] we check if the userunit is defined
0975:                    if (writer.getUserunit() > 0f) {
0976:                        page.put(PdfName.USERUNIT, new PdfNumber(writer
0977:                                .getUserunit()));
0978:                    }
0979:
0980:                    // [C5] and [C8] we add the annotations
0981:                    if (annotationsImp.hasUnusedAnnotations()) {
0982:                        PdfArray array = annotationsImp.rotateAnnotations(
0983:                                writer, pageSize);
0984:                        if (array.size() != 0)
0985:                            page.put(PdfName.ANNOTS, array);
0986:                    }
0987:
0988:                    // [F12] we add tag info
0989:                    if (writer.isTagged())
0990:                        page.put(PdfName.STRUCTPARENTS, new PdfNumber(writer
0991:                                .getCurrentPageNumber() - 1));
0992:
0993:                    if (text.size() > textEmptySize)
0994:                        text.endText();
0995:                    else
0996:                        text = null;
0997:                    writer.add(page, new PdfContents(writer
0998:                            .getDirectContentUnder(), graphics, text, writer
0999:                            .getDirectContent(), pageSize));
1000:                    // we initialize the new page
1001:                    initPage();
1002:                } catch (DocumentException de) {
1003:                    // maybe this never happens, but it's better to check.
1004:                    throw new ExceptionConverter(de);
1005:                } catch (IOException ioe) {
1006:                    throw new ExceptionConverter(ioe);
1007:                }
1008:                return true;
1009:            }
1010:
1011:            //	[L4] DocListener interface
1012:
1013:            /**
1014:             * Sets the pagesize.
1015:             *
1016:             * @param pageSize the new pagesize
1017:             * @return <CODE>true</CODE> if the page size was set
1018:             */
1019:            public boolean setPageSize(Rectangle pageSize) {
1020:                if (writer != null && writer.isPaused()) {
1021:                    return false;
1022:                }
1023:                nextPageSize = new Rectangle(pageSize);
1024:                return true;
1025:            }
1026:
1027:            //	[L5] DocListener interface
1028:
1029:            /** margin in x direction starting from the left. Will be valid in the next page */
1030:            protected float nextMarginLeft;
1031:
1032:            /** margin in x direction starting from the right. Will be valid in the next page */
1033:            protected float nextMarginRight;
1034:
1035:            /** margin in y direction starting from the top. Will be valid in the next page */
1036:            protected float nextMarginTop;
1037:
1038:            /** margin in y direction starting from the bottom. Will be valid in the next page */
1039:            protected float nextMarginBottom;
1040:
1041:            /**
1042:             * Sets the margins.
1043:             *
1044:             * @param	marginLeft		the margin on the left
1045:             * @param	marginRight		the margin on the right
1046:             * @param	marginTop		the margin on the top
1047:             * @param	marginBottom	the margin on the bottom
1048:             * @return	a <CODE>boolean</CODE>
1049:             */
1050:            public boolean setMargins(float marginLeft, float marginRight,
1051:                    float marginTop, float marginBottom) {
1052:                if (writer != null && writer.isPaused()) {
1053:                    return false;
1054:                }
1055:                nextMarginLeft = marginLeft;
1056:                nextMarginRight = marginRight;
1057:                nextMarginTop = marginTop;
1058:                nextMarginBottom = marginBottom;
1059:                return true;
1060:            }
1061:
1062:            //	[L6] DocListener interface
1063:
1064:            /**
1065:             * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
1066:             */
1067:            public boolean setMarginMirroring(boolean MarginMirroring) {
1068:                if (writer != null && writer.isPaused()) {
1069:                    return false;
1070:                }
1071:                return super .setMarginMirroring(MarginMirroring);
1072:            }
1073:
1074:            //	[L7] DocListener interface
1075:
1076:            /**
1077:             * Sets the page number.
1078:             *
1079:             * @param	pageN		the new page number
1080:             */
1081:            public void setPageCount(int pageN) {
1082:                if (writer != null && writer.isPaused()) {
1083:                    return;
1084:                }
1085:                super .setPageCount(pageN);
1086:            }
1087:
1088:            //	[L8] DocListener interface
1089:
1090:            /**
1091:             * Sets the page number to 0.
1092:             */
1093:            public void resetPageCount() {
1094:                if (writer != null && writer.isPaused()) {
1095:                    return;
1096:                }
1097:                super .resetPageCount();
1098:            }
1099:
1100:            //	[L9] DocListener interface
1101:
1102:            /**
1103:             * Changes the header of this document.
1104:             *
1105:             * @param header the new header
1106:             */
1107:            public void setHeader(HeaderFooter header) {
1108:                if (writer != null && writer.isPaused()) {
1109:                    return;
1110:                }
1111:                super .setHeader(header);
1112:            }
1113:
1114:            //	[L10] DocListener interface
1115:
1116:            /**
1117:             * Resets the header of this document.
1118:             */
1119:            public void resetHeader() {
1120:                if (writer != null && writer.isPaused()) {
1121:                    return;
1122:                }
1123:                super .resetHeader();
1124:            }
1125:
1126:            //	[L11] DocListener interface
1127:
1128:            /**
1129:             * Changes the footer of this document.
1130:             *
1131:             * @param	footer		the new footer
1132:             */
1133:            public void setFooter(HeaderFooter footer) {
1134:                if (writer != null && writer.isPaused()) {
1135:                    return;
1136:                }
1137:                super .setFooter(footer);
1138:            }
1139:
1140:            //	[L12] DocListener interface
1141:
1142:            /**
1143:             * Resets the footer of this document.
1144:             */
1145:            public void resetFooter() {
1146:                if (writer != null && writer.isPaused()) {
1147:                    return;
1148:                }
1149:                super .resetFooter();
1150:            }
1151:
1152:            // DOCLISTENER METHODS END
1153:
1154:            /** Signals that OnOpenDocument should be called. */
1155:            private boolean firstPageEvent = true;
1156:
1157:            /**
1158:             * Initializes a page.
1159:             * <P>
1160:             * If the footer/header is set, it is printed.
1161:             * @throws DocumentException on error
1162:             */
1163:            private void initPage() throws DocumentException {
1164:                // the pagenumber is incremented
1165:                pageN++;
1166:
1167:                // initialisation of some page objects
1168:                annotationsImp.resetAnnotations();
1169:                pageResources = new PageResources();
1170:
1171:                writer.resetContent();
1172:                graphics = new PdfContentByte(writer);
1173:                text = new PdfContentByte(writer);
1174:                text.reset();
1175:                text.beginText();
1176:                textEmptySize = text.size();
1177:
1178:                markPoint = 0;
1179:                setNewPageSizeAndMargins();
1180:                imageEnd = -1;
1181:                indentation.imageIndentRight = 0;
1182:                indentation.imageIndentLeft = 0;
1183:                indentation.indentBottom = 0;
1184:                indentation.indentTop = 0;
1185:                currentHeight = 0;
1186:
1187:                // backgroundcolors, etc...
1188:                this BoxSize = new HashMap(boxSize);
1189:                if (pageSize.getBackgroundColor() != null
1190:                        || pageSize.hasBorders()
1191:                        || pageSize.getBorderColor() != null) {
1192:                    add(pageSize);
1193:                }
1194:
1195:                float oldleading = leading;
1196:                int oldAlignment = alignment;
1197:                // if there is a footer, the footer is added
1198:                doFooter();
1199:                // we move to the left/top position of the page
1200:                text.moveText(left(), top());
1201:                doHeader();
1202:                pageEmpty = true;
1203:                // if there is an image waiting to be drawn, draw it
1204:                try {
1205:                    if (imageWait != null) {
1206:                        add(imageWait);
1207:                        imageWait = null;
1208:                    }
1209:                } catch (Exception e) {
1210:                    throw new ExceptionConverter(e);
1211:                }
1212:                leading = oldleading;
1213:                alignment = oldAlignment;
1214:                carriageReturn();
1215:
1216:                PdfPageEvent pageEvent = writer.getPageEvent();
1217:                if (pageEvent != null) {
1218:                    if (firstPageEvent) {
1219:                        pageEvent.onOpenDocument(writer, this );
1220:                    }
1221:                    pageEvent.onStartPage(writer, this );
1222:                }
1223:                firstPageEvent = false;
1224:            }
1225:
1226:            /** The line that is currently being written. */
1227:            private PdfLine line = null;
1228:            /** The lines that are written until now. */
1229:            private ArrayList lines = new ArrayList();
1230:
1231:            /**
1232:             * Adds the current line to the list of lines and also adds an empty line.
1233:             * @throws DocumentException on error
1234:             */
1235:            private void newLine() throws DocumentException {
1236:                lastElementType = -1;
1237:                carriageReturn();
1238:                if (lines != null && !lines.isEmpty()) {
1239:                    lines.add(line);
1240:                    currentHeight += line.height();
1241:                }
1242:                line = new PdfLine(indentLeft(), indentRight(), alignment,
1243:                        leading);
1244:            }
1245:
1246:            /**
1247:             * If the current line is not empty or null, it is added to the arraylist
1248:             * of lines and a new empty line is added.
1249:             * @throws DocumentException on error
1250:             */
1251:            private void carriageReturn() {
1252:                // the arraylist with lines may not be null
1253:                if (lines == null) {
1254:                    lines = new ArrayList();
1255:                }
1256:                // If the current line is not null
1257:                if (line != null) {
1258:                    // we check if the end of the page is reached (bugfix by Francois Gravel)
1259:                    if (currentHeight + line.height() + leading < indentTop()
1260:                            - indentBottom()) {
1261:                        // if so nonempty lines are added and the heigt is augmented
1262:                        if (line.size() > 0) {
1263:                            currentHeight += line.height();
1264:                            lines.add(line);
1265:                            pageEmpty = false;
1266:                        }
1267:                    }
1268:                    // if the end of the line is reached, we start a new page
1269:                    else {
1270:                        newPage();
1271:                    }
1272:                }
1273:                if (imageEnd > -1 && currentHeight > imageEnd) {
1274:                    imageEnd = -1;
1275:                    indentation.imageIndentRight = 0;
1276:                    indentation.imageIndentLeft = 0;
1277:                }
1278:                // a new current line is constructed
1279:                line = new PdfLine(indentLeft(), indentRight(), alignment,
1280:                        leading);
1281:            }
1282:
1283:            /**
1284:             * Gets the current vertical page position.
1285:             * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects 
1286:             *   for elements that do not terminate the lines they've started because those lines will get
1287:             *   terminated. 
1288:             * @return The current vertical page position.
1289:             */
1290:            public float getVerticalPosition(boolean ensureNewLine) {
1291:                // ensuring that a new line has been started.
1292:                if (ensureNewLine) {
1293:                    ensureNewLine();
1294:                }
1295:                return top() - currentHeight - indentation.indentTop;
1296:            }
1297:
1298:            /** Holds the type of the last element, that has been added to the document. */
1299:            private int lastElementType = -1;
1300:
1301:            /**
1302:             * Ensures that a new line has been started. 
1303:             */
1304:            private void ensureNewLine() {
1305:                try {
1306:                    if ((lastElementType == Element.PHRASE)
1307:                            || (lastElementType == Element.CHUNK)) {
1308:                        newLine();
1309:                        flushLines();
1310:                    }
1311:                } catch (DocumentException ex) {
1312:                    throw new ExceptionConverter(ex);
1313:                }
1314:            }
1315:
1316:            /**
1317:             * Writes all the lines to the text-object.
1318:             *
1319:             * @return the displacement that was caused
1320:             * @throws DocumentException on error
1321:             */
1322:            private float flushLines() throws DocumentException {
1323:                // checks if the ArrayList with the lines is not null
1324:                if (lines == null) {
1325:                    return 0;
1326:                }
1327:                // checks if a new Line has to be made.
1328:                if (line != null && line.size() > 0) {
1329:                    lines.add(line);
1330:                    line = new PdfLine(indentLeft(), indentRight(), alignment,
1331:                            leading);
1332:                }
1333:
1334:                // checks if the ArrayList with the lines is empty
1335:                if (lines.isEmpty()) {
1336:                    return 0;
1337:                }
1338:
1339:                // initialisation of some parameters
1340:                Object currentValues[] = new Object[2];
1341:                PdfFont currentFont = null;
1342:                float displacement = 0;
1343:                PdfLine l;
1344:                Float lastBaseFactor = new Float(0);
1345:                currentValues[1] = lastBaseFactor;
1346:                // looping over all the lines
1347:                for (Iterator i = lines.iterator(); i.hasNext();) {
1348:
1349:                    // this is a line in the loop
1350:                    l = (PdfLine) i.next();
1351:
1352:                    float moveTextX = l.indentLeft() - indentLeft()
1353:                            + indentation.listIndentLeft
1354:                            + indentation.sectionIndentLeft;
1355:                    text.moveText(moveTextX, -l.height());
1356:
1357:                    // is the line preceeded by a symbol?
1358:                    if (l.listSymbol() != null) {
1359:                        ColumnText.showTextAligned(graphics,
1360:                                Element.ALIGN_LEFT, new Phrase(l.listSymbol()),
1361:                                text.getXTLM() - l.listIndent(),
1362:                                text.getYTLM(), 0);
1363:                    }
1364:
1365:                    currentValues[0] = currentFont;
1366:
1367:                    writeLineToContent(l, text, graphics, currentValues, writer
1368:                            .getSpaceCharRatio());
1369:
1370:                    currentFont = (PdfFont) currentValues[0];
1371:
1372:                    displacement += l.height();
1373:                    text.moveText(-moveTextX, 0);
1374:
1375:                }
1376:                lines = new ArrayList();
1377:                return displacement;
1378:            }
1379:
1380:            /** The characters to be applied the hanging punctuation. */
1381:            static final String hangingPunctuation = ".,;:'";
1382:
1383:            /**
1384:             * Writes a text line to the document. It takes care of all the attributes.
1385:             * <P>
1386:             * Before entering the line position must have been established and the
1387:             * <CODE>text</CODE> argument must be in text object scope (<CODE>beginText()</CODE>).
1388:             * @param line the line to be written
1389:             * @param text the <CODE>PdfContentByte</CODE> where the text will be written to
1390:             * @param graphics the <CODE>PdfContentByte</CODE> where the graphics will be written to
1391:             * @param currentValues the current font and extra spacing values
1392:             * @param ratio
1393:             * @throws DocumentException on error
1394:             */
1395:            void writeLineToContent(PdfLine line, PdfContentByte text,
1396:                    PdfContentByte graphics, Object currentValues[], float ratio)
1397:                    throws DocumentException {
1398:                PdfFont currentFont = (PdfFont) (currentValues[0]);
1399:                float lastBaseFactor = ((Float) (currentValues[1]))
1400:                        .floatValue();
1401:                PdfChunk chunk;
1402:                int numberOfSpaces;
1403:                int lineLen;
1404:                boolean isJustified;
1405:                float hangingCorrection = 0;
1406:                float hScale = 1;
1407:                float lastHScale = Float.NaN;
1408:                float baseWordSpacing = 0;
1409:                float baseCharacterSpacing = 0;
1410:
1411:                numberOfSpaces = line.numberOfSpaces();
1412:                lineLen = line.toString().length();
1413:                // does the line need to be justified?
1414:                isJustified = line.hasToBeJustified()
1415:                        && (numberOfSpaces != 0 || lineLen > 1);
1416:                if (isJustified) {
1417:                    if (line.isNewlineSplit()
1418:                            && line.widthLeft() >= (lastBaseFactor * (ratio
1419:                                    * numberOfSpaces + lineLen - 1))) {
1420:                        if (line.isRTL()) {
1421:                            text
1422:                                    .moveText(
1423:                                            line.widthLeft()
1424:                                                    - lastBaseFactor
1425:                                                    * (ratio * numberOfSpaces
1426:                                                            + lineLen - 1), 0);
1427:                        }
1428:                        baseWordSpacing = ratio * lastBaseFactor;
1429:                        baseCharacterSpacing = lastBaseFactor;
1430:                    } else {
1431:                        float width = line.widthLeft();
1432:                        PdfChunk last = line.getChunk(line.size() - 1);
1433:                        if (last != null) {
1434:                            String s = last.toString();
1435:                            char c;
1436:                            if (s.length() > 0
1437:                                    && hangingPunctuation.indexOf((c = s
1438:                                            .charAt(s.length() - 1))) >= 0) {
1439:                                float oldWidth = width;
1440:                                width += last.font().width(c) * 0.4f;
1441:                                hangingCorrection = width - oldWidth;
1442:                            }
1443:                        }
1444:                        float baseFactor = width
1445:                                / (ratio * numberOfSpaces + lineLen - 1);
1446:                        baseWordSpacing = ratio * baseFactor;
1447:                        baseCharacterSpacing = baseFactor;
1448:                        lastBaseFactor = baseFactor;
1449:                    }
1450:                }
1451:
1452:                int lastChunkStroke = line.getLastStrokeChunk();
1453:                int chunkStrokeIdx = 0;
1454:                float xMarker = text.getXTLM();
1455:                float baseXMarker = xMarker;
1456:                float yMarker = text.getYTLM();
1457:                boolean adjustMatrix = false;
1458:
1459:                // looping over all the chunks in 1 line
1460:                for (Iterator j = line.iterator(); j.hasNext();) {
1461:                    chunk = (PdfChunk) j.next();
1462:                    Color color = chunk.color();
1463:                    hScale = 1;
1464:
1465:                    if (chunkStrokeIdx <= lastChunkStroke) {
1466:                        float width;
1467:                        if (isJustified) {
1468:                            width = chunk.getWidthCorrected(
1469:                                    baseCharacterSpacing, baseWordSpacing);
1470:                        } else
1471:                            width = chunk.width();
1472:                        if (chunk.isStroked()) {
1473:                            PdfChunk nextChunk = line
1474:                                    .getChunk(chunkStrokeIdx + 1);
1475:                            if (chunk.isAttribute(Chunk.BACKGROUND)) {
1476:                                float subtract = lastBaseFactor;
1477:                                if (nextChunk != null
1478:                                        && nextChunk
1479:                                                .isAttribute(Chunk.BACKGROUND))
1480:                                    subtract = 0;
1481:                                if (nextChunk == null)
1482:                                    subtract += hangingCorrection;
1483:                                float fontSize = chunk.font().size();
1484:                                float ascender = chunk.font().getFont()
1485:                                        .getFontDescriptor(BaseFont.ASCENT,
1486:                                                fontSize);
1487:                                float descender = chunk.font().getFont()
1488:                                        .getFontDescriptor(BaseFont.DESCENT,
1489:                                                fontSize);
1490:                                Object bgr[] = (Object[]) chunk
1491:                                        .getAttribute(Chunk.BACKGROUND);
1492:                                graphics.setColorFill((Color) bgr[0]);
1493:                                float extra[] = (float[]) bgr[1];
1494:                                graphics.rectangle(xMarker - extra[0], yMarker
1495:                                        + descender - extra[1]
1496:                                        + chunk.getTextRise(), width - subtract
1497:                                        + extra[0] + extra[2], ascender
1498:                                        - descender + extra[1] + extra[3]);
1499:                                graphics.fill();
1500:                                graphics.setGrayFill(0);
1501:                            }
1502:                            if (chunk.isAttribute(Chunk.UNDERLINE)) {
1503:                                float subtract = lastBaseFactor;
1504:                                if (nextChunk != null
1505:                                        && nextChunk
1506:                                                .isAttribute(Chunk.UNDERLINE))
1507:                                    subtract = 0;
1508:                                if (nextChunk == null)
1509:                                    subtract += hangingCorrection;
1510:                                Object unders[][] = (Object[][]) chunk
1511:                                        .getAttribute(Chunk.UNDERLINE);
1512:                                Color scolor = null;
1513:                                for (int k = 0; k < unders.length; ++k) {
1514:                                    Object obj[] = unders[k];
1515:                                    scolor = (Color) obj[0];
1516:                                    float ps[] = (float[]) obj[1];
1517:                                    if (scolor == null)
1518:                                        scolor = color;
1519:                                    if (scolor != null)
1520:                                        graphics.setColorStroke(scolor);
1521:                                    float fsize = chunk.font().size();
1522:                                    graphics
1523:                                            .setLineWidth(ps[0] + fsize * ps[1]);
1524:                                    float shift = ps[2] + fsize * ps[3];
1525:                                    int cap2 = (int) ps[4];
1526:                                    if (cap2 != 0)
1527:                                        graphics.setLineCap(cap2);
1528:                                    graphics.moveTo(xMarker, yMarker + shift);
1529:                                    graphics.lineTo(xMarker + width - subtract,
1530:                                            yMarker + shift);
1531:                                    graphics.stroke();
1532:                                    if (scolor != null)
1533:                                        graphics.resetGrayStroke();
1534:                                    if (cap2 != 0)
1535:                                        graphics.setLineCap(0);
1536:                                }
1537:                                graphics.setLineWidth(1);
1538:                            }
1539:                            if (chunk.isAttribute(Chunk.ACTION)) {
1540:                                float subtract = lastBaseFactor;
1541:                                if (nextChunk != null
1542:                                        && nextChunk.isAttribute(Chunk.ACTION))
1543:                                    subtract = 0;
1544:                                if (nextChunk == null)
1545:                                    subtract += hangingCorrection;
1546:                                text.addAnnotation(new PdfAnnotation(writer,
1547:                                        xMarker, yMarker, xMarker + width
1548:                                                - subtract, yMarker
1549:                                                + chunk.font().size(),
1550:                                        (PdfAction) chunk
1551:                                                .getAttribute(Chunk.ACTION)));
1552:                            }
1553:                            if (chunk.isAttribute(Chunk.REMOTEGOTO)) {
1554:                                float subtract = lastBaseFactor;
1555:                                if (nextChunk != null
1556:                                        && nextChunk
1557:                                                .isAttribute(Chunk.REMOTEGOTO))
1558:                                    subtract = 0;
1559:                                if (nextChunk == null)
1560:                                    subtract += hangingCorrection;
1561:                                Object obj[] = (Object[]) chunk
1562:                                        .getAttribute(Chunk.REMOTEGOTO);
1563:                                String filename = (String) obj[0];
1564:                                if (obj[1] instanceof  String)
1565:                                    remoteGoto(filename, (String) obj[1],
1566:                                            xMarker, yMarker, xMarker + width
1567:                                                    - subtract, yMarker
1568:                                                    + chunk.font().size());
1569:                                else
1570:                                    remoteGoto(filename, ((Integer) obj[1])
1571:                                            .intValue(), xMarker, yMarker,
1572:                                            xMarker + width - subtract, yMarker
1573:                                                    + chunk.font().size());
1574:                            }
1575:                            if (chunk.isAttribute(Chunk.LOCALGOTO)) {
1576:                                float subtract = lastBaseFactor;
1577:                                if (nextChunk != null
1578:                                        && nextChunk
1579:                                                .isAttribute(Chunk.LOCALGOTO))
1580:                                    subtract = 0;
1581:                                if (nextChunk == null)
1582:                                    subtract += hangingCorrection;
1583:                                localGoto((String) chunk
1584:                                        .getAttribute(Chunk.LOCALGOTO),
1585:                                        xMarker, yMarker, xMarker + width
1586:                                                - subtract, yMarker
1587:                                                + chunk.font().size());
1588:                            }
1589:                            if (chunk.isAttribute(Chunk.LOCALDESTINATION)) {
1590:                                float subtract = lastBaseFactor;
1591:                                if (nextChunk != null
1592:                                        && nextChunk
1593:                                                .isAttribute(Chunk.LOCALDESTINATION))
1594:                                    subtract = 0;
1595:                                if (nextChunk == null)
1596:                                    subtract += hangingCorrection;
1597:                                localDestination((String) chunk
1598:                                        .getAttribute(Chunk.LOCALDESTINATION),
1599:                                        new PdfDestination(PdfDestination.XYZ,
1600:                                                xMarker, yMarker
1601:                                                        + chunk.font().size(),
1602:                                                0));
1603:                            }
1604:                            if (chunk.isAttribute(Chunk.GENERICTAG)) {
1605:                                float subtract = lastBaseFactor;
1606:                                if (nextChunk != null
1607:                                        && nextChunk
1608:                                                .isAttribute(Chunk.GENERICTAG))
1609:                                    subtract = 0;
1610:                                if (nextChunk == null)
1611:                                    subtract += hangingCorrection;
1612:                                Rectangle rect = new Rectangle(xMarker,
1613:                                        yMarker, xMarker + width - subtract,
1614:                                        yMarker + chunk.font().size());
1615:                                PdfPageEvent pev = writer.getPageEvent();
1616:                                if (pev != null)
1617:                                    pev
1618:                                            .onGenericTag(
1619:                                                    writer,
1620:                                                    this ,
1621:                                                    rect,
1622:                                                    (String) chunk
1623:                                                            .getAttribute(Chunk.GENERICTAG));
1624:                            }
1625:                            if (chunk.isAttribute(Chunk.PDFANNOTATION)) {
1626:                                float subtract = lastBaseFactor;
1627:                                if (nextChunk != null
1628:                                        && nextChunk
1629:                                                .isAttribute(Chunk.PDFANNOTATION))
1630:                                    subtract = 0;
1631:                                if (nextChunk == null)
1632:                                    subtract += hangingCorrection;
1633:                                float fontSize = chunk.font().size();
1634:                                float ascender = chunk.font().getFont()
1635:                                        .getFontDescriptor(BaseFont.ASCENT,
1636:                                                fontSize);
1637:                                float descender = chunk.font().getFont()
1638:                                        .getFontDescriptor(BaseFont.DESCENT,
1639:                                                fontSize);
1640:                                PdfAnnotation annot = PdfFormField
1641:                                        .shallowDuplicate((PdfAnnotation) chunk
1642:                                                .getAttribute(Chunk.PDFANNOTATION));
1643:                                annot.put(PdfName.RECT, new PdfRectangle(
1644:                                        xMarker, yMarker + descender, xMarker
1645:                                                + width - subtract, yMarker
1646:                                                + ascender));
1647:                                text.addAnnotation(annot);
1648:                            }
1649:                            float params[] = (float[]) chunk
1650:                                    .getAttribute(Chunk.SKEW);
1651:                            Float hs = (Float) chunk.getAttribute(Chunk.HSCALE);
1652:                            if (params != null || hs != null) {
1653:                                float b = 0, c = 0;
1654:                                if (params != null) {
1655:                                    b = params[0];
1656:                                    c = params[1];
1657:                                }
1658:                                if (hs != null)
1659:                                    hScale = hs.floatValue();
1660:                                text.setTextMatrix(hScale, b, c, 1, xMarker,
1661:                                        yMarker);
1662:                            }
1663:                            if (chunk.isImage()) {
1664:                                Image image = chunk.getImage();
1665:                                float matrix[] = image.matrix();
1666:                                matrix[Image.CX] = xMarker
1667:                                        + chunk.getImageOffsetX()
1668:                                        - matrix[Image.CX];
1669:                                matrix[Image.CY] = yMarker
1670:                                        + chunk.getImageOffsetY()
1671:                                        - matrix[Image.CY];
1672:                                graphics.addImage(image, matrix[0], matrix[1],
1673:                                        matrix[2], matrix[3], matrix[4],
1674:                                        matrix[5]);
1675:                                text.moveText(xMarker + lastBaseFactor
1676:                                        + image.getScaledWidth()
1677:                                        - text.getXTLM(), 0);
1678:                            }
1679:                        }
1680:                        xMarker += width;
1681:                        ++chunkStrokeIdx;
1682:                    }
1683:
1684:                    if (chunk.font().compareTo(currentFont) != 0) {
1685:                        currentFont = chunk.font();
1686:                        text.setFontAndSize(currentFont.getFont(), currentFont
1687:                                .size());
1688:                    }
1689:                    float rise = 0;
1690:                    Object textRender[] = (Object[]) chunk
1691:                            .getAttribute(Chunk.TEXTRENDERMODE);
1692:                    int tr = 0;
1693:                    float strokeWidth = 1;
1694:                    Color strokeColor = null;
1695:                    Float fr = (Float) chunk.getAttribute(Chunk.SUBSUPSCRIPT);
1696:                    if (textRender != null) {
1697:                        tr = ((Integer) textRender[0]).intValue() & 3;
1698:                        if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
1699:                            text.setTextRenderingMode(tr);
1700:                        if (tr == PdfContentByte.TEXT_RENDER_MODE_STROKE
1701:                                || tr == PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE) {
1702:                            strokeWidth = ((Float) textRender[1]).floatValue();
1703:                            if (strokeWidth != 1)
1704:                                text.setLineWidth(strokeWidth);
1705:                            strokeColor = (Color) textRender[2];
1706:                            if (strokeColor == null)
1707:                                strokeColor = color;
1708:                            if (strokeColor != null)
1709:                                text.setColorStroke(strokeColor);
1710:                        }
1711:                    }
1712:                    if (fr != null)
1713:                        rise = fr.floatValue();
1714:                    if (color != null)
1715:                        text.setColorFill(color);
1716:                    if (rise != 0)
1717:                        text.setTextRise(rise);
1718:                    if (chunk.isImage()) {
1719:                        adjustMatrix = true;
1720:                    }
1721:                    // If it is a CJK chunk or Unicode TTF we will have to simulate the
1722:                    // space adjustment.
1723:                    else if (isJustified && numberOfSpaces > 0
1724:                            && chunk.isSpecialEncoding()) {
1725:                        if (hScale != lastHScale) {
1726:                            lastHScale = hScale;
1727:                            text.setWordSpacing(baseWordSpacing / hScale);
1728:                            text.setCharacterSpacing(baseCharacterSpacing
1729:                                    / hScale);
1730:                        }
1731:                        String s = chunk.toString();
1732:                        int idx = s.indexOf(' ');
1733:                        if (idx < 0)
1734:                            text.showText(chunk.toString());
1735:                        else {
1736:                            float spaceCorrection = -baseWordSpacing * 1000f
1737:                                    / chunk.font.size() / hScale;
1738:                            PdfTextArray textArray = new PdfTextArray(s
1739:                                    .substring(0, idx));
1740:                            int lastIdx = idx;
1741:                            while ((idx = s.indexOf(' ', lastIdx + 1)) >= 0) {
1742:                                textArray.add(spaceCorrection);
1743:                                textArray.add(s.substring(lastIdx, idx));
1744:                                lastIdx = idx;
1745:                            }
1746:                            textArray.add(spaceCorrection);
1747:                            textArray.add(s.substring(lastIdx));
1748:                            text.showText(textArray);
1749:                        }
1750:                    } else {
1751:                        if (isJustified && hScale != lastHScale) {
1752:                            lastHScale = hScale;
1753:                            text.setWordSpacing(baseWordSpacing / hScale);
1754:                            text.setCharacterSpacing(baseCharacterSpacing
1755:                                    / hScale);
1756:                        }
1757:                        text.showText(chunk.toString());
1758:                    }
1759:
1760:                    if (rise != 0)
1761:                        text.setTextRise(0);
1762:                    if (color != null)
1763:                        text.resetRGBColorFill();
1764:                    if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
1765:                        text
1766:                                .setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
1767:                    if (strokeColor != null)
1768:                        text.resetRGBColorStroke();
1769:                    if (strokeWidth != 1)
1770:                        text.setLineWidth(1);
1771:                    if (chunk.isAttribute(Chunk.SKEW)
1772:                            || chunk.isAttribute(Chunk.HSCALE)) {
1773:                        adjustMatrix = true;
1774:                        text.setTextMatrix(xMarker, yMarker);
1775:                    }
1776:                }
1777:                if (isJustified) {
1778:                    text.setWordSpacing(0);
1779:                    text.setCharacterSpacing(0);
1780:                    if (line.isNewlineSplit())
1781:                        lastBaseFactor = 0;
1782:                }
1783:                if (adjustMatrix)
1784:                    text.moveText(baseXMarker - text.getXTLM(), 0);
1785:                currentValues[0] = currentFont;
1786:                currentValues[1] = new Float(lastBaseFactor);
1787:            }
1788:
1789:            Indentation indentation = new Indentation();
1790:
1791:            public static class Indentation {
1792:
1793:                /** This represents the current indentation of the PDF Elements on the left side. */
1794:                private float indentLeft = 0;
1795:
1796:                /** Indentation to the left caused by a section. */
1797:                private float sectionIndentLeft = 0;
1798:
1799:                /** This represents the current indentation of the PDF Elements on the left side. */
1800:                private float listIndentLeft = 0;
1801:
1802:                /** This is the indentation caused by an image on the left. */
1803:                private float imageIndentLeft = 0;
1804:
1805:                /** This represents the current indentation of the PDF Elements on the right side. */
1806:                private float indentRight = 0;
1807:
1808:                /** Indentation to the right caused by a section. */
1809:                private float sectionIndentRight = 0;
1810:
1811:                /** This is the indentation caused by an image on the right. */
1812:                private float imageIndentRight = 0;
1813:
1814:                /** This represents the current indentation of the PDF Elements on the top side. */
1815:                private float indentTop = 0;
1816:
1817:                /** This represents the current indentation of the PDF Elements on the bottom side. */
1818:                private float indentBottom = 0;
1819:            }
1820:
1821:            /**
1822:             * Gets the indentation on the left side.
1823:             *
1824:             * @return	a margin
1825:             */
1826:
1827:            private float indentLeft() {
1828:                return left(indentation.indentLeft + indentation.listIndentLeft
1829:                        + indentation.imageIndentLeft
1830:                        + indentation.sectionIndentLeft);
1831:            }
1832:
1833:            /**
1834:             * Gets the indentation on the right side.
1835:             *
1836:             * @return	a margin
1837:             */
1838:
1839:            private float indentRight() {
1840:                return right(indentation.indentRight
1841:                        + indentation.sectionIndentRight);
1842:            }
1843:
1844:            /**
1845:             * Gets the indentation on the top side.
1846:             *
1847:             * @return	a margin
1848:             */
1849:
1850:            private float indentTop() {
1851:                return top(indentation.indentTop);
1852:            }
1853:
1854:            /**
1855:             * Gets the indentation on the bottom side.
1856:             *
1857:             * @return	a margin
1858:             */
1859:
1860:            float indentBottom() {
1861:                return bottom(indentation.indentBottom);
1862:            }
1863:
1864:            /**
1865:             * Adds extra space.
1866:             * This method should probably be rewritten.
1867:             */
1868:            private void addSpacing(float extraspace, float oldleading, Font f) {
1869:                if (extraspace == 0)
1870:                    return;
1871:                if (pageEmpty)
1872:                    return;
1873:                if (currentHeight + line.height() + leading > indentTop()
1874:                        - indentBottom())
1875:                    return;
1876:                leading = extraspace;
1877:                carriageReturn();
1878:                Chunk space = new Chunk(" ", f);
1879:                space.process(this );
1880:                carriageReturn();
1881:                leading = oldleading;
1882:            }
1883:
1884:            //	Info Dictionary and Catalog
1885:
1886:            /** some meta information about the Document. */
1887:            private PdfInfo info = new PdfInfo();
1888:
1889:            /**
1890:             * Gets the <CODE>PdfInfo</CODE>-object.
1891:             *
1892:             * @return	<CODE>PdfInfo</COPE>
1893:             */
1894:
1895:            PdfInfo getInfo() {
1896:                return info;
1897:            }
1898:
1899:            /**
1900:             * Gets the <CODE>PdfCatalog</CODE>-object.
1901:             *
1902:             * @param pages an indirect reference to this document pages
1903:             * @return <CODE>PdfCatalog</CODE>
1904:             */
1905:
1906:            PdfCatalog getCatalog(PdfIndirectReference pages) {
1907:                PdfCatalog catalog = new PdfCatalog(pages, writer);
1908:
1909:                // [C1] outlines
1910:                if (rootOutline.getKids().size() > 0) {
1911:                    catalog.put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
1912:                    catalog.put(PdfName.OUTLINES, rootOutline
1913:                            .indirectReference());
1914:                }
1915:
1916:                // [C2] version
1917:                writer.getPdfVersion().addToCatalog(catalog);
1918:
1919:                // [C3] preferences
1920:                viewerPreferences.addToCatalog(catalog);
1921:
1922:                // [C4] pagelabels
1923:                if (pageLabels != null) {
1924:                    catalog.put(PdfName.PAGELABELS, pageLabels
1925:                            .getDictionary(writer));
1926:                }
1927:
1928:                // [C5] named objects
1929:                catalog.addNames(localDestinations, getDocumentLevelJS(),
1930:                        documentFileAttachment, writer);
1931:
1932:                // [C6] actions
1933:                if (openActionName != null) {
1934:                    PdfAction action = getLocalGotoAction(openActionName);
1935:                    catalog.setOpenAction(action);
1936:                } else if (openActionAction != null)
1937:                    catalog.setOpenAction(openActionAction);
1938:                if (additionalActions != null) {
1939:                    catalog.setAdditionalActions(additionalActions);
1940:                }
1941:
1942:                // [C7] portable collections
1943:                if (collection != null) {
1944:                    catalog.put(PdfName.COLLECTION, collection);
1945:                }
1946:
1947:                // [C8] AcroForm
1948:                if (annotationsImp.hasValidAcroForm()) {
1949:                    try {
1950:                        catalog.put(PdfName.ACROFORM, writer.addToBody(
1951:                                annotationsImp.getAcroForm())
1952:                                .getIndirectReference());
1953:                    } catch (IOException e) {
1954:                        throw new ExceptionConverter(e);
1955:                    }
1956:                }
1957:
1958:                return catalog;
1959:            }
1960:
1961:            //	[C1] outlines
1962:
1963:            /** This is the root outline of the document. */
1964:            private PdfOutline rootOutline;
1965:
1966:            /** This is the current <CODE>PdfOutline</CODE> in the hierarchy of outlines. */
1967:            private PdfOutline currentOutline;
1968:
1969:            /**
1970:             * Adds a named outline to the document .
1971:             * @param outline the outline to be added
1972:             * @param name the name of this local destination
1973:             */
1974:            void addOutline(PdfOutline outline, String name) {
1975:                localDestination(name, outline.getPdfDestination());
1976:            }
1977:
1978:            /**
1979:             * Gets the root outline. All the outlines must be created with a parent.
1980:             * The first level is created with this outline.
1981:             * @return the root outline
1982:             */
1983:            public PdfOutline getRootOutline() {
1984:                return rootOutline;
1985:            }
1986:
1987:            /**
1988:             * Updates the count in the outlines.
1989:             */
1990:            void calculateOutlineCount() {
1991:                if (rootOutline.getKids().size() == 0)
1992:                    return;
1993:                traverseOutlineCount(rootOutline);
1994:            }
1995:
1996:            /**
1997:             * Recursive method to update the count in the outlines.
1998:             */
1999:            void traverseOutlineCount(PdfOutline outline) {
2000:                ArrayList kids = outline.getKids();
2001:                PdfOutline parent = outline.parent();
2002:                if (kids.isEmpty()) {
2003:                    if (parent != null) {
2004:                        parent.setCount(parent.getCount() + 1);
2005:                    }
2006:                } else {
2007:                    for (int k = 0; k < kids.size(); ++k) {
2008:                        traverseOutlineCount((PdfOutline) kids.get(k));
2009:                    }
2010:                    if (parent != null) {
2011:                        if (outline.isOpen()) {
2012:                            parent.setCount(outline.getCount()
2013:                                    + parent.getCount() + 1);
2014:                        } else {
2015:                            parent.setCount(parent.getCount() + 1);
2016:                            outline.setCount(-outline.getCount());
2017:                        }
2018:                    }
2019:                }
2020:            }
2021:
2022:            /**
2023:             * Writes the outline tree to the body of the PDF document.
2024:             */
2025:            void writeOutlines() throws IOException {
2026:                if (rootOutline.getKids().size() == 0)
2027:                    return;
2028:                outlineTree(rootOutline);
2029:                writer.addToBody(rootOutline, rootOutline.indirectReference());
2030:            }
2031:
2032:            /**
2033:             * Recursive method used to write outlines.
2034:             */
2035:            void outlineTree(PdfOutline outline) throws IOException {
2036:                outline.setIndirectReference(writer.getPdfIndirectReference());
2037:                if (outline.parent() != null)
2038:                    outline.put(PdfName.PARENT, outline.parent()
2039:                            .indirectReference());
2040:                ArrayList kids = outline.getKids();
2041:                int size = kids.size();
2042:                for (int k = 0; k < size; ++k)
2043:                    outlineTree((PdfOutline) kids.get(k));
2044:                for (int k = 0; k < size; ++k) {
2045:                    if (k > 0)
2046:                        ((PdfOutline) kids.get(k)).put(PdfName.PREV,
2047:                                ((PdfOutline) kids.get(k - 1))
2048:                                        .indirectReference());
2049:                    if (k < size - 1)
2050:                        ((PdfOutline) kids.get(k)).put(PdfName.NEXT,
2051:                                ((PdfOutline) kids.get(k + 1))
2052:                                        .indirectReference());
2053:                }
2054:                if (size > 0) {
2055:                    outline.put(PdfName.FIRST, ((PdfOutline) kids.get(0))
2056:                            .indirectReference());
2057:                    outline.put(PdfName.LAST, ((PdfOutline) kids.get(size - 1))
2058:                            .indirectReference());
2059:                }
2060:                for (int k = 0; k < size; ++k) {
2061:                    PdfOutline kid = (PdfOutline) kids.get(k);
2062:                    writer.addToBody(kid, kid.indirectReference());
2063:                }
2064:            }
2065:
2066:            //  [C3] PdfViewerPreferences interface
2067:
2068:            /** Contains the Viewer preferences of this PDF document. */
2069:            protected PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp();
2070:
2071:            /** @see com.lowagie.text.pdf.interfaces.PdfViewerPreferences#setViewerPreferences(int) */
2072:            void setViewerPreferences(int preferences) {
2073:                this .viewerPreferences.setViewerPreferences(preferences);
2074:            }
2075:
2076:            /** @see com.lowagie.text.pdf.interfaces.PdfViewerPreferences#addViewerPreference(com.lowagie.text.pdf.PdfName, com.lowagie.text.pdf.PdfObject) */
2077:            void addViewerPreference(PdfName key, PdfObject value) {
2078:                this .viewerPreferences.addViewerPreference(key, value);
2079:            }
2080:
2081:            //	[C4] Page labels
2082:
2083:            protected PdfPageLabels pageLabels;
2084:
2085:            /**
2086:             * Sets the page labels
2087:             * @param pageLabels the page labels
2088:             */
2089:            void setPageLabels(PdfPageLabels pageLabels) {
2090:                this .pageLabels = pageLabels;
2091:            }
2092:
2093:            //	[C5] named objects: local destinations, javascript, embedded files
2094:
2095:            /**
2096:             * Implements a link to other part of the document. The jump will
2097:             * be made to a local destination with the same name, that must exist.
2098:             * @param name the name for this link
2099:             * @param llx the lower left x corner of the activation area
2100:             * @param lly the lower left y corner of the activation area
2101:             * @param urx the upper right x corner of the activation area
2102:             * @param ury the upper right y corner of the activation area
2103:             */
2104:            void localGoto(String name, float llx, float lly, float urx,
2105:                    float ury) {
2106:                PdfAction action = getLocalGotoAction(name);
2107:                annotationsImp.addPlainAnnotation(new PdfAnnotation(writer,
2108:                        llx, lly, urx, ury, action));
2109:            }
2110:
2111:            /**
2112:             * Implements a link to another document.
2113:             * @param filename the filename for the remote document
2114:             * @param name the name to jump to
2115:             * @param llx the lower left x corner of the activation area
2116:             * @param lly the lower left y corner of the activation area
2117:             * @param urx the upper right x corner of the activation area
2118:             * @param ury the upper right y corner of the activation area
2119:             */
2120:            void remoteGoto(String filename, String name, float llx, float lly,
2121:                    float urx, float ury) {
2122:                annotationsImp.addPlainAnnotation(new PdfAnnotation(writer,
2123:                        llx, lly, urx, ury, new PdfAction(filename, name)));
2124:            }
2125:
2126:            /**
2127:             * Implements a link to another document.
2128:             * @param filename the filename for the remote document
2129:             * @param page the page to jump to
2130:             * @param llx the lower left x corner of the activation area
2131:             * @param lly the lower left y corner of the activation area
2132:             * @param urx the upper right x corner of the activation area
2133:             * @param ury the upper right y corner of the activation area
2134:             */
2135:            void remoteGoto(String filename, int page, float llx, float lly,
2136:                    float urx, float ury) {
2137:                addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury,
2138:                        new PdfAction(filename, page)));
2139:            }
2140:
2141:            /** Implements an action in an area.
2142:             * @param action the <CODE>PdfAction</CODE>
2143:             * @param llx the lower left x corner of the activation area
2144:             * @param lly the lower left y corner of the activation area
2145:             * @param urx the upper right x corner of the activation area
2146:             * @param ury the upper right y corner of the activation area
2147:             */
2148:            void setAction(PdfAction action, float llx, float lly, float urx,
2149:                    float ury) {
2150:                addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury,
2151:                        action));
2152:            }
2153:
2154:            /**
2155:             * Stores the destinations keyed by name. Value is
2156:             * <CODE>Object[]{PdfAction,PdfIndirectReference,PdfDestintion}</CODE>.
2157:             */
2158:            private TreeMap localDestinations = new TreeMap();
2159:
2160:            PdfAction getLocalGotoAction(String name) {
2161:                PdfAction action;
2162:                Object obj[] = (Object[]) localDestinations.get(name);
2163:                if (obj == null)
2164:                    obj = new Object[3];
2165:                if (obj[0] == null) {
2166:                    if (obj[1] == null) {
2167:                        obj[1] = writer.getPdfIndirectReference();
2168:                    }
2169:                    action = new PdfAction((PdfIndirectReference) obj[1]);
2170:                    obj[0] = action;
2171:                    localDestinations.put(name, obj);
2172:                } else {
2173:                    action = (PdfAction) obj[0];
2174:                }
2175:                return action;
2176:            }
2177:
2178:            /**
2179:             * The local destination to where a local goto with the same
2180:             * name will jump to.
2181:             * @param name the name of this local destination
2182:             * @param destination the <CODE>PdfDestination</CODE> with the jump coordinates
2183:             * @return <CODE>true</CODE> if the local destination was added,
2184:             * <CODE>false</CODE> if a local destination with the same name
2185:             * already existed
2186:             */
2187:            boolean localDestination(String name, PdfDestination destination) {
2188:                Object obj[] = (Object[]) localDestinations.get(name);
2189:                if (obj == null)
2190:                    obj = new Object[3];
2191:                if (obj[2] != null)
2192:                    return false;
2193:                obj[2] = destination;
2194:                localDestinations.put(name, obj);
2195:                destination.addPage(writer.getCurrentPage());
2196:                return true;
2197:            }
2198:
2199:            /**
2200:             * Stores a list of document level JavaScript actions.
2201:             */
2202:            int jsCounter;
2203:            private LinkedHashMap documentLevelJS = new LinkedHashMap();
2204:
2205:            void addJavaScript(PdfAction js) {
2206:                if (js.get(PdfName.JS) == null)
2207:                    throw new RuntimeException(
2208:                            "Only JavaScript actions are allowed.");
2209:                try {
2210:                    documentLevelJS.put("iTextJS_" + jsCounter, writer
2211:                            .addToBody(js).getIndirectReference());
2212:                    jsCounter++;
2213:                } catch (IOException e) {
2214:                    throw new ExceptionConverter(e);
2215:                }
2216:            }
2217:
2218:            void addJavaScript(String name, PdfAction js) {
2219:                if (js.get(PdfName.JS) == null)
2220:                    throw new RuntimeException(
2221:                            "Only JavaScript actions are allowed.");
2222:                try {
2223:                    documentLevelJS.put(name, writer.addToBody(js)
2224:                            .getIndirectReference());
2225:                } catch (IOException e) {
2226:                    throw new ExceptionConverter(e);
2227:                }
2228:            }
2229:
2230:            LinkedHashMap getDocumentLevelJS() {
2231:                return documentLevelJS;
2232:            }
2233:
2234:            private HashMap documentFileAttachment = new HashMap();
2235:
2236:            void addFileAttachment(String description, PdfFileSpecification fs)
2237:                    throws IOException {
2238:                if (description == null) {
2239:                    PdfString desc = (PdfString) fs.get(PdfName.DESC);
2240:                    if (desc == null) {
2241:                        description = "";
2242:                    } else {
2243:                        description = PdfEncodings.convertToString(desc
2244:                                .getBytes(), null);
2245:                    }
2246:                }
2247:                fs.addDescription(description, true);
2248:                if (description.length() == 0)
2249:                    description = "Unnamed";
2250:                String fn = PdfEncodings.convertToString(new PdfString(
2251:                        description, PdfObject.TEXT_UNICODE).getBytes(), null);
2252:                int k = 0;
2253:                while (documentFileAttachment.containsKey(fn)) {
2254:                    ++k;
2255:                    fn = PdfEncodings
2256:                            .convertToString(new PdfString(description + " "
2257:                                    + k, PdfObject.TEXT_UNICODE).getBytes(),
2258:                                    null);
2259:                }
2260:                documentFileAttachment.put(fn, fs.getReference());
2261:            }
2262:
2263:            HashMap getDocumentFileAttachment() {
2264:                return documentFileAttachment;
2265:            }
2266:
2267:            //	[C6] document level actions
2268:
2269:            private String openActionName;
2270:
2271:            void setOpenAction(String name) {
2272:                openActionName = name;
2273:                openActionAction = null;
2274:            }
2275:
2276:            private PdfAction openActionAction;
2277:
2278:            void setOpenAction(PdfAction action) {
2279:                openActionAction = action;
2280:                openActionName = null;
2281:            }
2282:
2283:            private PdfDictionary additionalActions;
2284:
2285:            void addAdditionalAction(PdfName actionType, PdfAction action) {
2286:                if (additionalActions == null) {
2287:                    additionalActions = new PdfDictionary();
2288:                }
2289:                if (action == null)
2290:                    additionalActions.remove(actionType);
2291:                else
2292:                    additionalActions.put(actionType, action);
2293:                if (additionalActions.size() == 0)
2294:                    additionalActions = null;
2295:            }
2296:
2297:            //	[C7] portable collections
2298:
2299:            private PdfCollection collection;
2300:
2301:            /**
2302:             * Sets the collection dictionary.
2303:             * @param collection a dictionary of type PdfCollection
2304:             */
2305:            public void setCollection(PdfCollection collection) {
2306:                this .collection = collection;
2307:            }
2308:
2309:            //	[C8] AcroForm
2310:
2311:            PdfAnnotationsImp annotationsImp;
2312:
2313:            /**
2314:             * Gets the AcroForm object.
2315:             * @return the PdfAcroform object of the PdfDocument
2316:             */
2317:            PdfAcroForm getAcroForm() {
2318:                return annotationsImp.getAcroForm();
2319:            }
2320:
2321:            void setSigFlags(int f) {
2322:                annotationsImp.setSigFlags(f);
2323:            }
2324:
2325:            void addCalculationOrder(PdfFormField formField) {
2326:                annotationsImp.addCalculationOrder(formField);
2327:            }
2328:
2329:            void addAnnotation(PdfAnnotation annot) {
2330:                pageEmpty = false;
2331:                annotationsImp.addAnnotation(annot);
2332:            }
2333:
2334:            //	[F12] tagged PDF
2335:
2336:            protected int markPoint;
2337:
2338:            int getMarkPoint() {
2339:                return markPoint;
2340:            }
2341:
2342:            void incMarkPoint() {
2343:                ++markPoint;
2344:            }
2345:
2346:            //	[U1] page sizes
2347:
2348:            /** This is the size of the next page. */
2349:            protected Rectangle nextPageSize = null;
2350:
2351:            /** This is the size of the several boxes of the current Page. */
2352:            protected HashMap this BoxSize = new HashMap();
2353:
2354:            /** This is the size of the several boxes that will be used in
2355:             * the next page. */
2356:            protected HashMap boxSize = new HashMap();
2357:
2358:            void setCropBoxSize(Rectangle crop) {
2359:                setBoxSize("crop", crop);
2360:            }
2361:
2362:            void setBoxSize(String boxName, Rectangle size) {
2363:                if (size == null)
2364:                    boxSize.remove(boxName);
2365:                else
2366:                    boxSize.put(boxName, new PdfRectangle(size));
2367:            }
2368:
2369:            private void setNewPageSizeAndMargins() {
2370:                pageSize = nextPageSize;
2371:                if (marginMirroring && (getPageNumber() & 1) == 0) {
2372:                    marginRight = nextMarginLeft;
2373:                    marginLeft = nextMarginRight;
2374:                } else {
2375:                    marginLeft = nextMarginLeft;
2376:                    marginRight = nextMarginRight;
2377:                }
2378:                marginTop = nextMarginTop;
2379:                marginBottom = nextMarginBottom;
2380:            }
2381:
2382:            /**
2383:             * Gives the size of a trim, art, crop or bleed box, or null if not defined.
2384:             * @param boxName crop, trim, art or bleed
2385:             */
2386:            Rectangle getBoxSize(String boxName) {
2387:                PdfRectangle r = (PdfRectangle) this BoxSize.get(boxName);
2388:                if (r != null)
2389:                    return r.getRectangle();
2390:                return null;
2391:            }
2392:
2393:            //	[U2] empty pages
2394:
2395:            /** This checks if the page is empty. */
2396:            private boolean pageEmpty = true;
2397:
2398:            void setPageEmpty(boolean pageEmpty) {
2399:                this .pageEmpty = pageEmpty;
2400:            }
2401:
2402:            //	[U3] page actions
2403:
2404:            /** The duration of the page */
2405:            protected int duration = -1; // negative values will indicate no duration
2406:
2407:            /** The page transition */
2408:            protected PdfTransition transition = null;
2409:
2410:            /**
2411:             * Sets the display duration for the page (for presentations)
2412:             * @param seconds   the number of seconds to display the page
2413:             */
2414:            void setDuration(int seconds) {
2415:                if (seconds > 0)
2416:                    this .duration = seconds;
2417:                else
2418:                    this .duration = -1;
2419:            }
2420:
2421:            /**
2422:             * Sets the transition for the page
2423:             * @param transition   the PdfTransition object
2424:             */
2425:            void setTransition(PdfTransition transition) {
2426:                this .transition = transition;
2427:            }
2428:
2429:            protected PdfDictionary pageAA = null;
2430:
2431:            void setPageAction(PdfName actionType, PdfAction action) {
2432:                if (pageAA == null) {
2433:                    pageAA = new PdfDictionary();
2434:                }
2435:                pageAA.put(actionType, action);
2436:            }
2437:
2438:            //	[U8] thumbnail images
2439:
2440:            private PdfIndirectReference thumb;
2441:
2442:            void setThumbnail(Image image) throws PdfException,
2443:                    DocumentException {
2444:                thumb = writer.getImageReference(writer
2445:                        .addDirectImageSimple(image));
2446:            }
2447:
2448:            //	[M0] Page resources contain references to fonts, extgstate, images,...
2449:
2450:            /** This are the page resources of the current Page. */
2451:            protected PageResources pageResources;
2452:
2453:            PageResources getPageResources() {
2454:                return pageResources;
2455:            }
2456:
2457:            //	[M3] Images
2458:
2459:            /** Holds value of property strictImageSequence. */
2460:            private boolean strictImageSequence = false;
2461:
2462:            /** Getter for property strictImageSequence.
2463:             * @return Value of property strictImageSequence.
2464:             *
2465:             */
2466:            boolean isStrictImageSequence() {
2467:                return this .strictImageSequence;
2468:            }
2469:
2470:            /** Setter for property strictImageSequence.
2471:             * @param strictImageSequence New value of property strictImageSequence.
2472:             *
2473:             */
2474:            void setStrictImageSequence(boolean strictImageSequence) {
2475:                this .strictImageSequence = strictImageSequence;
2476:            }
2477:
2478:            /** This is the position where the image ends. */
2479:            private float imageEnd = -1;
2480:
2481:            /**
2482:             * Method added by Pelikan Stephan
2483:             */
2484:            public void clearTextWrap() {
2485:                float tmpHeight = imageEnd - currentHeight;
2486:                if (line != null) {
2487:                    tmpHeight += line.height();
2488:                }
2489:                if ((imageEnd > -1) && (tmpHeight > 0)) {
2490:                    carriageReturn();
2491:                    currentHeight += tmpHeight;
2492:                }
2493:            }
2494:
2495:            /** This is the image that could not be shown on a previous page. */
2496:            private Image imageWait = null;
2497:
2498:            /**
2499:             * Adds an image to the document.
2500:             * @param image the <CODE>Image</CODE> to add
2501:             * @throws PdfException on error
2502:             * @throws DocumentException on error
2503:             */
2504:
2505:            private void add(Image image) throws PdfException,
2506:                    DocumentException {
2507:
2508:                if (image.hasAbsoluteY()) {
2509:                    graphics.addImage(image);
2510:                    pageEmpty = false;
2511:                    return;
2512:                }
2513:
2514:                // if there isn't enough room for the image on this page, save it for the next page
2515:                if (currentHeight != 0
2516:                        && indentTop() - currentHeight
2517:                                - image.getScaledHeight() < indentBottom()) {
2518:                    if (!strictImageSequence && imageWait == null) {
2519:                        imageWait = image;
2520:                        return;
2521:                    }
2522:                    newPage();
2523:                    if (currentHeight != 0
2524:                            && indentTop() - currentHeight
2525:                                    - image.getScaledHeight() < indentBottom()) {
2526:                        imageWait = image;
2527:                        return;
2528:                    }
2529:                }
2530:                pageEmpty = false;
2531:                // avoid endless loops
2532:                if (image == imageWait)
2533:                    imageWait = null;
2534:                boolean textwrap = (image.getAlignment() & Image.TEXTWRAP) == Image.TEXTWRAP
2535:                        && !((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE);
2536:                boolean underlying = (image.getAlignment() & Image.UNDERLYING) == Image.UNDERLYING;
2537:                float diff = leading / 2;
2538:                if (textwrap) {
2539:                    diff += leading;
2540:                }
2541:                float lowerleft = indentTop() - currentHeight
2542:                        - image.getScaledHeight() - diff;
2543:                float mt[] = image.matrix();
2544:                float startPosition = indentLeft() - mt[4];
2545:                if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT)
2546:                    startPosition = indentRight() - image.getScaledWidth()
2547:                            - mt[4];
2548:                if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE)
2549:                    startPosition = indentLeft()
2550:                            + ((indentRight() - indentLeft() - image
2551:                                    .getScaledWidth()) / 2) - mt[4];
2552:                if (image.hasAbsoluteX())
2553:                    startPosition = image.getAbsoluteX();
2554:                if (textwrap) {
2555:                    if (imageEnd < 0
2556:                            || imageEnd < currentHeight
2557:                                    + image.getScaledHeight() + diff) {
2558:                        imageEnd = currentHeight + image.getScaledHeight()
2559:                                + diff;
2560:                    }
2561:                    if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) {
2562:                        // indentation suggested by Pelikan Stephan
2563:                        indentation.imageIndentRight += image.getScaledWidth()
2564:                                + image.getIndentationLeft();
2565:                    } else {
2566:                        // indentation suggested by Pelikan Stephan
2567:                        indentation.imageIndentLeft += image.getScaledWidth()
2568:                                + image.getIndentationRight();
2569:                    }
2570:                } else {
2571:                    if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT)
2572:                        startPosition -= image.getIndentationRight();
2573:                    else if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE)
2574:                        startPosition += image.getIndentationLeft()
2575:                                - image.getIndentationRight();
2576:                    else
2577:                        startPosition += image.getIndentationLeft();
2578:                }
2579:                graphics.addImage(image, mt[0], mt[1], mt[2], mt[3],
2580:                        startPosition, lowerleft - mt[5]);
2581:                if (!(textwrap || underlying)) {
2582:                    currentHeight += image.getScaledHeight() + diff;
2583:                    flushLines();
2584:                    text.moveText(0, -(image.getScaledHeight() + diff));
2585:                    newLine();
2586:                }
2587:            }
2588:
2589:            //	[M4] Adding a PdfPTable
2590:
2591:            /** Adds a <CODE>PdfPTable</CODE> to the document.
2592:             * @param ptable the <CODE>PdfPTable</CODE> to be added to the document.
2593:             * @throws DocumentException on error
2594:             */
2595:            void addPTable(PdfPTable ptable) throws DocumentException {
2596:                ColumnText ct = new ColumnText(writer.getDirectContent());
2597:                if (currentHeight > 0) {
2598:                    Paragraph p = new Paragraph();
2599:                    p.setLeading(0);
2600:                    ct.addElement(p);
2601:                    // if the table prefers to be on a single page, and it wouldn't
2602:                    //fit on the current page, start a new page.
2603:                    if (ptable.getKeepTogether() && !fitsPage(ptable, 0f)) {
2604:                        newPage();
2605:                    }
2606:                }
2607:                ct.addElement(ptable);
2608:                boolean he = ptable.isHeadersInEvent();
2609:                ptable.setHeadersInEvent(true);
2610:                int loop = 0;
2611:                while (true) {
2612:                    ct.setSimpleColumn(indentLeft(), indentBottom(),
2613:                            indentRight(), indentTop() - currentHeight);
2614:                    int status = ct.go();
2615:                    if ((status & ColumnText.NO_MORE_TEXT) != 0) {
2616:                        text.moveText(0, ct.getYLine() - indentTop()
2617:                                + currentHeight);
2618:                        currentHeight = indentTop() - ct.getYLine();
2619:                        break;
2620:                    }
2621:                    if (indentTop() - currentHeight == ct.getYLine())
2622:                        ++loop;
2623:                    else
2624:                        loop = 0;
2625:                    if (loop == 3) {
2626:                        add(new Paragraph("ERROR: Infinite table loop"));
2627:                        break;
2628:                    }
2629:                    newPage();
2630:                }
2631:                ptable.setHeadersInEvent(he);
2632:            }
2633:
2634:            /**
2635:             * Checks if a <CODE>PdfPTable</CODE> fits the current page of the <CODE>PdfDocument</CODE>.
2636:             *
2637:             * @param	table	the table that has to be checked
2638:             * @param	margin	a certain margin
2639:             * @return	<CODE>true</CODE> if the <CODE>PdfPTable</CODE> fits the page, <CODE>false</CODE> otherwise.
2640:             */
2641:
2642:            boolean fitsPage(PdfPTable table, float margin) {
2643:                if (!table.isLockedWidth()) {
2644:                    float totalWidth = (indentRight() - indentLeft())
2645:                            * table.getWidthPercentage() / 100;
2646:                    table.setTotalWidth(totalWidth);
2647:                }
2648:                // ensuring that a new line has been started.
2649:                ensureNewLine();
2650:                return table.getTotalHeight() <= indentTop() - currentHeight
2651:                        - indentBottom() - margin;
2652:            }
2653:
2654:            //	[M4'] Adding a Table
2655:
2656:            /**
2657:             * Gets a PdfTable object
2658:             * (contributed by dperezcar@fcc.es)
2659:             * @param table a high level table object
2660:             * @param supportRowAdditions
2661:             * @return returns a PdfTable object
2662:             * @see PdfWriter#getPdfTable(Table)
2663:             */
2664:
2665:            PdfTable getPdfTable(Table table, boolean supportRowAdditions) {
2666:                return new PdfTable(table, indentLeft(), indentRight(),
2667:                        indentTop() - currentHeight, supportRowAdditions);
2668:            }
2669:
2670:            /**
2671:             * This is a helper class for adding a Table to a document.
2672:             */
2673:            private static class RenderingContext {
2674:                float pagetop = -1;
2675:                float oldHeight = -1;
2676:
2677:                PdfContentByte cellGraphics = null;
2678:
2679:                float lostTableBottom;
2680:
2681:                float maxCellBottom;
2682:                float maxCellHeight;
2683:
2684:                Map rowspanMap;
2685:                Map pageMap = new HashMap();
2686:                /**
2687:                 * A PdfPTable
2688:                 */
2689:                public PdfTable table;
2690:
2691:                /**
2692:                 * Consumes the rowspan
2693:                 * @param c
2694:                 * @return a rowspan.
2695:                 */
2696:                public int consumeRowspan(PdfCell c) {
2697:                    if (c.rowspan() == 1) {
2698:                        return 1;
2699:                    }
2700:
2701:                    Integer i = (Integer) rowspanMap.get(c);
2702:                    if (i == null) {
2703:                        i = new Integer(c.rowspan());
2704:                    }
2705:
2706:                    i = new Integer(i.intValue() - 1);
2707:                    rowspanMap.put(c, i);
2708:
2709:                    if (i.intValue() < 1) {
2710:                        return 1;
2711:                    }
2712:                    return i.intValue();
2713:                }
2714:
2715:                /**
2716:                 * Looks at the current rowspan.
2717:                 * @param c
2718:                 * @return the current rowspan
2719:                 */
2720:                public int currentRowspan(PdfCell c) {
2721:                    Integer i = (Integer) rowspanMap.get(c);
2722:                    if (i == null) {
2723:                        return c.rowspan();
2724:                    } else {
2725:                        return i.intValue();
2726:                    }
2727:                }
2728:
2729:                public int cellRendered(PdfCell cell, int pageNumber) {
2730:                    Integer i = (Integer) pageMap.get(cell);
2731:                    if (i == null) {
2732:                        i = new Integer(1);
2733:                    } else {
2734:                        i = new Integer(i.intValue() + 1);
2735:                    }
2736:                    pageMap.put(cell, i);
2737:
2738:                    Integer pageInteger = new Integer(pageNumber);
2739:                    Set set = (Set) pageMap.get(pageInteger);
2740:
2741:                    if (set == null) {
2742:                        set = new HashSet();
2743:                        pageMap.put(pageInteger, set);
2744:                    }
2745:
2746:                    set.add(cell);
2747:
2748:                    return i.intValue();
2749:                }
2750:
2751:                public int numCellRendered(PdfCell cell) {
2752:                    Integer i = (Integer) pageMap.get(cell);
2753:                    if (i == null) {
2754:                        i = new Integer(0);
2755:                    }
2756:                    return i.intValue();
2757:                }
2758:
2759:                public boolean isCellRenderedOnPage(PdfCell cell, int pageNumber) {
2760:                    Integer pageInteger = new Integer(pageNumber);
2761:                    Set set = (Set) pageMap.get(pageInteger);
2762:
2763:                    if (set != null) {
2764:                        return set.contains(cell);
2765:                    }
2766:
2767:                    return false;
2768:                }
2769:            };
2770:
2771:            /**
2772:             * Adds a new table to the document.
2773:             * @param table				Table to add.  Rendered rows will be deleted after processing.
2774:             * @param onlyFirstPage		Render only the first full page
2775:             * @throws DocumentException
2776:             */
2777:            private void add(PdfTable table, boolean onlyFirstPage)
2778:                    throws DocumentException {
2779:                // before every table, we flush all lines
2780:                flushLines();
2781:
2782:                RenderingContext ctx = new RenderingContext();
2783:                ctx.pagetop = indentTop();
2784:                ctx.oldHeight = currentHeight;
2785:                ctx.cellGraphics = new PdfContentByte(writer);
2786:                ctx.rowspanMap = new HashMap();
2787:                ctx.table = table;
2788:
2789:                // initialisation of parameters
2790:                PdfCell cell;
2791:
2792:                // drawing the table
2793:                ArrayList dataCells = table.getCells();
2794:
2795:                ArrayList headercells = table.getHeaderCells();
2796:                // Check if we have removed header cells in a previous call
2797:                if (!headercells.isEmpty()
2798:                        && (dataCells.isEmpty() || dataCells.get(0) != headercells
2799:                                .get(0))) {
2800:                    ArrayList allCells = new ArrayList(dataCells.size()
2801:                            + headercells.size());
2802:                    allCells.addAll(headercells);
2803:                    allCells.addAll(dataCells);
2804:                    dataCells = allCells;
2805:                }
2806:
2807:                ArrayList cells = dataCells;
2808:                ArrayList rows = extractRows(cells, ctx);
2809:                boolean isContinue = false;
2810:                while (!cells.isEmpty()) {
2811:                    // initialisation of some extra parameters;
2812:                    ctx.lostTableBottom = 0;
2813:
2814:                    // loop over the cells
2815:                    boolean cellsShown = false;
2816:
2817:                    // draw the cells (line by line)
2818:                    Iterator iterator = rows.iterator();
2819:
2820:                    boolean atLeastOneFits = false;
2821:                    while (iterator.hasNext()) {
2822:                        ArrayList row = (ArrayList) iterator.next();
2823:                        analyzeRow(rows, ctx);
2824:                        renderCells(ctx, row, table.hasToFitPageCells()
2825:                                & atLeastOneFits);
2826:
2827:                        if (!mayBeRemoved(row)) {
2828:                            break;
2829:                        }
2830:                        consumeRowspan(row, ctx);
2831:                        iterator.remove();
2832:                        atLeastOneFits = true;
2833:                    }
2834:
2835:                    //          compose cells array list for subsequent code
2836:                    cells.clear();
2837:                    Set opt = new HashSet();
2838:                    iterator = rows.iterator();
2839:                    while (iterator.hasNext()) {
2840:                        ArrayList row = (ArrayList) iterator.next();
2841:
2842:                        Iterator cellIterator = row.iterator();
2843:                        while (cellIterator.hasNext()) {
2844:                            cell = (PdfCell) cellIterator.next();
2845:
2846:                            if (!opt.contains(cell)) {
2847:                                cells.add(cell);
2848:                                opt.add(cell);
2849:                            }
2850:                        }
2851:                    }
2852:
2853:                    // we paint the graphics of the table after looping through all the cells
2854:                    Rectangle tablerec = new Rectangle(table);
2855:                    tablerec.setBorder(table.getBorder());
2856:                    tablerec.setBorderWidth(table.getBorderWidth());
2857:                    tablerec.setBorderColor(table.getBorderColor());
2858:                    tablerec.setBackgroundColor(table.getBackgroundColor());
2859:                    PdfContentByte under = writer.getDirectContentUnder();
2860:                    under.rectangle(tablerec.rectangle(top(), indentBottom()));
2861:                    under.add(ctx.cellGraphics);
2862:                    // bugfix by Gerald Fehringer: now again add the border for the table
2863:                    // since it might have been covered by cell backgrounds
2864:                    tablerec.setBackgroundColor(null);
2865:                    tablerec = tablerec.rectangle(top(), indentBottom());
2866:                    tablerec.setBorder(table.getBorder());
2867:                    under.rectangle(tablerec);
2868:                    // end bugfix
2869:
2870:                    ctx.cellGraphics = new PdfContentByte(null);
2871:                    // if the table continues on the next page
2872:
2873:                    if (!rows.isEmpty()) {
2874:                        isContinue = true;
2875:                        graphics.setLineWidth(table.getBorderWidth());
2876:                        if (cellsShown
2877:                                && (table.getBorder() & Rectangle.BOTTOM) == Rectangle.BOTTOM) {
2878:                            // Draw the bottom line
2879:
2880:                            // the color is set to the color of the element
2881:                            Color tColor = table.getBorderColor();
2882:                            if (tColor != null) {
2883:                                graphics.setColorStroke(tColor);
2884:                            }
2885:                            graphics.moveTo(table.getLeft(), Math.max(table
2886:                                    .getBottom(), indentBottom()));
2887:                            graphics.lineTo(table.getRight(), Math.max(table
2888:                                    .getBottom(), indentBottom()));
2889:                            graphics.stroke();
2890:                            if (tColor != null) {
2891:                                graphics.resetRGBColorStroke();
2892:                            }
2893:                        }
2894:
2895:                        // old page
2896:                        pageEmpty = false;
2897:                        float difference = ctx.lostTableBottom;
2898:
2899:                        // new page
2900:                        newPage();
2901:
2902:                        // G.F.: if something added in page event i.e. currentHeight > 0
2903:                        float heightCorrection = 0;
2904:                        boolean somethingAdded = false;
2905:                        if (currentHeight > 0) {
2906:                            heightCorrection = 6;
2907:                            currentHeight += heightCorrection;
2908:                            somethingAdded = true;
2909:                            newLine();
2910:                            flushLines();
2911:                            indentation.indentTop = currentHeight - leading;
2912:                            currentHeight = 0;
2913:                        } else {
2914:                            flushLines();
2915:                        }
2916:
2917:                        // this part repeats the table headers (if any)
2918:                        int size = headercells.size();
2919:                        if (size > 0) {
2920:                            // this is the top of the headersection
2921:                            cell = (PdfCell) headercells.get(0);
2922:                            float oldTop = cell.getTop(0);
2923:                            // loop over all the cells of the table header
2924:                            for (int i = 0; i < size; i++) {
2925:                                cell = (PdfCell) headercells.get(i);
2926:                                // calculation of the new cellpositions
2927:                                cell.setTop(indentTop() - oldTop
2928:                                        + cell.getTop(0));
2929:                                cell.setBottom(indentTop() - oldTop
2930:                                        + cell.getBottom(0));
2931:                                ctx.pagetop = cell.getBottom();
2932:                                // we paint the borders of the cell
2933:                                ctx.cellGraphics.rectangle(cell.rectangle(
2934:                                        indentTop(), indentBottom()));
2935:                                // we write the text of the cell
2936:                                ArrayList images = cell.getImages(indentTop(),
2937:                                        indentBottom());
2938:                                for (Iterator im = images.iterator(); im
2939:                                        .hasNext();) {
2940:                                    cellsShown = true;
2941:                                    Image image = (Image) im.next();
2942:                                    graphics.addImage(image);
2943:                                }
2944:                                lines = cell.getLines(indentTop(),
2945:                                        indentBottom());
2946:                                float cellTop = cell.getTop(indentTop());
2947:                                text.moveText(0, cellTop - heightCorrection);
2948:                                float cellDisplacement = flushLines() - cellTop
2949:                                        + heightCorrection;
2950:                                text.moveText(0, cellDisplacement);
2951:                            }
2952:
2953:                            currentHeight = indentTop() - ctx.pagetop
2954:                                    + table.cellspacing();
2955:                            text.moveText(0, ctx.pagetop - indentTop()
2956:                                    - currentHeight);
2957:                        } else {
2958:                            if (somethingAdded) {
2959:                                ctx.pagetop = indentTop();
2960:                                text.moveText(0, -table.cellspacing());
2961:                            }
2962:                        }
2963:                        ctx.oldHeight = currentHeight - heightCorrection;
2964:
2965:                        // calculating the new positions of the table and the cells
2966:                        size = Math.min(cells.size(), table.columns());
2967:                        int i = 0;
2968:                        while (i < size) {
2969:                            cell = (PdfCell) cells.get(i);
2970:                            if (cell.getTop(-table.cellspacing()) > ctx.lostTableBottom) {
2971:                                float newBottom = ctx.pagetop - difference
2972:                                        + cell.getBottom();
2973:                                float neededHeight = cell.remainingHeight();
2974:                                if (newBottom > ctx.pagetop - neededHeight) {
2975:                                    difference += newBottom
2976:                                            - (ctx.pagetop - neededHeight);
2977:                                }
2978:                            }
2979:                            i++;
2980:                        }
2981:                        size = cells.size();
2982:                        table.setTop(indentTop());
2983:                        table.setBottom(ctx.pagetop - difference
2984:                                + table.getBottom(table.cellspacing()));
2985:                        for (i = 0; i < size; i++) {
2986:                            cell = (PdfCell) cells.get(i);
2987:                            float newBottom = ctx.pagetop - difference
2988:                                    + cell.getBottom();
2989:                            float newTop = ctx.pagetop - difference
2990:                                    + cell.getTop(-table.cellspacing());
2991:                            if (newTop > indentTop() - currentHeight) {
2992:                                newTop = indentTop() - currentHeight;
2993:                            }
2994:
2995:                            cell.setTop(newTop);
2996:                            cell.setBottom(newBottom);
2997:                        }
2998:                        if (onlyFirstPage) {
2999:                            break;
3000:                        }
3001:                    }
3002:                }
3003:
3004:                float tableHeight = table.getTop() - table.getBottom();
3005:                // bugfix by Adauto Martins when have more than two tables and more than one page 
3006:                // If continuation of table in other page (bug report #1460051)
3007:                if (isContinue) {
3008:                    currentHeight = tableHeight;
3009:                    text.moveText(0, -(tableHeight - (ctx.oldHeight * 2)));
3010:                } else {
3011:                    currentHeight = ctx.oldHeight + tableHeight;
3012:                    text.moveText(0, -tableHeight);
3013:                }
3014:                // end bugfix
3015:                pageEmpty = false;
3016:            }
3017:
3018:            private void analyzeRow(ArrayList rows, RenderingContext ctx) {
3019:                ctx.maxCellBottom = indentBottom();
3020:
3021:                // determine whether row(index) is in a rowspan
3022:                int rowIndex = 0;
3023:
3024:                ArrayList row = (ArrayList) rows.get(rowIndex);
3025:                int maxRowspan = 1;
3026:                Iterator iterator = row.iterator();
3027:                while (iterator.hasNext()) {
3028:                    PdfCell cell = (PdfCell) iterator.next();
3029:                    maxRowspan = Math.max(ctx.currentRowspan(cell), maxRowspan);
3030:                }
3031:                rowIndex += maxRowspan;
3032:
3033:                boolean useTop = true;
3034:                if (rowIndex == rows.size()) {
3035:                    rowIndex = rows.size() - 1;
3036:                    useTop = false;
3037:                }
3038:
3039:                if (rowIndex < 0 || rowIndex >= rows.size())
3040:                    return;
3041:
3042:                row = (ArrayList) rows.get(rowIndex);
3043:                iterator = row.iterator();
3044:                while (iterator.hasNext()) {
3045:                    PdfCell cell = (PdfCell) iterator.next();
3046:                    Rectangle cellRect = cell.rectangle(ctx.pagetop,
3047:                            indentBottom());
3048:                    if (useTop) {
3049:                        ctx.maxCellBottom = Math.max(ctx.maxCellBottom,
3050:                                cellRect.getTop());
3051:                    } else {
3052:                        if (ctx.currentRowspan(cell) == 1) {
3053:                            ctx.maxCellBottom = Math.max(ctx.maxCellBottom,
3054:                                    cellRect.getBottom());
3055:                        }
3056:                    }
3057:                }
3058:            }
3059:
3060:            private boolean mayBeRemoved(ArrayList row) {
3061:                Iterator iterator = row.iterator();
3062:                boolean mayBeRemoved = true;
3063:                while (iterator.hasNext()) {
3064:                    PdfCell cell = (PdfCell) iterator.next();
3065:
3066:                    mayBeRemoved &= cell.mayBeRemoved();
3067:                }
3068:                return mayBeRemoved;
3069:            }
3070:
3071:            private void consumeRowspan(ArrayList row, RenderingContext ctx) {
3072:                Iterator iterator = row.iterator();
3073:                while (iterator.hasNext()) {
3074:                    PdfCell c = (PdfCell) iterator.next();
3075:                    ctx.consumeRowspan(c);
3076:                }
3077:            }
3078:
3079:            private ArrayList extractRows(ArrayList cells, RenderingContext ctx) {
3080:                PdfCell cell;
3081:                PdfCell previousCell = null;
3082:                ArrayList rows = new ArrayList();
3083:                java.util.List rowCells = new ArrayList();
3084:
3085:                Iterator iterator = cells.iterator();
3086:                while (iterator.hasNext()) {
3087:                    cell = (PdfCell) iterator.next();
3088:
3089:                    boolean isAdded = false;
3090:
3091:                    boolean isEndOfRow = !iterator.hasNext();
3092:                    boolean isCurrentCellPartOfRow = !iterator.hasNext();
3093:
3094:                    if (previousCell != null) {
3095:                        if (cell.getLeft() <= previousCell.getLeft()) {
3096:                            isEndOfRow = true;
3097:                            isCurrentCellPartOfRow = false;
3098:                        }
3099:                    }
3100:
3101:                    if (isCurrentCellPartOfRow) {
3102:                        rowCells.add(cell);
3103:                        isAdded = true;
3104:                    }
3105:
3106:                    if (isEndOfRow) {
3107:                        if (!rowCells.isEmpty()) {
3108:                            // add to rowlist
3109:                            rows.add(rowCells);
3110:                        }
3111:
3112:                        // start a new list for next line
3113:                        rowCells = new ArrayList();
3114:                    }
3115:
3116:                    if (!isAdded) {
3117:                        rowCells.add(cell);
3118:                    }
3119:
3120:                    previousCell = cell;
3121:                }
3122:
3123:                if (!rowCells.isEmpty()) {
3124:                    rows.add(rowCells);
3125:                }
3126:
3127:                // fill row information with rowspan cells to get complete "scan lines"
3128:                for (int i = rows.size() - 1; i >= 0; i--) {
3129:                    ArrayList row = (ArrayList) rows.get(i);
3130:                    // iterator through row
3131:                    for (int j = 0; j < row.size(); j++) {
3132:                        PdfCell c = (PdfCell) row.get(j);
3133:                        int rowspan = c.rowspan();
3134:                        // fill in missing rowspan cells to complete "scan line"
3135:                        for (int k = 1; k < rowspan && rows.size() < i + k; k++) {
3136:                            ArrayList spannedRow = ((ArrayList) rows.get(i + k));
3137:                            if (spannedRow.size() > j)
3138:                                spannedRow.add(j, c);
3139:                        }
3140:                    }
3141:                }
3142:
3143:                return rows;
3144:            }
3145:
3146:            private void renderCells(RenderingContext ctx,
3147:                    java.util.List cells, boolean hasToFit)
3148:                    throws DocumentException {
3149:                PdfCell cell;
3150:                Iterator iterator;
3151:                if (hasToFit) {
3152:                    iterator = cells.iterator();
3153:                    while (iterator.hasNext()) {
3154:                        cell = (PdfCell) iterator.next();
3155:                        if (!cell.isHeader()) {
3156:                            if (cell.getBottom() < indentBottom())
3157:                                return;
3158:                        }
3159:                    }
3160:                }
3161:                iterator = cells.iterator();
3162:
3163:                while (iterator.hasNext()) {
3164:                    cell = (PdfCell) iterator.next();
3165:                    if (!ctx.isCellRenderedOnPage(cell, getPageNumber())) {
3166:
3167:                        float correction = 0;
3168:                        if (ctx.numCellRendered(cell) >= 1) {
3169:                            correction = 1.0f;
3170:                        }
3171:
3172:                        lines = cell.getLines(ctx.pagetop, indentBottom()
3173:                                - correction);
3174:
3175:                        // if there is still text to render we render it
3176:                        if (lines != null && !lines.isEmpty()) {
3177:
3178:                            // we write the text
3179:                            float cellTop = cell.getTop(ctx.pagetop
3180:                                    - ctx.oldHeight);
3181:                            text.moveText(0, cellTop);
3182:                            float cellDisplacement = flushLines() - cellTop;
3183:
3184:                            text.moveText(0, cellDisplacement);
3185:                            if (ctx.oldHeight + cellDisplacement > currentHeight) {
3186:                                currentHeight = ctx.oldHeight
3187:                                        + cellDisplacement;
3188:                            }
3189:
3190:                            ctx.cellRendered(cell, getPageNumber());
3191:                        }
3192:                        float indentBottom = Math.max(cell.getBottom(),
3193:                                indentBottom());
3194:                        Rectangle tableRect = ctx.table.rectangle(ctx.pagetop,
3195:                                indentBottom());
3196:                        indentBottom = Math.max(tableRect.getBottom(),
3197:                                indentBottom);
3198:
3199:                        // we paint the borders of the cells
3200:                        Rectangle cellRect = cell.rectangle(tableRect.getTop(),
3201:                                indentBottom);
3202:                        //cellRect.setBottom(cellRect.bottom());
3203:                        if (cellRect.getHeight() > 0) {
3204:                            ctx.lostTableBottom = indentBottom;
3205:                            ctx.cellGraphics.rectangle(cellRect);
3206:                        }
3207:
3208:                        // and additional graphics
3209:                        ArrayList images = cell.getImages(ctx.pagetop,
3210:                                indentBottom());
3211:                        for (Iterator i = images.iterator(); i.hasNext();) {
3212:                            Image image = (Image) i.next();
3213:                            graphics.addImage(image);
3214:                        }
3215:
3216:                    }
3217:                }
3218:            }
3219:
3220:            /**
3221:             * @see PdfWriter#breakTableIfDoesntFit(PdfTable)
3222:             * (contributed by dperezcar@fcc.es)
3223:             * @param table				Table to add
3224:             * @return true if the table will be broken
3225:             * @throws DocumentException
3226:             * @deprecated
3227:             */
3228:
3229:            boolean breakTableIfDoesntFit(PdfTable table)
3230:                    throws DocumentException {
3231:                table.updateRowAdditions();
3232:                // Do we have any full page available?
3233:                if (!table.hasToFitPageTable()
3234:                        && table.getBottom() <= indentation.indentBottom) {
3235:                    // Then output that page
3236:                    add(table, true);
3237:                    return true;
3238:                }
3239:                return false;
3240:            }
3241:
3242:            /**
3243:             * Returns the bottomvalue of a <CODE>Table</CODE> if it were added to this document.
3244:             *
3245:             * @param	table	the table that may or may not be added to this document
3246:             * @return	a bottom value
3247:             * @deprecated
3248:             */
3249:
3250:            float bottom(Table table) {
3251:                // constructing a PdfTable
3252:                PdfTable tmp = getPdfTable(table, false);
3253:                return tmp.getBottom();
3254:            }
3255:
3256:            //	[M5] header/footer
3257:            private void doFooter() throws DocumentException {
3258:                if (footer == null)
3259:                    return;
3260:                // Begin added by Edgar Leonardo Prieto Perilla
3261:                // Avoid footer identation
3262:                float tmpIndentLeft = indentation.indentLeft;
3263:                float tmpIndentRight = indentation.indentRight;
3264:                // Begin added: Bonf (Marc Schneider) 2003-07-29
3265:                float tmpListIndentLeft = indentation.listIndentLeft;
3266:                float tmpImageIndentLeft = indentation.imageIndentLeft;
3267:                float tmpImageIndentRight = indentation.imageIndentRight;
3268:                // End added: Bonf (Marc Schneider) 2003-07-29
3269:
3270:                indentation.indentLeft = indentation.indentRight = 0;
3271:                // Begin added: Bonf (Marc Schneider) 2003-07-29
3272:                indentation.listIndentLeft = 0;
3273:                indentation.imageIndentLeft = 0;
3274:                indentation.imageIndentRight = 0;
3275:                // End added: Bonf (Marc Schneider) 2003-07-29
3276:                // End Added by Edgar Leonardo Prieto Perilla
3277:                footer.setPageNumber(pageN);
3278:                leading = footer.paragraph().getTotalLeading();
3279:                add(footer.paragraph());
3280:                // adding the footer limits the height
3281:                indentation.indentBottom = currentHeight;
3282:                text.moveText(left(), indentBottom());
3283:                flushLines();
3284:                text.moveText(-left(), -bottom());
3285:                footer.setTop(bottom(currentHeight));
3286:                footer.setBottom(bottom() - (0.75f * leading));
3287:                footer.setLeft(left());
3288:                footer.setRight(right());
3289:                graphics.rectangle(footer);
3290:                indentation.indentBottom = currentHeight + leading * 2;
3291:                currentHeight = 0;
3292:                // Begin added by Edgar Leonardo Prieto Perilla
3293:                indentation.indentLeft = tmpIndentLeft;
3294:                indentation.indentRight = tmpIndentRight;
3295:                // Begin added: Bonf (Marc Schneider) 2003-07-29
3296:                indentation.listIndentLeft = tmpListIndentLeft;
3297:                indentation.imageIndentLeft = tmpImageIndentLeft;
3298:                indentation.imageIndentRight = tmpImageIndentRight;
3299:                // End added: Bonf (Marc Schneider) 2003-07-29
3300:                // End added by Edgar Leonardo Prieto Perilla
3301:            }
3302:
3303:            private void doHeader() throws DocumentException {
3304:                // if there is a header, the header = added
3305:                if (header == null)
3306:                    return;
3307:                // Begin added by Edgar Leonardo Prieto Perilla
3308:                // Avoid header identation
3309:                float tmpIndentLeft = indentation.indentLeft;
3310:                float tmpIndentRight = indentation.indentRight;
3311:                // Begin added: Bonf (Marc Schneider) 2003-07-29
3312:                float tmpListIndentLeft = indentation.listIndentLeft;
3313:                float tmpImageIndentLeft = indentation.imageIndentLeft;
3314:                float tmpImageIndentRight = indentation.imageIndentRight;
3315:                // End added: Bonf (Marc Schneider) 2003-07-29
3316:                indentation.indentLeft = indentation.indentRight = 0;
3317:                //  Added: Bonf
3318:                indentation.listIndentLeft = 0;
3319:                indentation.imageIndentLeft = 0;
3320:                indentation.imageIndentRight = 0;
3321:                // End added: Bonf
3322:                // Begin added by Edgar Leonardo Prieto Perilla
3323:                header.setPageNumber(pageN);
3324:                leading = header.paragraph().getTotalLeading();
3325:                text.moveText(0, leading);
3326:                add(header.paragraph());
3327:                newLine();
3328:                indentation.indentTop = currentHeight - leading;
3329:                header.setTop(top() + leading);
3330:                header.setBottom(indentTop() + leading * 2 / 3);
3331:                header.setLeft(left());
3332:                header.setRight(right());
3333:                graphics.rectangle(header);
3334:                flushLines();
3335:                currentHeight = 0;
3336:                // Begin added by Edgar Leonardo Prieto Perilla
3337:                // Restore identation
3338:                indentation.indentLeft = tmpIndentLeft;
3339:                indentation.indentRight = tmpIndentRight;
3340:                // Begin added: Bonf (Marc Schneider) 2003-07-29
3341:                indentation.listIndentLeft = tmpListIndentLeft;
3342:                indentation.imageIndentLeft = tmpImageIndentLeft;
3343:                indentation.imageIndentRight = tmpImageIndentRight;
3344:                // End added: Bonf (Marc Schneider) 2003-07-29
3345:                // End Added by Edgar Leonardo Prieto Perilla
3346:            }
3347:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.