1 17 18 19 20 package org.apache.fop.render.rtf; 21 22 import java.awt.geom.Point2D ; 24 import java.io.IOException ; 25 import java.io.OutputStream ; 26 import java.io.OutputStreamWriter ; 27 import java.util.Iterator ; 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 ; 101 import org.xml.sax.SAXException ; 102 103 113 public class RTFHandler extends FOEventHandler { 114 115 private RtfFile rtfFile; 116 private final OutputStream os; 117 private static Log log = LogFactory.getLog(RTFHandler.class); 118 private RtfSection sect; 119 private RtfDocumentArea docArea; 120 private boolean bDefer; private boolean bPrevHeaderSpecified = false; private boolean bPrevFooterSpecified = false; private boolean bHeaderSpecified = false; private boolean bFooterSpecified = false; private BuilderContext builderContext = new BuilderContext(null); 131 132 private SimplePageMaster pagemaster; 133 134 139 public RTFHandler(FOUserAgent userAgent, OutputStream os) { 140 super(userAgent); 141 this.os = os; 142 bDefer = true; 143 144 FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent)); 145 } 146 147 151 public void startDocument() throws SAXException { 152 try { 154 rtfFile = new RtfFile(new OutputStreamWriter (os)); 155 docArea = rtfFile.startDocumentArea(); 156 } catch (IOException ioe) { 157 throw new SAXException (ioe); 159 } 160 } 161 162 166 public void endDocument() throws SAXException { 167 try { 168 rtfFile.flush(); 169 } catch (IOException ioe) { 170 throw new SAXException (ioe); 172 } 173 } 174 175 179 public void startPageSequence(PageSequence pageSeq) { 180 try { 181 if (this.pagemaster == null) { 183 String 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 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 ioe) { 217 log.error("startPageSequence: " + ioe.getMessage(), ioe); 219 } catch (FOPException fope) { 221 log.error("startPageSequence: " + fope.getMessage(), fope); 223 } 224 } 225 226 230 public void endPageSequence(PageSequence pageSeq) { 231 if (bDefer) { 232 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 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 (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 (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 ioe) { 331 log.error("startFlow: " + ioe.getMessage()); 332 throw new RuntimeException (ioe.getMessage()); 333 } catch (Exception e) { 334 log.error("startFlow: " + e.getMessage()); 335 throw new RuntimeException (e.getMessage()); 336 } 337 } 338 339 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 } 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 e) { 362 log.error("endFlow: " + e.getMessage()); 363 throw new RuntimeException (e.getMessage()); 364 } 365 } 366 367 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 ioe) { 391 log.error("startBlock: " + ioe.getMessage()); 393 throw new RuntimeException ("IOException: " + ioe); 394 } catch (Exception e) { 395 log.error("startBlock: " + e.getMessage()); 396 throw new RuntimeException ("Exception: " + e); 397 } 398 } 399 400 401 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 ioe) { 423 log.error("startBlock:" + ioe.getMessage()); 424 throw new RuntimeException (ioe.getMessage()); 425 } catch (Exception e) { 426 log.error("startBlock:" + e.getMessage()); 427 throw new RuntimeException (e.getMessage()); 428 } 429 } 430 431 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 ioe) { 454 log.error("startBlock: " + ioe.getMessage()); 456 throw new RuntimeException ("IOException: " + ioe); 457 } catch (Exception e) { 458 log.error("startBlock: " + e.getMessage()); 459 throw new RuntimeException ("Exception: " + e); 460 } 461 } 462 463 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 ioe) { 484 log.error("startBlock:" + ioe.getMessage()); 485 throw new RuntimeException (ioe.getMessage()); 486 } catch (Exception e) { 487 log.error("startBlock:" + e.getMessage()); 488 throw new RuntimeException (e.getMessage()); 489 } 490 } 491 492 496 public void startTable(Table tbl) { 497 if (bDefer) { 498 return; 499 } 500 501 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 e) { 530 log.error("startTable:" + e.getMessage()); 531 throw new RuntimeException (e.getMessage()); 532 } 533 534 builderContext.pushTableContext(tableContext); 535 } 536 537 541 public void endTable(Table tbl) { 542 if (bDefer) { 543 return; 544 } 545 546 builderContext.popTableContext(); 547 builderContext.popContainer(); 548 } 549 550 554 555 public void startColumn(TableColumn tc) { 556 if (bDefer) { 557 return; 558 } 559 560 try { 561 571 SimplePercentBaseContext context 572 = new SimplePercentBaseContext(null, 573 LengthBase.TABLE_UNITS, 574 100000); 575 576 Integer iWidth 577 = new Integer (tc.getColumnWidth().getValue(context) / 1000); 578 579 String strWidth = iWidth.toString() + "pt"; 580 Float width = new Float ( 581 FoUnitsConverter.getInstance().convertToTwips(strWidth)); 582 builderContext.getTableContext().setNextColumnWidth(width); 583 builderContext.getTableContext().setNextColumnRowSpanning( 584 new Integer (0), null); 585 builderContext.getTableContext().setNextFirstSpanningCol(false); 586 } catch (Exception e) { 587 log.error("startColumn: " + e.getMessage()); 588 throw new RuntimeException (e.getMessage()); 589 } 590 591 } 592 593 597 598 public void endColumn(TableColumn tc) { 599 if (bDefer) { 600 return; 601 } 602 } 603 604 608 public void startHeader(TableBody th) { 609 } 610 611 615 public void endHeader(TableBody th) { 616 } 617 618 622 public void startFooter(TableBody tf) { 623 } 624 625 629 public void endFooter(TableBody tf) { 630 } 631 632 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 ioe) { 653 log.error("startInline:" + ioe.getMessage()); 654 throw new RuntimeException (ioe.getMessage()); 655 } catch (FOPException fe) { 656 log.error("startInline:" + fe.getMessage()); 657 throw new RuntimeException (fe.getMessage()); 658 } catch (Exception e) { 659 log.error("startInline:" + e.getMessage()); 660 throw new RuntimeException (e.getMessage()); 661 } 662 } 663 664 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 ioe) { 681 log.error("startInline:" + ioe.getMessage()); 682 throw new RuntimeException (ioe.getMessage()); 683 } catch (Exception e) { 684 log.error("startInline:" + e.getMessage()); 685 throw new RuntimeException (e.getMessage()); 686 } 687 } 688 689 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 e) { 704 log.error("startBody: " + e.getMessage()); 705 throw new RuntimeException (e.getMessage()); 706 } 707 } 708 709 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 e) { 722 log.error("endBody: " + e.getMessage()); 723 throw new RuntimeException (e.getMessage()); 724 } 725 } 726 727 731 public void startRow(TableRow tr) { 732 if (bDefer) { 733 return; 734 } 735 736 try { 737 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 builderContext.getTableContext().selectFirstColumn(); 752 } catch (Exception e) { 753 log.error("startRow: " + e.getMessage()); 754 throw new RuntimeException (e.getMessage()); 755 } 756 } 757 758 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 (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 e) { 787 log.error("endRow: " + e.getMessage()); 788 throw new RuntimeException (e.getMessage()); 789 } 790 791 792 builderContext.popContainer(); 793 builderContext.getTableContext().decreaseRowSpannings(); 794 } 795 796 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 (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 float width = tctx.getColumnWidth(); 830 831 RtfAttributes atts = TableAttributesConverter.convertCellAttributes(tc); 833 RtfTableCell cell = row.newTableCell((int)width, atts); 834 835 if (numberRowsSpanned > 1) { 837 cell.setVMerge(RtfTableCell.MERGE_START); 839 840 tctx.setCurrentColumnRowSpanning(new Integer (numberRowsSpanned), 842 cell.getRtfAttributes()); 843 } else { 844 tctx.setCurrentColumnRowSpanning( 845 new Integer (numberRowsSpanned), null); 846 } 847 848 if (numberColumnsSpanned > 0) { 850 RtfTable table = row.getTable(); 852 tctx.setCurrentFirstSpanningCol(true); 853 854 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 hCell.setVMerge(RtfTableCell.MERGE_START); 866 867 tctx.setCurrentColumnRowSpanning( 869 new Integer (numberRowsSpanned), 870 cell.getRtfAttributes()); 871 } else { 872 tctx.setCurrentColumnRowSpanning( 873 new Integer (numberRowsSpanned), null); 874 } 875 } 876 } 877 878 builderContext.pushContainer(cell); 879 } catch (Exception e) { 880 log.error("startCell: " + e.getMessage()); 881 throw new RuntimeException (e.getMessage()); 882 } 883 } 884 885 889 public void endCell(TableCell tc) { 890 if (bDefer) { 891 return; 892 } 893 894 builderContext.popContainer(); 895 builderContext.getTableContext().selectNextColumn(); 896 } 897 898 903 public void startList(ListBlock lb) { 904 if (bDefer) { 905 return; 906 } 907 908 try { 909 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 ioe) { 917 log.error("startList: " + ioe.getMessage()); 918 throw new RuntimeException (ioe.getMessage()); 919 } catch (FOPException fe) { 920 log.error("startList: " + fe.getMessage()); 921 throw new RuntimeException (fe.getMessage()); 922 } catch (Exception e) { 923 log.error("startList: " + e.getMessage()); 924 throw new RuntimeException (e.getMessage()); 925 } 926 } 927 928 932 public void endList(ListBlock lb) { 933 if (bDefer) { 934 return; 935 } 936 937 builderContext.popContainer(); 938 } 939 940 944 public void startListItem(ListItem li) { 945 if (bDefer) { 946 return; 947 } 948 949 try { 951 RtfList list = (RtfList)builderContext.getContainer( 952 RtfList.class, true, this); 953 954 961 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 ioe) { 974 log.error("startList: " + ioe.getMessage()); 975 throw new RuntimeException (ioe.getMessage()); 976 } catch (Exception e) { 977 log.error("startList: " + e.getMessage()); 978 throw new RuntimeException (e.getMessage()); 979 } 980 } 981 982 986 public void endListItem(ListItem li) { 987 if (bDefer) { 988 return; 989 } 990 991 builderContext.popContainer(); 992 } 993 994 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 ioe) { 1009 log.error("startPageNumber:" + ioe.getMessage()); 1010 throw new RuntimeException (ioe.getMessage()); 1011 } catch (Exception e) { 1012 log.error("startPageNumber: " + e.getMessage()); 1013 throw new RuntimeException (e.getMessage()); 1014 } 1015 } 1016 1017 1020 public void endListLabel() { 1021 if (bDefer) { 1022 return; 1023 } 1024 1025 builderContext.popContainer(); 1026 } 1027 1028 1031 public void startListBody() { 1032 } 1033 1034 1037 public void endListBody() { 1038 } 1039 1040 1044 public void startStatic() { 1045 } 1046 1047 1050 public void endStatic() { 1051 } 1052 1053 1056 public void startMarkup() { 1057 } 1058 1059 1062 public void endMarkup() { 1063 } 1064 1065 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 ioe) { 1092 log.error("startLink:" + ioe.getMessage()); 1093 throw new RuntimeException (ioe.getMessage()); 1094 } catch (Exception e) { 1095 log.error("startLink: " + e.getMessage()); 1096 throw new RuntimeException (e.getMessage()); 1097 } 1098 } 1099 1100 1103 public void endLink() { 1104 if (bDefer) { 1105 return; 1106 } 1107 1108 builderContext.popContainer(); 1109 } 1110 1111 1115 public void image(ExternalGraphic eg) { 1116 if (bDefer) { 1117 return; 1118 } 1119 1120 try { 1121 String url = eg.getURL(); 1122 1123 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 e) { 1135 log.error("Error while handling an external-graphic: " + e.getMessage(), e); 1136 } 1137 } 1138 1139 1143 public void foreignObject(InstreamForeignObject ifo) { 1144 if (bDefer) { 1145 return; 1146 } 1147 1148 try { 1149 XMLObj child = (XMLObj) ifo.getChildXMLObj(); 1150 Document doc = child.getDOMDocument(); 1151 String ns = child.getNamespaceURI(); 1152 1153 if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) { 1154 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 FOUserAgent ua = ifo.getUserAgent(); 1163 info.dpiHorizontal = 25.4f / ua.getSourcePixelUnitToMillimeter(); 1164 info.dpiVertical = info.dpiHorizontal; 1165 1166 Point2D csize = new Point2D.Float (-1, -1); 1168 Point2D 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 e) { 1183 log.error("Error while handling an instream-foreign-object: " + e.getMessage(), e); 1184 } 1185 } 1186 1187 1193 private void putGraphic(AbstractGraphics abstractGraphic, FopImage fopImage) 1194 throws IOException { 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 rtfGraphic.setURL(fopImage.getOriginalURI()); 1215 rtfGraphic.setImageData(rawData); 1216 1217 if (abstractGraphic.getScaling() == Constants.EN_UNIFORM) { 1219 rtfGraphic.setScaling ("uniform"); 1220 } 1221 1222 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 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 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 contentwidth = abstractGraphic.getContentWidth().getValue(); 1249 } 1250 1251 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 contentheight = abstractGraphic.getContentHeight().getValue(); 1265 } 1266 1267 rtfGraphic.setWidth((long) (contentwidth / 50f) + "twips"); 1270 1271 rtfGraphic.setHeight((long) (contentheight / 50f) + "twips"); 1274 1275 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 1289 public void pageRef() { 1290 } 1291 1292 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 ioe) { 1313 log.error("startFootnote: " + ioe.getMessage()); 1315 throw new RuntimeException ("IOException: " + ioe); 1316 } catch (Exception e) { 1317 log.error("startFootnote: " + e.getMessage()); 1318 throw new RuntimeException ("Exception: " + e); 1319 } 1320 } 1321 1322 1326 public void endFootnote(Footnote footnote) { 1327 if (bDefer) { 1328 return; 1329 } 1330 1331 builderContext.popContainer(); 1332 } 1333 1334 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 ioe) { 1351 log.error("startFootnoteBody: " + ioe.getMessage()); 1353 throw new RuntimeException ("IOException: " + ioe); 1354 } catch (Exception e) { 1355 log.error("startFootnoteBody: " + e.getMessage()); 1356 throw new RuntimeException ("Exception: " + e); 1357 } 1358 } 1359 1360 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 ioe) { 1377 log.error("endFootnoteBody: " + ioe.getMessage()); 1379 throw new RuntimeException ("IOException: " + ioe); 1380 } catch (Exception e) { 1381 log.error("endFootnoteBody: " + e.getMessage()); 1382 throw new RuntimeException ("Exception: " + e); 1383 } 1384 } 1385 1386 1390 public void leader(Leader l) { 1391 } 1392 1393 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 (data, start, length - start)); 1415 textrun.popInlineAttributes(); 1416 } catch (IOException ioe) { 1417 log.error("characters: " + ioe.getMessage()); 1419 throw new RuntimeException (ioe.getMessage()); 1420 } catch (Exception e) { 1421 log.error("characters:" + e.getMessage()); 1422 throw new RuntimeException (e.getMessage()); 1423 } 1424 } 1425 1426 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 ioe) { 1447 log.error("startPageNumber:" + ioe.getMessage()); 1448 throw new RuntimeException (ioe.getMessage()); 1449 } catch (Exception e) { 1450 log.error("startPageNumber: " + e.getMessage()); 1451 throw new RuntimeException (e.getMessage()); 1452 } 1453 } 1454 1455 1459 public void endPageNumber(PageNumber pagenum) { 1460 if (bDefer) { 1461 return; 1462 } 1463 } 1464 1465 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 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 ) { 1529 if (bStart) { 1530 Character c = (Character ) 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 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 if (table.getColumns() != null) { 1645 for (Iterator it = table.getColumns().iterator(); it.hasNext();) { 1646 recurseFONode( (FONode) it.next() ); 1647 } 1648 } else { 1649 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 if (table.getTableHeader() != null) { 1656 recurseFONode( table.getTableHeader() ); 1657 } 1658 1659 if (table.getTableFooter() != null) { 1661 recurseFONode( table.getTableFooter() ); 1662 } 1663 1664 if (foNode.getChildNodes() != null) { 1665 for (Iterator 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 if (foNode.getChildNodes() != null) { 1682 for (Iterator 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 |