Source Code Cross Referenced for RtfWriter.java in  » PDF » pdf-itext » com » lowagie » text » rtf » 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.rtf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: RtfWriter.java 2849 2007-06-20 19:31:09Z xlv $
0003:         * $Name$
0004:         *
0005:         * Copyright 2001, 2002 by Mark Hall
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.rtf;
0052:
0053:        import java.awt.Color;
0054:        import java.io.ByteArrayInputStream;
0055:        import java.io.ByteArrayOutputStream;
0056:        import java.io.IOException;
0057:        import java.io.InputStream;
0058:        import java.io.OutputStream;
0059:        import java.text.ParsePosition;
0060:        import java.text.SimpleDateFormat;
0061:        import java.util.ArrayList;
0062:        import java.util.Calendar;
0063:        import java.util.Date;
0064:        import java.util.Iterator;
0065:        import java.util.ListIterator;
0066:
0067:        import com.lowagie.text.Anchor;
0068:        import com.lowagie.text.Annotation;
0069:        import com.lowagie.text.Chunk;
0070:        import com.lowagie.text.DocWriter;
0071:        import com.lowagie.text.Document;
0072:        import com.lowagie.text.DocumentException;
0073:        import com.lowagie.text.Element;
0074:        import com.lowagie.text.ExceptionConverter;
0075:        import com.lowagie.text.Font;
0076:        import com.lowagie.text.HeaderFooter;
0077:        import com.lowagie.text.Image;
0078:        import com.lowagie.text.ListItem;
0079:        import com.lowagie.text.Meta;
0080:        import com.lowagie.text.PageSize;
0081:        import com.lowagie.text.Paragraph;
0082:        import com.lowagie.text.Phrase;
0083:        import com.lowagie.text.Rectangle;
0084:        import com.lowagie.text.Section;
0085:        import com.lowagie.text.SimpleTable;
0086:        import com.lowagie.text.Table;
0087:        import com.lowagie.text.pdf.codec.wmf.MetaDo;
0088:
0089:        /**
0090:         * If you are creating a new project using the rtf part of iText, please
0091:         * consider using the new RtfWriter2. The RtfWriter is in bug-fix-only mode,
0092:         * will be deprecated end of 2005 and removed end of 2007.
0093:         * 
0094:         * A <CODE>DocWriter</CODE> class for Rich Text Files (RTF).
0095:         * <P>
0096:         * A <CODE>RtfWriter</CODE> can be added as a <CODE>DocListener</CODE>
0097:         * to a certain <CODE>Document</CODE> by getting an instance.
0098:         * Every <CODE>Element</CODE> added to the original <CODE>Document</CODE>
0099:         * will be written to the <CODE>OutputStream</CODE> of this <CODE>RtfWriter</CODE>.
0100:         * <P>
0101:         * Example:
0102:         * <BLOCKQUOTE><PRE>
0103:         * // creation of the document with a certain size and certain margins
0104:         * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
0105:         * try {
0106:         *    // this will write RTF to the Standard OutputStream
0107:         *    <STRONG>RtfWriter.getInstance(document, System.out);</STRONG>
0108:         *    // this will write Rtf to a file called text.rtf
0109:         *    <STRONG>RtfWriter.getInstance(document, new FileOutputStream("text.rtf"));</STRONG>
0110:         *    // this will write Rtf to for instance the OutputStream of a HttpServletResponse-object
0111:         *    <STRONG>RtfWriter.getInstance(document, response.getOutputStream());</STRONG>
0112:         * }
0113:         * catch(DocumentException de) {
0114:         *    System.err.println(de.getMessage());
0115:         * }
0116:         * // this will close the document and all the OutputStreams listening to it
0117:         * <STRONG>document.close();</CODE>
0118:         * </PRE></BLOCKQUOTE>
0119:         * <P>
0120:         * <STRONG>LIMITATIONS</STRONG><BR>
0121:         * There are currently still a few limitations on what the RTF Writer can do:
0122:         * <ul>
0123:         *    <li>Watermarks</li>
0124:         *    <li>Viewer preferences</li>
0125:         *    <li>Encryption</li>
0126:         *    <li>Embedded fonts</li>
0127:         *    <li>Phrases with a leading</li>
0128:         *    <li>Lists with non-bullet symbols</li>
0129:         *    <li>Nested tables</li>
0130:         *    <li>Images other than JPEG and PNG</li>
0131:         *    <li>Rotated images</li>
0132:         * </ul>
0133:         * <br />
0134:         *
0135:         * @author Mark Hall (mhall@edu.uni-klu.ac.at)
0136:         * @author Steffen Stundzig (Steffen.Stundzig@smb-tec.com)
0137:         * @author Eric Mattes (ericmattes@yahoo.com)
0138:         * @author Raul Wegmann (raul.wegmann@uam.es)
0139:         * @deprecated The RtfWriter is deprecated and will be removed from the iText library end of 2007
0140:         */
0141:        public class RtfWriter extends DocWriter {
0142:            /**
0143:             * Static Constants
0144:             */
0145:
0146:            /**
0147:             * General
0148:             */
0149:
0150:            /** This is the escape character which introduces RTF tags. */
0151:            public static final byte escape = (byte) '\\';
0152:
0153:            /** This is another escape character which introduces RTF tags. */
0154:            private static final byte[] extendedEscape = "\\*\\".getBytes();
0155:
0156:            /** This is the delimiter between RTF tags and normal text. */
0157:            protected static final byte delimiter = (byte) ' ';
0158:
0159:            /** This is another delimiter between RTF tags and normal text. */
0160:            private static final byte commaDelimiter = (byte) ';';
0161:
0162:            /** This is the character for beginning a new group. */
0163:            public static final byte openGroup = (byte) '{';
0164:
0165:            /** This is the character for closing a group. */
0166:            public static final byte closeGroup = (byte) '}';
0167:
0168:            /**
0169:             * RTF Information
0170:             */
0171:
0172:            /** RTF begin and version. */
0173:            private static final byte[] docBegin = "rtf1".getBytes();
0174:
0175:            /** RTF encoding. */
0176:            private static final byte[] ansi = "ansi".getBytes();
0177:
0178:            /** RTF encoding codepage. */
0179:            private static final byte[] ansiCodepage = "ansicpg".getBytes();
0180:
0181:            /**
0182:             *Font Data
0183:             */
0184:
0185:            /** Begin the font table tag. */
0186:            private static final byte[] fontTable = "fonttbl".getBytes();
0187:
0188:            /** Font number tag. */
0189:            protected static final byte fontNumber = (byte) 'f';
0190:
0191:            /** Font size tag. */
0192:            protected static final byte[] fontSize = "fs".getBytes();
0193:
0194:            /** Font color tag. */
0195:            protected static final byte[] fontColor = "cf".getBytes();
0196:
0197:            /** Modern font tag. */
0198:            private static final byte[] fontModern = "fmodern".getBytes();
0199:
0200:            /** Swiss font tag. */
0201:            private static final byte[] fontSwiss = "fswiss".getBytes();
0202:
0203:            /** Roman font tag. */
0204:            private static final byte[] fontRoman = "froman".getBytes();
0205:
0206:            /** Tech font tag. */
0207:            private static final byte[] fontTech = "ftech".getBytes();
0208:
0209:            /** Font charset tag. */
0210:            private static final byte[] fontCharset = "fcharset".getBytes();
0211:
0212:            /** Font Courier tag. */
0213:            private static final byte[] fontCourier = "Courier".getBytes();
0214:
0215:            /** Font Arial tag. */
0216:            private static final byte[] fontArial = "Arial".getBytes();
0217:
0218:            /** Font Symbol tag. */
0219:            private static final byte[] fontSymbol = "Symbol".getBytes();
0220:
0221:            /** Font Times New Roman tag. */
0222:            private static final byte[] fontTimesNewRoman = "Times New Roman"
0223:                    .getBytes();
0224:
0225:            /** Font Windings tag. */
0226:            private static final byte[] fontWindings = "Windings".getBytes();
0227:
0228:            /** Default Font. */
0229:            private static final byte[] defaultFont = "deff".getBytes();
0230:
0231:            /** First indent tag. */
0232:            private static final byte[] firstIndent = "fi".getBytes();
0233:
0234:            /** Left indent tag. */
0235:            private static final byte[] listIndent = "li".getBytes();
0236:
0237:            /** Right indent tag. */
0238:            private static final byte[] rightIndent = "ri".getBytes();
0239:
0240:            /**
0241:             * Sections / Paragraphs
0242:             */
0243:
0244:            /** Reset section defaults tag. */
0245:            private static final byte[] sectionDefaults = "sectd".getBytes();
0246:
0247:            /** Begin new section tag. */
0248:            private static final byte[] section = "sect".getBytes();
0249:
0250:            /** Reset paragraph defaults tag. */
0251:            public static final byte[] paragraphDefaults = "pard".getBytes();
0252:
0253:            /** Begin new paragraph tag. */
0254:            public static final byte[] paragraph = "par".getBytes();
0255:
0256:            /** Page width of a section. */
0257:            public static final byte[] sectionPageWidth = "pgwsxn".getBytes();
0258:
0259:            /** Page height of a section. */
0260:            public static final byte[] sectionPageHeight = "pghsxn".getBytes();
0261:
0262:            /**
0263:             * Lists
0264:             */
0265:
0266:            /** Begin the List Table */
0267:            private static final byte[] listtableGroup = "listtable".getBytes();
0268:
0269:            /** Begin the List Override Table */
0270:            private static final byte[] listoverridetableGroup = "listoverridetable"
0271:                    .getBytes();
0272:
0273:            /** Begin a List definition */
0274:            private static final byte[] listDefinition = "list".getBytes();
0275:
0276:            /** List Template ID */
0277:            private static final byte[] listTemplateID = "listtemplateid"
0278:                    .getBytes();
0279:
0280:            /** RTF Writer outputs hybrid lists */
0281:            private static final byte[] hybridList = "hybrid".getBytes();
0282:
0283:            /** Current List level */
0284:            private static final byte[] listLevelDefinition = "listlevel"
0285:                    .getBytes();
0286:
0287:            /** Level numbering (old) */
0288:            private static final byte[] listLevelTypeOld = "levelnfc"
0289:                    .getBytes();
0290:
0291:            /** Level numbering (new) */
0292:            private static final byte[] listLevelTypeNew = "levelnfcn"
0293:                    .getBytes();
0294:
0295:            /** Level alignment (old) */
0296:            private static final byte[] listLevelAlignOld = "leveljc"
0297:                    .getBytes();
0298:
0299:            /** Level alignment (new) */
0300:            private static final byte[] listLevelAlignNew = "leveljcn"
0301:                    .getBytes();
0302:
0303:            /** Level starting number */
0304:            private static final byte[] listLevelStartAt = "levelstartat"
0305:                    .getBytes();
0306:
0307:            /** Level text group */
0308:            private static final byte[] listLevelTextDefinition = "leveltext"
0309:                    .getBytes();
0310:
0311:            /** Filler for Level Text Length */
0312:            private static final byte[] listLevelTextLength = "\'0".getBytes();
0313:
0314:            /** Level Text Numbering Style */
0315:            private static final byte[] listLevelTextStyleNumbers = "\'00."
0316:                    .getBytes();
0317:
0318:            /** Level Text Bullet Style */
0319:            private static final byte[] listLevelTextStyleBullet = "u-3913 ?"
0320:                    .getBytes();
0321:
0322:            /** Level Numbers Definition */
0323:            private static final byte[] listLevelNumbersDefinition = "levelnumbers"
0324:                    .getBytes();
0325:
0326:            /** Filler for Level Numbers */
0327:            private static final byte[] listLevelNumbers = "\\'0".getBytes();
0328:
0329:            /** Tab Stop */
0330:            private static final byte[] tabStop = "tx".getBytes();
0331:
0332:            /** Actual list begin */
0333:            private static final byte[] listBegin = "ls".getBytes();
0334:
0335:            /** Current list level */
0336:            private static final byte[] listCurrentLevel = "ilvl".getBytes();
0337:
0338:            /** List text group for older browsers */
0339:            private static final byte[] listTextOld = "listtext".getBytes();
0340:
0341:            /** Tab */
0342:            private static final byte[] tab = "tab".getBytes();
0343:
0344:            /** Old Bullet Style */
0345:            private static final byte[] listBulletOld = "\'b7".getBytes();
0346:
0347:            /** Current List ID */
0348:            private static final byte[] listID = "listid".getBytes();
0349:
0350:            /** List override */
0351:            private static final byte[] listOverride = "listoverride"
0352:                    .getBytes();
0353:
0354:            /** Number of overrides */
0355:            private static final byte[] listOverrideCount = "listoverridecount"
0356:                    .getBytes();
0357:
0358:            /**
0359:             * Text Style
0360:             */
0361:
0362:            /** Bold tag. */
0363:            protected static final byte bold = (byte) 'b';
0364:
0365:            /** Italic tag. */
0366:            protected static final byte italic = (byte) 'i';
0367:
0368:            /** Underline tag. */
0369:            protected static final byte[] underline = "ul".getBytes();
0370:
0371:            /** Strikethrough tag. */
0372:            protected static final byte[] strikethrough = "strike".getBytes();
0373:
0374:            /** Text alignment left tag. */
0375:            public static final byte[] alignLeft = "ql".getBytes();
0376:
0377:            /** Text alignment center tag. */
0378:            public static final byte[] alignCenter = "qc".getBytes();
0379:
0380:            /** Text alignment right tag. */
0381:            public static final byte[] alignRight = "qr".getBytes();
0382:
0383:            /** Text alignment justify tag. */
0384:            public static final byte[] alignJustify = "qj".getBytes();
0385:
0386:            /**
0387:             * Colors
0388:             */
0389:
0390:            /** Begin colour table tag. */
0391:            private static final byte[] colorTable = "colortbl".getBytes();
0392:
0393:            /** Red value tag. */
0394:            private static final byte[] colorRed = "red".getBytes();
0395:
0396:            /** Green value tag. */
0397:            private static final byte[] colorGreen = "green".getBytes();
0398:
0399:            /** Blue value tag. */
0400:            private static final byte[] colorBlue = "blue".getBytes();
0401:
0402:            /**
0403:             * Information Group
0404:             */
0405:
0406:            /** Begin the info group tag.*/
0407:            private static final byte[] infoBegin = "info".getBytes();
0408:
0409:            /** Author tag. */
0410:            private static final byte[] metaAuthor = "author".getBytes();
0411:
0412:            /** Subject tag. */
0413:            private static final byte[] metaSubject = "subject".getBytes();
0414:
0415:            /** Keywords tag. */
0416:            private static final byte[] metaKeywords = "keywords".getBytes();
0417:
0418:            /** Title tag. */
0419:            private static final byte[] metaTitle = "title".getBytes();
0420:
0421:            /** Producer tag. */
0422:            private static final byte[] metaProducer = "operator".getBytes();
0423:
0424:            /** Creation Date tag. */
0425:            private static final byte[] metaCreationDate = "creationdate"
0426:                    .getBytes();
0427:
0428:            /** Year tag. */
0429:            private static final byte[] year = "yr".getBytes();
0430:
0431:            /** Month tag. */
0432:            private static final byte[] month = "mo".getBytes();
0433:
0434:            /** Day tag. */
0435:            private static final byte[] day = "dy".getBytes();
0436:
0437:            /** Hour tag. */
0438:            private static final byte[] hour = "hr".getBytes();
0439:
0440:            /** Minute tag. */
0441:            private static final byte[] minute = "min".getBytes();
0442:
0443:            /** Second tag. */
0444:            private static final byte[] second = "sec".getBytes();
0445:
0446:            /** Start superscript. */
0447:            private static final byte[] startSuper = "super".getBytes();
0448:
0449:            /** Start subscript. */
0450:            private static final byte[] startSub = "sub".getBytes();
0451:
0452:            /** End super/sub script. */
0453:            private static final byte[] endSuperSub = "nosupersub".getBytes();
0454:
0455:            /**
0456:             * Header / Footer
0457:             */
0458:
0459:            /** Title Page tag */
0460:            private static final byte[] titlePage = "titlepg".getBytes();
0461:
0462:            /** Facing pages tag */
0463:            private static final byte[] facingPages = "facingp".getBytes();
0464:
0465:            /** Begin header group tag. */
0466:            private static final byte[] headerBegin = "header".getBytes();
0467:
0468:            /** Begin footer group tag. */
0469:            private static final byte[] footerBegin = "footer".getBytes();
0470:
0471:            // header footer 'left', 'right', 'first'
0472:            private static final byte[] headerlBegin = "headerl".getBytes();
0473:
0474:            private static final byte[] footerlBegin = "footerl".getBytes();
0475:
0476:            private static final byte[] headerrBegin = "headerr".getBytes();
0477:
0478:            private static final byte[] footerrBegin = "footerr".getBytes();
0479:
0480:            private static final byte[] headerfBegin = "headerf".getBytes();
0481:
0482:            private static final byte[] footerfBegin = "footerf".getBytes();
0483:
0484:            /**
0485:             * Paper Properties
0486:             */
0487:
0488:            /** Paper width tag. */
0489:            private static final byte[] rtfPaperWidth = "paperw".getBytes();
0490:
0491:            /** Paper height tag. */
0492:            private static final byte[] rtfPaperHeight = "paperh".getBytes();
0493:
0494:            /** Margin left tag. */
0495:            private static final byte[] rtfMarginLeft = "margl".getBytes();
0496:
0497:            /** Margin right tag. */
0498:            private static final byte[] rtfMarginRight = "margr".getBytes();
0499:
0500:            /** Margin top tag. */
0501:            private static final byte[] rtfMarginTop = "margt".getBytes();
0502:
0503:            /** Margin bottom tag. */
0504:            private static final byte[] rtfMarginBottom = "margb".getBytes();
0505:
0506:            /** New Page tag. */
0507:            private static final byte[] newPage = "page".getBytes();
0508:
0509:            /** Document Landscape tag 1. */
0510:            private static final byte[] landscapeTag1 = "landscape".getBytes();
0511:
0512:            /** Document Landscape tag 2. */
0513:            private static final byte[] landscapeTag2 = "lndscpsxn".getBytes();
0514:
0515:            /**
0516:             * Annotations
0517:             */
0518:
0519:            /** Annotation ID tag. */
0520:            private static final byte[] annotationID = "atnid".getBytes();
0521:
0522:            /** Annotation Author tag. */
0523:            private static final byte[] annotationAuthor = "atnauthor"
0524:                    .getBytes();
0525:
0526:            /** Annotation text tag. */
0527:            private static final byte[] annotation = "annotation".getBytes();
0528:
0529:            /**
0530:             * Images
0531:             */
0532:
0533:            /** Begin the main Picture group tag */
0534:            private static final byte[] pictureGroup = "shppict".getBytes();
0535:
0536:            /** Begin the picture tag */
0537:            private static final byte[] picture = "pict".getBytes();
0538:
0539:            /** PNG Image */
0540:            private static final byte[] picturePNG = "pngblip".getBytes();
0541:
0542:            /** JPEG Image */
0543:            private static final byte[] pictureJPEG = "jpegblip".getBytes();
0544:
0545:            /** BMP Image */
0546:            private static final byte[] pictureBMP = "dibitmap0".getBytes();
0547:
0548:            /** WMF Image */
0549:            private static final byte[] pictureWMF = "wmetafile8".getBytes();
0550:
0551:            /** Picture width */
0552:            private static final byte[] pictureWidth = "picw".getBytes();
0553:
0554:            /** Picture height */
0555:            private static final byte[] pictureHeight = "pich".getBytes();
0556:
0557:            /** Picture scale horizontal percent */
0558:            private static final byte[] pictureScaleX = "picscalex".getBytes();
0559:
0560:            /** Picture scale vertical percent */
0561:            private static final byte[] pictureScaleY = "picscaley".getBytes();
0562:
0563:            /**
0564:             * Fields (for page numbering)
0565:             */
0566:
0567:            /** Begin field tag */
0568:            protected static final byte[] field = "field".getBytes();
0569:
0570:            /** Content fo the field */
0571:            protected static final byte[] fieldContent = "fldinst".getBytes();
0572:
0573:            /** PAGE numbers */
0574:            protected static final byte[] fieldPage = "PAGE".getBytes();
0575:
0576:            /** HYPERLINK field */
0577:            protected static final byte[] fieldHyperlink = "HYPERLINK"
0578:                    .getBytes();
0579:
0580:            /** Last page number (not used) */
0581:            protected static final byte[] fieldDisplay = "fldrslt".getBytes();
0582:
0583:            /** Class variables */
0584:
0585:            /**
0586:             * Because of the way RTF works and the way itext works, the text has to be
0587:             * stored and is only written to the actual OutputStream at the end.
0588:             */
0589:
0590:            /** This <code>ArrayList</code> contains all fonts used in the document. */
0591:            private ArrayList fontList = new ArrayList();
0592:
0593:            /** This <code>ArrayList</code> contains all colours used in the document. */
0594:            private ArrayList colorList = new ArrayList();
0595:
0596:            /** This <code>ByteArrayOutputStream</code> contains the main body of the document. */
0597:            private ByteArrayOutputStream content = null;
0598:
0599:            /** This <code>ByteArrayOutputStream</code> contains the information group. */
0600:            private ByteArrayOutputStream info = null;
0601:
0602:            /** This <code>ByteArrayOutputStream</code> contains the list table. */
0603:            private ByteArrayOutputStream listtable = null;
0604:
0605:            /** This <code>ByteArrayOutputStream</code> contains the list override table. */
0606:            private ByteArrayOutputStream listoverride = null;
0607:
0608:            /** Document header. */
0609:            private HeaderFooter header = null;
0610:
0611:            /** Document footer. */
0612:            private HeaderFooter footer = null;
0613:
0614:            /** Left margin. */
0615:            private int marginLeft = 1800;
0616:
0617:            /** Right margin. */
0618:            private int marginRight = 1800;
0619:
0620:            /** Top margin. */
0621:            private int marginTop = 1440;
0622:
0623:            /** Bottom margin. */
0624:            private int marginBottom = 1440;
0625:
0626:            /** Page width. */
0627:            private int pageWidth = 11906;
0628:
0629:            /** Page height. */
0630:            private int pageHeight = 16838;
0631:
0632:            /** Factor to use when converting. */
0633:            public final static double TWIPSFACTOR = 20;//20.57140;
0634:
0635:            /** Current list ID. */
0636:            private int currentListID = 1;
0637:
0638:            /** List of current Lists. */
0639:            private ArrayList listIds = null;
0640:
0641:            /** Current List Level. */
0642:            private int listLevel = 0;
0643:
0644:            /** Current maximum List Level. */
0645:            private int maxListLevel = 0;
0646:
0647:            /** Write a TOC */
0648:            private boolean writeTOC = false;
0649:
0650:            /** Special title page */
0651:            private boolean hasTitlePage = false;
0652:
0653:            /** Currently writing either Header or Footer */
0654:            private boolean inHeaderFooter = false;
0655:
0656:            /** Currently writing a Table */
0657:            private boolean inTable = false;
0658:
0659:            /** Landscape or Portrait Document */
0660:            private boolean landscape = false;
0661:
0662:            /** Protected Constructor */
0663:
0664:            /**
0665:             * Constructs a <CODE>RtfWriter</CODE>.
0666:             *
0667:             * @param doc         The <CODE>Document</CODE> that is to be written as RTF
0668:             * @param os          The <CODE>OutputStream</CODE> the writer has to write to.
0669:             */
0670:
0671:            protected RtfWriter(Document doc, OutputStream os) {
0672:                super (doc, os);
0673:                document.addDocListener(this );
0674:                initDefaults();
0675:            }
0676:
0677:            /** Public functions special to the RtfWriter */
0678:
0679:            /**
0680:             * This method controls whether TOC entries are automatically generated
0681:             *
0682:             * @param writeTOC    boolean value indicating whether a TOC is to be generated
0683:             */
0684:            public void setGenerateTOCEntries(boolean writeTOC) {
0685:                this .writeTOC = writeTOC;
0686:            }
0687:
0688:            /**
0689:             * Gets the current setting of writeTOC
0690:             *
0691:             * @return    boolean value indicating whether a TOC is being generated
0692:             */
0693:            public boolean getGeneratingTOCEntries() {
0694:                return writeTOC;
0695:            }
0696:
0697:            /**
0698:             * This method controls whether the first page is a title page
0699:             *
0700:             * @param hasTitlePage    boolean value indicating whether the first page is a title page
0701:             */
0702:            public void setHasTitlePage(boolean hasTitlePage) {
0703:                this .hasTitlePage = hasTitlePage;
0704:            }
0705:
0706:            /**
0707:             * Gets the current setting of hasTitlePage
0708:             *
0709:             * @return    boolean value indicating whether the first page is a title page
0710:             */
0711:            public boolean getHasTitlePage() {
0712:                return hasTitlePage;
0713:            }
0714:
0715:            /**
0716:             * Explicitly sets the page format to use.
0717:             * Otherwise the RtfWriter will try to guess the format by comparing pagewidth and pageheight
0718:             *
0719:             * @param landscape boolean value indicating whether we are using landscape format or not
0720:             */
0721:            public void setLandscape(boolean landscape) {
0722:                this .landscape = landscape;
0723:            }
0724:
0725:            /**
0726:             * Returns the current landscape setting
0727:             *
0728:             * @return boolean value indicating the current page format
0729:             */
0730:            public boolean getLandscape() {
0731:                return landscape;
0732:            }
0733:
0734:            /** Public functions from the DocWriter Interface */
0735:
0736:            /**
0737:             * Gets an instance of the <CODE>RtfWriter</CODE>.
0738:             *
0739:             * @param document    The <CODE>Document</CODE> that has to be written
0740:             * @param os  The <CODE>OutputStream</CODE> the writer has to write to.
0741:             * @return    a new <CODE>RtfWriter</CODE>
0742:             */
0743:            public static RtfWriter getInstance(Document document,
0744:                    OutputStream os) {
0745:                return new RtfWriter(document, os);
0746:            }
0747:
0748:            /**
0749:             * Signals that the <CODE>Document</CODE> was closed and that no other
0750:             * <CODE>Elements</CODE> will be added.
0751:             * <p>
0752:             * The content of the font table, color table, information group, content, header, footer are merged into the final
0753:             * <code>OutputStream</code>
0754:             */
0755:            public void close() {
0756:                if (open) {
0757:                    writeDocument();
0758:                    super .close();
0759:                }
0760:            }
0761:
0762:            /**
0763:             * Adds the footer to the bottom of the <CODE>Document</CODE>.
0764:             * @param footer
0765:             */
0766:            public void setFooter(HeaderFooter footer) {
0767:                this .footer = footer;
0768:                processHeaderFooter(this .footer);
0769:            }
0770:
0771:            /**
0772:             * Adds the header to the top of the <CODE>Document</CODE>.
0773:             * @param header
0774:             */
0775:            public void setHeader(HeaderFooter header) {
0776:                this .header = header;
0777:                processHeaderFooter(this .header);
0778:            }
0779:
0780:            /**
0781:             * Resets the footer.
0782:             */
0783:            public void resetFooter() {
0784:                setFooter(null);
0785:            }
0786:
0787:            /**
0788:             * Resets the header.
0789:             */
0790:            public void resetHeader() {
0791:                setHeader(null);
0792:            }
0793:
0794:            /**
0795:             * Tells the <code>RtfWriter</code> that a new page is to be begun.
0796:             *
0797:             * @return <code>true</code> if a new Page was begun.
0798:             * @throws DocumentException if the Document was not open or had been closed.
0799:             */
0800:            public boolean newPage() {
0801:                try {
0802:                    content.write(escape);
0803:                    content.write(newPage);
0804:                    content.write(escape);
0805:                    content.write(paragraph);
0806:                } catch (IOException e) {
0807:                    throw new ExceptionConverter(e);
0808:                }
0809:                return true;
0810:            }
0811:
0812:            /**
0813:             * Sets the page margins
0814:             *
0815:             * @param marginLeft The left margin
0816:             * @param marginRight The right margin
0817:             * @param marginTop The top margin
0818:             * @param marginBottom The bottom margin
0819:             *
0820:             * @return <code>true</code> if the page margins were set.
0821:             */
0822:            public boolean setMargins(float marginLeft, float marginRight,
0823:                    float marginTop, float marginBottom) {
0824:                this .marginLeft = (int) (marginLeft * TWIPSFACTOR);
0825:                this .marginRight = (int) (marginRight * TWIPSFACTOR);
0826:                this .marginTop = (int) (marginTop * TWIPSFACTOR);
0827:                this .marginBottom = (int) (marginBottom * TWIPSFACTOR);
0828:                return true;
0829:            }
0830:
0831:            /**
0832:             * Sets the page size
0833:             *
0834:             * @param pageSize A <code>Rectangle</code> specifying the page size
0835:             *
0836:             * @return <code>true</code> if the page size was set
0837:             */
0838:            public boolean setPageSize(Rectangle pageSize) {
0839:                if (!parseFormat(pageSize, false)) {
0840:                    pageWidth = (int) (pageSize.getWidth() * TWIPSFACTOR);
0841:                    pageHeight = (int) (pageSize.getHeight() * TWIPSFACTOR);
0842:                    landscape = pageWidth > pageHeight;
0843:                }
0844:                return true;
0845:            }
0846:
0847:            /**
0848:             * Write the table of contents.
0849:             *
0850:             * @param tocTitle The title that will be displayed above the TOC
0851:             * @param titleFont The <code>Font</code> that will be used for the tocTitle
0852:             * @param showTOCasEntry Set this to true if you want the TOC to appear as an entry in the TOC
0853:             * @param showTOCEntryFont Use this <code>Font</code> to specify what Font to use when showTOCasEntry is true
0854:             *
0855:             * @return <code>true</code> if the TOC was added.
0856:             */
0857:            public boolean writeTOC(String tocTitle, Font titleFont,
0858:                    boolean showTOCasEntry, Font showTOCEntryFont) {
0859:                try {
0860:                    RtfTOC toc = new RtfTOC(tocTitle, titleFont);
0861:                    if (showTOCasEntry) {
0862:                        toc.addTOCAsTOCEntry(tocTitle, showTOCEntryFont);
0863:                    }
0864:                    add(new Paragraph(toc));
0865:                } catch (DocumentException de) {
0866:                    return false;
0867:                }
0868:                return true;
0869:            }
0870:
0871:            /**
0872:             * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
0873:             * 
0874:             * @param element A high level object to add
0875:             * @return    <CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
0876:             * @throws    DocumentException   if a document isn't open yet, or has been closed
0877:             */
0878:            public boolean add(Element element) throws DocumentException {
0879:                if (pause) {
0880:                    return false;
0881:                }
0882:                return addElement(element, content);
0883:            }
0884:
0885:            /** Private functions */
0886:
0887:            /**
0888:             * Adds an <CODE>Element</CODE> to the <CODE>Document</CODE>.
0889:             * @param element the high level element to add
0890:             * @param out the outputstream to which the RTF data is sent
0891:             * @return    <CODE>true</CODE> if the element was added, <CODE>false</CODE> if not.
0892:             * @throws    DocumentException   if a document isn't open yet, or has been closed
0893:             */
0894:            protected boolean addElement(Element element,
0895:                    ByteArrayOutputStream out) throws DocumentException {
0896:                try {
0897:                    switch (element.type()) {
0898:                    case Element.CHUNK:
0899:                        writeChunk((Chunk) element, out);
0900:                        break;
0901:                    case Element.PARAGRAPH:
0902:                        writeParagraph((Paragraph) element, out);
0903:                        break;
0904:                    case Element.ANCHOR:
0905:                        writeAnchor((Anchor) element, out);
0906:                        break;
0907:                    case Element.PHRASE:
0908:                        writePhrase((Phrase) element, out);
0909:                        break;
0910:                    case Element.CHAPTER:
0911:                    case Element.SECTION:
0912:                        writeSection((Section) element, out);
0913:                        break;
0914:                    case Element.LIST:
0915:                        writeList((com.lowagie.text.List) element, out);
0916:                        break;
0917:                    case Element.TABLE:
0918:                        try {
0919:                            writeTable((Table) element, out);
0920:                        } catch (ClassCastException cce) {
0921:                            writeTable(((SimpleTable) element).createTable(),
0922:                                    out);
0923:                        }
0924:                        break;
0925:                    case Element.ANNOTATION:
0926:                        writeAnnotation((Annotation) element, out);
0927:                        break;
0928:                    case Element.IMGRAW:
0929:                    case Element.IMGTEMPLATE:
0930:                    case Element.JPEG:
0931:                        Image img = (Image) element;
0932:                        writeImage(img, out);
0933:                        break;
0934:
0935:                    case Element.AUTHOR:
0936:                        writeMeta(metaAuthor, (Meta) element);
0937:                        break;
0938:                    case Element.SUBJECT:
0939:                        writeMeta(metaSubject, (Meta) element);
0940:                        break;
0941:                    case Element.KEYWORDS:
0942:                        writeMeta(metaKeywords, (Meta) element);
0943:                        break;
0944:                    case Element.TITLE:
0945:                        writeMeta(metaTitle, (Meta) element);
0946:                        break;
0947:                    case Element.PRODUCER:
0948:                        writeMeta(metaProducer, (Meta) element);
0949:                        break;
0950:                    case Element.CREATIONDATE:
0951:                        writeMeta(metaCreationDate, (Meta) element);
0952:                        break;
0953:                    }
0954:                } catch (IOException e) {
0955:                    return false;
0956:                }
0957:                return true;
0958:            }
0959:
0960:            /**
0961:             * Write the beginning of a new <code>Section</code>
0962:             *
0963:             * @param sectionElement The <code>Section</code> be written
0964:             * @param out The <code>ByteArrayOutputStream</code> to write to
0965:             *
0966:             * @throws IOException
0967:             * @throws DocumentException
0968:             */
0969:            private void writeSection(Section sectionElement,
0970:                    ByteArrayOutputStream out) throws IOException,
0971:                    DocumentException {
0972:                if (sectionElement.type() == Element.CHAPTER) {
0973:                    out.write(escape);
0974:                    out.write(sectionDefaults);
0975:                    writeSectionDefaults(out);
0976:                }
0977:                if (sectionElement.getTitle() != null) {
0978:                    if (writeTOC) {
0979:                        StringBuffer title = new StringBuffer("");
0980:                        for (ListIterator li = sectionElement.getTitle()
0981:                                .getChunks().listIterator(); li.hasNext();) {
0982:                            title.append(((Chunk) li.next()).getContent());
0983:                        }
0984:                        add(new RtfTOCEntry(title.toString(), sectionElement
0985:                                .getTitle().getFont()));
0986:                    } else {
0987:                        add(sectionElement.getTitle());
0988:                    }
0989:                    out.write(escape);
0990:                    out.write(paragraph);
0991:                }
0992:                sectionElement.process(this );
0993:                if (sectionElement.type() == Element.CHAPTER) {
0994:                    out.write(escape);
0995:                    out.write(section);
0996:                }
0997:                if (sectionElement.type() == Element.SECTION) {
0998:                    out.write(escape);
0999:                    out.write(paragraph);
1000:                }
1001:            }
1002:
1003:            /**
1004:             * Write the beginning of a new <code>Paragraph</code>
1005:             *
1006:             * @param paragraphElement The <code>Paragraph</code> to be written
1007:             * @param out The <code>ByteArrayOutputStream</code> to write to
1008:             *
1009:             * @throws IOException
1010:             */
1011:            private void writeParagraph(Paragraph paragraphElement,
1012:                    ByteArrayOutputStream out) throws IOException {
1013:                out.write(escape);
1014:                out.write(paragraphDefaults);
1015:                if (inTable) {
1016:                    out.write(escape);
1017:                    out.write(RtfCell.cellInTable);
1018:                }
1019:                switch (paragraphElement.getAlignment()) {
1020:                case Element.ALIGN_LEFT:
1021:                    out.write(escape);
1022:                    out.write(alignLeft);
1023:                    break;
1024:                case Element.ALIGN_RIGHT:
1025:                    out.write(escape);
1026:                    out.write(alignRight);
1027:                    break;
1028:                case Element.ALIGN_CENTER:
1029:                    out.write(escape);
1030:                    out.write(alignCenter);
1031:                    break;
1032:                case Element.ALIGN_JUSTIFIED:
1033:                case Element.ALIGN_JUSTIFIED_ALL:
1034:                    out.write(escape);
1035:                    out.write(alignJustify);
1036:                    break;
1037:                }
1038:                out.write(escape);
1039:                out.write(listIndent);
1040:                writeInt(
1041:                        out,
1042:                        (int) (paragraphElement.getIndentationLeft() * TWIPSFACTOR));
1043:                out.write(escape);
1044:                out.write(rightIndent);
1045:                writeInt(
1046:                        out,
1047:                        (int) (paragraphElement.getIndentationRight() * TWIPSFACTOR));
1048:                Iterator chunks = paragraphElement.getChunks().iterator();
1049:                while (chunks.hasNext()) {
1050:                    Chunk ch = (Chunk) chunks.next();
1051:                    ch.setFont(paragraphElement.getFont().difference(
1052:                            ch.getFont()));
1053:                }
1054:                ByteArrayOutputStream save = content;
1055:                content = out;
1056:                paragraphElement.process(this );
1057:                content = save;
1058:                if (!inTable) {
1059:                    out.write(escape);
1060:                    out.write(paragraph);
1061:                }
1062:            }
1063:
1064:            /**
1065:             * Write a <code>Phrase</code>.
1066:             *
1067:             * @param phrase  The <code>Phrase</code> item to be written
1068:             * @param out     The <code>ByteArrayOutputStream</code> to write to
1069:             *
1070:             * @throws IOException
1071:             */
1072:            private void writePhrase(Phrase phrase, ByteArrayOutputStream out)
1073:                    throws IOException {
1074:                out.write(escape);
1075:                out.write(paragraphDefaults);
1076:                if (inTable) {
1077:                    out.write(escape);
1078:                    out.write(RtfCell.cellInTable);
1079:                }
1080:                Iterator chunks = phrase.getChunks().iterator();
1081:                while (chunks.hasNext()) {
1082:                    Chunk ch = (Chunk) chunks.next();
1083:                    ch.setFont(phrase.getFont().difference(ch.getFont()));
1084:                }
1085:                ByteArrayOutputStream save = content;
1086:                content = out;
1087:                phrase.process(this );
1088:                content = save;
1089:            }
1090:
1091:            /**
1092:             * Write an <code>Anchor</code>. Anchors are treated like Phrases.
1093:             *
1094:             * @param anchor  The <code>Chunk</code> item to be written
1095:             * @param out     The <code>ByteArrayOutputStream</code> to write to
1096:             *
1097:             * @throws IOException
1098:             */
1099:            private void writeAnchor(Anchor anchor, ByteArrayOutputStream out)
1100:                    throws IOException {
1101:                if (anchor.getUrl() != null) {
1102:                    out.write(openGroup);
1103:                    out.write(escape);
1104:                    out.write(field);
1105:                    out.write(openGroup);
1106:                    out.write(extendedEscape);
1107:                    out.write(fieldContent);
1108:                    out.write(openGroup);
1109:                    out.write(fieldHyperlink);
1110:                    out.write(delimiter);
1111:                    out.write(anchor.getUrl().toString().getBytes());
1112:                    out.write(closeGroup);
1113:                    out.write(closeGroup);
1114:                    out.write(openGroup);
1115:                    out.write(escape);
1116:                    out.write(fieldDisplay);
1117:                    out.write(delimiter);
1118:                    writePhrase(anchor, out);
1119:                    out.write(closeGroup);
1120:                    out.write(closeGroup);
1121:                } else {
1122:                    writePhrase(anchor, out);
1123:                }
1124:            }
1125:
1126:            /**
1127:             * Write a <code>Chunk</code> and all its font properties.
1128:             *
1129:             * @param chunk The <code>Chunk</code> item to be written
1130:             * @param out The <code>ByteArrayOutputStream</code> to write to
1131:             *
1132:             * @throws IOException
1133:             * @throws DocumentException
1134:             */
1135:            private void writeChunk(Chunk chunk, ByteArrayOutputStream out)
1136:                    throws IOException, DocumentException {
1137:                if (chunk instanceof  RtfField) {
1138:                    ((RtfField) chunk).write(this , out);
1139:                } else {
1140:                    if (chunk.getImage() != null) {
1141:                        writeImage(chunk.getImage(), out);
1142:                    } else {
1143:                        writeInitialFontSignature(out, chunk);
1144:                        out.write(filterSpecialChar(chunk.getContent(), false)
1145:                                .getBytes());
1146:                        writeFinishingFontSignature(out, chunk);
1147:                    }
1148:                }
1149:            }
1150:
1151:            protected void writeInitialFontSignature(OutputStream out,
1152:                    Chunk chunk) throws IOException {
1153:                Font font = chunk.getFont();
1154:
1155:                out.write(escape);
1156:                out.write(fontNumber);
1157:                if (!font.getFamilyname().equalsIgnoreCase("unknown")) {
1158:                    writeInt(out, addFont(font));
1159:                } else {
1160:                    writeInt(out, 0);
1161:                }
1162:                out.write(escape);
1163:                out.write(fontSize);
1164:                if (font.getSize() > 0) {
1165:                    writeInt(out, (int) (font.getSize() * 2));
1166:                } else {
1167:                    writeInt(out, 20);
1168:                }
1169:                out.write(escape);
1170:                out.write(fontColor);
1171:                writeInt(out, addColor(font.getColor()));
1172:                if (font.isBold()) {
1173:                    out.write(escape);
1174:                    out.write(bold);
1175:                }
1176:                if (font.isItalic()) {
1177:                    out.write(escape);
1178:                    out.write(italic);
1179:                }
1180:                if (font.isUnderlined()) {
1181:                    out.write(escape);
1182:                    out.write(underline);
1183:                }
1184:                if (font.isStrikethru()) {
1185:                    out.write(escape);
1186:                    out.write(strikethrough);
1187:                }
1188:
1189:                /*
1190:                 * Superscript / Subscript added by Scott Dietrich (sdietrich@emlab.com)
1191:                 */
1192:                if (chunk.getAttributes() != null) {
1193:                    Float f = (Float) chunk.getAttributes().get(
1194:                            Chunk.SUBSUPSCRIPT);
1195:                    if (f != null)
1196:                        if (f.floatValue() > 0) {
1197:                            out.write(escape);
1198:                            out.write(startSuper);
1199:                        } else if (f.floatValue() < 0) {
1200:                            out.write(escape);
1201:                            out.write(startSub);
1202:                        }
1203:                }
1204:
1205:                out.write(delimiter);
1206:            }
1207:
1208:            protected void writeFinishingFontSignature(OutputStream out,
1209:                    Chunk chunk) throws IOException {
1210:                Font font = chunk.getFont();
1211:
1212:                if (font.isBold()) {
1213:                    out.write(escape);
1214:                    out.write(bold);
1215:                    writeInt(out, 0);
1216:                }
1217:                if (font.isItalic()) {
1218:                    out.write(escape);
1219:                    out.write(italic);
1220:                    writeInt(out, 0);
1221:                }
1222:                if (font.isUnderlined()) {
1223:                    out.write(escape);
1224:                    out.write(underline);
1225:                    writeInt(out, 0);
1226:                }
1227:                if (font.isStrikethru()) {
1228:                    out.write(escape);
1229:                    out.write(strikethrough);
1230:                    writeInt(out, 0);
1231:                }
1232:
1233:                /*
1234:                 * Superscript / Subscript added by Scott Dietrich (sdietrich@emlab.com)
1235:                 */
1236:                if (chunk.getAttributes() != null) {
1237:                    Float f = (Float) chunk.getAttributes().get(
1238:                            Chunk.SUBSUPSCRIPT);
1239:                    if (f != null)
1240:                        if (f.floatValue() != 0) {
1241:                            out.write(escape);
1242:                            out.write(endSuperSub);
1243:                        }
1244:                }
1245:            }
1246:
1247:            /**
1248:             * Write a <code>ListItem</code>
1249:             *
1250:             * @param listItem The <code>ListItem</code> to be written
1251:             * @param out The <code>ByteArrayOutputStream</code> to write to
1252:             *
1253:             * @throws IOException
1254:             * @throws DocumentException
1255:             */
1256:            private void writeListElement(ListItem listItem,
1257:                    ByteArrayOutputStream out) throws IOException,
1258:                    DocumentException {
1259:                Iterator chunks = listItem.getChunks().iterator();
1260:                while (chunks.hasNext()) {
1261:                    Chunk ch = (Chunk) chunks.next();
1262:                    addElement(ch, out);
1263:                }
1264:                out.write(escape);
1265:                out.write(paragraph);
1266:            }
1267:
1268:            /**
1269:             * Write a <code>List</code>
1270:             *
1271:             * @param list The <code>List</code> to be written
1272:             * @param out The <code>ByteArrayOutputStream</code> to write to
1273:             *
1274:             * @throws    IOException
1275:             * @throws    DocumentException
1276:             */
1277:            private void writeList(com.lowagie.text.List list,
1278:                    ByteArrayOutputStream out) throws IOException,
1279:                    DocumentException {
1280:                int type = 0;
1281:                int align = 0;
1282:                int fontNr = addFont(new Font(Font.SYMBOL, 10, Font.NORMAL,
1283:                        new Color(0, 0, 0)));
1284:                if (!list.isNumbered())
1285:                    type = 23;
1286:                if (listLevel == 0) {
1287:                    maxListLevel = 0;
1288:                    listtable.write(openGroup);
1289:                    listtable.write(escape);
1290:                    listtable.write(listDefinition);
1291:                    int i = getRandomInt();
1292:                    listtable.write(escape);
1293:                    listtable.write(listTemplateID);
1294:                    writeInt(listtable, i);
1295:                    listtable.write(escape);
1296:                    listtable.write(hybridList);
1297:                    listtable.write((byte) '\n');
1298:                }
1299:                if (listLevel >= maxListLevel) {
1300:                    maxListLevel++;
1301:                    listtable.write(openGroup);
1302:                    listtable.write(escape);
1303:                    listtable.write(listLevelDefinition);
1304:                    listtable.write(escape);
1305:                    listtable.write(listLevelTypeOld);
1306:                    writeInt(listtable, type);
1307:                    listtable.write(escape);
1308:                    listtable.write(listLevelTypeNew);
1309:                    writeInt(listtable, type);
1310:                    listtable.write(escape);
1311:                    listtable.write(listLevelAlignOld);
1312:                    writeInt(listtable, align);
1313:                    listtable.write(escape);
1314:                    listtable.write(listLevelAlignNew);
1315:                    writeInt(listtable, align);
1316:                    listtable.write(escape);
1317:                    listtable.write(listLevelStartAt);
1318:                    writeInt(listtable, 1);
1319:                    listtable.write(openGroup);
1320:                    listtable.write(escape);
1321:                    listtable.write(listLevelTextDefinition);
1322:                    listtable.write(escape);
1323:                    listtable.write(listLevelTextLength);
1324:                    if (list.isNumbered()) {
1325:                        writeInt(listtable, 2);
1326:                    } else {
1327:                        writeInt(listtable, 1);
1328:                    }
1329:                    listtable.write(escape);
1330:                    if (list.isNumbered()) {
1331:                        listtable.write(listLevelTextStyleNumbers);
1332:                    } else {
1333:                        listtable.write(listLevelTextStyleBullet);
1334:                    }
1335:                    listtable.write(commaDelimiter);
1336:                    listtable.write(closeGroup);
1337:                    listtable.write(openGroup);
1338:                    listtable.write(escape);
1339:                    listtable.write(listLevelNumbersDefinition);
1340:                    if (list.isNumbered()) {
1341:                        listtable.write(delimiter);
1342:                        listtable.write(listLevelNumbers);
1343:                        writeInt(listtable, listLevel + 1);
1344:                    }
1345:                    listtable.write(commaDelimiter);
1346:                    listtable.write(closeGroup);
1347:                    if (!list.isNumbered()) {
1348:                        listtable.write(escape);
1349:                        listtable.write(fontNumber);
1350:                        writeInt(listtable, fontNr);
1351:                    }
1352:                    listtable.write(escape);
1353:                    listtable.write(firstIndent);
1354:                    writeInt(listtable, (int) (list.getIndentationLeft()
1355:                            * TWIPSFACTOR * -1));
1356:                    listtable.write(escape);
1357:                    listtable.write(listIndent);
1358:                    writeInt(listtable,
1359:                            (int) ((list.getIndentationLeft() + list
1360:                                    .getSymbolIndent()) * TWIPSFACTOR));
1361:                    listtable.write(escape);
1362:                    listtable.write(rightIndent);
1363:                    writeInt(listtable,
1364:                            (int) (list.getIndentationRight() * TWIPSFACTOR));
1365:                    listtable.write(escape);
1366:                    listtable.write(tabStop);
1367:                    writeInt(listtable,
1368:                            (int) (list.getSymbolIndent() * TWIPSFACTOR));
1369:                    listtable.write(closeGroup);
1370:                    listtable.write((byte) '\n');
1371:                }
1372:                // Actual List Begin in Content
1373:                out.write(escape);
1374:                out.write(paragraphDefaults);
1375:                out.write(escape);
1376:                out.write(alignLeft);
1377:                out.write(escape);
1378:                out.write(firstIndent);
1379:                writeInt(out,
1380:                        (int) (list.getIndentationLeft() * TWIPSFACTOR * -1));
1381:                out.write(escape);
1382:                out.write(listIndent);
1383:                writeInt(out, (int) ((list.getIndentationLeft() + list
1384:                        .getSymbolIndent()) * TWIPSFACTOR));
1385:                out.write(escape);
1386:                out.write(rightIndent);
1387:                writeInt(out, (int) (list.getIndentationRight() * TWIPSFACTOR));
1388:                out.write(escape);
1389:                out.write(fontSize);
1390:                writeInt(out, 20);
1391:                out.write(escape);
1392:                out.write(listBegin);
1393:                writeInt(out, currentListID);
1394:                if (listLevel > 0) {
1395:                    out.write(escape);
1396:                    out.write(listCurrentLevel);
1397:                    writeInt(out, listLevel);
1398:                }
1399:                out.write(openGroup);
1400:                ListIterator listItems = list.getItems().listIterator();
1401:                Element listElem;
1402:                int count = 1;
1403:                while (listItems.hasNext()) {
1404:                    listElem = (Element) listItems.next();
1405:                    if (listElem.type() == Element.CHUNK) {
1406:                        listElem = new ListItem((Chunk) listElem);
1407:                    }
1408:                    if (listElem.type() == Element.LISTITEM) {
1409:                        out.write(openGroup);
1410:                        out.write(escape);
1411:                        out.write(listTextOld);
1412:                        out.write(escape);
1413:                        out.write(paragraphDefaults);
1414:                        out.write(escape);
1415:                        out.write(fontNumber);
1416:                        if (list.isNumbered()) {
1417:                            writeInt(out, addFont(new Font(Font.TIMES_ROMAN,
1418:                                    Font.NORMAL, 10, new Color(0, 0, 0))));
1419:                        } else {
1420:                            writeInt(out, fontNr);
1421:                        }
1422:                        out.write(escape);
1423:                        out.write(firstIndent);
1424:                        writeInt(out, (int) (list.getIndentationLeft()
1425:                                * TWIPSFACTOR * -1));
1426:                        out.write(escape);
1427:                        out.write(listIndent);
1428:                        writeInt(out, (int) ((list.getIndentationLeft() + list
1429:                                .getSymbolIndent()) * TWIPSFACTOR));
1430:                        out.write(escape);
1431:                        out.write(rightIndent);
1432:                        writeInt(
1433:                                out,
1434:                                (int) (list.getIndentationRight() * TWIPSFACTOR));
1435:                        out.write(delimiter);
1436:                        if (list.isNumbered()) {
1437:                            writeInt(out, count);
1438:                            out.write(".".getBytes());
1439:                        } else {
1440:                            out.write(escape);
1441:                            out.write(listBulletOld);
1442:                        }
1443:                        out.write(escape);
1444:                        out.write(tab);
1445:                        out.write(closeGroup);
1446:                        writeListElement((ListItem) listElem, out);
1447:                        count++;
1448:                    } else if (listElem.type() == Element.LIST) {
1449:                        listLevel++;
1450:                        writeList((com.lowagie.text.List) listElem, out);
1451:                        listLevel--;
1452:                        out.write(escape);
1453:                        out.write(paragraphDefaults);
1454:                        out.write(escape);
1455:                        out.write(alignLeft);
1456:                        out.write(escape);
1457:                        out.write(firstIndent);
1458:                        writeInt(out, (int) (list.getIndentationLeft()
1459:                                * TWIPSFACTOR * -1));
1460:                        out.write(escape);
1461:                        out.write(listIndent);
1462:                        writeInt(out, (int) ((list.getIndentationLeft() + list
1463:                                .getSymbolIndent()) * TWIPSFACTOR));
1464:                        out.write(escape);
1465:                        out.write(rightIndent);
1466:                        writeInt(
1467:                                out,
1468:                                (int) (list.getIndentationRight() * TWIPSFACTOR));
1469:                        out.write(escape);
1470:                        out.write(fontSize);
1471:                        writeInt(out, 20);
1472:                        out.write(escape);
1473:                        out.write(listBegin);
1474:                        writeInt(out, currentListID);
1475:                        if (listLevel > 0) {
1476:                            out.write(escape);
1477:                            out.write(listCurrentLevel);
1478:                            writeInt(out, listLevel);
1479:                        }
1480:                    }
1481:                    out.write((byte) '\n');
1482:                }
1483:                out.write(closeGroup);
1484:                if (listLevel == 0) {
1485:                    int i = getRandomInt();
1486:                    listtable.write(escape);
1487:                    listtable.write(listID);
1488:                    writeInt(listtable, i);
1489:                    listtable.write(closeGroup);
1490:                    listtable.write((byte) '\n');
1491:                    listoverride.write(openGroup);
1492:                    listoverride.write(escape);
1493:                    listoverride.write(listOverride);
1494:                    listoverride.write(escape);
1495:                    listoverride.write(listID);
1496:                    writeInt(listoverride, i);
1497:                    listoverride.write(escape);
1498:                    listoverride.write(listOverrideCount);
1499:                    writeInt(listoverride, 0);
1500:                    listoverride.write(escape);
1501:                    listoverride.write(listBegin);
1502:                    writeInt(listoverride, currentListID);
1503:                    currentListID++;
1504:                    listoverride.write(closeGroup);
1505:                    listoverride.write((byte) '\n');
1506:                }
1507:                out.write(escape);
1508:                out.write(paragraphDefaults);
1509:            }
1510:
1511:            /**
1512:             * Write a <code>Table</code>.
1513:             *
1514:             * @param table The <code>table</code> to be written
1515:             * @param out The <code>ByteArrayOutputStream</code> to write to
1516:             *
1517:             * Currently no nesting of tables is supported. If a cell contains anything but a Cell Object it is ignored.
1518:             *
1519:             * @throws IOException
1520:             * @throws DocumentException
1521:             */
1522:            private void writeTable(Table table, ByteArrayOutputStream out)
1523:                    throws IOException, DocumentException {
1524:                inTable = true;
1525:                table.complete();
1526:                RtfTable rtfTable = new RtfTable(this );
1527:                rtfTable.importTable(table, pageWidth - marginLeft
1528:                        - marginRight);
1529:                rtfTable.writeTable(out);
1530:                inTable = false;
1531:            }
1532:
1533:            /**
1534:             * Write an <code>Image</code>.
1535:             *
1536:             * @param image The <code>image</code> to be written
1537:             * @param out The <code>ByteArrayOutputStream</code> to write to
1538:             *
1539:             * At the moment only PNG and JPEG Images are supported.
1540:             *
1541:             * @throws IOException
1542:             * @throws DocumentException
1543:             */
1544:            private void writeImage(Image image, ByteArrayOutputStream out)
1545:                    throws IOException, DocumentException {
1546:                int type = image.getOriginalType();
1547:                if (!(type == Image.ORIGINAL_JPEG || type == Image.ORIGINAL_BMP
1548:                        || type == Image.ORIGINAL_PNG || type == Image.ORIGINAL_WMF))
1549:                    throw new DocumentException(
1550:                            "Only BMP, PNG, WMF and JPEG images are supported by the RTF Writer");
1551:                switch (image.getAlignment()) {
1552:                case Element.ALIGN_LEFT:
1553:                    out.write(escape);
1554:                    out.write(alignLeft);
1555:                    break;
1556:                case Element.ALIGN_RIGHT:
1557:                    out.write(escape);
1558:                    out.write(alignRight);
1559:                    break;
1560:                case Element.ALIGN_CENTER:
1561:                    out.write(escape);
1562:                    out.write(alignCenter);
1563:                    break;
1564:                case Element.ALIGN_JUSTIFIED:
1565:                    out.write(escape);
1566:                    out.write(alignJustify);
1567:                    break;
1568:                }
1569:                out.write(openGroup);
1570:                out.write(extendedEscape);
1571:                out.write(pictureGroup);
1572:                out.write(openGroup);
1573:                out.write(escape);
1574:                out.write(picture);
1575:                out.write(escape);
1576:                switch (type) {
1577:                case Image.ORIGINAL_JPEG:
1578:                    out.write(pictureJPEG);
1579:                    break;
1580:                case Image.ORIGINAL_PNG:
1581:                    out.write(picturePNG);
1582:                    break;
1583:                case Image.ORIGINAL_WMF:
1584:                case Image.ORIGINAL_BMP:
1585:                    out.write(pictureWMF);
1586:                    break;
1587:                }
1588:                out.write(escape);
1589:                out.write(pictureWidth);
1590:                writeInt(out, (int) (image.getPlainWidth() * TWIPSFACTOR));
1591:                out.write(escape);
1592:                out.write(pictureHeight);
1593:                writeInt(out, (int) (image.getPlainHeight() * TWIPSFACTOR));
1594:
1595:                // For some reason this messes up the intended image size. It makes it too big. Weird
1596:                //
1597:                //        out.write(escape);
1598:                //        out.write(pictureIntendedWidth);
1599:                //        writeInt(out, (int) (image.plainWidth() * twipsFactor));
1600:                //        out.write(escape);
1601:                //        out.write(pictureIntendedHeight);
1602:                //        writeInt(out, (int) (image.plainHeight() * twipsFactor));
1603:
1604:                if (image.getWidth() > 0) {
1605:                    out.write(escape);
1606:                    out.write(pictureScaleX);
1607:                    writeInt(out, (int) (100 / image.getWidth() * image
1608:                            .getPlainWidth()));
1609:                }
1610:                if (image.getHeight() > 0) {
1611:                    out.write(escape);
1612:                    out.write(pictureScaleY);
1613:                    writeInt(out, (int) (100 / image.getHeight() * image
1614:                            .getPlainHeight()));
1615:                }
1616:                out.write(delimiter);
1617:                InputStream imgIn;
1618:                if (type == Image.ORIGINAL_BMP) {
1619:                    imgIn = new ByteArrayInputStream(MetaDo.wrapBMP(image));
1620:                } else {
1621:                    if (image.getOriginalData() == null) {
1622:                        imgIn = image.getUrl().openStream();
1623:                    } else {
1624:                        imgIn = new ByteArrayInputStream(image
1625:                                .getOriginalData());
1626:                    }
1627:                    if (type == Image.ORIGINAL_WMF) { //remove the placeable header
1628:                        long skipLength = 22;
1629:                        while (skipLength > 0) {
1630:                            skipLength = skipLength - imgIn.skip(skipLength);
1631:                        }
1632:                    }
1633:                }
1634:                int buffer = -1;
1635:                int count = 0;
1636:                out.write((byte) '\n');
1637:                while ((buffer = imgIn.read()) != -1) {
1638:                    String helperStr = Integer.toHexString(buffer);
1639:                    if (helperStr.length() < 2)
1640:                        helperStr = "0" + helperStr;
1641:                    out.write(helperStr.getBytes());
1642:                    count++;
1643:                    if (count == 64) {
1644:                        out.write((byte) '\n');
1645:                        count = 0;
1646:                    }
1647:                }
1648:                imgIn.close();
1649:                out.write(closeGroup);
1650:                out.write(closeGroup);
1651:                out.write((byte) '\n');
1652:            }
1653:
1654:            /**
1655:             * Write an <code>Annotation</code>
1656:             *
1657:             * @param annotationElement The <code>Annotation</code> to be written
1658:             * @param out The <code>ByteArrayOutputStream</code> to write to
1659:             *
1660:             * @throws IOException
1661:             */
1662:            private void writeAnnotation(Annotation annotationElement,
1663:                    ByteArrayOutputStream out) throws IOException {
1664:                int id = getRandomInt();
1665:                out.write(openGroup);
1666:                out.write(extendedEscape);
1667:                out.write(annotationID);
1668:                out.write(delimiter);
1669:                writeInt(out, id);
1670:                out.write(closeGroup);
1671:                out.write(openGroup);
1672:                out.write(extendedEscape);
1673:                out.write(annotationAuthor);
1674:                out.write(delimiter);
1675:                out.write(annotationElement.title().getBytes());
1676:                out.write(closeGroup);
1677:                out.write(openGroup);
1678:                out.write(extendedEscape);
1679:                out.write(annotation);
1680:                out.write(escape);
1681:                out.write(paragraphDefaults);
1682:                out.write(delimiter);
1683:                out.write(annotationElement.content().getBytes());
1684:                out.write(closeGroup);
1685:            }
1686:
1687:            /**
1688:             * Add a <code>Meta</code> element. It is written to the Inforamtion Group
1689:             * and merged with the main <code>ByteArrayOutputStream</code> when the
1690:             * Document is closed.
1691:             *
1692:             * @param metaName The type of <code>Meta</code> element to be added
1693:             * @param meta The <code>Meta</code> element to be added
1694:             *
1695:             * Currently only the Meta Elements Author, Subject, Keywords, Title, Producer and CreationDate are supported.
1696:             *
1697:             * @throws IOException
1698:             */
1699:            private void writeMeta(byte[] metaName, Meta meta)
1700:                    throws IOException {
1701:                info.write(openGroup);
1702:                try {
1703:                    info.write(escape);
1704:                    info.write(metaName);
1705:                    info.write(delimiter);
1706:                    if (meta.type() == Meta.CREATIONDATE) {
1707:                        writeFormatedDateTime(meta.getContent());
1708:                    } else {
1709:                        info.write(meta.getContent().getBytes());
1710:                    }
1711:                } finally {
1712:                    info.write(closeGroup);
1713:                }
1714:            }
1715:
1716:            /**
1717:             * Writes a date. The date is formated <strong>Year, Month, Day, Hour, Minute, Second</strong>
1718:             *
1719:             * @param date The date to be written
1720:             *
1721:             * @throws IOException
1722:             */
1723:            private void writeFormatedDateTime(String date) throws IOException {
1724:                Calendar cal = Calendar.getInstance();
1725:                SimpleDateFormat sdf = new SimpleDateFormat(
1726:                        "EEE MMM dd HH:mm:ss zzz yyyy");
1727:                ParsePosition pp = new ParsePosition(0);
1728:                Date d = sdf.parse(date, pp);
1729:                if (d == null) {
1730:                    d = new Date();
1731:                }
1732:                cal.setTime(d);
1733:                info.write(escape);
1734:                info.write(year);
1735:                writeInt(info, cal.get(Calendar.YEAR));
1736:                info.write(escape);
1737:                info.write(month);
1738:                writeInt(info, cal.get(Calendar.MONTH));
1739:                info.write(escape);
1740:                info.write(day);
1741:                writeInt(info, cal.get(Calendar.DAY_OF_MONTH));
1742:                info.write(escape);
1743:                info.write(hour);
1744:                writeInt(info, cal.get(Calendar.HOUR_OF_DAY));
1745:                info.write(escape);
1746:                info.write(minute);
1747:                writeInt(info, cal.get(Calendar.MINUTE));
1748:                info.write(escape);
1749:                info.write(second);
1750:                writeInt(info, cal.get(Calendar.SECOND));
1751:            }
1752:
1753:            /**
1754:             * Add a new <code>Font</code> to the list of fonts. If the <code>Font</code>
1755:             * already exists in the list of fonts, then it is not added again.
1756:             *
1757:             * @param newFont The <code>Font</code> to be added
1758:             *
1759:             * @return The index of the <code>Font</code> in the font list
1760:             */
1761:            protected int addFont(Font newFont) {
1762:                int fn = -1;
1763:
1764:                for (int i = 0; i < fontList.size(); i++) {
1765:                    if (newFont.getFamilyname().equals(
1766:                            ((Font) fontList.get(i)).getFamilyname())) {
1767:                        fn = i;
1768:                    }
1769:                }
1770:                if (fn == -1) {
1771:                    fontList.add(newFont);
1772:                    return fontList.size() - 1;
1773:                }
1774:                return fn;
1775:            }
1776:
1777:            /**
1778:             * Add a new <code>Color</code> to the list of colours. If the <code>Color</code>
1779:             * already exists in the list of colours, then it is not added again.
1780:             *
1781:             * @param newColor The <code>Color</code> to be added
1782:             *
1783:             * @return The index of the <code>color</code> in the colour list
1784:             */
1785:            protected int addColor(Color newColor) {
1786:                int cn = 0;
1787:                if (newColor == null) {
1788:                    return cn;
1789:                }
1790:                cn = colorList.indexOf(newColor);
1791:                if (cn == -1) {
1792:                    colorList.add(newColor);
1793:                    return colorList.size() - 1;
1794:                }
1795:                return cn;
1796:            }
1797:
1798:            /**
1799:             * Merge all the different <code>ArrayList</code>s and <code>ByteArrayOutputStream</code>s
1800:             * to the final <code>ByteArrayOutputStream</code>
1801:             *
1802:             * @return <code>true</code> if all information was sucessfully written to the <code>ByteArrayOutputStream</code>
1803:             */
1804:            private boolean writeDocument() {
1805:                try {
1806:                    writeDocumentIntro();
1807:                    writeFontList();
1808:                    os.write((byte) '\n');
1809:                    writeColorList();
1810:                    os.write((byte) '\n');
1811:                    writeList();
1812:                    os.write((byte) '\n');
1813:                    writeInfoGroup();
1814:                    os.write((byte) '\n');
1815:                    writeDocumentFormat();
1816:                    os.write((byte) '\n');
1817:                    ByteArrayOutputStream hf = new ByteArrayOutputStream();
1818:                    writeSectionDefaults(hf);
1819:                    hf.writeTo(os);
1820:                    content.writeTo(os);
1821:                    os.write(closeGroup);
1822:                    return true;
1823:                } catch (IOException e) {
1824:                    System.err.println(e.getMessage());
1825:                    return false;
1826:                }
1827:
1828:            }
1829:
1830:            /** Write the Rich Text file settings
1831:             * @throws IOException
1832:             */
1833:            private void writeDocumentIntro() throws IOException {
1834:                os.write(openGroup);
1835:                os.write(escape);
1836:                os.write(docBegin);
1837:                os.write(escape);
1838:                os.write(ansi);
1839:                os.write(escape);
1840:                os.write(ansiCodepage);
1841:                writeInt(os, 1252);
1842:                os.write((byte) '\n');
1843:                os.write(escape);
1844:                os.write(defaultFont);
1845:                writeInt(os, 0);
1846:            }
1847:
1848:            /**
1849:             * Write the font list to the final <code>ByteArrayOutputStream</code>
1850:             * @throws IOException
1851:             */
1852:            private void writeFontList() throws IOException {
1853:                Font fnt;
1854:
1855:                os.write(openGroup);
1856:                os.write(escape);
1857:                os.write(fontTable);
1858:                for (int i = 0; i < fontList.size(); i++) {
1859:                    fnt = (Font) fontList.get(i);
1860:                    os.write(openGroup);
1861:                    os.write(escape);
1862:                    os.write(fontNumber);
1863:                    writeInt(os, i);
1864:                    os.write(escape);
1865:                    switch (Font.getFamilyIndex(fnt.getFamilyname())) {
1866:                    case Font.COURIER:
1867:                        os.write(fontModern);
1868:                        os.write(escape);
1869:                        os.write(fontCharset);
1870:                        writeInt(os, 0);
1871:                        os.write(delimiter);
1872:                        os.write(fontCourier);
1873:                        break;
1874:                    case Font.HELVETICA:
1875:                        os.write(fontSwiss);
1876:                        os.write(escape);
1877:                        os.write(fontCharset);
1878:                        writeInt(os, 0);
1879:                        os.write(delimiter);
1880:                        os.write(fontArial);
1881:                        break;
1882:                    case Font.SYMBOL:
1883:                        os.write(fontRoman);
1884:                        os.write(escape);
1885:                        os.write(fontCharset);
1886:                        writeInt(os, 2);
1887:                        os.write(delimiter);
1888:                        os.write(fontSymbol);
1889:                        break;
1890:                    case Font.TIMES_ROMAN:
1891:                        os.write(fontRoman);
1892:                        os.write(escape);
1893:                        os.write(fontCharset);
1894:                        writeInt(os, 0);
1895:                        os.write(delimiter);
1896:                        os.write(fontTimesNewRoman);
1897:                        break;
1898:                    case Font.ZAPFDINGBATS:
1899:                        os.write(fontTech);
1900:                        os.write(escape);
1901:                        os.write(fontCharset);
1902:                        writeInt(os, 0);
1903:                        os.write(delimiter);
1904:                        os.write(fontWindings);
1905:                        break;
1906:                    default:
1907:                        os.write(fontRoman);
1908:                        os.write(escape);
1909:                        os.write(fontCharset);
1910:                        writeInt(os, 0);
1911:                        os.write(delimiter);
1912:                        os.write(filterSpecialChar(fnt.getFamilyname(), true)
1913:                                .getBytes());
1914:                    }
1915:                    os.write(commaDelimiter);
1916:                    os.write(closeGroup);
1917:                }
1918:                os.write(closeGroup);
1919:            }
1920:
1921:            /**
1922:             * Write the colour list to the final <code>ByteArrayOutputStream</code>
1923:             * @throws IOException
1924:             */
1925:            private void writeColorList() throws IOException {
1926:                Color color = null;
1927:
1928:                os.write(openGroup);
1929:                os.write(escape);
1930:                os.write(colorTable);
1931:                for (int i = 0; i < colorList.size(); i++) {
1932:                    color = (Color) colorList.get(i);
1933:                    os.write(escape);
1934:                    os.write(colorRed);
1935:                    writeInt(os, color.getRed());
1936:                    os.write(escape);
1937:                    os.write(colorGreen);
1938:                    writeInt(os, color.getGreen());
1939:                    os.write(escape);
1940:                    os.write(colorBlue);
1941:                    writeInt(os, color.getBlue());
1942:                    os.write(commaDelimiter);
1943:                }
1944:                os.write(closeGroup);
1945:            }
1946:
1947:            /**
1948:             * Write the Information Group to the final <code>ByteArrayOutputStream</code>
1949:             * @throws IOException
1950:             */
1951:            private void writeInfoGroup() throws IOException {
1952:                os.write(openGroup);
1953:                os.write(escape);
1954:                os.write(infoBegin);
1955:                info.writeTo(os);
1956:                os.write(closeGroup);
1957:            }
1958:
1959:            /**
1960:             * Write the listtable and listoverridetable to the final <code>ByteArrayOutputStream</code>
1961:             * @throws IOException
1962:             */
1963:            private void writeList() throws IOException {
1964:                listtable.write(closeGroup);
1965:                listoverride.write(closeGroup);
1966:                listtable.writeTo(os);
1967:                os.write((byte) '\n');
1968:                listoverride.writeTo(os);
1969:            }
1970:
1971:            /**
1972:             * Write an integer
1973:             *
1974:             * @param out The <code>OuputStream</code> to which the <code>int</code> value is to be written
1975:             * @param i The <code>int</code> value to be written
1976:             * @throws IOException
1977:             */
1978:            public final static void writeInt(OutputStream out, int i)
1979:                    throws IOException {
1980:                out.write(Integer.toString(i).getBytes());
1981:            }
1982:
1983:            /**
1984:             * Get a random integer.
1985:             * This returns a <b>unique</b> random integer to be used with listids.
1986:             *
1987:             * @return Random <code>int</code> value.
1988:             */
1989:            private int getRandomInt() {
1990:                boolean ok = false;
1991:                Integer newInt = null;
1992:                Integer oldInt = null;
1993:                while (!ok) {
1994:                    newInt = new Integer(
1995:                            (int) (Math.random() * Integer.MAX_VALUE));
1996:                    ok = true;
1997:                    for (int i = 0; i < listIds.size(); i++) {
1998:                        oldInt = (Integer) listIds.get(i);
1999:                        if (oldInt.equals(newInt)) {
2000:                            ok = true;
2001:                        }
2002:                    }
2003:                }
2004:                listIds.add(newInt);
2005:                return newInt.intValue();
2006:            }
2007:
2008:            /**
2009:             * Write the current header and footer to a <code>ByteArrayOutputStream</code>
2010:             *
2011:             * @param os		The <code>ByteArrayOutputStream</code> to which the header and footer will be written.
2012:             * @throws IOException
2013:             */
2014:            public void writeHeadersFooters(ByteArrayOutputStream os)
2015:                    throws IOException {
2016:                if (this .footer instanceof  RtfHeaderFooters) {
2017:                    RtfHeaderFooters rtfHf = (RtfHeaderFooters) this .footer;
2018:                    HeaderFooter hf = rtfHf.get(RtfHeaderFooters.ALL_PAGES);
2019:                    if (hf != null) {
2020:                        writeHeaderFooter(hf, footerBegin, os);
2021:                    }
2022:                    hf = rtfHf.get(RtfHeaderFooters.LEFT_PAGES);
2023:                    if (hf != null) {
2024:                        writeHeaderFooter(hf, footerlBegin, os);
2025:                    }
2026:                    hf = rtfHf.get(RtfHeaderFooters.RIGHT_PAGES);
2027:                    if (hf != null) {
2028:                        writeHeaderFooter(hf, footerrBegin, os);
2029:                    }
2030:                    hf = rtfHf.get(RtfHeaderFooters.FIRST_PAGE);
2031:                    if (hf != null) {
2032:                        writeHeaderFooter(hf, footerfBegin, os);
2033:                    }
2034:                } else {
2035:                    writeHeaderFooter(this .footer, footerBegin, os);
2036:                }
2037:                if (this .header instanceof  RtfHeaderFooters) {
2038:                    RtfHeaderFooters rtfHf = (RtfHeaderFooters) this .header;
2039:                    HeaderFooter hf = rtfHf.get(RtfHeaderFooters.ALL_PAGES);
2040:                    if (hf != null) {
2041:                        writeHeaderFooter(hf, headerBegin, os);
2042:                    }
2043:                    hf = rtfHf.get(RtfHeaderFooters.LEFT_PAGES);
2044:                    if (hf != null) {
2045:                        writeHeaderFooter(hf, headerlBegin, os);
2046:                    }
2047:                    hf = rtfHf.get(RtfHeaderFooters.RIGHT_PAGES);
2048:                    if (hf != null) {
2049:                        writeHeaderFooter(hf, headerrBegin, os);
2050:                    }
2051:                    hf = rtfHf.get(RtfHeaderFooters.FIRST_PAGE);
2052:                    if (hf != null) {
2053:                        writeHeaderFooter(hf, headerfBegin, os);
2054:                    }
2055:                } else {
2056:                    writeHeaderFooter(this .header, headerBegin, os);
2057:                }
2058:            }
2059:
2060:            /**
2061:             * Write a <code>HeaderFooter</code> to a <code>ByteArrayOutputStream</code>
2062:             *
2063:             * @param headerFooter	The <code>HeaderFooter</code> object to be written.
2064:             * @param hfType		The type of header or footer to be added.
2065:             * @param target		The <code>ByteArrayOutputStream</code> to which the <code>HeaderFooter</code> will be written.
2066:             * @throws IOException
2067:             */
2068:            private void writeHeaderFooter(HeaderFooter headerFooter,
2069:                    byte[] hfType, ByteArrayOutputStream target)
2070:                    throws IOException {
2071:                inHeaderFooter = true;
2072:                try {
2073:                    target.write(openGroup);
2074:                    target.write(escape);
2075:                    target.write(hfType);
2076:                    target.write(delimiter);
2077:                    if (headerFooter != null) {
2078:                        if (headerFooter instanceof  RtfHeaderFooter
2079:                                && ((RtfHeaderFooter) headerFooter).content() != null) {
2080:                            this .addElement(((RtfHeaderFooter) headerFooter)
2081:                                    .content(), target);
2082:                        } else {
2083:                            Paragraph par = new Paragraph();
2084:                            par.setAlignment(headerFooter.alignment());
2085:                            if (headerFooter.getBefore() != null) {
2086:                                par.add(headerFooter.getBefore());
2087:                            }
2088:                            if (headerFooter.isNumbered()) {
2089:                                par.add(new RtfPageNumber("", headerFooter
2090:                                        .getBefore().getFont()));
2091:                            }
2092:                            if (headerFooter.getAfter() != null) {
2093:                                par.add(headerFooter.getAfter());
2094:                            }
2095:                            this .addElement(par, target);
2096:                        }
2097:                    }
2098:                    target.write(closeGroup);
2099:                } catch (DocumentException e) {
2100:                    throw new IOException("DocumentException - "
2101:                            + e.getMessage());
2102:                }
2103:                inHeaderFooter = false;
2104:            }
2105:
2106:            /**
2107:             *  Write the <code>Document</code>'s Paper and Margin Size
2108:             *  to the final <code>ByteArrayOutputStream</code>
2109:             * @throws IOException
2110:             */
2111:            private void writeDocumentFormat() throws IOException {
2112:                //        os.write(openGroup);
2113:                os.write(escape);
2114:                os.write(rtfPaperWidth);
2115:                writeInt(os, pageWidth);
2116:                os.write(escape);
2117:                os.write(rtfPaperHeight);
2118:                writeInt(os, pageHeight);
2119:                os.write(escape);
2120:                os.write(rtfMarginLeft);
2121:                writeInt(os, marginLeft);
2122:                os.write(escape);
2123:                os.write(rtfMarginRight);
2124:                writeInt(os, marginRight);
2125:                os.write(escape);
2126:                os.write(rtfMarginTop);
2127:                writeInt(os, marginTop);
2128:                os.write(escape);
2129:                os.write(rtfMarginBottom);
2130:                writeInt(os, marginBottom);
2131:                //        os.write(closeGroup);
2132:            }
2133:
2134:            /**
2135:             * Initialise all helper classes.
2136:             * Clears alls lists, creates new <code>ByteArrayOutputStream</code>'s
2137:             */
2138:            private void initDefaults() {
2139:                fontList.clear();
2140:                colorList.clear();
2141:                info = new ByteArrayOutputStream();
2142:                content = new ByteArrayOutputStream();
2143:                listtable = new ByteArrayOutputStream();
2144:                listoverride = new ByteArrayOutputStream();
2145:                document.addProducer();
2146:                document.addCreationDate();
2147:                addFont(new Font(Font.TIMES_ROMAN, 10, Font.NORMAL));
2148:                addColor(new Color(0, 0, 0));
2149:                addColor(new Color(255, 255, 255));
2150:                listIds = new ArrayList();
2151:                try {
2152:                    listtable.write(openGroup);
2153:                    listtable.write(extendedEscape);
2154:                    listtable.write(listtableGroup);
2155:                    listtable.write((byte) '\n');
2156:                    listoverride.write(openGroup);
2157:                    listoverride.write(extendedEscape);
2158:                    listoverride.write(listoverridetableGroup);
2159:                    listoverride.write((byte) '\n');
2160:                } catch (IOException e) {
2161:                    System.err.println("InitDefaultsError" + e);
2162:                }
2163:            }
2164:
2165:            /**
2166:             * Writes the default values for the current Section
2167:             *
2168:             * @param out The <code>ByteArrayOutputStream</code> to be written to
2169:             * @throws IOException
2170:             */
2171:            private void writeSectionDefaults(ByteArrayOutputStream out)
2172:                    throws IOException {
2173:                if (header instanceof  RtfHeaderFooters
2174:                        || footer instanceof  RtfHeaderFooters) {
2175:                    RtfHeaderFooters rtfHeader = (RtfHeaderFooters) header;
2176:                    RtfHeaderFooters rtfFooter = (RtfHeaderFooters) footer;
2177:                    if ((rtfHeader != null && (rtfHeader
2178:                            .get(RtfHeaderFooters.LEFT_PAGES) != null || rtfHeader
2179:                            .get(RtfHeaderFooters.RIGHT_PAGES) != null))
2180:                            || (rtfFooter != null && (rtfFooter
2181:                                    .get(RtfHeaderFooters.LEFT_PAGES) != null || rtfFooter
2182:                                    .get(RtfHeaderFooters.RIGHT_PAGES) != null))) {
2183:                        out.write(escape);
2184:                        out.write(facingPages);
2185:                    }
2186:                }
2187:                if (hasTitlePage) {
2188:                    out.write(escape);
2189:                    out.write(titlePage);
2190:                }
2191:                writeHeadersFooters(out);
2192:                if (landscape) {
2193:                    //out.write(escape);
2194:                    //out.write(landscapeTag1);
2195:                    out.write(escape);
2196:                    out.write(landscapeTag2);
2197:                    out.write(escape);
2198:                    out.write(sectionPageWidth);
2199:                    writeInt(out, pageWidth);
2200:                    out.write(escape);
2201:                    out.write(sectionPageHeight);
2202:                    writeInt(out, pageHeight);
2203:                } else {
2204:                    out.write(escape);
2205:                    out.write(sectionPageWidth);
2206:                    writeInt(out, pageWidth);
2207:                    out.write(escape);
2208:                    out.write(sectionPageHeight);
2209:                    writeInt(out, pageHeight);
2210:                }
2211:            }
2212:
2213:            /**
2214:             * This method tries to fit the <code>Rectangle pageSize</code> to one of the predefined PageSize rectangles.
2215:             * If a match is found the pageWidth and pageHeight will be set according to values determined from files
2216:             * generated by MS Word2000 and OpenOffice 641. If no match is found the method will try to match the rotated
2217:             * Rectangle by calling itself with the parameter rotate set to true.
2218:             * @param pageSize a rectangle defining the size of the page
2219:             * @param rotate portrait or lanscape?
2220:             * @return true if the format parsing succeeded
2221:             */
2222:            private boolean parseFormat(Rectangle pageSize, boolean rotate) {
2223:                if (rotate) {
2224:                    pageSize = pageSize.rotate();
2225:                }
2226:                if (rectEquals(pageSize, PageSize.A3)) {
2227:                    pageWidth = 16837;
2228:                    pageHeight = 23811;
2229:                    landscape = rotate;
2230:                    return true;
2231:                }
2232:                if (rectEquals(pageSize, PageSize.A4)) {
2233:                    pageWidth = 11907;
2234:                    pageHeight = 16840;
2235:                    landscape = rotate;
2236:                    return true;
2237:                }
2238:                if (rectEquals(pageSize, PageSize.A5)) {
2239:                    pageWidth = 8391;
2240:                    pageHeight = 11907;
2241:                    landscape = rotate;
2242:                    return true;
2243:                }
2244:                if (rectEquals(pageSize, PageSize.A6)) {
2245:                    pageWidth = 5959;
2246:                    pageHeight = 8420;
2247:                    landscape = rotate;
2248:                    return true;
2249:                }
2250:                if (rectEquals(pageSize, PageSize.B4)) {
2251:                    pageWidth = 14570;
2252:                    pageHeight = 20636;
2253:                    landscape = rotate;
2254:                    return true;
2255:                }
2256:                if (rectEquals(pageSize, PageSize.B5)) {
2257:                    pageWidth = 10319;
2258:                    pageHeight = 14572;
2259:                    landscape = rotate;
2260:                    return true;
2261:                }
2262:                if (rectEquals(pageSize, PageSize.HALFLETTER)) {
2263:                    pageWidth = 7927;
2264:                    pageHeight = 12247;
2265:                    landscape = rotate;
2266:                    return true;
2267:                }
2268:                if (rectEquals(pageSize, PageSize.LETTER)) {
2269:                    pageWidth = 12242;
2270:                    pageHeight = 15842;
2271:                    landscape = rotate;
2272:                    return true;
2273:                }
2274:                if (rectEquals(pageSize, PageSize.LEGAL)) {
2275:                    pageWidth = 12252;
2276:                    pageHeight = 20163;
2277:                    landscape = rotate;
2278:                    return true;
2279:                }
2280:                if (!rotate && parseFormat(pageSize, true)) {
2281:                    int x = pageWidth;
2282:                    pageWidth = pageHeight;
2283:                    pageHeight = x;
2284:                    return true;
2285:                }
2286:                return false;
2287:            }
2288:
2289:            /**
2290:             * This method compares to Rectangles. They are considered equal if width and height are the same
2291:             * @param rect1
2292:             * @param rect2
2293:             * @return true if rect1 and rect2 represent the same rectangle
2294:             */
2295:            private boolean rectEquals(Rectangle rect1, Rectangle rect2) {
2296:                return (rect1.getWidth() == rect2.getWidth())
2297:                        && (rect1.getHeight() == rect2.getHeight());
2298:            }
2299:
2300:            /**
2301:             * Returns whether we are currently writing a header or footer
2302:             *
2303:             * @return the value of inHeaderFooter
2304:             */
2305:            public boolean writingHeaderFooter() {
2306:                return inHeaderFooter;
2307:            }
2308:
2309:            /**
2310:             * Replaces special characters with their unicode values
2311:             *
2312:             * @param str The original <code>String</code>
2313:             * @param useHex
2314:             * @return The converted String
2315:             */
2316:            public final static String filterSpecialChar(String str,
2317:                    boolean useHex) {
2318:                int length = str.length();
2319:                int z = (int) 'z';
2320:                StringBuffer ret = new StringBuffer(length);
2321:                for (int i = 0; i < length; i++) {
2322:                    char ch = str.charAt(i);
2323:
2324:                    if (ch == '\\') {
2325:                        ret.append("\\\\");
2326:                    } else if (ch == '\n') {
2327:                        ret.append("\\par ");
2328:                    } else if (((int) ch) > z) {
2329:                        if (useHex) {
2330:                            ret.append("\\\'").append(
2331:                                    Long.toHexString((long) ch));
2332:                        } else {
2333:                            ret.append("\\u").append((long) ch).append('?');
2334:                        }
2335:                    } else {
2336:                        ret.append(ch);
2337:                    }
2338:                }
2339:                String s = ret.toString();
2340:                if (s.indexOf("$newpage$") >= 0) {
2341:                    String before = s.substring(0, s.indexOf("$newpage$"));
2342:                    String after = s.substring(s.indexOf("$newpage$") + 9);
2343:                    ret = new StringBuffer(before);
2344:                    ret.append("\\page\\par ");
2345:                    ret.append(after);
2346:                    return ret.toString();
2347:                }
2348:                return s;
2349:            }
2350:
2351:            private void addHeaderFooterFontColor(HeaderFooter hf) {
2352:                if (hf instanceof  RtfHeaderFooter) {
2353:                    RtfHeaderFooter rhf = (RtfHeaderFooter) hf;
2354:                    if (rhf.content() instanceof  Chunk) {
2355:                        addFont(((Chunk) rhf.content()).getFont());
2356:                        addColor(((Chunk) rhf.content()).getFont().getColor());
2357:                    } else if (rhf.content() instanceof  Phrase) {
2358:                        addFont(((Phrase) rhf.content()).getFont());
2359:                        addColor(((Phrase) rhf.content()).getFont().getColor());
2360:                    }
2361:                }
2362:                if (hf.getBefore() != null) {
2363:                    addFont(hf.getBefore().getFont());
2364:                    addColor(hf.getBefore().getFont().getColor());
2365:                }
2366:                if (hf.getAfter() != null) {
2367:                    addFont(hf.getAfter().getFont());
2368:                    addColor(hf.getAfter().getFont().getColor());
2369:                }
2370:            }
2371:
2372:            private void processHeaderFooter(HeaderFooter hf) {
2373:                if (hf != null) {
2374:                    if (hf instanceof  RtfHeaderFooters) {
2375:                        RtfHeaderFooters rhf = (RtfHeaderFooters) hf;
2376:                        if (rhf.get(RtfHeaderFooters.ALL_PAGES) != null) {
2377:                            addHeaderFooterFontColor(rhf
2378:                                    .get(RtfHeaderFooters.ALL_PAGES));
2379:                        }
2380:                        if (rhf.get(RtfHeaderFooters.LEFT_PAGES) != null) {
2381:                            addHeaderFooterFontColor(rhf
2382:                                    .get(RtfHeaderFooters.LEFT_PAGES));
2383:                        }
2384:                        if (rhf.get(RtfHeaderFooters.RIGHT_PAGES) != null) {
2385:                            addHeaderFooterFontColor(rhf
2386:                                    .get(RtfHeaderFooters.RIGHT_PAGES));
2387:                        }
2388:                        if (rhf.get(RtfHeaderFooters.FIRST_PAGE) != null) {
2389:                            addHeaderFooterFontColor(rhf
2390:                                    .get(RtfHeaderFooters.FIRST_PAGE));
2391:                        }
2392:                    } else {
2393:                        addHeaderFooterFontColor(hf);
2394:                    }
2395:                }
2396:            }
2397:
2398:            /**
2399:             * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
2400:             */
2401:            public boolean setMarginMirroring(boolean MarginMirroring) {
2402:                return false;
2403:            }
2404:
2405:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.