KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > rtf > RTFHandler


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: RTFHandler.java 473975 2006-11-12 15:28:15Z jeremias $ */
19
20 package org.apache.fop.render.rtf;
21
22 // Java
23
import java.awt.geom.Point2D JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.OutputStreamWriter JavaDoc;
27 import java.util.Iterator JavaDoc;
28
29 import org.apache.batik.dom.svg.SVGDOMImplementation;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.fop.apps.FOPException;
33 import org.apache.fop.apps.FOUserAgent;
34 import org.apache.fop.datatypes.LengthBase;
35 import org.apache.fop.datatypes.SimplePercentBaseContext;
36 import org.apache.fop.fo.Constants;
37 import org.apache.fop.fo.FOEventHandler;
38 import org.apache.fop.fo.FONode;
39 import org.apache.fop.fo.FOText;
40 import org.apache.fop.fo.XMLObj;
41 import org.apache.fop.fo.flow.AbstractGraphics;
42 import org.apache.fop.fo.flow.BasicLink;
43 import org.apache.fop.fo.flow.Block;
44 import org.apache.fop.fo.flow.BlockContainer;
45 import org.apache.fop.fo.flow.Character;
46 import org.apache.fop.fo.flow.ExternalGraphic;
47 import org.apache.fop.fo.flow.Footnote;
48 import org.apache.fop.fo.flow.FootnoteBody;
49 import org.apache.fop.fo.flow.Inline;
50 import org.apache.fop.fo.flow.InstreamForeignObject;
51 import org.apache.fop.fo.flow.Leader;
52 import org.apache.fop.fo.flow.ListBlock;
53 import org.apache.fop.fo.flow.ListItem;
54 import org.apache.fop.fo.flow.ListItemBody;
55 import org.apache.fop.fo.flow.ListItemLabel;
56 import org.apache.fop.fo.flow.PageNumber;
57 import org.apache.fop.fo.flow.Table;
58 import org.apache.fop.fo.flow.TableBody;
59 import org.apache.fop.fo.flow.TableCell;
60 import org.apache.fop.fo.flow.TableColumn;
61 import org.apache.fop.fo.flow.TableHeader;
62 import org.apache.fop.fo.flow.TableRow;
63 import org.apache.fop.fo.pagination.Flow;
64 import org.apache.fop.fo.pagination.PageSequence;
65 import org.apache.fop.fo.pagination.PageSequenceMaster;
66 import org.apache.fop.fo.pagination.Region;
67 import org.apache.fop.fo.pagination.SimplePageMaster;
68 import org.apache.fop.fo.pagination.StaticContent;
69 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
70 import org.apache.fop.fonts.FontSetup;
71 import org.apache.fop.image.FopImage;
72 import org.apache.fop.image.ImageFactory;
73 import org.apache.fop.image.XMLImage;
74 import org.apache.fop.render.DefaultFontResolver;
75 import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer;
76 import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer;
77 import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfListContainer;
78 import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTableContainer;
79 import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTextrunContainer;
80 import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes;
81 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAfter;
82 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
83 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfBefore;
84 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfDocumentArea;
85 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfElement;
86 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfExternalGraphic;
87 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFile;
88 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFootnote;
89 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink;
90 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList;
91 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem;
92 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
93 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
94 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
95 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
96 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun;
97 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel;
98 import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
99 import org.apache.fop.render.rtf.rtflib.tools.TableContext;
100 import org.w3c.dom.Document JavaDoc;
101 import org.xml.sax.SAXException JavaDoc;
102
103 /**
104  * RTF Handler: generates RTF output using the structure events from
105  * the FO Tree sent to this structure handler.
106  *
107  * @author Bertrand Delacretaz <bdelacretaz@codeconsult.ch>
108  * @author Trembicki-Guy, Ed <GuyE@DNB.com>
109  * @author Boris Poudérous <boris.pouderous@eads-telecom.com>
110  * @author Peter Herweg <pherweg@web.de>
111  * @author Andreas Putz <a.putz@skynamics.com>
112  */

113 public class RTFHandler extends FOEventHandler {
114
115     private RtfFile rtfFile;
116     private final OutputStream JavaDoc os;
117     private static Log log = LogFactory.getLog(RTFHandler.class);
118     private RtfSection sect;
119     private RtfDocumentArea docArea;
120     private boolean bDefer; //true, if each called handler shall be
121
//processed at later time.
122
private boolean bPrevHeaderSpecified = false; //true, if there has been a
123
//header in any page-sequence
124
private boolean bPrevFooterSpecified = false; //true, if there has been a
125
//footer in any page-sequence
126
private boolean bHeaderSpecified = false; //true, if there is a header
127
//in current page-sequence
128
private boolean bFooterSpecified = false; //true, if there is a footer
129
//in current page-sequence
130
private BuilderContext builderContext = new BuilderContext(null);
131
132     private SimplePageMaster pagemaster;
133
134     /**
135      * Creates a new RTF structure handler.
136      * @param userAgent the FOUserAgent for this process
137      * @param os OutputStream to write to
138      */

139     public RTFHandler(FOUserAgent userAgent, OutputStream JavaDoc os) {
140         super(userAgent);
141         this.os = os;
142         bDefer = true;
143
144         FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent));
145     }
146
147     /**
148      * @see org.apache.fop.fo.FOEventHandler#startDocument()
149      * @throws SAXException In case of a IO-problem
150      */

151     public void startDocument() throws SAXException JavaDoc {
152         // TODO sections should be created
153
try {
154             rtfFile = new RtfFile(new OutputStreamWriter JavaDoc(os));
155             docArea = rtfFile.startDocumentArea();
156         } catch (IOException JavaDoc ioe) {
157             // TODO could we throw Exception in all FOEventHandler events?
158
throw new SAXException JavaDoc(ioe);
159         }
160     }
161
162     /**
163      * @see org.apache.fop.fo.FOEventHandler#endDocument()
164      * @throws SAXException In case of a IO-problem
165      */

166     public void endDocument() throws SAXException JavaDoc {
167         try {
168             rtfFile.flush();
169         } catch (IOException JavaDoc ioe) {
170             // TODO could we throw Exception in all FOEventHandler events?
171
throw new SAXException JavaDoc(ioe);
172         }
173     }
174
175     /**
176      * @see org.apache.fop.fo.FOEventHandler
177      * @param pageSeq PageSequence that is starting
178      */

179     public void startPageSequence(PageSequence pageSeq) {
180         try {
181             //This is needed for region handling
182
if (this.pagemaster == null) {
183                 String JavaDoc reference = pageSeq.getMasterReference();
184                 this.pagemaster
185                         = pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(reference);
186                 if (this.pagemaster == null) {
187                     log.warn("Only simple-page-masters are supported on page-sequences: "
188                             + reference);
189                     log.warn("Using default simple-page-master from page-sequence-master...");
190                     PageSequenceMaster master
191                         = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference);
192                     this.pagemaster = master.getNextSimplePageMaster(false, false, false, false);
193                 }
194             }
195
196             if (bDefer) {
197                 return;
198             }
199
200             sect = docArea.newSection();
201
202             //read page size and margins, if specified
203
//only simple-page-master supported, so pagemaster may be null
204
if (pagemaster != null) {
205                 sect.getRtfAttributes().set(
206                     PageAttributesConverter.convertPageAttributes(
207                             pagemaster));
208             } else {
209                 log.warn("No simple-page-master could be determined!");
210             }
211
212             builderContext.pushContainer(sect);
213
214             bHeaderSpecified = false;
215             bFooterSpecified = false;
216         } catch (IOException JavaDoc ioe) {
217             // TODO could we throw Exception in all FOEventHandler events?
218
log.error("startPageSequence: " + ioe.getMessage(), ioe);
219             //TODO throw new FOPException(ioe);
220
} catch (FOPException fope) {
221             // TODO could we throw Exception in all FOEventHandler events?
222
log.error("startPageSequence: " + fope.getMessage(), fope);
223         }
224     }
225
226     /**
227      * @see org.apache.fop.fo.FOEventHandler#endPageSequence(PageSequence)
228      * @param pageSeq PageSequence that is ending
229      */

230     public void endPageSequence(PageSequence pageSeq) {
231         if (bDefer) {
232             //If endBlock was called while SAX parsing, and the passed FO is Block
233
//nested within another Block, stop deferring.
234
//Now process all deferred FOs.
235
bDefer = false;
236             recurseFONode(pageSeq);
237             this.pagemaster = null;
238             bDefer = true;
239
240             return;
241         } else {
242             builderContext.popContainer();
243             this.pagemaster = null;
244         }
245     }
246
247     /**
248      * @see org.apache.fop.fo.FOEventHandler#startFlow(Flow)
249      * @param fl Flow that is starting
250      */

251     public void startFlow(Flow fl) {
252         if (bDefer) {
253             return;
254         }
255
256         try {
257             log.debug("starting flow: " + fl.getFlowName());
258             boolean handled = false;
259             Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
260             Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
261             Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
262             if (fl.getFlowName().equals(regionBody.getRegionName())) {
263                 // if there is no header in current page-sequence but there has been
264
// a header in a previous page-sequence, insert an empty header.
265
if (bPrevHeaderSpecified && !bHeaderSpecified) {
266                     RtfAttributes attr = new RtfAttributes();
267                     attr.set(RtfBefore.HEADER);
268
269                     final IRtfBeforeContainer contBefore
270                         = (IRtfBeforeContainer)builderContext.getContainer
271                                 (IRtfBeforeContainer.class, true, this);
272                     contBefore.newBefore(attr);
273                 }
274
275                 // if there is no footer in current page-sequence but there has been
276
// a footer in a previous page-sequence, insert an empty footer.
277
if (bPrevFooterSpecified && !bFooterSpecified) {
278                     RtfAttributes attr = new RtfAttributes();
279                     attr.set(RtfAfter.FOOTER);
280
281                     final IRtfAfterContainer contAfter
282                         = (IRtfAfterContainer)builderContext.getContainer
283                                 (IRtfAfterContainer.class, true, this);
284                     contAfter.newAfter(attr);
285                 }
286                 handled = true;
287             } else if (regionBefore != null
288                     && fl.getFlowName().equals(regionBefore.getRegionName())) {
289                 bHeaderSpecified = true;
290                 bPrevHeaderSpecified = true;
291
292                 final IRtfBeforeContainer c
293                     = (IRtfBeforeContainer)builderContext.getContainer(
294                         IRtfBeforeContainer.class,
295                         true, this);
296
297                 RtfAttributes beforeAttributes = ((RtfElement)c).getRtfAttributes();
298                 if (beforeAttributes == null) {
299                     beforeAttributes = new RtfAttributes();
300                 }
301                 beforeAttributes.set(RtfBefore.HEADER);
302
303                 RtfBefore before = c.newBefore(beforeAttributes);
304                 builderContext.pushContainer(before);
305                 handled = true;
306             } else if (regionAfter != null
307                     && fl.getFlowName().equals(regionAfter.getRegionName())) {
308                 bFooterSpecified = true;
309                 bPrevFooterSpecified = true;
310
311                 final IRtfAfterContainer c
312                     = (IRtfAfterContainer)builderContext.getContainer(
313                         IRtfAfterContainer.class,
314                         true, this);
315
316                 RtfAttributes afterAttributes = ((RtfElement)c).getRtfAttributes();
317                 if (afterAttributes == null) {
318                     afterAttributes = new RtfAttributes();
319                 }
320
321                 afterAttributes.set(RtfAfter.FOOTER);
322
323                 RtfAfter after = c.newAfter(afterAttributes);
324                 builderContext.pushContainer(after);
325                 handled = true;
326             }
327             if (!handled) {
328                 log.warn("A " + fl.getLocalName() + " has been skipped: " + fl.getFlowName());
329             }
330         } catch (IOException JavaDoc ioe) {
331             log.error("startFlow: " + ioe.getMessage());
332             throw new RuntimeException JavaDoc(ioe.getMessage());
333         } catch (Exception JavaDoc e) {
334             log.error("startFlow: " + e.getMessage());
335             throw new RuntimeException JavaDoc(e.getMessage());
336         }
337     }
338
339     /**
340      * @see org.apache.fop.fo.FOEventHandler#endFlow(Flow)
341      * @param fl Flow that is ending
342      */

343     public void endFlow(Flow fl) {
344         if (bDefer) {
345             return;
346         }
347
348         try {
349             Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
350             Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
351             Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
352             if (fl.getFlowName().equals(regionBody.getRegionName())) {
353                 //just do nothing
354
} else if (regionBefore != null
355                     && fl.getFlowName().equals(regionBefore.getRegionName())) {
356                 builderContext.popContainer();
357             } else if (regionAfter != null
358                     && fl.getFlowName().equals(regionAfter.getRegionName())) {
359                 builderContext.popContainer();
360             }
361         } catch (Exception JavaDoc e) {
362             log.error("endFlow: " + e.getMessage());
363             throw new RuntimeException JavaDoc(e.getMessage());
364         }
365     }
366
367     /**
368      * @see org.apache.fop.fo.FOEventHandler#startBlock(Block)
369      * @param bl Block that is starting
370      */

371     public void startBlock(Block bl) {
372         if (bDefer) {
373             return;
374         }
375
376         try {
377             RtfAttributes rtfAttr
378                 = TextAttributesConverter.convertAttributes(bl);
379
380             IRtfTextrunContainer container
381                 = (IRtfTextrunContainer)builderContext.getContainer(
382                     IRtfTextrunContainer.class,
383                     true, this);
384
385             RtfTextrun textrun = container.getTextrun();
386
387             textrun.addParagraphBreak();
388             textrun.pushBlockAttributes(rtfAttr);
389             textrun.addBookmark(bl.getId());
390         } catch (IOException JavaDoc ioe) {
391             // TODO could we throw Exception in all FOEventHandler events?
392
log.error("startBlock: " + ioe.getMessage());
393             throw new RuntimeException JavaDoc("IOException: " + ioe);
394         } catch (Exception JavaDoc e) {
395             log.error("startBlock: " + e.getMessage());
396             throw new RuntimeException JavaDoc("Exception: " + e);
397         }
398     }
399
400
401     /**
402      * @see org.apache.fop.fo.FOEventHandler#endBlock(Block)
403      * @param bl Block that is ending
404      */

405     public void endBlock(Block bl) {
406
407         if (bDefer) {
408             return;
409         }
410
411         try {
412             IRtfTextrunContainer container
413                 = (IRtfTextrunContainer)builderContext.getContainer(
414                     IRtfTextrunContainer.class,
415                     true, this);
416
417             RtfTextrun textrun = container.getTextrun();
418
419             textrun.addParagraphBreak();
420             textrun.popBlockAttributes();
421
422         } catch (IOException JavaDoc ioe) {
423             log.error("startBlock:" + ioe.getMessage());
424             throw new RuntimeException JavaDoc(ioe.getMessage());
425         } catch (Exception JavaDoc e) {
426             log.error("startBlock:" + e.getMessage());
427             throw new RuntimeException JavaDoc(e.getMessage());
428         }
429     }
430
431     /**
432      * @see org.apache.fop.fo.FOEventHandler#startBlockContainer(BlockContainer)
433      * @param blc BlockContainer that is starting
434      */

435     public void startBlockContainer(BlockContainer blc) {
436         if (bDefer) {
437             return;
438         }
439
440         try {
441             RtfAttributes rtfAttr
442                 = TextAttributesConverter.convertBlockContainerAttributes(blc);
443
444             IRtfTextrunContainer container
445                 = (IRtfTextrunContainer)builderContext.getContainer(
446                     IRtfTextrunContainer.class,
447                     true, this);
448
449             RtfTextrun textrun = container.getTextrun();
450
451             textrun.addParagraphBreak();
452             textrun.pushBlockAttributes(rtfAttr);
453         } catch (IOException JavaDoc ioe) {
454             // TODO could we throw Exception in all FOEventHandler events?
455
log.error("startBlock: " + ioe.getMessage());
456             throw new RuntimeException JavaDoc("IOException: " + ioe);
457         } catch (Exception JavaDoc e) {
458             log.error("startBlock: " + e.getMessage());
459             throw new RuntimeException JavaDoc("Exception: " + e);
460         }
461     }
462
463     /**
464      * @see org.apache.fop.fo.FOEventHandler#endBlockContainer(BlockContainer)
465      * @param bl BlockContainer that is ending
466      */

467     public void endBlockContainer(BlockContainer bl) {
468         if (bDefer) {
469             return;
470         }
471
472         try {
473             IRtfTextrunContainer container
474                 = (IRtfTextrunContainer)builderContext.getContainer(
475                     IRtfTextrunContainer.class,
476                     true, this);
477
478             RtfTextrun textrun = container.getTextrun();
479
480             textrun.addParagraphBreak();
481             textrun.popBlockAttributes();
482
483         } catch (IOException JavaDoc ioe) {
484             log.error("startBlock:" + ioe.getMessage());
485             throw new RuntimeException JavaDoc(ioe.getMessage());
486         } catch (Exception JavaDoc e) {
487             log.error("startBlock:" + e.getMessage());
488             throw new RuntimeException JavaDoc(e.getMessage());
489         }
490     }
491
492     /**
493      * @see org.apache.fop.fo.FOEventHandler#startTable(Table)
494      * @param tbl Table that is starting
495      */

496     public void startTable(Table tbl) {
497         if (bDefer) {
498             return;
499         }
500
501         // create an RtfTable in the current table container
502
TableContext tableContext = new TableContext(builderContext);
503
504         try {
505             final IRtfTableContainer tc
506                 = (IRtfTableContainer)builderContext.getContainer(
507                         IRtfTableContainer.class, true, null);
508             
509             RtfAttributes atts
510                 = TableAttributesConverter.convertTableAttributes(tbl);
511             
512             RtfTable table = tc.newTable(atts, tableContext);
513             
514             CommonBorderPaddingBackground border = tbl.getCommonBorderPaddingBackground();
515             RtfAttributes borderAttributes = new RtfAttributes();
516                     
517             BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.BEFORE,
518                     borderAttributes, ITableAttributes.CELL_BORDER_TOP);
519             BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.AFTER,
520                     borderAttributes, ITableAttributes.CELL_BORDER_BOTTOM);
521             BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.START,
522                     borderAttributes, ITableAttributes.CELL_BORDER_LEFT);
523             BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.END,
524                     borderAttributes, ITableAttributes.CELL_BORDER_RIGHT);
525             
526             table.setBorderAttributes(borderAttributes);
527             
528             builderContext.pushContainer(table);
529         } catch (Exception JavaDoc e) {
530             log.error("startTable:" + e.getMessage());
531             throw new RuntimeException JavaDoc(e.getMessage());
532         }
533
534         builderContext.pushTableContext(tableContext);
535     }
536
537     /**
538      * @see org.apache.fop.fo.FOEventHandler#endTable(Table)
539      * @param tbl Table that is ending
540      */

541     public void endTable(Table tbl) {
542         if (bDefer) {
543             return;
544         }
545
546         builderContext.popTableContext();
547         builderContext.popContainer();
548     }
549
550     /**
551     *
552     * @param tc TableColumn that is starting;
553     */

554
555     public void startColumn(TableColumn tc) {
556         if (bDefer) {
557             return;
558         }
559
560         try {
561             /**
562              * Pass a SimplePercentBaseContext to getValue in order to
563              * avoid a NullPointerException, which occurs when you use
564              * proportional-column-width function in column-width attribute.
565              * Of course the results won't be correct, but at least the
566              * rest of the document will be rendered. Usage of the
567              * TableLayoutManager is not welcome due to design reasons and
568              * it also does not provide the correct values.
569              * TODO: Make proportional-column-width working for rtf output
570              */

571              SimplePercentBaseContext context
572                 = new SimplePercentBaseContext(null,
573                                                LengthBase.TABLE_UNITS,
574                                                100000);
575             
576             Integer JavaDoc iWidth
577                 = new Integer JavaDoc(tc.getColumnWidth().getValue(context) / 1000);
578             
579             String JavaDoc strWidth = iWidth.toString() + "pt";
580             Float JavaDoc width = new Float JavaDoc(
581                     FoUnitsConverter.getInstance().convertToTwips(strWidth));
582             builderContext.getTableContext().setNextColumnWidth(width);
583             builderContext.getTableContext().setNextColumnRowSpanning(
584                     new Integer JavaDoc(0), null);
585             builderContext.getTableContext().setNextFirstSpanningCol(false);
586         } catch (Exception JavaDoc e) {
587             log.error("startColumn: " + e.getMessage());
588             throw new RuntimeException JavaDoc(e.getMessage());
589         }
590
591     }
592
593      /**
594      *
595      * @param tc TableColumn that is ending;
596      */

597
598     public void endColumn(TableColumn tc) {
599         if (bDefer) {
600             return;
601         }
602     }
603
604     /**
605      * @see org.apache.fop.fo.FOEventHandler#startHeader(TableBody)
606      * @param th TableBody that is starting
607      */

608     public void startHeader(TableBody th) {
609     }
610
611     /**
612      * @see org.apache.fop.fo.FOEventHandler#endHeader(TableBody)
613      * @param th TableBody that is ending
614      */

615     public void endHeader(TableBody th) {
616     }
617
618     /**
619      * @see org.apache.fop.fo.FOEventHandler#startFooter(TableBody)
620      * @param tf TableFooter that is starting
621      */

622     public void startFooter(TableBody tf) {
623     }
624
625     /**
626      * @see org.apache.fop.fo.FOEventHandler#endFooter(TableBody)
627      * @param tf TableFooter that is ending
628      */

629     public void endFooter(TableBody tf) {
630     }
631
632     /**
633      *
634      * @param inl Inline that is starting.
635      */

636     public void startInline(Inline inl) {
637         if (bDefer) {
638             return;
639         }
640
641         try {
642             RtfAttributes rtfAttr
643                 = TextAttributesConverter.convertCharacterAttributes(inl);
644
645             IRtfTextrunContainer container
646                 = (IRtfTextrunContainer)builderContext.getContainer(
647                     IRtfTextrunContainer.class, true, this);
648
649             RtfTextrun textrun = container.getTextrun();
650             textrun.pushInlineAttributes(rtfAttr);
651             textrun.addBookmark(inl.getId());
652         } catch (IOException JavaDoc ioe) {
653             log.error("startInline:" + ioe.getMessage());
654             throw new RuntimeException JavaDoc(ioe.getMessage());
655         } catch (FOPException fe) {
656             log.error("startInline:" + fe.getMessage());
657             throw new RuntimeException JavaDoc(fe.getMessage());
658         } catch (Exception JavaDoc e) {
659             log.error("startInline:" + e.getMessage());
660             throw new RuntimeException JavaDoc(e.getMessage());
661         }
662     }
663
664     /**
665      *
666      * @param inl Inline that is ending.
667      */

668     public void endInline(Inline inl) {
669         if (bDefer) {
670             return;
671         }
672
673         try {
674             IRtfTextrunContainer container
675                 = (IRtfTextrunContainer)builderContext.getContainer(
676                     IRtfTextrunContainer.class, true, this);
677
678             RtfTextrun textrun = container.getTextrun();
679             textrun.popInlineAttributes();
680         } catch (IOException JavaDoc ioe) {
681             log.error("startInline:" + ioe.getMessage());
682             throw new RuntimeException JavaDoc(ioe.getMessage());
683         } catch (Exception JavaDoc e) {
684             log.error("startInline:" + e.getMessage());
685             throw new RuntimeException JavaDoc(e.getMessage());
686         }
687     }
688
689      /**
690      * @see org.apache.fop.fo.FOEventHandler#startBody(TableBody)
691      * @param tb TableBody that is starting
692      */

693     public void startBody(TableBody tb) {
694         if (bDefer) {
695             return;
696         }
697
698         try {
699             RtfAttributes atts = TableAttributesConverter.convertTableBodyAttributes(tb);
700
701             RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
702             tbl.setHeaderAttribs(atts);
703         } catch (Exception JavaDoc e) {
704             log.error("startBody: " + e.getMessage());
705             throw new RuntimeException JavaDoc(e.getMessage());
706         }
707     }
708
709     /**
710      * @see org.apache.fop.fo.FOEventHandler#endBody(TableBody)
711      * @param tb TableBody that is ending
712      */

713     public void endBody(TableBody tb) {
714         if (bDefer) {
715             return;
716         }
717
718         try {
719             RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
720             tbl.setHeaderAttribs(null);
721         } catch (Exception JavaDoc e) {
722             log.error("endBody: " + e.getMessage());
723             throw new RuntimeException JavaDoc(e.getMessage());
724         }
725     }
726
727     /**
728      * @see org.apache.fop.fo.FOEventHandler#startRow(TableRow)
729      * @param tr TableRow that is starting
730      */

731     public void startRow(TableRow tr) {
732         if (bDefer) {
733             return;
734         }
735
736         try {
737             // create an RtfTableRow in the current RtfTable
738
final RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class,
739                     true, null);
740
741             RtfAttributes atts = TableAttributesConverter.convertRowAttributes(tr,
742                     tbl.getHeaderAttribs());
743
744             if (tr.getParent() instanceof TableHeader) {
745                 atts.set(ITableAttributes.ATTR_HEADER);
746             }
747
748             builderContext.pushContainer(tbl.newTableRow(atts));
749
750             // reset column iteration index to correctly access column widths
751
builderContext.getTableContext().selectFirstColumn();
752         } catch (Exception JavaDoc e) {
753             log.error("startRow: " + e.getMessage());
754             throw new RuntimeException JavaDoc(e.getMessage());
755         }
756     }
757
758     /**
759      * @see org.apache.fop.fo.FOEventHandler#endRow(TableRow)
760      * @param tr TableRow that is ending
761      */

762     public void endRow(TableRow tr) {
763         if (bDefer) {
764             return;
765         }
766         
767         try {
768             TableContext tctx = builderContext.getTableContext();
769             final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
770                     true, null);
771
772             //while the current column is in row-spanning, act as if
773
//a vertical merged cell would have been specified.
774
while (tctx.getNumberOfColumns() > tctx.getColumnIndex()
775                   && tctx.getColumnRowSpanningNumber().intValue() > 0) {
776                 RtfTableCell vCell = row.newTableCellMergedVertically(
777                         (int)tctx.getColumnWidth(),
778                         tctx.getColumnRowSpanningAttrs());
779                 
780                 if (!tctx.getFirstSpanningCol()) {
781                     vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
782                 }
783                 
784                 tctx.selectNextColumn();
785             }
786         } catch (Exception JavaDoc e) {
787             log.error("endRow: " + e.getMessage());
788             throw new RuntimeException JavaDoc(e.getMessage());
789         }
790
791
792         builderContext.popContainer();
793         builderContext.getTableContext().decreaseRowSpannings();
794     }
795
796     /**
797      * @see org.apache.fop.fo.FOEventHandler#startCell(TableCell)
798      * @param tc TableCell that is starting
799      */

800     public void startCell(TableCell tc) {
801         if (bDefer) {
802             return;
803         }
804
805         try {
806             TableContext tctx = builderContext.getTableContext();
807             final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
808                     true, null);
809
810             int numberRowsSpanned = tc.getNumberRowsSpanned();
811             int numberColumnsSpanned = tc.getNumberColumnsSpanned();
812
813             //while the current column is in row-spanning, act as if
814
//a vertical merged cell would have been specified.
815
while (tctx.getNumberOfColumns() > tctx.getColumnIndex()
816                   && tctx.getColumnRowSpanningNumber().intValue() > 0) {
817                 RtfTableCell vCell = row.newTableCellMergedVertically(
818                         (int)tctx.getColumnWidth(),
819                         tctx.getColumnRowSpanningAttrs());
820                 
821                 if (!tctx.getFirstSpanningCol()) {
822                     vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
823                 }
824                 
825                 tctx.selectNextColumn();
826             }
827
828             //get the width of the currently started cell
829
float width = tctx.getColumnWidth();
830
831             // create an RtfTableCell in the current RtfTableRow
832
RtfAttributes atts = TableAttributesConverter.convertCellAttributes(tc);
833             RtfTableCell cell = row.newTableCell((int)width, atts);
834             
835             //process number-rows-spanned attribute
836
if (numberRowsSpanned > 1) {
837                 // Start vertical merge
838
cell.setVMerge(RtfTableCell.MERGE_START);
839
840                 // set the number of rows spanned
841
tctx.setCurrentColumnRowSpanning(new Integer JavaDoc(numberRowsSpanned),
842                         cell.getRtfAttributes());
843             } else {
844                 tctx.setCurrentColumnRowSpanning(
845                         new Integer JavaDoc(numberRowsSpanned), null);
846             }
847
848             //process number-columns-spanned attribute
849
if (numberColumnsSpanned > 0) {
850                 // Get the number of columns spanned
851
RtfTable table = row.getTable();
852                 tctx.setCurrentFirstSpanningCol(true);
853                 
854                 // We widthdraw one cell because the first cell is already created
855
// (it's the current cell) !
856
for (int i = 0; i < numberColumnsSpanned - 1; ++i) {
857                     tctx.selectNextColumn();
858                     
859                     tctx.setCurrentFirstSpanningCol(false);
860                     RtfTableCell hCell = row.newTableCellMergedHorizontally(
861                             0, null);
862                     
863                     if (numberRowsSpanned > 1) {
864                         // Start vertical merge
865
hCell.setVMerge(RtfTableCell.MERGE_START);
866
867                         // set the number of rows spanned
868
tctx.setCurrentColumnRowSpanning(
869                                 new Integer JavaDoc(numberRowsSpanned),
870                                 cell.getRtfAttributes());
871                     } else {
872                         tctx.setCurrentColumnRowSpanning(
873                                 new Integer JavaDoc(numberRowsSpanned), null);
874                     }
875                 }
876             }
877             
878             builderContext.pushContainer(cell);
879         } catch (Exception JavaDoc e) {
880             log.error("startCell: " + e.getMessage());
881             throw new RuntimeException JavaDoc(e.getMessage());
882         }
883     }
884
885     /**
886      * @see org.apache.fop.fo.FOEventHandler#endCell(TableCell)
887      * @param tc TableCell that is ending
888      */

889     public void endCell(TableCell tc) {
890         if (bDefer) {
891             return;
892         }
893
894         builderContext.popContainer();
895         builderContext.getTableContext().selectNextColumn();
896     }
897
898     // Lists
899
/**
900      * @see org.apache.fop.fo.FOEventHandler#startList(ListBlock)
901      * @param lb ListBlock that is starting
902      */

903     public void startList(ListBlock lb) {
904         if (bDefer) {
905             return;
906         }
907
908         try {
909             // create an RtfList in the current list container
910
final IRtfListContainer c
911                 = (IRtfListContainer)builderContext.getContainer(
912                     IRtfListContainer.class, true, this);
913             final RtfList newList = c.newList(
914                 ListAttributesConverter.convertAttributes(lb));
915             builderContext.pushContainer(newList);
916         } catch (IOException JavaDoc ioe) {
917             log.error("startList: " + ioe.getMessage());
918             throw new RuntimeException JavaDoc(ioe.getMessage());
919         } catch (FOPException fe) {
920             log.error("startList: " + fe.getMessage());
921             throw new RuntimeException JavaDoc(fe.getMessage());
922         } catch (Exception JavaDoc e) {
923             log.error("startList: " + e.getMessage());
924             throw new RuntimeException JavaDoc(e.getMessage());
925         }
926     }
927
928     /**
929      * @see org.apache.fop.fo.FOEventHandler#endList(ListBlock)
930      * @param lb ListBlock that is ending
931      */

932     public void endList(ListBlock lb) {
933         if (bDefer) {
934             return;
935         }
936
937         builderContext.popContainer();
938     }
939
940     /**
941      * @see org.apache.fop.fo.FOEventHandler#startListItem(ListItem)
942      * @param li ListItem that is starting
943      */

944     public void startListItem(ListItem li) {
945         if (bDefer) {
946             return;
947         }
948         
949         // create an RtfListItem in the current RtfList
950
try {
951             RtfList list = (RtfList)builderContext.getContainer(
952                     RtfList.class, true, this);
953             
954             /**
955              * If the current list already contains a list item, then close the
956              * list and open a new one, so every single list item gets its own
957              * list. This allows every item to have a different list label.
958              * If all the items would be in the same list, they had all the
959              * same label.
960              */

961             //TODO: do this only, if the labels content <> previous labels content
962
if (list.getChildCount() > 0) {
963                 this.endListBody();
964                 this.endList((ListBlock) li.getParent());
965                 this.startList((ListBlock) li.getParent());
966                 this.startListBody();
967                 
968                 list = (RtfList)builderContext.getContainer(
969                         RtfList.class, true, this);
970             }
971             
972             builderContext.pushContainer(list.newListItem());
973         } catch (IOException JavaDoc ioe) {
974             log.error("startList: " + ioe.getMessage());
975             throw new RuntimeException JavaDoc(ioe.getMessage());
976         } catch (Exception JavaDoc e) {
977             log.error("startList: " + e.getMessage());
978             throw new RuntimeException JavaDoc(e.getMessage());
979         }
980     }
981
982     /**
983      * @see org.apache.fop.fo.FOEventHandler#endListItem(ListItem)
984      * @param li ListItem that is ending
985      */

986     public void endListItem(ListItem li) {
987         if (bDefer) {
988             return;
989         }
990
991         builderContext.popContainer();
992     }
993
994     /**
995      * @see org.apache.fop.fo.FOEventHandler#startListLabel()
996      */

997     public void startListLabel() {
998         if (bDefer) {
999             return;
1000        }
1001
1002        try {
1003            RtfListItem item
1004                = (RtfListItem)builderContext.getContainer(RtfListItem.class, true, this);
1005
1006            RtfListItemLabel label = item.new RtfListItemLabel(item);
1007            builderContext.pushContainer(label);
1008        } catch (IOException JavaDoc ioe) {
1009            log.error("startPageNumber:" + ioe.getMessage());
1010            throw new RuntimeException JavaDoc(ioe.getMessage());
1011        } catch (Exception JavaDoc e) {
1012            log.error("startPageNumber: " + e.getMessage());
1013            throw new RuntimeException JavaDoc(e.getMessage());
1014        }
1015    }
1016
1017    /**
1018     * @see org.apache.fop.fo.FOEventHandler#endListLabel()
1019     */

1020    public void endListLabel() {
1021        if (bDefer) {
1022            return;
1023        }
1024
1025        builderContext.popContainer();
1026    }
1027
1028    /**
1029     * @see org.apache.fop.fo.FOEventHandler#startListBody()
1030     */

1031    public void startListBody() {
1032    }
1033
1034    /**
1035     * @see org.apache.fop.fo.FOEventHandler#endListBody()
1036     */

1037    public void endListBody() {
1038    }
1039
1040    // Static Regions
1041
/**
1042     * @see org.apache.fop.fo.FOEventHandler#startStatic()
1043     */

1044    public void startStatic() {
1045    }
1046
1047    /**
1048     * @see org.apache.fop.fo.FOEventHandler#endStatic()
1049     */

1050    public void endStatic() {
1051    }
1052
1053    /**
1054     * @see org.apache.fop.fo.FOEventHandler#startMarkup()
1055     */

1056    public void startMarkup() {
1057    }
1058
1059    /**
1060     * @see org.apache.fop.fo.FOEventHandler#endMarkup()
1061     */

1062    public void endMarkup() {
1063    }
1064
1065    /**
1066     * @see org.apache.fop.fo.FOEventHandler#startLink(BasicLink basicLink)
1067     * @param basicLink BasicLink that is starting
1068     */

1069    public void startLink(BasicLink basicLink) {
1070        if (bDefer) {
1071            return;
1072        }
1073
1074        try {
1075            IRtfTextrunContainer container
1076                = (IRtfTextrunContainer)builderContext.getContainer(
1077                    IRtfTextrunContainer.class, true, this);
1078
1079            RtfTextrun textrun = container.getTextrun();
1080
1081            RtfHyperLink link = textrun.addHyperlink(new RtfAttributes());
1082
1083            if (basicLink.getExternalDestination() != null) {
1084                link.setExternalURL(basicLink.getExternalDestination());
1085            } else {
1086                link.setInternalURL(basicLink.getInternalDestination());
1087            }
1088
1089            builderContext.pushContainer(link);
1090
1091        } catch (IOException JavaDoc ioe) {
1092            log.error("startLink:" + ioe.getMessage());
1093            throw new RuntimeException JavaDoc(ioe.getMessage());
1094        } catch (Exception JavaDoc e) {
1095            log.error("startLink: " + e.getMessage());
1096            throw new RuntimeException JavaDoc(e.getMessage());
1097        }
1098    }
1099
1100    /**
1101     * @see org.apache.fop.fo.FOEventHandler#endLink()
1102     */

1103    public void endLink() {
1104        if (bDefer) {
1105            return;
1106        }
1107
1108        builderContext.popContainer();
1109    }
1110
1111    /**
1112     * @see org.apache.fop.fo.FOEventHandler#image(ExternalGraphic)
1113     * @param eg ExternalGraphic that is starting
1114     */

1115    public void image(ExternalGraphic eg) {
1116        if (bDefer) {
1117            return;
1118        }
1119
1120        try {
1121            String JavaDoc url = eg.getURL();
1122
1123            //set image data
1124
FOUserAgent userAgent = eg.getUserAgent();
1125            ImageFactory fact = userAgent.getFactory().getImageFactory();
1126            FopImage fopimage = fact.getImage(url, userAgent);
1127            if (fopimage == null) {
1128                log.error("Image could not be found: " + url);
1129                return;
1130            }
1131            fopimage.load(FopImage.ORIGINAL_DATA);
1132            
1133            putGraphic(eg, fopimage);
1134        } catch (Exception JavaDoc e) {
1135            log.error("Error while handling an external-graphic: " + e.getMessage(), e);
1136        }
1137    }
1138
1139    /**
1140     * @see org.apache.fop.fo.FOEventHandler#foreignObject(InstreamForeignObject)
1141     * @param ifo InstreamForeignObject that is starting
1142     */

1143    public void foreignObject(InstreamForeignObject ifo) {
1144        if (bDefer) {
1145            return;
1146        }
1147        
1148        try {
1149            XMLObj child = (XMLObj) ifo.getChildXMLObj();
1150            Document JavaDoc doc = child.getDOMDocument();
1151            String JavaDoc ns = child.getNamespaceURI();
1152            
1153            if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
1154                // Build the image info.
1155
FopImage.ImageInfo info = new FopImage.ImageInfo();
1156                info.mimeType = "image/svg+xml";
1157                info.str = SVGDOMImplementation.SVG_NAMESPACE_URI;
1158                info.originalURI = "";
1159                info.data = doc;
1160
1161                // Set the resolution to that of the FOUserAgent
1162
FOUserAgent ua = ifo.getUserAgent();
1163                info.dpiHorizontal = 25.4f / ua.getSourcePixelUnitToMillimeter();
1164                info.dpiVertical = info.dpiHorizontal;
1165                
1166                // Set the image size to the size of the svg.
1167
Point2D JavaDoc csize = new Point2D.Float JavaDoc(-1, -1);
1168                Point2D JavaDoc intrinsicDimensions = child.getDimension(csize);
1169                info.width = (int) intrinsicDimensions.getX();
1170                info.height = (int) intrinsicDimensions.getY();
1171                
1172                FopImage fopImage = new XMLImage(info);
1173                fopImage.load(FopImage.ORIGINAL_DATA);
1174
1175                putGraphic(ifo, fopImage);
1176            } else {
1177                log.warn("The namespace " + ns
1178                        + " for instream-foreign-objects is not supported.");
1179            }
1180            
1181            
1182        } catch (Exception JavaDoc e) {
1183            log.error("Error while handling an instream-foreign-object: " + e.getMessage(), e);
1184        }
1185    }
1186
1187    /**
1188     * Puts a graphic/image into the generated RTF file.
1189     * @param abstractGraphic the graphic (external-graphic or instream-foreign-object)
1190     * @param fopImage the image
1191     * @throws IOException In case of an I/O error
1192     */

1193    private void putGraphic(AbstractGraphics abstractGraphic, FopImage fopImage)
1194            throws IOException JavaDoc {
1195        byte[] rawData;
1196        if ("image/svg+xml".equals(fopImage.getMimeType())) {
1197            rawData = SVGConverter.convertToJPEG((XMLImage) fopImage);
1198        } else {
1199            rawData = fopImage.getRessourceBytes();
1200        }
1201        if (rawData == null) {
1202            log.warn(FONode.decorateWithContextInfo("Image could not be embedded: "
1203                    + fopImage.getOriginalURI(), abstractGraphic));
1204            return;
1205        }
1206
1207        final IRtfTextrunContainer c
1208            = (IRtfTextrunContainer)builderContext.getContainer(
1209                IRtfTextrunContainer.class, true, this);
1210
1211        final RtfExternalGraphic rtfGraphic = c.getTextrun().newImage();
1212   
1213        //set URL
1214
rtfGraphic.setURL(fopImage.getOriginalURI());
1215        rtfGraphic.setImageData(rawData);
1216
1217        //set scaling
1218
if (abstractGraphic.getScaling() == Constants.EN_UNIFORM) {
1219            rtfGraphic.setScaling ("uniform");
1220        }
1221
1222        //get width
1223
int width = 0;
1224        if (abstractGraphic.getWidth().getEnum() == Constants.EN_AUTO) {
1225            width = fopImage.getIntrinsicWidth();
1226        } else {
1227            width = abstractGraphic.getWidth().getValue();
1228        }
1229
1230        //get height
1231
int height = 0;
1232        if (abstractGraphic.getWidth().getEnum() == Constants.EN_AUTO) {
1233            height = fopImage.getIntrinsicHeight();
1234        } else {
1235            height = abstractGraphic.getHeight().getValue();
1236        }
1237
1238        //get content-width
1239
int contentwidth = 0;
1240        if (abstractGraphic.getContentWidth().getEnum()
1241                == Constants.EN_AUTO) {
1242            contentwidth = fopImage.getIntrinsicWidth();
1243        } else if (abstractGraphic.getContentWidth().getEnum()
1244                == Constants.EN_SCALE_TO_FIT) {
1245            contentwidth = width;
1246        } else {
1247            //TODO: check, if the value is a percent value
1248
contentwidth = abstractGraphic.getContentWidth().getValue();
1249        }
1250
1251        //get content-width
1252
int contentheight = 0;
1253        if (abstractGraphic.getContentHeight().getEnum()
1254                == Constants.EN_AUTO) {
1255
1256            contentheight = fopImage.getIntrinsicHeight();
1257
1258        } else if (abstractGraphic.getContentHeight().getEnum()
1259                == Constants.EN_SCALE_TO_FIT) {
1260
1261            contentheight = height;
1262        } else {
1263            //TODO: check, if the value is a percent value
1264
contentheight = abstractGraphic.getContentHeight().getValue();
1265        }
1266
1267        //set width in rtf
1268
//newGraphic.setWidth((long) (contentwidth / 1000f) + "pt");
1269
rtfGraphic.setWidth((long) (contentwidth / 50f) + "twips");
1270
1271        //set height in rtf
1272
//newGraphic.setHeight((long) (contentheight / 1000f) + "pt");
1273
rtfGraphic.setHeight((long) (contentheight / 50f) + "twips");
1274
1275        //TODO: make this configurable:
1276
// int compression = m_context.m_options.getRtfExternalGraphicCompressionRate ();
1277
int compression = 0;
1278        if (compression != 0) {
1279            if (!rtfGraphic.setCompressionRate(compression)) {
1280                log.warn("The compression rate " + compression
1281                    + " is invalid. The value has to be between 1 and 100 %.");
1282            }
1283        }
1284    }
1285    
1286    /**
1287     * @see org.apache.fop.fo.FOEventHandler#pageRef()
1288     */

1289    public void pageRef() {
1290    }
1291
1292    /**
1293     * @see org.apache.fop.fo.FOEventHandler#startFootnote(Footnote)
1294     * @param footnote Footnote that is starting
1295     */

1296    public void startFootnote(Footnote footnote) {
1297        if (bDefer) {
1298            return;
1299        }
1300
1301        try {
1302            IRtfTextrunContainer container
1303                = (IRtfTextrunContainer)builderContext.getContainer(
1304                    IRtfTextrunContainer.class,
1305                    true, this);
1306
1307            RtfTextrun textrun = container.getTextrun();
1308            RtfFootnote rtfFootnote = textrun.addFootnote();
1309
1310            builderContext.pushContainer(rtfFootnote);
1311
1312        } catch (IOException JavaDoc ioe) {
1313            // TODO could we throw Exception in all FOEventHandler events?
1314
log.error("startFootnote: " + ioe.getMessage());
1315            throw new RuntimeException JavaDoc("IOException: " + ioe);
1316        } catch (Exception JavaDoc e) {
1317            log.error("startFootnote: " + e.getMessage());
1318            throw new RuntimeException JavaDoc("Exception: " + e);
1319        }
1320    }
1321
1322    /**
1323     * @see org.apache.fop.fo.FOEventHandler#endFootnote(Footnote)
1324     * @param footnote Footnote that is ending
1325     */

1326    public void endFootnote(Footnote footnote) {
1327        if (bDefer) {
1328            return;
1329        }
1330
1331        builderContext.popContainer();
1332    }
1333
1334    /**
1335     * @see org.apache.fop.fo.FOEventHandler#startFootnoteBody(FootnoteBody)
1336     * @param body FootnoteBody that is starting
1337     */

1338    public void startFootnoteBody(FootnoteBody body) {
1339        if (bDefer) {
1340            return;
1341        }
1342
1343        try {
1344            RtfFootnote rtfFootnote
1345                = (RtfFootnote)builderContext.getContainer(
1346                    RtfFootnote.class,
1347                    true, this);
1348
1349            rtfFootnote.startBody();
1350        } catch (IOException JavaDoc ioe) {
1351            // TODO could we throw Exception in all FOEventHandler events?
1352
log.error("startFootnoteBody: " + ioe.getMessage());
1353            throw new RuntimeException JavaDoc("IOException: " + ioe);
1354        } catch (Exception JavaDoc e) {
1355            log.error("startFootnoteBody: " + e.getMessage());
1356            throw new RuntimeException JavaDoc("Exception: " + e);
1357        }
1358    }
1359
1360    /**
1361     * @see org.apache.fop.fo.FOEventHandler#endFootnoteBody(FootnoteBody)
1362     * @param body FootnoteBody that is ending
1363     */

1364    public void endFootnoteBody(FootnoteBody body) {
1365        if (bDefer) {
1366            return;
1367        }
1368
1369        try {
1370            RtfFootnote rtfFootnote
1371                = (RtfFootnote)builderContext.getContainer(
1372                    RtfFootnote.class,
1373                    true, this);
1374
1375            rtfFootnote.endBody();
1376        } catch (IOException JavaDoc ioe) {
1377            // TODO could we throw Exception in all FOEventHandler events?
1378
log.error("endFootnoteBody: " + ioe.getMessage());
1379            throw new RuntimeException JavaDoc("IOException: " + ioe);
1380        } catch (Exception JavaDoc e) {
1381            log.error("endFootnoteBody: " + e.getMessage());
1382            throw new RuntimeException JavaDoc("Exception: " + e);
1383        }
1384    }
1385
1386    /**
1387     * @see org.apache.fop.fo.FOEventHandler#leader(Leader)
1388     * @param l Leader that is starting
1389     */

1390    public void leader(Leader l) {
1391    }
1392
1393    /**
1394     * @param text FOText object
1395     * @param data Array of characters to process.
1396     * @param start Offset for characters to process.
1397     * @param length Portion of array to process.
1398     */

1399    public void text(FOText text, char[] data, int start, int length) {
1400        if (bDefer) {
1401            return;
1402        }
1403
1404        try {
1405            IRtfTextrunContainer container
1406                = (IRtfTextrunContainer)builderContext.getContainer(
1407                    IRtfTextrunContainer.class, true, this);
1408
1409            RtfTextrun textrun = container.getTextrun();
1410            RtfAttributes rtfAttr
1411                = TextAttributesConverter.convertCharacterAttributes(text);
1412
1413            textrun.pushInlineAttributes(rtfAttr);
1414            textrun.addString(new String JavaDoc(data, start, length - start));
1415            textrun.popInlineAttributes();
1416         } catch (IOException JavaDoc ioe) {
1417            // FIXME could we throw Exception in all FOEventHandler events?
1418
log.error("characters: " + ioe.getMessage());
1419            throw new RuntimeException JavaDoc(ioe.getMessage());
1420        } catch (Exception JavaDoc e) {
1421            log.error("characters:" + e.getMessage());
1422            throw new RuntimeException JavaDoc(e.getMessage());
1423        }
1424    }
1425
1426    /**
1427     *
1428     * @param pagenum PageNumber that is starting.
1429     */

1430    public void startPageNumber(PageNumber pagenum) {
1431        if (bDefer) {
1432            return;
1433        }
1434
1435        try {
1436            RtfAttributes rtfAttr
1437                = TextAttributesConverter.convertCharacterAttributes(
1438                    pagenum);
1439
1440            IRtfTextrunContainer container
1441                = (IRtfTextrunContainer)builderContext.getContainer(
1442                    IRtfTextrunContainer.class, true, this);
1443
1444            RtfTextrun textrun = container.getTextrun();
1445            textrun.addPageNumber(rtfAttr);
1446        } catch (IOException JavaDoc ioe) {
1447            log.error("startPageNumber:" + ioe.getMessage());
1448            throw new RuntimeException JavaDoc(ioe.getMessage());
1449        } catch (Exception JavaDoc e) {
1450            log.error("startPageNumber: " + e.getMessage());
1451            throw new RuntimeException JavaDoc(e.getMessage());
1452        }
1453    }
1454
1455    /**
1456     *
1457     * @param pagenum PageNumber that is ending.
1458     */

1459    public void endPageNumber(PageNumber pagenum) {
1460        if (bDefer) {
1461            return;
1462        }
1463    }
1464
1465    /**
1466     * Calls the appropriate event handler for the passed FObj.
1467     *
1468     * @param foNode FO node whose event is to be called
1469     * @param bStart TRUE calls the start handler, FALSE the end handler
1470     */

1471    private void invokeDeferredEvent(FONode foNode, boolean bStart) {
1472        if (foNode instanceof PageSequence) {
1473            if (bStart) {
1474                startPageSequence( (PageSequence) foNode);
1475            } else {
1476                endPageSequence( (PageSequence) foNode);
1477            }
1478        } else if (foNode instanceof Flow) {
1479            if (bStart) {
1480                startFlow( (Flow) foNode);
1481            } else {
1482                endFlow( (Flow) foNode);
1483            }
1484        } else if (foNode instanceof StaticContent) {
1485            if (bStart) {
1486                startStatic();
1487            } else {
1488                endStatic();
1489            }
1490        } else if (foNode instanceof ExternalGraphic) {
1491            if (bStart) {
1492                image( (ExternalGraphic) foNode );
1493            }
1494        } else if (foNode instanceof InstreamForeignObject) {
1495            if (bStart) {
1496                foreignObject( (InstreamForeignObject) foNode );
1497            }
1498        } else if (foNode instanceof Block) {
1499            if (bStart) {
1500                startBlock( (Block) foNode);
1501            } else {
1502                endBlock( (Block) foNode);
1503            }
1504        } else if (foNode instanceof BlockContainer) {
1505            if (bStart) {
1506                startBlockContainer( (BlockContainer) foNode);
1507            } else {
1508                endBlockContainer( (BlockContainer) foNode);
1509            }
1510        } else if (foNode instanceof BasicLink) {
1511            //BasicLink must be placed before Inline
1512
if (bStart) {
1513                startLink( (BasicLink) foNode);
1514            } else {
1515                endLink();
1516            }
1517        } else if (foNode instanceof Inline) {
1518            if (bStart) {
1519                startInline( (Inline) foNode);
1520            } else {
1521                endInline( (Inline) foNode);
1522            }
1523        } else if (foNode instanceof FOText) {
1524            if (bStart) {
1525                FOText text = (FOText) foNode;
1526                text(text, text.ca, text.startIndex, text.endIndex);
1527            }
1528        } else if (foNode instanceof Character JavaDoc) {
1529            if (bStart) {
1530                Character JavaDoc c = (Character JavaDoc) foNode;
1531                character(c);
1532            }
1533        } else if (foNode instanceof PageNumber) {
1534            if (bStart) {
1535                startPageNumber( (PageNumber) foNode);
1536            } else {
1537                endPageNumber( (PageNumber) foNode);
1538            }
1539        } else if (foNode instanceof Footnote) {
1540            if (bStart) {
1541                startFootnote( (Footnote) foNode);
1542            } else {
1543                endFootnote( (Footnote) foNode);
1544            }
1545        } else if (foNode instanceof FootnoteBody) {
1546            if (bStart) {
1547                startFootnoteBody( (FootnoteBody) foNode);
1548            } else {
1549                endFootnoteBody( (FootnoteBody) foNode);
1550            }
1551        } else if (foNode instanceof ListBlock) {
1552            if (bStart) {
1553                startList( (ListBlock) foNode);
1554            } else {
1555                endList( (ListBlock) foNode);
1556            }
1557        } else if (foNode instanceof ListItemBody) {
1558            if (bStart) {
1559                startListBody();
1560            } else {
1561                endListBody();
1562            }
1563        } else if (foNode instanceof ListItem) {
1564            if (bStart) {
1565                startListItem( (ListItem) foNode);
1566            } else {
1567                endListItem( (ListItem) foNode);
1568            }
1569        } else if (foNode instanceof ListItemLabel) {
1570            if (bStart) {
1571                startListLabel();
1572            } else {
1573                endListLabel();
1574            }
1575        } else if (foNode instanceof Table) {
1576            if (bStart) {
1577                startTable( (Table) foNode);
1578            } else {
1579                endTable( (Table) foNode);
1580            }
1581        } else if (foNode instanceof TableBody) {
1582            if (bStart) {
1583                startBody( (TableBody) foNode);
1584            } else {
1585                endBody( (TableBody) foNode);
1586            }
1587        } else if (foNode instanceof TableColumn) {
1588            if (bStart) {
1589                startColumn( (TableColumn) foNode);
1590            } else {
1591                endColumn( (TableColumn) foNode);
1592            }
1593        } else if (foNode instanceof TableRow) {
1594            if (bStart) {
1595                startRow( (TableRow) foNode);
1596            } else {
1597                endRow( (TableRow) foNode);
1598            }
1599        } else if (foNode instanceof TableCell) {
1600            if (bStart) {
1601                startCell( (TableCell) foNode);
1602            } else {
1603                endCell( (TableCell) foNode);
1604            }
1605        } else {
1606            log.warn("Ignored deferred event for " + foNode);
1607        }
1608    }
1609
1610    /**
1611     * Calls the event handlers for the passed FONode and all its elements.
1612     *
1613     * @param foNode FONode object which shall be recursed
1614     */

1615    private void recurseFONode(FONode foNode) {
1616        invokeDeferredEvent(foNode, true);
1617
1618        if (foNode instanceof PageSequence) {
1619            PageSequence pageSequence = (PageSequence) foNode;
1620
1621            Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
1622            if (regionBefore != null) {
1623                FONode staticBefore = (FONode) pageSequence.getFlowMap().get(
1624                        regionBefore.getRegionName());
1625                if (staticBefore != null) {
1626                    recurseFONode(staticBefore);
1627                }
1628            }
1629            Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
1630            if (regionAfter != null) {
1631                FONode staticAfter = (FONode) pageSequence.getFlowMap().get(
1632                        regionAfter.getRegionName());
1633                if (staticAfter != null) {
1634                    recurseFONode(staticAfter);
1635                }
1636            }
1637
1638
1639            recurseFONode( pageSequence.getMainFlow() );
1640        } else if (foNode instanceof Table) {
1641            Table table = (Table) foNode;
1642
1643            //recurse all table-columns
1644
if (table.getColumns() != null) {
1645                for (Iterator JavaDoc it = table.getColumns().iterator(); it.hasNext();) {
1646                    recurseFONode( (FONode) it.next() );
1647                }
1648            } else {
1649                //TODO Implement implicit column setup handling!
1650
log.warn("No table-columns found on table. RTF output requires that all"
1651                        + " table-columns for a table are defined. Output will be incorrect.");
1652            }
1653
1654            //recurse table-header
1655
if (table.getTableHeader() != null) {
1656                recurseFONode( table.getTableHeader() );
1657            }
1658
1659            //recurse table-footer
1660
if (table.getTableFooter() != null) {
1661                recurseFONode( table.getTableFooter() );
1662            }
1663
1664            if (foNode.getChildNodes() != null) {
1665                for (Iterator JavaDoc it = foNode.getChildNodes(); it.hasNext();) {
1666                    recurseFONode( (FONode) it.next() );
1667                }
1668            }
1669        } else if (foNode instanceof ListItem) {
1670            ListItem item = (ListItem) foNode;
1671
1672            recurseFONode(item.getLabel());
1673            recurseFONode(item.getBody());
1674        } else if (foNode instanceof Footnote) {
1675            Footnote fn = (Footnote)foNode;
1676
1677            recurseFONode(fn.getFootnoteCitation());
1678            recurseFONode(fn.getFootnoteBody());
1679        } else {
1680            //Any other FO-Object: Simply recurse through all childNodes.
1681
if (foNode.getChildNodes() != null) {
1682                for (Iterator JavaDoc it = foNode.getChildNodes(); it.hasNext();) {
1683                    FONode fn = (FONode)it.next();
1684                    if (log.isTraceEnabled()) {
1685                        log.trace(" ChildNode for " + fn + " (" + fn.getName() + ")");
1686                    }
1687                    recurseFONode(fn);
1688                }
1689            }
1690        }
1691
1692        invokeDeferredEvent(foNode, false);
1693    }
1694}
1695
Popular Tags