1 2 17 18 19 20 package org.apache.poi.hdf.extractor; 21 22 23 import org.apache.poi.hdf.extractor.util.*; 24 import org.apache.poi.hdf.extractor.data.*; 25 import java.util.*; 26 import java.io.*; 27 import javax.swing.*; 28 29 import java.awt.*; 30 31 import org.apache.poi.poifs.filesystem.POIFSFileSystem; 32 import org.apache.poi.poifs.filesystem.POIFSDocument; 33 import org.apache.poi.poifs.filesystem.DocumentEntry; 34 35 import org.apache.poi.util.LittleEndian; 36 37 44 45 public class WordDocument 46 { 47 48 byte[] _header; 49 50 StyleSheet _styleSheet; 51 52 ListTables _listTables; 53 54 DOP _docProps = new DOP(); 55 56 int _currentList = -1; 57 int _tableSize; 58 int _sectionCounter = 1; 59 60 FontTable _fonts; 61 62 63 BTreeSet _text = new BTreeSet(); 64 65 BTreeSet _characterTable = new BTreeSet(); 66 67 BTreeSet _paragraphTable = new BTreeSet(); 68 69 BTreeSet _sectionTable = new BTreeSet(); 70 71 72 StringBuffer _headerBuffer = new StringBuffer (); 73 74 StringBuffer _bodyBuffer = new StringBuffer (); 75 76 StringBuffer _cellBuffer; 77 78 ArrayList _cells; 79 80 ArrayList _table; 81 82 83 byte[] _plcfHdd; 84 85 86 int _fcMin; 87 88 int _ccpText; 89 90 int _ccpFtn; 91 92 93 private static String _outName; 94 95 96 private InputStream istream; 97 98 private POIFSFileSystem filesystem; 99 100 private static int HEADER_EVEN_INDEX = 0; 102 private static int HEADER_ODD_INDEX = 1; 103 private static int FOOTER_EVEN_INDEX = 2; 104 private static int FOOTER_ODD_INDEX = 3; 105 private static int HEADER_FIRST_INDEX = 4; 106 private static int FOOTER_FIRST_INDEX = 5; 107 108 112 public static void main(String args[]) 113 { 114 126 try 127 { 128 _outName = args[1]; 129 WordDocument file = new WordDocument(args[0]); 130 file.closeDoc(); 131 } 132 catch(Exception e) 133 { 134 e.printStackTrace(); 135 } 136 System.exit(0); 137 } 138 145 public void writeAllText(Writer out) throws IOException 146 { 147 int textStart = Utils.convertBytesToInt(_header, 0x18); 148 int textEnd = Utils.convertBytesToInt(_header, 0x1c); 149 ArrayList textPieces = findProperties(textStart, textEnd, _text.root); 150 int size = textPieces.size(); 151 152 for(int x = 0; x < size; x++) 153 { 154 TextPiece nextPiece = (TextPiece)textPieces.get(x); 155 int start = nextPiece.getStart(); 156 int end = nextPiece.getEnd(); 157 boolean unicode = nextPiece.usesUnicode(); 158 int add = 1; 159 160 if(unicode) 161 { 162 add = 2; 163 char ch; 164 for(int y = start; y < end; y += add) 165 { 166 ch = (char)Utils.convertBytesToShort(_header, y); 167 out.write(ch); 168 } 169 } 170 else 171 { 172 String sText = new String (_header, start, end-start); 173 out.write(sText); 174 } 175 } 176 } 177 184 public WordDocument(String fileName) throws IOException 185 { 186 this(new FileInputStream(fileName)); 187 } 188 189 public WordDocument(InputStream inputStream) throws IOException 190 { 191 istream = inputStream; 193 filesystem = new POIFSFileSystem(istream); 194 195 readFIB(); 198 199 ArrayList sections = findProperties(_fcMin, _fcMin + _ccpText, _sectionTable.root); 201 202 int size = sections.size(); 205 for(int x = 0; x < size; x++) 206 { 207 SepxNode node = (SepxNode)sections.get(x); 208 int start = node.getStart(); 209 int end = node.getEnd(); 210 SEP sep = (SEP)StyleSheet.uncompressProperty(node.getSepx(), new SEP(), _styleSheet); 211 writeSection(Math.max(_fcMin, start), Math.min(_fcMin + _ccpText, end), sep, _text, _paragraphTable, _characterTable, _styleSheet); 212 } 213 istream.close(); 215 216 } 217 223 private void readFIB() throws IOException 224 { 225 DocumentEntry headerProps = 227 (DocumentEntry)filesystem.getRoot().getEntry("WordDocument"); 228 229 _header = new byte[headerProps.getSize()]; 231 filesystem.createDocumentInputStream("WordDocument").read(_header); 232 233 int info = LittleEndian.getShort(_header, 0xa); 235 236 _fcMin = LittleEndian.getInt(_header, 0x18); 237 _ccpText = LittleEndian.getInt(_header, 0x4c); 238 _ccpFtn = LittleEndian.getInt(_header, 0x50); 239 240 int charPLC = LittleEndian.getInt(_header, 0xfa); 241 int charPlcSize = LittleEndian.getInt(_header, 0xfe); 242 int parPLC = LittleEndian.getInt(_header, 0x102); 243 int parPlcSize = LittleEndian.getInt(_header, 0x106); 244 boolean useTable1 = (info & 0x200) != 0; 245 246 processComplexFile(useTable1, charPLC, charPlcSize, parPLC, parPlcSize); 248 } 249 250 264 private void processComplexFile(boolean useTable1, int charTable, 265 int charPlcSize, int parTable, int parPlcSize) throws IOException 266 { 267 268 int complexOffset = LittleEndian.getInt(_header, 0x1a2); 270 271 String tablename=null; 272 DocumentEntry tableEntry = null; 273 if(useTable1) 274 { 275 tablename="1Table"; 276 } 277 else 278 { 279 tablename="0Table"; 280 } 281 tableEntry = (DocumentEntry)filesystem.getRoot().getEntry(tablename); 282 283 int size = tableEntry.getSize(); 285 byte[] tableStream = new byte[size]; 286 filesystem.createDocumentInputStream(tablename).read(tableStream); 287 288 initDocProperties(tableStream); 290 initPclfHdd(tableStream); 292 findText(tableStream, complexOffset); 294 findFormatting(tableStream, charTable, charPlcSize, parTable, parPlcSize); 296 297 } 298 307 private void findText(byte[] tableStream, int complexOffset) throws IOException 308 { 309 int pos = complexOffset; 311 while(tableStream[pos] == 1) 314 { 315 pos++; 316 int skip = LittleEndian.getShort(tableStream, pos); 317 pos += 2 + skip; 318 } 319 if(tableStream[pos] != 2) 320 { 321 throw new IOException("corrupted Word file"); 322 } 323 else 324 { 325 int pieceTableSize = LittleEndian.getInt(tableStream, ++pos); 327 pos += 4; 328 int pieces = (pieceTableSize - 4) / 12; 329 for (int x = 0; x < pieces; x++) 330 { 331 int filePos = LittleEndian.getInt(tableStream, pos + ((pieces + 1) * 4) + (x * 8) + 2); 332 boolean unicode = false; 333 if ((filePos & 0x40000000) == 0) 334 { 335 unicode = true; 336 } 337 else 338 { 339 unicode = false; 340 filePos &= ~(0x40000000); filePos /= 2; 342 } 343 int totLength = LittleEndian.getInt(tableStream, pos + (x + 1) * 4) - 344 LittleEndian.getInt(tableStream, pos + (x * 4)); 345 346 TextPiece piece = new TextPiece(filePos, totLength, unicode); 347 _text.add(piece); 348 349 } 350 351 } 352 } 353 354 363 private void findFormatting(byte[] tableStream, int charOffset, 364 int charPlcSize, int parOffset, int parPlcSize) throws IOException 365 { 366 openDoc(); 367 createStyleSheet(tableStream); 368 createListTables(tableStream); 369 createFontTable(tableStream); 370 371 374 int arraySize = (charPlcSize - 4)/8; 375 376 for(int x = 0; x < arraySize; x++) 378 { 379 380 381 int PN = LittleEndian.getInt(tableStream, charOffset + (4 * (arraySize + 1) + (4 * x))); 384 385 byte[] fkp = new byte[512]; 386 System.arraycopy(_header, (PN * 512), fkp, 0, 512); 387 int crun = Utils.convertUnsignedByteToInt(fkp[511]); 389 for(int y = 0; y < crun; y++) 390 { 391 int fcStart = LittleEndian.getInt(fkp, y * 4); 393 int fcEnd = LittleEndian.getInt(fkp, (y+1) * 4); 394 int chpxOffset = 2 * Utils.convertUnsignedByteToInt(fkp[((crun + 1) * 4) + y]); 396 397 if(chpxOffset == 0) 399 400 { 401 _characterTable.add(new ChpxNode(fcStart, fcEnd, new byte[0])); 402 continue; 403 } 404 405 int size = Utils.convertUnsignedByteToInt(fkp[chpxOffset]); 406 407 byte[] chpx = new byte[size]; 408 System.arraycopy(fkp, ++chpxOffset, chpx, 0, size); 409 _characterTable.add(new ChpxNode(fcStart, fcEnd, chpx)); 411 } 412 413 } 414 415 arraySize = (parPlcSize - 4)/8; 417 for(int x = 0; x < arraySize; x++) 419 { 420 int PN = LittleEndian.getInt(tableStream, parOffset + (4 * (arraySize + 1) + (4 * x))); 421 422 byte[] fkp = new byte[512]; 423 System.arraycopy(_header, (PN * 512), fkp, 0, 512); 424 int crun = Utils.convertUnsignedByteToInt(fkp[511]); 426 for(int y = 0; y < crun; y++) 427 { 428 int fcStart = LittleEndian.getInt(fkp, y * 4); 430 int fcEnd = LittleEndian.getInt(fkp, (y+1) * 4); 431 int papxOffset = 2 * Utils.convertUnsignedByteToInt(fkp[((crun + 1) * 4) + (y * 13)]); 433 int size = 2 * Utils.convertUnsignedByteToInt(fkp[papxOffset]); 434 if(size == 0) 435 { 436 size = 2 * Utils.convertUnsignedByteToInt(fkp[++papxOffset]); 437 } 438 else 439 { 440 size--; 441 } 442 443 byte[] papx = new byte[size]; 444 System.arraycopy(fkp, ++papxOffset, papx, 0, size); 445 _paragraphTable.add(new PapxNode(fcStart, fcEnd, papx)); 446 447 } 448 449 } 450 451 int fcMin = Utils.convertBytesToInt(_header, 0x18); 453 int plcfsedFC = Utils.convertBytesToInt(_header, 0xca); 454 int plcfsedSize = Utils.convertBytesToInt(_header, 0xce); 455 byte[] plcfsed = new byte[plcfsedSize]; 456 System.arraycopy(tableStream, plcfsedFC, plcfsed, 0, plcfsedSize); 457 458 arraySize = (plcfsedSize - 4)/16; 459 460 462 for(int x = 0; x < arraySize; x++) 463 { 464 int sectionStart = Utils.convertBytesToInt(plcfsed, x * 4) + fcMin; 465 int sectionEnd = Utils.convertBytesToInt(plcfsed, (x+1) * 4) + fcMin; 466 int sepxStart = Utils.convertBytesToInt(plcfsed, 4 * (arraySize + 1) + (x * 12) + 2); 467 int sepxSize = Utils.convertBytesToShort(_header, sepxStart); 468 byte[] sepx = new byte[sepxSize]; 469 System.arraycopy(_header, sepxStart + 2, sepx, 0, sepxSize); 470 SepxNode node = new SepxNode(x + 1, sectionStart, sectionEnd, sepx); 471 _sectionTable.add(node); 472 } 473 474 475 } 476 477 public void openDoc() 478 { 479 _headerBuffer.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\r\n"); 480 _headerBuffer.append("<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\r\n"); 481 _headerBuffer.append("<fo:layout-master-set>\r\n"); 482 483 } 484 private HeaderFooter findSectionHdrFtr(int type, int index) 485 { 486 if(_plcfHdd.length < 50) 487 { 488 return new HeaderFooter(0,0,0); 489 } 490 int start = _fcMin + _ccpText + _ccpFtn; 491 int end = start; 492 int arrayIndex = 0; 493 494 switch(type) 495 { 496 case HeaderFooter.HEADER_EVEN: 497 arrayIndex = (HEADER_EVEN_INDEX + (index * 6)); 498 break; 499 case HeaderFooter.FOOTER_EVEN: 500 arrayIndex = (FOOTER_EVEN_INDEX + (index * 6)); 501 break; 502 case HeaderFooter.HEADER_ODD: 503 arrayIndex = (HEADER_ODD_INDEX + (index * 6)); 504 break; 505 case HeaderFooter.FOOTER_ODD: 506 arrayIndex = (FOOTER_ODD_INDEX + (index * 6)); 507 break; 508 case HeaderFooter.HEADER_FIRST: 509 arrayIndex = (HEADER_FIRST_INDEX + (index * 6)); 510 break; 511 case HeaderFooter.FOOTER_FIRST: 512 arrayIndex = (FOOTER_FIRST_INDEX + (index * 6)); 513 break; 514 } 515 start += Utils.convertBytesToInt(_plcfHdd, (arrayIndex * 4)); 516 end += Utils.convertBytesToInt(_plcfHdd, (arrayIndex + 1) * 4); 517 518 HeaderFooter retValue = new HeaderFooter(type, start, end); 519 520 if((end - start) == 0 && index > 1) 521 { 522 retValue = findSectionHdrFtr(type, index - 1); 523 } 524 return retValue; 525 } 526 531 private void initDocProperties(byte[] tableStream) 532 { 533 int pos = LittleEndian.getInt(_header, 0x192); 534 int size = LittleEndian.getInt(_header, 0x196); 535 byte[] dop = new byte[size]; 536 537 System.arraycopy(tableStream, pos, dop, 0, size); 538 539 _docProps._fFacingPages = (dop[0] & 0x1) > 0; 540 _docProps._fpc = (dop[0] & 0x60) >> 5; 541 542 short num = LittleEndian.getShort(dop, 2); 543 _docProps._rncFtn = (num & 0x3); 544 _docProps._nFtn = (short)(num & 0xfffc) >> 2; 545 num = LittleEndian.getShort(dop, 52); 546 _docProps._rncEdn = num & 0x3; 547 _docProps._nEdn = (short)(num & 0xfffc) >> 2; 548 num = LittleEndian.getShort(dop, 54); 549 _docProps._epc = num & 0x3; 550 } 551 552 public void writeSection(int start, int end, SEP sep, BTreeSet text, 553 BTreeSet paragraphTable, BTreeSet characterTable, 554 StyleSheet stylesheet) 555 { 556 557 HeaderFooter titleHeader = findSectionHdrFtr(HeaderFooter.HEADER_FIRST, _sectionCounter); 558 HeaderFooter titleFooter = findSectionHdrFtr(HeaderFooter.FOOTER_FIRST, _sectionCounter); 559 HeaderFooter oddHeader = findSectionHdrFtr(HeaderFooter.HEADER_ODD, _sectionCounter); 560 HeaderFooter evenHeader = findSectionHdrFtr(HeaderFooter.HEADER_EVEN, _sectionCounter); 561 HeaderFooter oddFooter = findSectionHdrFtr(HeaderFooter.FOOTER_ODD, _sectionCounter); 562 HeaderFooter evenFooter = findSectionHdrFtr(HeaderFooter.FOOTER_EVEN, _sectionCounter); 563 564 String titlePage = null; 565 String evenPage = null; 566 String oddPage = null; 567 String regPage = null; 568 569 String sequenceName = null; 570 571 584 585 if(_docProps._fFacingPages) 586 { 587 if(sep._fTitlePage) 588 { 589 String before = createRegion(true, titleHeader, sep, "title-header" + _sectionCounter); 590 String after = createRegion(false, titleFooter, sep, "title-footer" + _sectionCounter); 591 titlePage = createPageMaster(sep, "first", _sectionCounter, before, after); 592 } 593 String before = createRegion(true, evenHeader, sep, "even-header" + _sectionCounter); 594 String after = createRegion(false, evenFooter, sep, "even-footer" + _sectionCounter); 595 evenPage = createPageMaster(sep, "even", _sectionCounter, before, after); 596 before = createRegion(true, oddHeader, sep, "odd-header" + _sectionCounter); 597 after = createRegion(false, oddFooter, sep, "odd-footer" + _sectionCounter); 598 oddPage = createPageMaster(sep, "odd", _sectionCounter, before, after); 599 sequenceName = createEvenOddPageSequence(titlePage, evenPage, oddPage, _sectionCounter); 600 601 openPage(sequenceName, "reference"); 602 603 if(sep._fTitlePage) 604 { 605 606 607 if(!titleHeader.isEmpty()) 608 { 609 addStaticContent("title-header" + _sectionCounter, titleHeader); 610 } 611 if(!titleFooter.isEmpty()) 612 { 613 addStaticContent("title-footer" + _sectionCounter, titleFooter); 614 } 615 } 616 617 if(!oddHeader.isEmpty()) 619 { 620 addStaticContent("odd-header" + _sectionCounter, oddHeader); 621 } 622 if(!oddFooter.isEmpty()) 623 { 624 addStaticContent("odd-footer" + _sectionCounter, oddFooter); 625 } 626 if(!evenHeader.isEmpty()) 627 { 628 addStaticContent("even-header" + _sectionCounter, evenHeader); 629 } 630 if(!evenFooter.isEmpty()) 631 { 632 addStaticContent("even-footer" + _sectionCounter, evenFooter); 633 } 634 openFlow(); 635 addBlockContent(start, end, text, paragraphTable, characterTable); 636 closeFlow(); 637 closePage(); 638 } 639 else 640 { 641 647 String before = createRegion(true, oddHeader, sep, null); 648 String after = createRegion(false, oddFooter, sep, null); 649 regPage = createPageMaster(sep, "page", _sectionCounter, before, after); 650 651 if(sep._fTitlePage) 652 { 653 before = createRegion(true, titleHeader, sep, "title-header" + _sectionCounter); 654 after = createRegion(false, titleFooter, sep, "title-footer" + _sectionCounter); 655 titlePage = createPageMaster(sep, "first", _sectionCounter, before, after); 656 sequenceName = createPageSequence(titlePage, regPage, _sectionCounter); 657 openPage(sequenceName, "reference"); 658 659 if(!titleHeader.isEmpty()) 660 { 661 addStaticContent("title-header" + _sectionCounter, titleHeader); 662 } 663 if(!titleFooter.isEmpty()) 664 { 665 addStaticContent("title-footer" + _sectionCounter, titleFooter); 666 } 667 } 668 else 669 { 670 openPage(regPage, "name"); 671 } 672 if(!oddHeader.isEmpty()) 673 { 674 addStaticContent("xsl-region-before", oddHeader); 675 } 676 if(!oddFooter.isEmpty()) 677 { 678 addStaticContent("xsl-region-after", oddFooter); 679 } 680 openFlow(); 681 addBlockContent(start, end, text, paragraphTable, characterTable); 682 closeFlow(); 683 closePage(); 684 } 685 _sectionCounter++; 686 } 687 688 private int calculateHeaderHeight(int start, int end, int pageWidth) 689 { 690 ArrayList paragraphs = findProperties(start, end, _paragraphTable.root); 691 int size = paragraphs.size(); 692 ArrayList lineHeights = new ArrayList(); 693 695 for(int x = 0; x < size; x++) 696 { 697 PapxNode node = (PapxNode)paragraphs.get(x); 698 int parStart = Math.max(node.getStart(), start); 699 int parEnd = Math.min(node.getEnd(), end); 700 701 int lineWidth = 0; 702 int maxHeight = 0; 703 704 ArrayList textRuns = findProperties(parStart, parEnd, _characterTable.root); 705 int charSize = textRuns.size(); 706 707 for(int y = 0; y < charSize; y++) 709 { 710 ChpxNode charNode = (ChpxNode)textRuns.get(y); 711 int istd = Utils.convertBytesToShort(node.getPapx(), 0); 712 StyleDescription sd = _styleSheet.getStyleDescription(istd); 713 CHP chp = (CHP)StyleSheet.uncompressProperty(charNode.getChpx(), sd.getCHP(), _styleSheet); 714 715 718 int height = 10; maxHeight = Math.max(maxHeight, height); 720 721 int charStart = Math.max(parStart, charNode.getStart()); 722 int charEnd = Math.min(parEnd, charNode.getEnd()); 723 724 ArrayList text = findProperties(charStart, charEnd, _text.root); 725 726 int textSize = text.size(); 727 StringBuffer buf = new StringBuffer (); 728 for(int z = 0; z < textSize; z++) 729 { 730 731 TextPiece piece = (TextPiece)text.get(z); 732 int textStart = Math.max(piece.getStart(), charStart); 733 int textEnd = Math.min(piece.getEnd(), charEnd); 734 735 if(piece.usesUnicode()) 736 { 737 addUnicodeText(textStart, textEnd, buf); 738 } 739 else 740 { 741 addText(textStart, textEnd, buf); 742 } 743 } 744 745 String tempString = buf.toString(); 746 lineWidth += 10 * tempString.length(); if(lineWidth > pageWidth) 748 { 749 lineHeights.add(new Integer (maxHeight)); 750 maxHeight = 0; 751 lineWidth = 0; 752 } 753 } 754 lineHeights.add(new Integer (maxHeight)); 755 } 756 int sum = 0; 757 size = lineHeights.size(); 758 for(int x = 0; x < size; x++) 759 { 760 Integer height = (Integer )lineHeights.get(x); 761 sum += height.intValue(); 762 } 763 764 return sum; 765 } 766 784 private String createRegion(boolean before, HeaderFooter header, SEP sep, String name) 785 { 786 if(header.isEmpty()) 787 { 788 return ""; 789 } 790 String region = "region-name=\"" + name + "\""; 791 if(name == null) 792 { 793 region = ""; 794 } 795 int height = calculateHeaderHeight(header.getStart(), header.getEnd(), sep._xaPage/20); 796 int marginTop = 0; 797 int marginBottom = 0; 798 int extent = 0; 799 String where = null; 800 String align = null; 801 802 if(before) 803 { 804 where = "before"; 805 align = "before"; 806 marginTop = sep._dyaHdrTop/20; 807 extent = height + marginTop; 808 sep._dyaTop = Math.max(extent*20, sep._dyaTop); 809 } 810 else 811 { 812 where = "after"; 813 align = "after"; 814 marginBottom = sep._dyaHdrBottom/20; 815 extent = height + marginBottom; 816 sep._dyaBottom = Math.max(extent*20, sep._dyaBottom); 817 } 818 819 int marginLeft = sep._dxaLeft/20; 820 int marginRight = sep._dxaRight/20; 821 822 return "<fo:region-" + where + " display-align=\"" + align + "\" extent=\"" + 823 extent + "pt\" padding-left=\"" + marginLeft + "pt\" padding-right=\"" + 824 marginRight + "pt\" padding-top=\"" + marginTop + "pt\" padding-bottom=\"" + 825 marginBottom + "pt\" " + region + "/>"; 826 827 } 828 private String createRegion(String where, String name) 829 { 830 return "<fo:region-" + where + " overflow=\"scroll\" region-name=\"" + name + "\"/>"; 831 } 832 private String createEvenOddPageSequence(String titlePage, String evenPage, String oddPage, int counter) 833 { 834 String name = "my-sequence" + counter; 835 _headerBuffer.append("<fo:page-sequence-master master-name=\"" + name + "\"> "); 836 _headerBuffer.append("<fo:repeatable-page-master-alternatives>"); 837 if(titlePage != null) 838 { 839 _headerBuffer.append("<fo:conditional-page-master-reference " + 840 "page-position=\"first\" master-reference=\"" + 841 titlePage + "\"/>"); 842 } 843 _headerBuffer.append("<fo:conditional-page-master-reference odd-or-even=\"odd\" "); 844 _headerBuffer.append("master-reference=\""+ oddPage + "\"/> "); 845 _headerBuffer.append("<fo:conditional-page-master-reference odd-or-even=\"even\" "); 846 _headerBuffer.append("master-reference=\"" + evenPage + "\"/> "); 847 _headerBuffer.append("</fo:repeatable-page-master-alternatives>"); 848 _headerBuffer.append("</fo:page-sequence-master>"); 849 return name; 850 } 851 private String createPageSequence(String titlePage, String regPage, int counter) 852 { 853 String name = null; 854 if(titlePage != null) 855 { 856 name = "my-sequence" + counter; 857 _headerBuffer.append("<fo:page-sequence-master master-name=\"" + name + "\"> "); 858 _headerBuffer.append("<fo:single-page-master-reference master-reference=\"" + titlePage + "\"/>"); 859 _headerBuffer.append("<fo:repeatable-page-master-reference master-reference=\"" + regPage + "\"/>"); 860 _headerBuffer.append("</fo:page-sequence-master>"); 861 } 862 return name; 863 } 864 private void addBlockContent(int start, int end, BTreeSet text, 865 BTreeSet paragraphTable, BTreeSet characterTable) 866 { 867 868 BTreeSet.BTreeNode root = paragraphTable.root; 869 ArrayList pars = findProperties(start, end, root); 870 int size = pars.size(); 872 873 for(int c = 0; c < size; c++) 874 { 875 PapxNode currentNode = (PapxNode)pars.get(c); 876 createParagraph(start, end, currentNode, characterTable, text); 877 } 878 } 880 private String getTextAlignment(byte jc) 881 { 882 switch(jc) 883 { 884 case 0: 885 return "start"; 886 case 1: 887 return "center"; 888 case 2: 889 return "end"; 890 case 3: 891 return "justify"; 892 default: 893 return "left"; 894 } 895 } 896 private void createParagraph(int start, int end, PapxNode currentNode, 897 BTreeSet characterTable, BTreeSet text) 898 { 899 StringBuffer blockBuffer = _bodyBuffer; 900 byte[] papx = currentNode.getPapx(); 901 int istd = Utils.convertBytesToShort(papx, 0); 902 StyleDescription std = _styleSheet.getStyleDescription(istd); 903 PAP pap = (PAP)StyleSheet.uncompressProperty(papx, std.getPAP(), _styleSheet); 904 905 if(pap._fInTable > 0) 907 { 908 if(pap._fTtp == 0) 909 { 910 if(_cellBuffer == null) 911 { 912 _cellBuffer = new StringBuffer (); 913 } 914 blockBuffer = _cellBuffer; 915 } 916 else 917 { 918 if(_table == null) 919 { 920 _table = new ArrayList(); 921 } 922 TAP tap = (TAP)StyleSheet.uncompressProperty(papx, new TAP(), _styleSheet); 923 TableRow nextRow = new TableRow(_cells, tap); 924 _table.add(nextRow); 925 _cells = null; 926 return; 927 } 928 } 929 else 930 { 931 printTable(); 933 } 934 935 if(pap._ilfo > 0) 936 { 937 LVL lvl = _listTables.getLevel(pap._ilfo, pap._ilvl); 938 addListParagraphContent(lvl, blockBuffer, pap, currentNode, start, end, std); 939 } 940 else 941 { 942 addParagraphContent(blockBuffer, pap, currentNode, start, end, std); 943 } 944 945 } 946 947 private void addListParagraphContent(LVL lvl, StringBuffer blockBuffer, PAP pap, 948 PapxNode currentNode, int start, int end, 949 StyleDescription std) 950 { 951 pap = (PAP)StyleSheet.uncompressProperty(lvl._papx, pap, _styleSheet, false); 952 953 addParagraphProperties(pap, blockBuffer); 954 955 ArrayList charRuns = findProperties(Math.max(currentNode.getStart(), start), 956 Math.min(currentNode.getEnd(), end), 957 _characterTable.root); 958 int len = charRuns.size(); 959 960 CHP numChp = (CHP)StyleSheet.uncompressProperty(((ChpxNode)charRuns.get(len-1)).getChpx(), std.getCHP(), _styleSheet); 961 962 numChp = (CHP)StyleSheet.uncompressProperty(lvl._chpx, numChp, _styleSheet); 963 964 int indent = -1 * pap._dxaLeft1; 967 String bulletText = getBulletText(lvl, pap); 968 969 indent = indent - (bulletText.length() * 10) * 20; 971 if(indent > 0) 972 { 973 numChp._paddingEnd = (short)indent; 974 } 975 976 addCharacterProperties(numChp, blockBuffer); 977 int listNum = 0; 978 979 blockBuffer.append(bulletText); 982 985 990 991 switch (lvl._ixchFollow) 992 { 993 case 0: 994 addText('\u0009', blockBuffer); 995 break; 996 case 1: 997 addText(' ', blockBuffer); 998 break; 999 } 1000 1001 closeLine(blockBuffer); 1002 for(int x = 0; x < len; x++) 1003 { 1004 ChpxNode charNode = (ChpxNode)charRuns.get(x); 1005 byte[] chpx = charNode.getChpx(); 1006 CHP chp = (CHP)StyleSheet.uncompressProperty(chpx, std.getCHP(), _styleSheet); 1007 1008 1009 addCharacterProperties(chp, blockBuffer); 1010 1011 int charStart = Math.max(charNode.getStart(), currentNode.getStart()); 1012 int charEnd = Math.min(charNode.getEnd(), currentNode.getEnd()); 1013 ArrayList textRuns = findProperties(charStart, charEnd, _text.root); 1014 int textRunLen = textRuns.size(); 1015 for(int y = 0; y < textRunLen; y++) 1016 { 1017 TextPiece piece = (TextPiece)textRuns.get(y); 1018 charStart = Math.max(charStart, piece.getStart()); 1019 charEnd = Math.min(charEnd, piece.getEnd()); 1020 1021 if(piece.usesUnicode()) 1022 { 1023 addUnicodeText(charStart, charEnd, blockBuffer); 1024 } 1025 else 1026 { 1027 addText(charStart, charEnd, blockBuffer); 1028 } 1029 closeLine(blockBuffer); 1030 } 1031 } 1032 closeBlock(blockBuffer); 1033 } 1034 1035 private void addParagraphContent(StringBuffer blockBuffer, PAP pap, 1036 PapxNode currentNode, int start, int end, 1037 StyleDescription std) 1038 { 1039 addParagraphProperties(pap, blockBuffer); 1040 1041 ArrayList charRuns = findProperties(Math.max(currentNode.getStart(), start), 1042 Math.min(currentNode.getEnd(), end), 1043 _characterTable.root); 1044 int len = charRuns.size(); 1045 1046 for(int x = 0; x < len; x++) 1047 { 1048 ChpxNode charNode = (ChpxNode)charRuns.get(x); 1049 byte[] chpx = charNode.getChpx(); 1050 CHP chp = (CHP)StyleSheet.uncompressProperty(chpx, std.getCHP(), _styleSheet); 1051 1052 addCharacterProperties(chp, blockBuffer); 1053 1054 int charStart = Math.max(charNode.getStart(), currentNode.getStart()); 1055 int charEnd = Math.min(charNode.getEnd(), currentNode.getEnd()); 1056 ArrayList textRuns = findProperties(charStart, charEnd, _text.root); 1057 int textRunLen = textRuns.size(); 1058 for(int y = 0; y < textRunLen; y++) 1059 { 1060 TextPiece piece = (TextPiece)textRuns.get(y); 1061 charStart = Math.max(charStart, piece.getStart()); 1062 charEnd = Math.min(charEnd, piece.getEnd()); 1063 1064 if(piece.usesUnicode()) 1065 { 1066 addUnicodeText(charStart, charEnd, blockBuffer); 1067 } 1068 else 1069 { 1070 addText(charStart, charEnd, blockBuffer); 1071 } 1072 closeLine(blockBuffer); 1073 } 1074 } 1075 closeBlock(blockBuffer); 1076 } 1077 private void addText(int start, int end, StringBuffer buf) 1078 { 1079 for(int x = start; x < end; x++) 1080 { 1081 char ch = '?'; 1082 1083 1084 ch = (char)_header[x]; 1085 1086 addText(ch, buf); 1087 } 1088 } 1089 private void addText(char ch, StringBuffer buf) 1090 { 1091 int num = 0xffff & ch; 1092 if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || 1093 (ch >= '0' && ch <= '9') || ch == '_' || ch == ' ' || ch == '-' || ch == '.' || ch == '$') 1094 { 1095 buf.append(ch); 1096 } 1097 else if(num == 0x07 && _cellBuffer != null) 1098 { 1099 1100 if(_cells == null) 1101 { 1102 _cells = new ArrayList(); 1103 } 1104 closeLine(_cellBuffer); 1105 closeBlock(_cellBuffer); 1106 _cells.add(_cellBuffer.toString()); 1107 _cellBuffer = null; 1108 1109 } 1110 1111 else 1112 { 1113 1114 if(num < 0x20) 1115 num=0x20; 1116 buf.append("&#"); 1117 buf.append(num); 1118 buf.append(';'); 1119 } 1120 } 1121 private void addUnicodeText(int start, int end, StringBuffer buf) 1122 { 1123 for(int x = start; x < end; x += 2) 1124 { 1125 char ch = Utils.getUnicodeCharacter(_header, x); 1126 addText(ch, buf); 1133 } 1135 } 1136 private void addParagraphProperties(PAP pap, StringBuffer buf) 1137 { 1138 buf.append("<fo:block "); 1139 buf.append("text-align=\"" + getTextAlignment(pap._jc) + "\"\r\n"); 1140 buf.append("linefeed-treatment=\"preserve\" "); 1141 buf.append("white-space-collapse=\"false\" "); 1142 1143 if(pap._fKeep > 0) 1144 { 1145 buf.append("keep-together.within-page=\"always\"\r\n"); 1146 } 1147 if(pap._fKeepFollow > 0) 1148 { 1149 buf.append("keep-with-next.within-page=\"always\"\r\n"); 1150 } 1151 if(pap._fPageBreakBefore > 0) 1152 { 1153 buf.append("break-before=\"page\"\r\n"); 1154 } 1155 if(pap._fNoAutoHyph == 0) 1156 { 1157 buf.append("hyphenate=\"true\"\r\n"); 1158 } 1159 else 1160 { 1161 buf.append("hyphenate=\"false\"\r\n"); 1162 } 1163 if(pap._dxaLeft > 0) 1164 { 1165 buf.append("start-indent=\"" + ((float)pap._dxaLeft)/1440.0f + "in\"\r\n"); 1166 } 1167 if(pap._dxaRight > 0) 1168 { 1169 buf.append("end-indent=\"" + ((float)pap._dxaRight)/1440.0f + "in\"\r\n"); 1170 } 1171 if(pap._dxaLeft1 != 0) 1172 { 1173 buf.append("text-indent=\"" + ((float)pap._dxaLeft1)/1440.0f + "in\"\r\n"); 1174 } 1175 if(pap._lspd[1] == 0) 1176 { 1177 } 1179 addBorder(buf, pap._brcTop, "top"); 1180 addBorder(buf, pap._brcBottom, "bottom"); 1181 addBorder(buf, pap._brcLeft, "left"); 1182 addBorder(buf, pap._brcRight, "right"); 1183 1184 buf.append(">"); 1185 1186 } 1187 1188 private void addCharacterProperties(CHP chp, StringBuffer buf) 1189 { 1190 buf.append("<fo:inline "); 1191 buf.append("font-family=\"" + _fonts.getFont(chp._ftcAscii) + "\" "); 1192 buf.append("font-size=\"" + (chp._hps / 2) + "pt\" "); 1193 buf.append("color=\"" + getColor(chp._ico) + "\" "); 1194 1197 addBorder(buf, chp._brc, "top"); 1198 addBorder(buf, chp._brc, "bottom"); 1199 addBorder(buf, chp._brc, "left"); 1200 addBorder(buf, chp._brc, "right"); 1201 1202 if(chp._italic) 1203 { 1204 buf.append("font-style=\"italic\" "); 1205 } 1206 if(chp._bold) 1207 { 1208 buf.append("font-weight=\"bold\" "); 1209 } 1210 if(chp._fSmallCaps) 1211 { 1212 buf.append("font-variant=\"small-caps\" "); 1213 } 1214 if(chp._fCaps) 1215 { 1216 buf.append("text-transform=\"uppercase\" "); 1217 } 1218 if(chp._fStrike || chp._fDStrike) 1219 { 1220 buf.append("text-decoration=\"line-through\" "); 1221 } 1222 if(chp._fShadow) 1223 { 1224 int size = chp._hps/24; 1225 buf.append("text-shadow=\"" + size + "pt\""); 1226 } 1227 if(chp._fLowerCase) 1228 { 1229 buf.append("text-transform=\"lowercase\" "); 1230 } 1231 if(chp._kul > 0) 1232 { 1233 buf.append("text-decoration=\"underline\" "); 1234 } 1235 if(chp._highlighted) 1236 { 1237 buf.append("background-color=\"" + getColor(chp._icoHighlight) + "\" "); 1238 } 1239 if(chp._paddingStart != 0) 1240 { 1241 buf.append("padding-start=\"" + (float)chp._paddingStart/1440.0f + "in\" "); 1242 } 1243 if(chp._paddingEnd != 0) 1244 { 1245 buf.append("padding-end=\"" + (float)chp._paddingEnd/1440.0f + "in\" "); 1246 } 1247 buf.append(">"); 1248 } 1249 private void addStaticContent(String flowName, HeaderFooter content) 1250 { 1251 _bodyBuffer.append("<fo:static-content flow-name=\"" + flowName + "\">"); 1252 addBlockContent(content.getStart(), content.getEnd(),_text, _paragraphTable, _characterTable); 1254 _bodyBuffer.append("</fo:static-content>"); 1256 1257 } 1258 private String getBulletText(LVL lvl, PAP pap) 1259 { 1260 StringBuffer bulletBuffer = new StringBuffer (); 1261 for(int x = 0; x < lvl._xst.length; x++) 1262 { 1263 if(lvl._xst[x] < 9) 1264 { 1265 LVL numLevel = _listTables.getLevel(pap._ilfo, lvl._xst[x]); 1266 int num = numLevel._iStartAt; 1267 if(lvl == numLevel) 1268 { 1269 numLevel._iStartAt++; 1270 } 1271 else if(num > 1) 1272 { 1273 num--; 1274 } 1275 bulletBuffer.append(NumberFormatter.getNumber(num, lvl._nfc)); 1276 1277 } 1278 else 1279 { 1280 bulletBuffer.append(lvl._xst[x]); 1281 } 1282 1283 } 1284 return bulletBuffer.toString(); 1285 } 1286 1289 private ArrayList findProperties(int start, int end, BTreeSet.BTreeNode root) 1290 { 1291 ArrayList results = new ArrayList(); 1292 BTreeSet.Entry[] entries = root.entries; 1293 1294 for(int x = 0; x < entries.length; x++) 1295 { 1296 if(entries[x] != null) 1297 { 1298 BTreeSet.BTreeNode child = entries[x].child; 1299 PropertyNode xNode = (PropertyNode)entries[x].element; 1300 if(xNode != null) 1301 { 1302 int xStart = xNode.getStart(); 1303 int xEnd = xNode.getEnd(); 1304 if(xStart < end) 1305 { 1306 if(xStart >= start) 1307 { 1308 if(child != null) 1309 { 1310 ArrayList beforeItems = findProperties(start, end, child); 1311 results.addAll(beforeItems); 1312 } 1313 results.add(xNode); 1314 } 1315 else if(start < xEnd) 1316 { 1317 results.add(xNode); 1318 } 1320 } 1321 else 1322 { 1323 if(child != null) 1324 { 1325 ArrayList beforeItems = findProperties(start, end, child); 1326 results.addAll(beforeItems); 1327 } 1328 break; 1329 } 1330 } 1331 else if(child != null) 1332 { 1333 ArrayList afterItems = findProperties(start, end, child); 1334 results.addAll(afterItems); 1335 } 1336 } 1337 else 1338 { 1339 break; 1340 } 1341 } 1342 return results; 1343 } 1344 private void openPage(String page, String type) 1345 { 1346 _bodyBuffer.append("<fo:page-sequence master-reference=\"" + page + "\">\r\n"); 1347 } 1348 private void openFlow() 1349 { 1350 _bodyBuffer.append("<fo:flow flow-name=\"xsl-region-body\">\r\n"); 1351 } 1352 private void closeFlow() 1353 { 1354 _bodyBuffer.append("</fo:flow>\r\n"); 1355 } 1356 private void closePage() 1357 { 1358 _bodyBuffer.append("</fo:page-sequence>\r\n"); 1359 } 1360 private void closeLine(StringBuffer buf) 1361 { 1362 buf.append("</fo:inline>"); 1363 } 1364 private void closeBlock(StringBuffer buf) 1365 { 1366 buf.append("</fo:block>\r\n"); 1367 } 1368 private ArrayList findPAPProperties(int start, int end, BTreeSet.BTreeNode root) 1369 { 1370 ArrayList results = new ArrayList(); 1371 BTreeSet.Entry[] entries = root.entries; 1372 1373 for(int x = 0; x < entries.length; x++) 1374 { 1375 if(entries[x] != null) 1376 { 1377 BTreeSet.BTreeNode child = entries[x].child; 1378 PapxNode papxNode = (PapxNode)entries[x].element; 1379 if(papxNode != null) 1380 { 1381 int papxStart = papxNode.getStart(); 1382 if(papxStart < end) 1383 { 1384 if(papxStart >= start) 1385 { 1386 if(child != null) 1387 { 1388 ArrayList beforeItems = findPAPProperties(start, end, child); 1389 results.addAll(beforeItems); 1390 } 1391 results.add(papxNode); 1392 } 1393 } 1394 else 1395 { 1396 if(child != null) 1397 { 1398 ArrayList beforeItems = findPAPProperties(start, end, child); 1399 results.addAll(beforeItems); 1400 } 1401 break; 1402 } 1403 } 1404 else if(child != null) 1405 { 1406 ArrayList afterItems = findPAPProperties(start, end, child); 1407 results.addAll(afterItems); 1408 } 1409 } 1410 else 1411 { 1412 break; 1413 } 1414 } 1415 return results; 1416 } 1417 1418 private String createPageMaster(SEP sep, String type, int section, 1419 String regionBefore, String regionAfter) 1420 { 1421 float height = ((float)sep._yaPage)/1440.0f; 1422 float width = ((float)sep._xaPage)/1440.0f; 1423 float leftMargin = ((float)sep._dxaLeft)/1440.0f; 1424 float rightMargin = ((float)sep._dxaRight)/1440.0f; 1425 float topMargin = ((float)sep._dyaTop)/1440.0f; 1426 float bottomMargin = ((float)sep._dyaBottom)/1440.0f; 1427 1428 String thisPage = type + "-page" + section; 1430 1431 _headerBuffer.append("<fo:simple-page-master master-name=\"" + 1432 thisPage + "\"\r\n"); 1433 _headerBuffer.append("page-height=\"" + height + "in\"\r\n"); 1434 _headerBuffer.append("page-width=\"" + width + "in\"\r\n"); 1435 _headerBuffer.append(">\r\n"); 1436 1437 1438 1439 _headerBuffer.append("<fo:region-body "); 1440 1442 _headerBuffer.append("margin=\"" + topMargin + "in " + rightMargin + "in " + 1443 bottomMargin + "in " + leftMargin + "in\"\r\n"); 1444 1445 addBorder(_headerBuffer, sep._brcTop, "top"); 1448 addBorder(_headerBuffer, sep._brcBottom, "bottom"); 1449 addBorder(_headerBuffer, sep._brcLeft, "left"); 1450 addBorder(_headerBuffer, sep._brcRight, "right"); 1451 1452 if(sep._ccolM1 > 0) 1453 { 1454 _headerBuffer.append("column-count=\"" + (sep._ccolM1 + 1) + "\" "); 1455 if(sep._fEvenlySpaced) 1456 { 1457 _headerBuffer.append("column-gap=\"" + ((float)(sep._dxaColumns))/1440.0f + "in\""); 1458 } 1459 else 1460 { 1461 _headerBuffer.append("column-gap=\"0.25in\""); 1462 } 1463 } 1464 _headerBuffer.append("/>\r\n"); 1465 1466 if(regionBefore != null) 1467 { 1468 _headerBuffer.append(regionBefore); 1469 } 1470 if(regionAfter != null) 1471 { 1472 _headerBuffer.append(regionAfter); 1473 } 1474 1475 _headerBuffer.append("</fo:simple-page-master>\r\n"); 1476 return thisPage; 1477 } 1478 private void addBorder(StringBuffer buf, short[] brc, String where) 1479 { 1480 if((brc[0] & 0xff00) != 0 && brc[0] != -1) 1481 { 1482 int type = (brc[0] & 0xff00) >> 8; 1483 float width = ((float)(brc[0] & 0x00ff))/8.0f; 1484 String style = getBorderStyle(brc[0]); 1485 String color = getColor(brc[1] & 0x00ff); 1486 String thickness = getBorderThickness(brc[0]); 1487 buf.append("border-" + where + "-style=\"" + style + "\"\r\n"); 1488 buf.append("border-" + where + "-color=\"" + color + "\"\r\n"); 1489 buf.append("border-" + where + "-width=\"" + width + "pt\"\r\n"); 1490 } 1491 } 1492 public void closeDoc() 1493 { 1494 _headerBuffer.append("</fo:layout-master-set>"); 1495 _bodyBuffer.append("</fo:root>"); 1496 1498 try 1500 { 1501 OutputStreamWriter test = new OutputStreamWriter(new FileOutputStream(_outName), "8859_1"); 1502 test.write(_headerBuffer.toString()); 1503 test.write(_bodyBuffer.toString()); 1504 test.flush(); 1505 test.close(); 1506 } 1507 catch(Throwable t) 1508 { 1509 t.printStackTrace(); 1510 } 1511 } 1512 private String getBorderThickness(int style) 1513 { 1514 switch(style) 1515 { 1516 case 1: 1517 return "medium"; 1518 case 2: 1519 return "thick"; 1520 case 3: 1521 return "medium"; 1522 case 5: 1523 return "thin"; 1524 default: 1525 return "medium"; 1526 } 1527 } 1528 1529 1530 private String getColor(int ico) 1531 { 1532 switch(ico) 1533 { 1534 case 1: 1535 return "black"; 1536 case 2: 1537 return "blue"; 1538 case 3: 1539 return "cyan"; 1540 case 4: 1541 return "green"; 1542 case 5: 1543 return "magenta"; 1544 case 6: 1545 return "red"; 1546 case 7: 1547 return "yellow"; 1548 case 8: 1549 return "white"; 1550 case 9: 1551 return "darkblue"; 1552 case 10: 1553 return "darkcyan"; 1554 case 11: 1555 return "darkgreen"; 1556 case 12: 1557 return "darkmagenta"; 1558 case 13: 1559 return "darkred"; 1560 case 14: 1561 return "darkyellow"; 1562 case 15: 1563 return "darkgray"; 1564 case 16: 1565 return "lightgray"; 1566 default: 1567 return "black"; 1568 } 1569 } 1570 1571 private String getBorderStyle(int type) 1572 { 1573 1574 switch(type) 1575 { 1576 case 1: 1577 case 2: 1578 return "solid"; 1579 case 3: 1580 return "double"; 1581 case 5: 1582 return "solid"; 1583 case 6: 1584 return "dotted"; 1585 case 7: 1586 case 8: 1587 return "dashed"; 1588 case 9: 1589 return "dotted"; 1590 case 10: 1591 case 11: 1592 case 12: 1593 case 13: 1594 case 14: 1595 case 15: 1596 case 16: 1597 case 17: 1598 case 18: 1599 case 19: 1600 return "double"; 1601 case 20: 1602 return "solid"; 1603 case 21: 1604 return "double"; 1605 case 22: 1606 return "dashed"; 1607 case 23: 1608 return "dashed"; 1609 case 24: 1610 return "ridge"; 1611 case 25: 1612 return "grooved"; 1613 default: 1614 return "solid"; 1615 } 1616 } 1617 1622 private void createListTables(byte[] tableStream) 1623 { 1624 1625 1626 int lfoOffset = LittleEndian.getInt(_header, 0x2ea); 1627 int lfoSize = LittleEndian.getInt(_header, 0x2ee); 1628 byte[] plflfo = new byte[lfoSize]; 1629 1630 System.arraycopy(tableStream, lfoOffset, plflfo, 0, lfoSize); 1631 1632 int lstOffset = LittleEndian.getInt(_header, 0x2e2); 1633 int lstSize = LittleEndian.getInt(_header, 0x2e2); 1634 if(lstOffset > 0 && lstSize > 0) 1635 { 1636 lstSize = lfoOffset - lstOffset; 1637 byte[] plcflst = new byte[lstSize]; 1638 System.arraycopy(tableStream, lstOffset, plcflst, 0, lstSize); 1639 _listTables = new ListTables(plcflst, plflfo); 1640 } 1641 1642 } 1643 1649 private void createStyleSheet(byte[] tableStream) 1650 { 1651 int stshIndex = LittleEndian.getInt(_header, 0xa2); 1652 int stshSize = LittleEndian.getInt(_header, 0xa6); 1653 byte[] stsh = new byte[stshSize]; 1654 System.arraycopy(tableStream, stshIndex, stsh, 0, stshSize); 1655 1656 _styleSheet = new StyleSheet(stsh); 1657 1658 } 1659 1664 private void createFontTable(byte[] tableStream) 1665 { 1666 int fontTableIndex = LittleEndian.getInt(_header, 0x112); 1667 int fontTableSize = LittleEndian.getInt(_header, 0x116); 1668 byte[] fontTable = new byte[fontTableSize]; 1669 System.arraycopy(tableStream, fontTableIndex, fontTable, 0, fontTableSize); 1670 _fonts = new FontTable(fontTable); 1671 } 1672 1673 1674 private void overrideCellBorder(int row, int col, int height, 1675 int width, TC tc, TAP tap) 1676 { 1677 1678 if(row == 0) 1679 { 1680 if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1) 1681 { 1682 tc._brcTop = tap._brcTop; 1683 } 1684 if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1) 1685 { 1686 tc._brcBottom = tap._brcHorizontal; 1687 } 1688 } 1689 else if(row == (height - 1)) 1690 { 1691 if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1) 1692 { 1693 tc._brcTop = tap._brcHorizontal; 1694 } 1695 if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1) 1696 { 1697 tc._brcBottom = tap._brcBottom; 1698 } 1699 } 1700 else 1701 { 1702 if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1) 1703 { 1704 tc._brcTop = tap._brcHorizontal; 1705 } 1706 if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1) 1707 { 1708 tc._brcBottom = tap._brcHorizontal; 1709 } 1710 } 1711 if(col == 0) 1712 { 1713 if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1) 1714 { 1715 tc._brcLeft = tap._brcLeft; 1716 } 1717 if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1) 1718 { 1719 tc._brcRight = tap._brcVertical; 1720 } 1721 } 1722 else if(col == (width - 1)) 1723 { 1724 if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1) 1725 { 1726 tc._brcLeft = tap._brcVertical; 1727 } 1728 if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1) 1729 { 1730 tc._brcRight = tap._brcRight; 1731 } 1732 } 1733 else 1734 { 1735 if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1) 1736 { 1737 tc._brcLeft = tap._brcVertical; 1738 } 1739 if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1) 1740 { 1741 tc._brcRight = tap._brcVertical; 1742 } 1743 } 1744 } 1745 private void printTable() 1746 { 1747 if(_table != null) 1748 { 1749 int size = _table.size(); 1750 1751 StringBuffer tableHeaderBuffer = new StringBuffer (); 1753 StringBuffer tableBodyBuffer = new StringBuffer (); 1754 1755 for(int x = 0; x < size; x++) 1756 { 1757 StringBuffer rowBuffer = tableBodyBuffer; 1758 TableRow row = (TableRow)_table.get(x); 1759 TAP tap = row.getTAP(); 1760 ArrayList cells = row.getCells(); 1761 1762 if(tap._fTableHeader) 1763 { 1764 rowBuffer = tableHeaderBuffer; 1765 } 1766 rowBuffer.append("<fo:table-row "); 1767 if(tap._dyaRowHeight > 0) 1768 { 1769 rowBuffer.append("height=\"" + ((float)tap._dyaRowHeight)/1440.0f + "in\" "); 1770 } 1771 if(tap._fCantSplit) 1772 { 1773 rowBuffer.append("keep-together=\"always\" "); 1774 } 1775 rowBuffer.append(">"); 1776 for(int y = 0; y < tap._itcMac; y++) 1778 { 1779 TC tc = tap._rgtc[y]; 1780 overrideCellBorder(x, y, size, tap._itcMac, tc, tap); 1781 rowBuffer.append("<fo:table-cell "); 1782 rowBuffer.append("width=\"" + ((float)(tap._rgdxaCenter[y+1] - tap._rgdxaCenter[y]))/1440.0f + "in\" "); 1783 rowBuffer.append("padding-start=\"" + ((float)tap._dxaGapHalf)/1440.0f + "in\" "); 1784 rowBuffer.append("padding-end=\"" + ((float)tap._dxaGapHalf)/1440.0f + "in\" "); 1785 addBorder(rowBuffer, tc._brcTop, "top"); 1786 addBorder(rowBuffer, tc._brcLeft, "left"); 1787 addBorder(rowBuffer, tc._brcBottom, "bottom"); 1788 addBorder(rowBuffer, tc._brcRight, "right"); 1789 rowBuffer.append(">"); 1790 rowBuffer.append((String )cells.get(y)); 1791 rowBuffer.append("</fo:table-cell>"); 1792 } 1793 rowBuffer.append("</fo:table-row>"); 1794 } 1795 StringBuffer tableBuffer = new StringBuffer (); 1796 tableBuffer.append("<fo:table>"); 1797 if(tableHeaderBuffer.length() > 0) 1798 { 1799 tableBuffer.append("<fo:table-header>"); 1800 tableBuffer.append(tableHeaderBuffer.toString()); 1801 tableBuffer.append("</fo:table-header>"); 1802 } 1803 tableBuffer.append("<fo:table-body>"); 1804 tableBuffer.append(tableBodyBuffer.toString()); 1805 tableBuffer.append("</fo:table-body>"); 1806 tableBuffer.append("</fo:table>"); 1807 _bodyBuffer.append(tableBuffer.toString()); 1808 _table = null; 1809 } 1810 } 1811 private void initPclfHdd(byte[] tableStream) 1812 { 1813 int size = Utils.convertBytesToInt(_header, 0xf6); 1814 int pos = Utils.convertBytesToInt(_header, 0xf2); 1815 1816 _plcfHdd = new byte[size]; 1817 1818 System.arraycopy(tableStream, pos, _plcfHdd, 0, size); 1819 } 1820 1821 1822 1823 1824} 1825 | Popular Tags |