You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RTFHandler.java 56KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  1. /*
  2. * Copyright 1999-2006 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.render.rtf;
  18. // Java
  19. import java.io.IOException;
  20. import java.io.OutputStream;
  21. import java.io.OutputStreamWriter;
  22. import java.util.Iterator;
  23. // Libs
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.xml.sax.SAXException;
  27. // FOP
  28. import org.apache.fop.apps.FOPException;
  29. import org.apache.fop.apps.FOUserAgent;
  30. import org.apache.fop.datatypes.LengthBase;
  31. import org.apache.fop.datatypes.SimplePercentBaseContext;
  32. import org.apache.fop.fo.FOEventHandler;
  33. import org.apache.fop.fo.FONode;
  34. import org.apache.fop.fo.flow.BasicLink;
  35. import org.apache.fop.fo.flow.Block;
  36. import org.apache.fop.fo.flow.BlockContainer;
  37. import org.apache.fop.fo.flow.Character;
  38. import org.apache.fop.fo.flow.ExternalGraphic;
  39. import org.apache.fop.fo.flow.Footnote;
  40. import org.apache.fop.fo.flow.FootnoteBody;
  41. import org.apache.fop.fo.flow.Inline;
  42. import org.apache.fop.fo.flow.InstreamForeignObject;
  43. import org.apache.fop.fo.flow.Leader;
  44. import org.apache.fop.fo.flow.ListBlock;
  45. import org.apache.fop.fo.flow.ListItem;
  46. import org.apache.fop.fo.flow.ListItemBody;
  47. import org.apache.fop.fo.flow.ListItemLabel;
  48. import org.apache.fop.fo.flow.PageNumber;
  49. import org.apache.fop.fo.flow.Table;
  50. import org.apache.fop.fo.flow.TableColumn;
  51. import org.apache.fop.fo.flow.TableBody;
  52. import org.apache.fop.fo.flow.TableCell;
  53. import org.apache.fop.fo.flow.TableHeader;
  54. import org.apache.fop.fo.flow.TableRow;
  55. import org.apache.fop.fo.pagination.Flow;
  56. import org.apache.fop.fo.pagination.PageSequence;
  57. import org.apache.fop.fo.pagination.PageSequenceMaster;
  58. import org.apache.fop.fo.pagination.Region;
  59. import org.apache.fop.fo.pagination.SimplePageMaster;
  60. import org.apache.fop.fo.pagination.StaticContent;
  61. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  62. import org.apache.fop.fo.Constants;
  63. import org.apache.fop.fo.FOText;
  64. import org.apache.fop.render.DefaultFontResolver;
  65. import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes;
  66. import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer;
  67. import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer;
  68. import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfListContainer;
  69. import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTextrunContainer;
  70. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAfter;
  71. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
  72. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfBefore;
  73. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfDocumentArea;
  74. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfElement;
  75. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfExternalGraphic;
  76. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFile;
  77. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFootnote;
  78. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink;
  79. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList;
  80. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem;
  81. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel;
  82. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
  83. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun;
  84. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
  85. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
  86. import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
  87. import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTableContainer;
  88. import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
  89. import org.apache.fop.render.rtf.rtflib.tools.TableContext;
  90. import org.apache.fop.fonts.FontSetup;
  91. import org.apache.fop.image.FopImage;
  92. import org.apache.fop.image.ImageFactory;
  93. import org.apache.fop.image.XMLImage;
  94. /**
  95. * RTF Handler: generates RTF output using the structure events from
  96. * the FO Tree sent to this structure handler.
  97. *
  98. * @author Bertrand Delacretaz <bdelacretaz@codeconsult.ch>
  99. * @author Trembicki-Guy, Ed <GuyE@DNB.com>
  100. * @author Boris Poudérous <boris.pouderous@eads-telecom.com>
  101. * @author Peter Herweg <pherweg@web.de>
  102. * @author Andreas Putz <a.putz@skynamics.com>
  103. */
  104. public class RTFHandler extends FOEventHandler {
  105. private RtfFile rtfFile;
  106. private final OutputStream os;
  107. private static Log log = LogFactory.getLog(RTFHandler.class);
  108. private RtfSection sect;
  109. private RtfDocumentArea docArea;
  110. private boolean bDefer; //true, if each called handler shall be
  111. //processed at later time.
  112. private boolean bPrevHeaderSpecified = false; //true, if there has been a
  113. //header in any page-sequence
  114. private boolean bPrevFooterSpecified = false; //true, if there has been a
  115. //footer in any page-sequence
  116. private boolean bHeaderSpecified = false; //true, if there is a header
  117. //in current page-sequence
  118. private boolean bFooterSpecified = false; //true, if there is a footer
  119. //in current page-sequence
  120. private BuilderContext builderContext = new BuilderContext(null);
  121. private SimplePageMaster pagemaster;
  122. /**
  123. * Creates a new RTF structure handler.
  124. * @param userAgent the FOUserAgent for this process
  125. * @param os OutputStream to write to
  126. */
  127. public RTFHandler(FOUserAgent userAgent, OutputStream os) {
  128. super(userAgent);
  129. this.os = os;
  130. bDefer = true;
  131. FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent));
  132. }
  133. /**
  134. * @see org.apache.fop.fo.FOEventHandler#startDocument()
  135. * @throws SAXException In case of a IO-problem
  136. */
  137. public void startDocument() throws SAXException {
  138. // TODO sections should be created
  139. try {
  140. rtfFile = new RtfFile(new OutputStreamWriter(os));
  141. docArea = rtfFile.startDocumentArea();
  142. } catch (IOException ioe) {
  143. // TODO could we throw Exception in all FOEventHandler events?
  144. throw new SAXException(ioe);
  145. }
  146. }
  147. /**
  148. * @see org.apache.fop.fo.FOEventHandler#endDocument()
  149. * @throws SAXException In case of a IO-problem
  150. */
  151. public void endDocument() throws SAXException {
  152. try {
  153. rtfFile.flush();
  154. } catch (IOException ioe) {
  155. // TODO could we throw Exception in all FOEventHandler events?
  156. throw new SAXException(ioe);
  157. }
  158. }
  159. /**
  160. * @see org.apache.fop.fo.FOEventHandler
  161. * @param pageSeq PageSequence that is starting
  162. */
  163. public void startPageSequence(PageSequence pageSeq) {
  164. try {
  165. //This is needed for region handling
  166. if (this.pagemaster == null) {
  167. String reference = pageSeq.getMasterReference();
  168. this.pagemaster
  169. = pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(reference);
  170. if (this.pagemaster == null) {
  171. log.warn("Only simple-page-masters are supported on page-sequences: "
  172. + reference);
  173. log.warn("Using default simple-page-master from page-sequence-master...");
  174. PageSequenceMaster master
  175. = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference);
  176. this.pagemaster = master.getNextSimplePageMaster(false, false, false, false);
  177. }
  178. }
  179. if (bDefer) {
  180. return;
  181. }
  182. sect = docArea.newSection();
  183. //read page size and margins, if specified
  184. //only simple-page-master supported, so pagemaster may be null
  185. if (pagemaster != null) {
  186. sect.getRtfAttributes().set(
  187. PageAttributesConverter.convertPageAttributes(
  188. pagemaster));
  189. } else {
  190. log.warn("No simple-page-master could be determined!");
  191. }
  192. builderContext.pushContainer(sect);
  193. bHeaderSpecified = false;
  194. bFooterSpecified = false;
  195. } catch (IOException ioe) {
  196. // TODO could we throw Exception in all FOEventHandler events?
  197. log.error("startPageSequence: " + ioe.getMessage(), ioe);
  198. //TODO throw new FOPException(ioe);
  199. } catch (FOPException fope) {
  200. // TODO could we throw Exception in all FOEventHandler events?
  201. log.error("startPageSequence: " + fope.getMessage(), fope);
  202. }
  203. }
  204. /**
  205. * @see org.apache.fop.fo.FOEventHandler#endPageSequence(PageSequence)
  206. * @param pageSeq PageSequence that is ending
  207. */
  208. public void endPageSequence(PageSequence pageSeq) {
  209. if (bDefer) {
  210. //If endBlock was called while SAX parsing, and the passed FO is Block
  211. //nested within another Block, stop deferring.
  212. //Now process all deferred FOs.
  213. bDefer = false;
  214. recurseFONode(pageSeq);
  215. this.pagemaster = null;
  216. bDefer = true;
  217. return;
  218. } else {
  219. builderContext.popContainer();
  220. this.pagemaster = null;
  221. }
  222. }
  223. /**
  224. * @see org.apache.fop.fo.FOEventHandler#startFlow(Flow)
  225. * @param fl Flow that is starting
  226. */
  227. public void startFlow(Flow fl) {
  228. if (bDefer) {
  229. return;
  230. }
  231. try {
  232. log.debug("starting flow: " + fl.getFlowName());
  233. boolean handled = false;
  234. Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
  235. Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
  236. Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
  237. if (fl.getFlowName().equals(regionBody.getRegionName())) {
  238. // if there is no header in current page-sequence but there has been
  239. // a header in a previous page-sequence, insert an empty header.
  240. if (bPrevHeaderSpecified && !bHeaderSpecified) {
  241. RtfAttributes attr = new RtfAttributes();
  242. attr.set(RtfBefore.HEADER);
  243. final IRtfBeforeContainer contBefore
  244. = (IRtfBeforeContainer)builderContext.getContainer
  245. (IRtfBeforeContainer.class, true, this);
  246. contBefore.newBefore(attr);
  247. }
  248. // if there is no footer in current page-sequence but there has been
  249. // a footer in a previous page-sequence, insert an empty footer.
  250. if (bPrevFooterSpecified && !bFooterSpecified) {
  251. RtfAttributes attr = new RtfAttributes();
  252. attr.set(RtfAfter.FOOTER);
  253. final IRtfAfterContainer contAfter
  254. = (IRtfAfterContainer)builderContext.getContainer
  255. (IRtfAfterContainer.class, true, this);
  256. contAfter.newAfter(attr);
  257. }
  258. handled = true;
  259. } else if (regionBefore != null
  260. && fl.getFlowName().equals(regionBefore.getRegionName())) {
  261. bHeaderSpecified = true;
  262. bPrevHeaderSpecified = true;
  263. final IRtfBeforeContainer c
  264. = (IRtfBeforeContainer)builderContext.getContainer(
  265. IRtfBeforeContainer.class,
  266. true, this);
  267. RtfAttributes beforeAttributes = ((RtfElement)c).getRtfAttributes();
  268. if (beforeAttributes == null) {
  269. beforeAttributes = new RtfAttributes();
  270. }
  271. beforeAttributes.set(RtfBefore.HEADER);
  272. RtfBefore before = c.newBefore(beforeAttributes);
  273. builderContext.pushContainer(before);
  274. handled = true;
  275. } else if (regionAfter != null
  276. && fl.getFlowName().equals(regionAfter.getRegionName())) {
  277. bFooterSpecified = true;
  278. bPrevFooterSpecified = true;
  279. final IRtfAfterContainer c
  280. = (IRtfAfterContainer)builderContext.getContainer(
  281. IRtfAfterContainer.class,
  282. true, this);
  283. RtfAttributes afterAttributes = ((RtfElement)c).getRtfAttributes();
  284. if (afterAttributes == null) {
  285. afterAttributes = new RtfAttributes();
  286. }
  287. afterAttributes.set(RtfAfter.FOOTER);
  288. RtfAfter after = c.newAfter(afterAttributes);
  289. builderContext.pushContainer(after);
  290. handled = true;
  291. }
  292. if (!handled) {
  293. log.warn("A " + fl.getLocalName() + " has been skipped: " + fl.getFlowName());
  294. }
  295. } catch (IOException ioe) {
  296. log.error("startFlow: " + ioe.getMessage());
  297. throw new RuntimeException(ioe.getMessage());
  298. } catch (Exception e) {
  299. log.error("startFlow: " + e.getMessage());
  300. throw new RuntimeException(e.getMessage());
  301. }
  302. }
  303. /**
  304. * @see org.apache.fop.fo.FOEventHandler#endFlow(Flow)
  305. * @param fl Flow that is ending
  306. */
  307. public void endFlow(Flow fl) {
  308. if (bDefer) {
  309. return;
  310. }
  311. try {
  312. Region regionBody = pagemaster.getRegion(Constants.FO_REGION_BODY);
  313. Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
  314. Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
  315. if (fl.getFlowName().equals(regionBody.getRegionName())) {
  316. //just do nothing
  317. } else if (regionBefore != null
  318. && fl.getFlowName().equals(regionBefore.getRegionName())) {
  319. builderContext.popContainer();
  320. } else if (regionAfter != null
  321. && fl.getFlowName().equals(regionAfter.getRegionName())) {
  322. builderContext.popContainer();
  323. }
  324. } catch (Exception e) {
  325. log.error("endFlow: " + e.getMessage());
  326. throw new RuntimeException(e.getMessage());
  327. }
  328. }
  329. /**
  330. * @see org.apache.fop.fo.FOEventHandler#startBlock(Block)
  331. * @param bl Block that is starting
  332. */
  333. public void startBlock(Block bl) {
  334. if (bDefer) {
  335. return;
  336. }
  337. try {
  338. RtfAttributes rtfAttr
  339. = TextAttributesConverter.convertAttributes(bl);
  340. IRtfTextrunContainer container
  341. = (IRtfTextrunContainer)builderContext.getContainer(
  342. IRtfTextrunContainer.class,
  343. true, this);
  344. RtfTextrun textrun = container.getTextrun();
  345. textrun.addParagraphBreak();
  346. textrun.pushBlockAttributes(rtfAttr);
  347. textrun.addBookmark(bl.getId());
  348. } catch (IOException ioe) {
  349. // TODO could we throw Exception in all FOEventHandler events?
  350. log.error("startBlock: " + ioe.getMessage());
  351. throw new RuntimeException("IOException: " + ioe);
  352. } catch (Exception e) {
  353. log.error("startBlock: " + e.getMessage());
  354. throw new RuntimeException("Exception: " + e);
  355. }
  356. }
  357. /**
  358. * @see org.apache.fop.fo.FOEventHandler#endBlock(Block)
  359. * @param bl Block that is ending
  360. */
  361. public void endBlock(Block bl) {
  362. if (bDefer) {
  363. return;
  364. }
  365. try {
  366. IRtfTextrunContainer container
  367. = (IRtfTextrunContainer)builderContext.getContainer(
  368. IRtfTextrunContainer.class,
  369. true, this);
  370. RtfTextrun textrun = container.getTextrun();
  371. textrun.addParagraphBreak();
  372. textrun.popBlockAttributes();
  373. } catch (IOException ioe) {
  374. log.error("startBlock:" + ioe.getMessage());
  375. throw new RuntimeException(ioe.getMessage());
  376. } catch (Exception e) {
  377. log.error("startBlock:" + e.getMessage());
  378. throw new RuntimeException(e.getMessage());
  379. }
  380. }
  381. /**
  382. * @see org.apache.fop.fo.FOEventHandler#startBlockContainer(BlockContainer)
  383. * @param blc BlockContainer that is starting
  384. */
  385. public void startBlockContainer(BlockContainer blc) {
  386. if (bDefer) {
  387. return;
  388. }
  389. try {
  390. RtfAttributes rtfAttr
  391. = TextAttributesConverter.convertBlockContainerAttributes(blc);
  392. IRtfTextrunContainer container
  393. = (IRtfTextrunContainer)builderContext.getContainer(
  394. IRtfTextrunContainer.class,
  395. true, this);
  396. RtfTextrun textrun = container.getTextrun();
  397. textrun.addParagraphBreak();
  398. textrun.pushBlockAttributes(rtfAttr);
  399. } catch (IOException ioe) {
  400. // TODO could we throw Exception in all FOEventHandler events?
  401. log.error("startBlock: " + ioe.getMessage());
  402. throw new RuntimeException("IOException: " + ioe);
  403. } catch (Exception e) {
  404. log.error("startBlock: " + e.getMessage());
  405. throw new RuntimeException("Exception: " + e);
  406. }
  407. }
  408. /**
  409. * @see org.apache.fop.fo.FOEventHandler#endBlockContainer(BlockContainer)
  410. * @param bl BlockContainer that is ending
  411. */
  412. public void endBlockContainer(BlockContainer bl) {
  413. if (bDefer) {
  414. return;
  415. }
  416. try {
  417. IRtfTextrunContainer container
  418. = (IRtfTextrunContainer)builderContext.getContainer(
  419. IRtfTextrunContainer.class,
  420. true, this);
  421. RtfTextrun textrun = container.getTextrun();
  422. textrun.addParagraphBreak();
  423. textrun.popBlockAttributes();
  424. } catch (IOException ioe) {
  425. log.error("startBlock:" + ioe.getMessage());
  426. throw new RuntimeException(ioe.getMessage());
  427. } catch (Exception e) {
  428. log.error("startBlock:" + e.getMessage());
  429. throw new RuntimeException(e.getMessage());
  430. }
  431. }
  432. /**
  433. * @see org.apache.fop.fo.FOEventHandler#startTable(Table)
  434. * @param tbl Table that is starting
  435. */
  436. public void startTable(Table tbl) {
  437. if (bDefer) {
  438. return;
  439. }
  440. // create an RtfTable in the current table container
  441. TableContext tableContext = new TableContext(builderContext);
  442. try {
  443. final IRtfTableContainer tc
  444. = (IRtfTableContainer)builderContext.getContainer(
  445. IRtfTableContainer.class, true, null);
  446. RtfAttributes atts
  447. = TableAttributesConverter.convertTableAttributes(tbl);
  448. RtfTable table = tc.newTable(atts, tableContext);
  449. CommonBorderPaddingBackground border = tbl.getCommonBorderPaddingBackground();
  450. RtfAttributes borderAttributes = new RtfAttributes();
  451. BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.BEFORE,
  452. borderAttributes, ITableAttributes.CELL_BORDER_TOP);
  453. BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.AFTER,
  454. borderAttributes, ITableAttributes.CELL_BORDER_BOTTOM);
  455. BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.START,
  456. borderAttributes, ITableAttributes.CELL_BORDER_LEFT);
  457. BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.END,
  458. borderAttributes, ITableAttributes.CELL_BORDER_RIGHT);
  459. table.setBorderAttributes(borderAttributes);
  460. builderContext.pushContainer(table);
  461. } catch (Exception e) {
  462. log.error("startTable:" + e.getMessage());
  463. throw new RuntimeException(e.getMessage());
  464. }
  465. builderContext.pushTableContext(tableContext);
  466. }
  467. /**
  468. * @see org.apache.fop.fo.FOEventHandler#endTable(Table)
  469. * @param tbl Table that is ending
  470. */
  471. public void endTable(Table tbl) {
  472. if (bDefer) {
  473. return;
  474. }
  475. builderContext.popTableContext();
  476. builderContext.popContainer();
  477. }
  478. /**
  479. *
  480. * @param tc TableColumn that is starting;
  481. */
  482. public void startColumn(TableColumn tc) {
  483. if (bDefer) {
  484. return;
  485. }
  486. try {
  487. /**
  488. * Pass a SimplePercentBaseContext to getValue in order to
  489. * avoid a NullPointerException, which occurs when you use
  490. * proportional-column-width function in column-width attribute.
  491. * Of course the results won't be correct, but at least the
  492. * rest of the document will be rendered. Usage of the
  493. * TableLayoutManager is not welcome due to design reasons and
  494. * it also does not provide the correct values.
  495. * TODO: Make proportional-column-width working for rtf output
  496. */
  497. SimplePercentBaseContext context
  498. = new SimplePercentBaseContext(null,
  499. LengthBase.TABLE_UNITS,
  500. 100000);
  501. Integer iWidth
  502. = new Integer(tc.getColumnWidth().getValue(context) / 1000);
  503. String strWidth = iWidth.toString() + "pt";
  504. Float width = new Float(
  505. FoUnitsConverter.getInstance().convertToTwips(strWidth));
  506. builderContext.getTableContext().setNextColumnWidth(width);
  507. builderContext.getTableContext().setNextColumnRowSpanning(
  508. new Integer(0), null);
  509. builderContext.getTableContext().setNextFirstSpanningCol(false);
  510. } catch (Exception e) {
  511. log.error("startColumn: " + e.getMessage());
  512. throw new RuntimeException(e.getMessage());
  513. }
  514. }
  515. /**
  516. *
  517. * @param tc TableColumn that is ending;
  518. */
  519. public void endColumn(TableColumn tc) {
  520. if (bDefer) {
  521. return;
  522. }
  523. }
  524. /**
  525. * @see org.apache.fop.fo.FOEventHandler#startHeader(TableBody)
  526. * @param th TableBody that is starting
  527. */
  528. public void startHeader(TableBody th) {
  529. }
  530. /**
  531. * @see org.apache.fop.fo.FOEventHandler#endHeader(TableBody)
  532. * @param th TableBody that is ending
  533. */
  534. public void endHeader(TableBody th) {
  535. }
  536. /**
  537. * @see org.apache.fop.fo.FOEventHandler#startFooter(TableBody)
  538. * @param tf TableFooter that is starting
  539. */
  540. public void startFooter(TableBody tf) {
  541. }
  542. /**
  543. * @see org.apache.fop.fo.FOEventHandler#endFooter(TableBody)
  544. * @param tf TableFooter that is ending
  545. */
  546. public void endFooter(TableBody tf) {
  547. }
  548. /**
  549. *
  550. * @param inl Inline that is starting.
  551. */
  552. public void startInline(Inline inl) {
  553. if (bDefer) {
  554. return;
  555. }
  556. try {
  557. RtfAttributes rtfAttr
  558. = TextAttributesConverter.convertCharacterAttributes(inl);
  559. IRtfTextrunContainer container
  560. = (IRtfTextrunContainer)builderContext.getContainer(
  561. IRtfTextrunContainer.class, true, this);
  562. RtfTextrun textrun = container.getTextrun();
  563. textrun.pushInlineAttributes(rtfAttr);
  564. textrun.addBookmark(inl.getId());
  565. } catch (IOException ioe) {
  566. log.error("startInline:" + ioe.getMessage());
  567. throw new RuntimeException(ioe.getMessage());
  568. } catch (FOPException fe) {
  569. log.error("startInline:" + fe.getMessage());
  570. throw new RuntimeException(fe.getMessage());
  571. } catch (Exception e) {
  572. log.error("startInline:" + e.getMessage());
  573. throw new RuntimeException(e.getMessage());
  574. }
  575. }
  576. /**
  577. *
  578. * @param inl Inline that is ending.
  579. */
  580. public void endInline(Inline inl) {
  581. if (bDefer) {
  582. return;
  583. }
  584. try {
  585. IRtfTextrunContainer container
  586. = (IRtfTextrunContainer)builderContext.getContainer(
  587. IRtfTextrunContainer.class, true, this);
  588. RtfTextrun textrun = container.getTextrun();
  589. textrun.popInlineAttributes();
  590. } catch (IOException ioe) {
  591. log.error("startInline:" + ioe.getMessage());
  592. throw new RuntimeException(ioe.getMessage());
  593. } catch (Exception e) {
  594. log.error("startInline:" + e.getMessage());
  595. throw new RuntimeException(e.getMessage());
  596. }
  597. }
  598. /**
  599. * @see org.apache.fop.fo.FOEventHandler#startBody(TableBody)
  600. * @param tb TableBody that is starting
  601. */
  602. public void startBody(TableBody tb) {
  603. if (bDefer) {
  604. return;
  605. }
  606. try {
  607. RtfAttributes atts = TableAttributesConverter.convertTableBodyAttributes(tb);
  608. RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
  609. tbl.setHeaderAttribs(atts);
  610. } catch (Exception e) {
  611. log.error("startBody: " + e.getMessage());
  612. throw new RuntimeException(e.getMessage());
  613. }
  614. }
  615. /**
  616. * @see org.apache.fop.fo.FOEventHandler#endBody(TableBody)
  617. * @param tb TableBody that is ending
  618. */
  619. public void endBody(TableBody tb) {
  620. if (bDefer) {
  621. return;
  622. }
  623. try {
  624. RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this);
  625. tbl.setHeaderAttribs(null);
  626. } catch (Exception e) {
  627. log.error("endBody: " + e.getMessage());
  628. throw new RuntimeException(e.getMessage());
  629. }
  630. }
  631. /**
  632. * @see org.apache.fop.fo.FOEventHandler#startRow(TableRow)
  633. * @param tr TableRow that is starting
  634. */
  635. public void startRow(TableRow tr) {
  636. if (bDefer) {
  637. return;
  638. }
  639. try {
  640. // create an RtfTableRow in the current RtfTable
  641. final RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class,
  642. true, null);
  643. RtfAttributes atts = TableAttributesConverter.convertRowAttributes(tr,
  644. tbl.getHeaderAttribs());
  645. if (tr.getParent() instanceof TableHeader) {
  646. atts.set(ITableAttributes.ATTR_HEADER);
  647. }
  648. builderContext.pushContainer(tbl.newTableRow(atts));
  649. // reset column iteration index to correctly access column widths
  650. builderContext.getTableContext().selectFirstColumn();
  651. } catch (Exception e) {
  652. log.error("startRow: " + e.getMessage());
  653. throw new RuntimeException(e.getMessage());
  654. }
  655. }
  656. /**
  657. * @see org.apache.fop.fo.FOEventHandler#endRow(TableRow)
  658. * @param tr TableRow that is ending
  659. */
  660. public void endRow(TableRow tr) {
  661. if (bDefer) {
  662. return;
  663. }
  664. try {
  665. TableContext tctx = builderContext.getTableContext();
  666. final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
  667. true, null);
  668. //while the current column is in row-spanning, act as if
  669. //a vertical merged cell would have been specified.
  670. while (tctx.getNumberOfColumns() > tctx.getColumnIndex()
  671. && tctx.getColumnRowSpanningNumber().intValue() > 0) {
  672. RtfTableCell vCell = row.newTableCellMergedVertically(
  673. (int)tctx.getColumnWidth(),
  674. tctx.getColumnRowSpanningAttrs());
  675. if (!tctx.getFirstSpanningCol()) {
  676. vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
  677. }
  678. tctx.selectNextColumn();
  679. }
  680. } catch (Exception e) {
  681. log.error("endRow: " + e.getMessage());
  682. throw new RuntimeException(e.getMessage());
  683. }
  684. builderContext.popContainer();
  685. builderContext.getTableContext().decreaseRowSpannings();
  686. }
  687. /**
  688. * @see org.apache.fop.fo.FOEventHandler#startCell(TableCell)
  689. * @param tc TableCell that is starting
  690. */
  691. public void startCell(TableCell tc) {
  692. if (bDefer) {
  693. return;
  694. }
  695. try {
  696. TableContext tctx = builderContext.getTableContext();
  697. final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class,
  698. true, null);
  699. int numberRowsSpanned = tc.getNumberRowsSpanned();
  700. int numberColumnsSpanned = tc.getNumberColumnsSpanned();
  701. //while the current column is in row-spanning, act as if
  702. //a vertical merged cell would have been specified.
  703. while (tctx.getNumberOfColumns() > tctx.getColumnIndex()
  704. && tctx.getColumnRowSpanningNumber().intValue() > 0) {
  705. RtfTableCell vCell = row.newTableCellMergedVertically(
  706. (int)tctx.getColumnWidth(),
  707. tctx.getColumnRowSpanningAttrs());
  708. if (!tctx.getFirstSpanningCol()) {
  709. vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
  710. }
  711. tctx.selectNextColumn();
  712. }
  713. //get the width of the currently started cell
  714. float width = tctx.getColumnWidth();
  715. // create an RtfTableCell in the current RtfTableRow
  716. RtfAttributes atts = TableAttributesConverter.convertCellAttributes(tc);
  717. RtfTableCell cell = row.newTableCell((int)width, atts);
  718. //process number-rows-spanned attribute
  719. if (numberRowsSpanned > 1) {
  720. // Start vertical merge
  721. cell.setVMerge(RtfTableCell.MERGE_START);
  722. // set the number of rows spanned
  723. tctx.setCurrentColumnRowSpanning(new Integer(numberRowsSpanned),
  724. cell.getRtfAttributes());
  725. } else {
  726. tctx.setCurrentColumnRowSpanning(
  727. new Integer(numberRowsSpanned), null);
  728. }
  729. //process number-columns-spanned attribute
  730. if (numberColumnsSpanned > 0) {
  731. // Get the number of columns spanned
  732. RtfTable table = row.getTable();
  733. tctx.setCurrentFirstSpanningCol(true);
  734. // We widthdraw one cell because the first cell is already created
  735. // (it's the current cell) !
  736. for (int i = 0; i < numberColumnsSpanned - 1; ++i) {
  737. tctx.selectNextColumn();
  738. tctx.setCurrentFirstSpanningCol(false);
  739. RtfTableCell hCell = row.newTableCellMergedHorizontally(
  740. 0, null);
  741. if (numberRowsSpanned > 1) {
  742. // Start vertical merge
  743. hCell.setVMerge(RtfTableCell.MERGE_START);
  744. // set the number of rows spanned
  745. tctx.setCurrentColumnRowSpanning(
  746. new Integer(numberRowsSpanned),
  747. cell.getRtfAttributes());
  748. } else {
  749. tctx.setCurrentColumnRowSpanning(
  750. new Integer(numberRowsSpanned), null);
  751. }
  752. }
  753. }
  754. builderContext.pushContainer(cell);
  755. } catch (Exception e) {
  756. log.error("startCell: " + e.getMessage());
  757. throw new RuntimeException(e.getMessage());
  758. }
  759. }
  760. /**
  761. * @see org.apache.fop.fo.FOEventHandler#endCell(TableCell)
  762. * @param tc TableCell that is ending
  763. */
  764. public void endCell(TableCell tc) {
  765. if (bDefer) {
  766. return;
  767. }
  768. builderContext.popContainer();
  769. builderContext.getTableContext().selectNextColumn();
  770. }
  771. // Lists
  772. /**
  773. * @see org.apache.fop.fo.FOEventHandler#startList(ListBlock)
  774. * @param lb ListBlock that is starting
  775. */
  776. public void startList(ListBlock lb) {
  777. if (bDefer) {
  778. return;
  779. }
  780. try {
  781. // create an RtfList in the current list container
  782. final IRtfListContainer c
  783. = (IRtfListContainer)builderContext.getContainer(
  784. IRtfListContainer.class, true, this);
  785. final RtfList newList = c.newList(
  786. ListAttributesConverter.convertAttributes(lb));
  787. builderContext.pushContainer(newList);
  788. } catch (IOException ioe) {
  789. log.error("startList: " + ioe.getMessage());
  790. throw new RuntimeException(ioe.getMessage());
  791. } catch (FOPException fe) {
  792. log.error("startList: " + fe.getMessage());
  793. throw new RuntimeException(fe.getMessage());
  794. } catch (Exception e) {
  795. log.error("startList: " + e.getMessage());
  796. throw new RuntimeException(e.getMessage());
  797. }
  798. }
  799. /**
  800. * @see org.apache.fop.fo.FOEventHandler#endList(ListBlock)
  801. * @param lb ListBlock that is ending
  802. */
  803. public void endList(ListBlock lb) {
  804. if (bDefer) {
  805. return;
  806. }
  807. builderContext.popContainer();
  808. }
  809. /**
  810. * @see org.apache.fop.fo.FOEventHandler#startListItem(ListItem)
  811. * @param li ListItem that is starting
  812. */
  813. public void startListItem(ListItem li) {
  814. if (bDefer) {
  815. return;
  816. }
  817. // create an RtfListItem in the current RtfList
  818. try {
  819. RtfList list = (RtfList)builderContext.getContainer(
  820. RtfList.class, true, this);
  821. /**
  822. * If the current list already contains a list item, then close the
  823. * list and open a new one, so every single list item gets its own
  824. * list. This allows every item to have a different list label.
  825. * If all the items would be in the same list, they had all the
  826. * same label.
  827. */
  828. //TODO: do this only, if the labels content <> previous labels content
  829. if (list.getChildCount() > 0) {
  830. this.endListBody();
  831. this.endList((ListBlock) li.getParent());
  832. this.startList((ListBlock) li.getParent());
  833. this.startListBody();
  834. list = (RtfList)builderContext.getContainer(
  835. RtfList.class, true, this);
  836. }
  837. builderContext.pushContainer(list.newListItem());
  838. } catch (IOException ioe) {
  839. log.error("startList: " + ioe.getMessage());
  840. throw new RuntimeException(ioe.getMessage());
  841. } catch (FOPException fe) {
  842. log.error("startList: " + fe.getMessage());
  843. throw new RuntimeException(fe.getMessage());
  844. } catch (Exception e) {
  845. log.error("startList: " + e.getMessage());
  846. throw new RuntimeException(e.getMessage());
  847. }
  848. }
  849. /**
  850. * @see org.apache.fop.fo.FOEventHandler#endListItem(ListItem)
  851. * @param li ListItem that is ending
  852. */
  853. public void endListItem(ListItem li) {
  854. if (bDefer) {
  855. return;
  856. }
  857. builderContext.popContainer();
  858. }
  859. /**
  860. * @see org.apache.fop.fo.FOEventHandler#startListLabel()
  861. */
  862. public void startListLabel() {
  863. if (bDefer) {
  864. return;
  865. }
  866. try {
  867. RtfListItem item
  868. = (RtfListItem)builderContext.getContainer(RtfListItem.class, true, this);
  869. RtfListItemLabel label = item.new RtfListItemLabel(item);
  870. builderContext.pushContainer(label);
  871. } catch (IOException ioe) {
  872. log.error("startPageNumber:" + ioe.getMessage());
  873. throw new RuntimeException(ioe.getMessage());
  874. } catch (Exception e) {
  875. log.error("startPageNumber: " + e.getMessage());
  876. throw new RuntimeException(e.getMessage());
  877. }
  878. }
  879. /**
  880. * @see org.apache.fop.fo.FOEventHandler#endListLabel()
  881. */
  882. public void endListLabel() {
  883. if (bDefer) {
  884. return;
  885. }
  886. builderContext.popContainer();
  887. }
  888. /**
  889. * @see org.apache.fop.fo.FOEventHandler#startListBody()
  890. */
  891. public void startListBody() {
  892. }
  893. /**
  894. * @see org.apache.fop.fo.FOEventHandler#endListBody()
  895. */
  896. public void endListBody() {
  897. }
  898. // Static Regions
  899. /**
  900. * @see org.apache.fop.fo.FOEventHandler#startStatic()
  901. */
  902. public void startStatic() {
  903. }
  904. /**
  905. * @see org.apache.fop.fo.FOEventHandler#endStatic()
  906. */
  907. public void endStatic() {
  908. }
  909. /**
  910. * @see org.apache.fop.fo.FOEventHandler#startMarkup()
  911. */
  912. public void startMarkup() {
  913. }
  914. /**
  915. * @see org.apache.fop.fo.FOEventHandler#endMarkup()
  916. */
  917. public void endMarkup() {
  918. }
  919. /**
  920. * @see org.apache.fop.fo.FOEventHandler#startLink(BasicLink basicLink)
  921. * @param basicLink BasicLink that is starting
  922. */
  923. public void startLink(BasicLink basicLink) {
  924. if (bDefer) {
  925. return;
  926. }
  927. try {
  928. IRtfTextrunContainer container
  929. = (IRtfTextrunContainer)builderContext.getContainer(
  930. IRtfTextrunContainer.class, true, this);
  931. RtfTextrun textrun = container.getTextrun();
  932. RtfHyperLink link = textrun.addHyperlink(new RtfAttributes());
  933. if (basicLink.getExternalDestination() != null) {
  934. link.setExternalURL(basicLink.getExternalDestination());
  935. } else {
  936. link.setInternalURL(basicLink.getInternalDestination());
  937. }
  938. builderContext.pushContainer(link);
  939. } catch (IOException ioe) {
  940. log.error("startLink:" + ioe.getMessage());
  941. throw new RuntimeException(ioe.getMessage());
  942. } catch (Exception e) {
  943. log.error("startLink: " + e.getMessage());
  944. throw new RuntimeException(e.getMessage());
  945. }
  946. }
  947. /**
  948. * @see org.apache.fop.fo.FOEventHandler#endLink()
  949. */
  950. public void endLink() {
  951. if (bDefer) {
  952. return;
  953. }
  954. builderContext.popContainer();
  955. }
  956. /**
  957. * @see org.apache.fop.fo.FOEventHandler#image(ExternalGraphic)
  958. * @param eg ExternalGraphic that is starting
  959. */
  960. public void image(ExternalGraphic eg) {
  961. if (bDefer) {
  962. return;
  963. }
  964. try {
  965. String url = eg.getURL();
  966. //set image data
  967. FOUserAgent userAgent = eg.getUserAgent();
  968. ImageFactory fact = userAgent.getFactory().getImageFactory();
  969. FopImage fopimage = fact.getImage(url, userAgent);
  970. if (fopimage == null) {
  971. log.error("Image could not be found: " + url);
  972. return;
  973. }
  974. fopimage.load(FopImage.ORIGINAL_DATA);
  975. byte[] rawData;
  976. if ("image/svg+xml".equals(fopimage.getMimeType())) {
  977. rawData = SVGConverter.convertToJPEG((XMLImage)fopimage);
  978. } else {
  979. rawData = fopimage.getRessourceBytes();
  980. }
  981. if (rawData == null) {
  982. log.warn(FONode.decorateWithContextInfo(
  983. "Image could not be embedded: " + url, eg));
  984. return;
  985. }
  986. final IRtfTextrunContainer c
  987. = (IRtfTextrunContainer)builderContext.getContainer(
  988. IRtfTextrunContainer.class, true, this);
  989. final RtfExternalGraphic newGraphic = c.getTextrun().newImage();
  990. //set URL
  991. newGraphic.setURL(url);
  992. newGraphic.setImageData(rawData);
  993. //set scaling
  994. if (eg.getScaling() == Constants.EN_UNIFORM) {
  995. newGraphic.setScaling ("uniform");
  996. }
  997. //get width
  998. int width = 0;
  999. if (eg.getWidth().getEnum() == Constants.EN_AUTO) {
  1000. width = fopimage.getIntrinsicWidth();
  1001. } else {
  1002. width = eg.getWidth().getValue();
  1003. }
  1004. //get height
  1005. int height = 0;
  1006. if (eg.getWidth().getEnum() == Constants.EN_AUTO) {
  1007. height = fopimage.getIntrinsicHeight();
  1008. } else {
  1009. height = eg.getHeight().getValue();
  1010. }
  1011. //get content-width
  1012. int contentwidth = 0;
  1013. if (eg.getContentWidth().getEnum()
  1014. == Constants.EN_AUTO) {
  1015. contentwidth = fopimage.getIntrinsicWidth();
  1016. } else if (eg.getContentWidth().getEnum()
  1017. == Constants.EN_SCALE_TO_FIT) {
  1018. contentwidth = width;
  1019. } else {
  1020. //TODO: check, if the value is a percent value
  1021. contentwidth = eg.getContentWidth().getValue();
  1022. }
  1023. //get content-width
  1024. int contentheight = 0;
  1025. if (eg.getContentHeight().getEnum()
  1026. == Constants.EN_AUTO) {
  1027. contentheight = fopimage.getIntrinsicHeight();
  1028. } else if (eg.getContentHeight().getEnum()
  1029. == Constants.EN_SCALE_TO_FIT) {
  1030. contentheight = height;
  1031. } else {
  1032. //TODO: check, if the value is a percent value
  1033. contentheight = eg.getContentHeight().getValue();
  1034. }
  1035. //set width in rtf
  1036. //newGraphic.setWidth((long) (contentwidth / 1000f) + "pt");
  1037. newGraphic.setWidth((long) (contentwidth / 50f) + "twips");
  1038. //set height in rtf
  1039. //newGraphic.setHeight((long) (contentheight / 1000f) + "pt");
  1040. newGraphic.setHeight((long) (contentheight / 50f) + "twips");
  1041. //TODO: make this configurable:
  1042. // int compression = m_context.m_options.getRtfExternalGraphicCompressionRate ();
  1043. int compression = 0;
  1044. if (compression != 0) {
  1045. if (!newGraphic.setCompressionRate(compression)) {
  1046. log.warn("The compression rate " + compression
  1047. + " is invalid. The value has to be between 1 and 100 %.");
  1048. }
  1049. }
  1050. } catch (Exception e) {
  1051. log.error("Error while handling an external-graphic: " + e.getMessage(), e);
  1052. }
  1053. }
  1054. /**
  1055. * @see org.apache.fop.fo.FOEventHandler#pageRef()
  1056. */
  1057. public void pageRef() {
  1058. }
  1059. /**
  1060. * @see org.apache.fop.fo.FOEventHandler#foreignObject(InstreamForeignObject)
  1061. * @param ifo InstreamForeignObject that is starting
  1062. */
  1063. public void foreignObject(InstreamForeignObject ifo) {
  1064. }
  1065. /**
  1066. * @see org.apache.fop.fo.FOEventHandler#startFootnote(Footnote)
  1067. * @param footnote Footnote that is starting
  1068. */
  1069. public void startFootnote(Footnote footnote) {
  1070. if (bDefer) {
  1071. return;
  1072. }
  1073. try {
  1074. IRtfTextrunContainer container
  1075. = (IRtfTextrunContainer)builderContext.getContainer(
  1076. IRtfTextrunContainer.class,
  1077. true, this);
  1078. RtfTextrun textrun = container.getTextrun();
  1079. RtfFootnote rtfFootnote = textrun.addFootnote();
  1080. builderContext.pushContainer(rtfFootnote);
  1081. } catch (IOException ioe) {
  1082. // TODO could we throw Exception in all FOEventHandler events?
  1083. log.error("startFootnote: " + ioe.getMessage());
  1084. throw new RuntimeException("IOException: " + ioe);
  1085. } catch (Exception e) {
  1086. log.error("startFootnote: " + e.getMessage());
  1087. throw new RuntimeException("Exception: " + e);
  1088. }
  1089. }
  1090. /**
  1091. * @see org.apache.fop.fo.FOEventHandler#endFootnote(Footnote)
  1092. * @param footnote Footnote that is ending
  1093. */
  1094. public void endFootnote(Footnote footnote) {
  1095. if (bDefer) {
  1096. return;
  1097. }
  1098. builderContext.popContainer();
  1099. }
  1100. /**
  1101. * @see org.apache.fop.fo.FOEventHandler#startFootnoteBody(FootnoteBody)
  1102. * @param body FootnoteBody that is starting
  1103. */
  1104. public void startFootnoteBody(FootnoteBody body) {
  1105. if (bDefer) {
  1106. return;
  1107. }
  1108. try {
  1109. RtfFootnote rtfFootnote
  1110. = (RtfFootnote)builderContext.getContainer(
  1111. RtfFootnote.class,
  1112. true, this);
  1113. rtfFootnote.startBody();
  1114. } catch (IOException ioe) {
  1115. // TODO could we throw Exception in all FOEventHandler events?
  1116. log.error("startFootnoteBody: " + ioe.getMessage());
  1117. throw new RuntimeException("IOException: " + ioe);
  1118. } catch (Exception e) {
  1119. log.error("startFootnoteBody: " + e.getMessage());
  1120. throw new RuntimeException("Exception: " + e);
  1121. }
  1122. }
  1123. /**
  1124. * @see org.apache.fop.fo.FOEventHandler#endFootnoteBody(FootnoteBody)
  1125. * @param body FootnoteBody that is ending
  1126. */
  1127. public void endFootnoteBody(FootnoteBody body) {
  1128. if (bDefer) {
  1129. return;
  1130. }
  1131. try {
  1132. RtfFootnote rtfFootnote
  1133. = (RtfFootnote)builderContext.getContainer(
  1134. RtfFootnote.class,
  1135. true, this);
  1136. rtfFootnote.endBody();
  1137. } catch (IOException ioe) {
  1138. // TODO could we throw Exception in all FOEventHandler events?
  1139. log.error("endFootnoteBody: " + ioe.getMessage());
  1140. throw new RuntimeException("IOException: " + ioe);
  1141. } catch (Exception e) {
  1142. log.error("endFootnoteBody: " + e.getMessage());
  1143. throw new RuntimeException("Exception: " + e);
  1144. }
  1145. }
  1146. /**
  1147. * @see org.apache.fop.fo.FOEventHandler#leader(Leader)
  1148. * @param l Leader that is starting
  1149. */
  1150. public void leader(Leader l) {
  1151. }
  1152. /**
  1153. * @param text FOText object
  1154. * @param data Array of characters to process.
  1155. * @param start Offset for characters to process.
  1156. * @param length Portion of array to process.
  1157. */
  1158. public void text(FOText text, char[] data, int start, int length) {
  1159. if (bDefer) {
  1160. return;
  1161. }
  1162. try {
  1163. IRtfTextrunContainer container
  1164. = (IRtfTextrunContainer)builderContext.getContainer(
  1165. IRtfTextrunContainer.class, true, this);
  1166. RtfTextrun textrun = container.getTextrun();
  1167. RtfAttributes rtfAttr
  1168. = TextAttributesConverter.convertCharacterAttributes(text);
  1169. textrun.pushInlineAttributes(rtfAttr);
  1170. textrun.addString(new String(data, start, length - start));
  1171. textrun.popInlineAttributes();
  1172. } catch (IOException ioe) {
  1173. // FIXME could we throw Exception in all FOEventHandler events?
  1174. log.error("characters: " + ioe.getMessage());
  1175. throw new RuntimeException(ioe.getMessage());
  1176. } catch (Exception e) {
  1177. log.error("characters:" + e.getMessage());
  1178. throw new RuntimeException(e.getMessage());
  1179. }
  1180. }
  1181. /**
  1182. *
  1183. * @param pagenum PageNumber that is starting.
  1184. */
  1185. public void startPageNumber(PageNumber pagenum) {
  1186. if (bDefer) {
  1187. return;
  1188. }
  1189. try {
  1190. RtfAttributes rtfAttr
  1191. = TextAttributesConverter.convertCharacterAttributes(
  1192. pagenum);
  1193. IRtfTextrunContainer container
  1194. = (IRtfTextrunContainer)builderContext.getContainer(
  1195. IRtfTextrunContainer.class, true, this);
  1196. RtfTextrun textrun = container.getTextrun();
  1197. textrun.addPageNumber(rtfAttr);
  1198. } catch (IOException ioe) {
  1199. log.error("startPageNumber:" + ioe.getMessage());
  1200. throw new RuntimeException(ioe.getMessage());
  1201. } catch (Exception e) {
  1202. log.error("startPageNumber: " + e.getMessage());
  1203. throw new RuntimeException(e.getMessage());
  1204. }
  1205. }
  1206. /**
  1207. *
  1208. * @param pagenum PageNumber that is ending.
  1209. */
  1210. public void endPageNumber(PageNumber pagenum) {
  1211. if (bDefer) {
  1212. return;
  1213. }
  1214. }
  1215. /**
  1216. * Calls the appropriate event handler for the passed FObj.
  1217. *
  1218. * @param foNode FO node whose event is to be called
  1219. * @param bStart TRUE calls the start handler, FALSE the end handler
  1220. */
  1221. private void invokeDeferredEvent(FONode foNode, boolean bStart) {
  1222. if (foNode instanceof PageSequence) {
  1223. if (bStart) {
  1224. startPageSequence( (PageSequence) foNode);
  1225. } else {
  1226. endPageSequence( (PageSequence) foNode);
  1227. }
  1228. } else if (foNode instanceof Flow) {
  1229. if (bStart) {
  1230. startFlow( (Flow) foNode);
  1231. } else {
  1232. endFlow( (Flow) foNode);
  1233. }
  1234. } else if (foNode instanceof StaticContent) {
  1235. if (bStart) {
  1236. startStatic();
  1237. } else {
  1238. endStatic();
  1239. }
  1240. } else if (foNode instanceof ExternalGraphic) {
  1241. if (bStart) {
  1242. image( (ExternalGraphic) foNode );
  1243. }
  1244. } else if (foNode instanceof Block) {
  1245. if (bStart) {
  1246. startBlock( (Block) foNode);
  1247. } else {
  1248. endBlock( (Block) foNode);
  1249. }
  1250. } else if (foNode instanceof BlockContainer) {
  1251. if (bStart) {
  1252. startBlockContainer( (BlockContainer) foNode);
  1253. } else {
  1254. endBlockContainer( (BlockContainer) foNode);
  1255. }
  1256. } else if (foNode instanceof BasicLink) {
  1257. //BasicLink must be placed before Inline
  1258. if (bStart) {
  1259. startLink( (BasicLink) foNode);
  1260. } else {
  1261. endLink();
  1262. }
  1263. } else if (foNode instanceof Inline) {
  1264. if (bStart) {
  1265. startInline( (Inline) foNode);
  1266. } else {
  1267. endInline( (Inline) foNode);
  1268. }
  1269. } else if (foNode instanceof FOText) {
  1270. if (bStart) {
  1271. FOText text = (FOText) foNode;
  1272. text(text, text.ca, text.startIndex, text.endIndex);
  1273. }
  1274. } else if (foNode instanceof Character) {
  1275. if (bStart) {
  1276. Character c = (Character) foNode;
  1277. character(c);
  1278. }
  1279. } else if (foNode instanceof PageNumber) {
  1280. if (bStart) {
  1281. startPageNumber( (PageNumber) foNode);
  1282. } else {
  1283. endPageNumber( (PageNumber) foNode);
  1284. }
  1285. } else if (foNode instanceof Footnote) {
  1286. if (bStart) {
  1287. startFootnote( (Footnote) foNode);
  1288. } else {
  1289. endFootnote( (Footnote) foNode);
  1290. }
  1291. } else if (foNode instanceof FootnoteBody) {
  1292. if (bStart) {
  1293. startFootnoteBody( (FootnoteBody) foNode);
  1294. } else {
  1295. endFootnoteBody( (FootnoteBody) foNode);
  1296. }
  1297. } else if (foNode instanceof ListBlock) {
  1298. if (bStart) {
  1299. startList( (ListBlock) foNode);
  1300. } else {
  1301. endList( (ListBlock) foNode);
  1302. }
  1303. } else if (foNode instanceof ListItemBody) {
  1304. if (bStart) {
  1305. startListBody();
  1306. } else {
  1307. endListBody();
  1308. }
  1309. } else if (foNode instanceof ListItem) {
  1310. if (bStart) {
  1311. startListItem( (ListItem) foNode);
  1312. } else {
  1313. endListItem( (ListItem) foNode);
  1314. }
  1315. } else if (foNode instanceof ListItemLabel) {
  1316. if (bStart) {
  1317. startListLabel();
  1318. } else {
  1319. endListLabel();
  1320. }
  1321. } else if (foNode instanceof Table) {
  1322. if (bStart) {
  1323. startTable( (Table) foNode);
  1324. } else {
  1325. endTable( (Table) foNode);
  1326. }
  1327. } else if (foNode instanceof TableBody) {
  1328. if (bStart) {
  1329. startBody( (TableBody) foNode);
  1330. } else {
  1331. endBody( (TableBody) foNode);
  1332. }
  1333. } else if (foNode instanceof TableColumn) {
  1334. if (bStart) {
  1335. startColumn( (TableColumn) foNode);
  1336. } else {
  1337. endColumn( (TableColumn) foNode);
  1338. }
  1339. } else if (foNode instanceof TableRow) {
  1340. if (bStart) {
  1341. startRow( (TableRow) foNode);
  1342. } else {
  1343. endRow( (TableRow) foNode);
  1344. }
  1345. } else if (foNode instanceof TableCell) {
  1346. if (bStart) {
  1347. startCell( (TableCell) foNode);
  1348. } else {
  1349. endCell( (TableCell) foNode);
  1350. }
  1351. } else {
  1352. log.warn("Ignored deferred event for " + foNode);
  1353. }
  1354. }
  1355. /**
  1356. * Calls the event handlers for the passed FONode and all its elements.
  1357. *
  1358. * @param foNode FONode object which shall be recursed
  1359. */
  1360. private void recurseFONode(FONode foNode) {
  1361. invokeDeferredEvent(foNode, true);
  1362. if (foNode instanceof PageSequence) {
  1363. PageSequence pageSequence = (PageSequence) foNode;
  1364. Region regionBefore = pagemaster.getRegion(Constants.FO_REGION_BEFORE);
  1365. if (regionBefore != null) {
  1366. FONode staticBefore = (FONode) pageSequence.getFlowMap().get(
  1367. regionBefore.getRegionName());
  1368. if (staticBefore != null) {
  1369. recurseFONode(staticBefore);
  1370. }
  1371. }
  1372. Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER);
  1373. if (regionAfter != null) {
  1374. FONode staticAfter = (FONode) pageSequence.getFlowMap().get(
  1375. regionAfter.getRegionName());
  1376. if (staticAfter != null) {
  1377. recurseFONode(staticAfter);
  1378. }
  1379. }
  1380. recurseFONode( pageSequence.getMainFlow() );
  1381. } else if (foNode instanceof Table) {
  1382. Table table = (Table) foNode;
  1383. //recurse all table-columns
  1384. for (Iterator it = table.getColumns().iterator(); it.hasNext();) {
  1385. recurseFONode( (FONode) it.next() );
  1386. }
  1387. //recurse table-header
  1388. if (table.getTableHeader() != null) {
  1389. recurseFONode( table.getTableHeader() );
  1390. }
  1391. //recurse table-footer
  1392. if (table.getTableFooter() != null) {
  1393. recurseFONode( table.getTableFooter() );
  1394. }
  1395. if (foNode.getChildNodes() != null) {
  1396. for (Iterator it = foNode.getChildNodes(); it.hasNext();) {
  1397. recurseFONode( (FONode) it.next() );
  1398. }
  1399. }
  1400. } else if (foNode instanceof ListItem) {
  1401. ListItem item = (ListItem) foNode;
  1402. recurseFONode(item.getLabel());
  1403. recurseFONode(item.getBody());
  1404. } else if (foNode instanceof Footnote) {
  1405. Footnote fn = (Footnote)foNode;
  1406. recurseFONode(fn.getFootnoteCitation());
  1407. recurseFONode(fn.getFootnoteBody());
  1408. } else {
  1409. //Any other FO-Object: Simply recurse through all childNodes.
  1410. if (foNode.getChildNodes() != null) {
  1411. for (Iterator it = foNode.getChildNodes(); it.hasNext();) {
  1412. FONode fn = (FONode)it.next();
  1413. if (log.isTraceEnabled()) {
  1414. log.trace(" ChildNode for " + fn + " (" + fn.getName() + ")");
  1415. }
  1416. recurseFONode(fn);
  1417. }
  1418. }
  1419. }
  1420. invokeDeferredEvent(foNode, false);
  1421. }
  1422. }