PageRenderTime 1676ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/thirdparties-extension/org.apache.poi.xwpf.converter/src/main/java/org/apache/poi/xwpf/converter/internal/itext/PDFMapper.java

https://github.com/minstrelsy/xdocreport
Java | 883 lines | 666 code | 89 blank | 128 comment | 123 complexity | 58f5f4b9d6f4406c0fcea13e358fb18b MD5 | raw file
  1. /**
  2. * Copyright (C) 2011 The XDocReport Team <xdocreport@googlegroups.com>
  3. *
  4. * All rights reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. package org.apache.poi.xwpf.converter.internal.itext;
  26. import static org.apache.poi.xwpf.converter.internal.DxaUtil.dxa2points;
  27. import java.awt.Color;
  28. import java.io.OutputStream;
  29. import java.math.BigInteger;
  30. import java.util.List;
  31. import java.util.logging.Logger;
  32. import org.apache.poi.xwpf.converter.internal.XWPFDocumentVisitor;
  33. import org.apache.poi.xwpf.converter.internal.XWPFUtils;
  34. import org.apache.poi.xwpf.converter.internal.itext.stylable.IStylableContainer;
  35. import org.apache.poi.xwpf.converter.internal.itext.stylable.IStylableElement;
  36. import org.apache.poi.xwpf.converter.internal.itext.stylable.StylableDocument;
  37. import org.apache.poi.xwpf.converter.internal.itext.stylable.StylableHeaderFooter;
  38. import org.apache.poi.xwpf.converter.internal.itext.stylable.StylableMasterPage;
  39. import org.apache.poi.xwpf.converter.internal.itext.stylable.StylableParagraph;
  40. import org.apache.poi.xwpf.converter.internal.itext.stylable.StylableTable;
  41. import org.apache.poi.xwpf.converter.internal.itext.stylable.StylableTableCell;
  42. import org.apache.poi.xwpf.converter.internal.itext.styles.Style;
  43. import org.apache.poi.xwpf.converter.itext.PDFViaITextOptions;
  44. import org.apache.poi.xwpf.converter.styles.pargraph.ParagraphIndentationLeftValueProvider;
  45. import org.apache.poi.xwpf.usermodel.BodyElementType;
  46. import org.apache.poi.xwpf.usermodel.Borders;
  47. import org.apache.poi.xwpf.usermodel.IBodyElement;
  48. import org.apache.poi.xwpf.usermodel.LineSpacingRule;
  49. import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
  50. import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
  51. import org.apache.poi.xwpf.usermodel.XWPFAbstractNum;
  52. import org.apache.poi.xwpf.usermodel.XWPFDocument;
  53. import org.apache.poi.xwpf.usermodel.XWPFFooter;
  54. import org.apache.poi.xwpf.usermodel.XWPFHeader;
  55. import org.apache.poi.xwpf.usermodel.XWPFNum;
  56. import org.apache.poi.xwpf.usermodel.XWPFParagraph;
  57. import org.apache.poi.xwpf.usermodel.XWPFPictureData;
  58. import org.apache.poi.xwpf.usermodel.XWPFRun;
  59. import org.apache.poi.xwpf.usermodel.XWPFStyle;
  60. import org.apache.poi.xwpf.usermodel.XWPFTable;
  61. import org.apache.poi.xwpf.usermodel.XWPFTableCell;
  62. import org.apache.poi.xwpf.usermodel.XWPFTableRow;
  63. import org.apache.xmlbeans.XmlCursor;
  64. import org.apache.xmlbeans.XmlObject;
  65. import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
  66. import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
  67. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr;
  68. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
  69. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
  70. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTEmpty;
  71. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef;
  72. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl;
  73. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumPr;
  74. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff;
  75. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
  76. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPTab;
  77. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
  78. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
  79. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell;
  80. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
  81. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
  82. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
  83. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
  84. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;
  85. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
  86. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
  87. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
  88. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
  89. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTextDirection;
  90. import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc;
  91. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
  92. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
  93. import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc.Enum;
  94. import com.lowagie.text.Chunk;
  95. import com.lowagie.text.DocumentException;
  96. import com.lowagie.text.Element;
  97. import com.lowagie.text.Font;
  98. import com.lowagie.text.Image;
  99. import com.lowagie.text.Rectangle;
  100. import com.lowagie.text.pdf.PdfPCell;
  101. import com.lowagie.text.pdf.draw.VerticalPositionMark;
  102. import fr.opensagres.xdocreport.itext.extension.ExtendedParagraph;
  103. import fr.opensagres.xdocreport.itext.extension.ExtendedPdfPCell;
  104. import fr.opensagres.xdocreport.itext.extension.ExtendedPdfPTable;
  105. import fr.opensagres.xdocreport.itext.extension.IITextContainer;
  106. public class PDFMapper
  107. extends XWPFDocumentVisitor<IITextContainer, StylableMasterPage>
  108. {
  109. /**
  110. * Logger for this class
  111. */
  112. private static final Logger LOGGER = Logger.getLogger( PDFMapper.class.getName() );
  113. // Create instance of PDF document
  114. private StylableDocument pdfDocument;
  115. private StyleEngineForIText styleEngine;
  116. private final PDFViaITextOptions options;
  117. public PDFMapper( XWPFDocument document, PDFViaITextOptions options )
  118. throws Exception
  119. {
  120. super( document );
  121. this.options = options != null ? options : PDFViaITextOptions.create();
  122. }
  123. @Override
  124. protected IITextContainer startVisitDocument( OutputStream out )
  125. throws Exception
  126. {
  127. // Create instance of PDF document
  128. styleEngine = new StyleEngineForIText( document, options );
  129. this.pdfDocument = new StylableDocument( out, styleEngine );
  130. this.pdfDocument.setMasterPageManager( getMasterPageManager() );
  131. return pdfDocument;
  132. }
  133. @Override
  134. protected void endVisitDocument()
  135. throws Exception
  136. {
  137. pdfDocument.close();
  138. }
  139. @Override
  140. protected void visitHeader( XWPFHeader header, CTHdrFtrRef headerRef, CTSectPr sectPr, StylableMasterPage masterPage )
  141. throws Exception
  142. {
  143. StylableHeaderFooter pdfHeader = new StylableHeaderFooter( pdfDocument, true );
  144. List<IBodyElement> bodyElements = header.getBodyElements();
  145. StylableTableCell tableCell = getHeaderFooterTableCell( pdfHeader, bodyElements );
  146. visitBodyElements( bodyElements, tableCell );
  147. masterPage.setHeader( pdfHeader );
  148. }
  149. @Override
  150. protected void visitFooter( XWPFFooter footer, CTHdrFtrRef footerRef, CTSectPr sectPr, StylableMasterPage masterPage )
  151. throws Exception
  152. {
  153. StylableHeaderFooter pdfFooter = new StylableHeaderFooter( pdfDocument, false );
  154. List<IBodyElement> bodyElements = footer.getBodyElements();
  155. StylableTableCell tableCell = getHeaderFooterTableCell( pdfFooter, bodyElements );
  156. visitBodyElements( footer.getBodyElements(), tableCell );
  157. masterPage.setFooter( pdfFooter );
  158. }
  159. private StylableTableCell getHeaderFooterTableCell( StylableHeaderFooter pdfHeaderFooter,
  160. List<IBodyElement> bodyElements )
  161. throws DocumentException
  162. {
  163. // XWPFTable table = getFirstTable( bodyElements );
  164. // if ( table != null )
  165. // {
  166. // StylableTable pdfTable = createPDFTable( table );
  167. // return pdfHeaderFooter.getTableCell( pdfTable );
  168. // }
  169. return pdfHeaderFooter.getTableCell();
  170. }
  171. private XWPFTable getFirstTable( List<IBodyElement> bodyElements )
  172. {
  173. if ( bodyElements.isEmpty() )
  174. {
  175. return null;
  176. }
  177. IBodyElement firstElement = bodyElements.get( 0 );
  178. if ( firstElement.getElementType() == BodyElementType.TABLE )
  179. {
  180. return (XWPFTable) firstElement;
  181. }
  182. return null;
  183. }
  184. @Override
  185. protected IITextContainer startVisitPargraph( XWPFParagraph docxParagraph, IITextContainer parentContainer )
  186. throws Exception
  187. {
  188. if ( docxParagraph.getText().startsWith( "Cette commande client est co" ) )
  189. {
  190. System.err.println();
  191. }
  192. // 1) Instanciate a pdfParagraph
  193. StylableParagraph pdfParagraph = pdfDocument.createParagraph( (IStylableContainer) null );
  194. pdfParagraph.setITextContainer( parentContainer );
  195. // Paragraph Background color
  196. Color backgroundColor = XWPFParagraphUtils.getBackgroundColor( docxParagraph );
  197. if ( backgroundColor != null )
  198. {
  199. pdfParagraph.setBackgroundColor( backgroundColor );
  200. }
  201. // Paragraph border
  202. int border = 0;
  203. Borders borderTop = docxParagraph.getBorderTop();
  204. if ( hasBorder( borderTop ) )
  205. {
  206. border = border | Rectangle.TOP;
  207. }
  208. Borders borderBottom = docxParagraph.getBorderBottom();
  209. if ( hasBorder( borderBottom ) )
  210. {
  211. border = border | Rectangle.BOTTOM;
  212. }
  213. Borders borderLeft = docxParagraph.getBorderLeft();
  214. if ( hasBorder( borderLeft ) )
  215. {
  216. border = border | Rectangle.LEFT;
  217. }
  218. Borders borderRight = docxParagraph.getBorderRight();
  219. if ( hasBorder( borderRight ) )
  220. {
  221. border = border | Rectangle.RIGHT;
  222. }
  223. if ( border > 0 )
  224. {
  225. // pdfParagraph.getPdfPCell().setBorder( border );
  226. // pdfParagraph.getPdfPCell().setCellEvent( new CustomPdfPCellEvent() );
  227. }
  228. // text-indent
  229. Float indentationLeft = stylesDocument.getIndentationLeft( docxParagraph );
  230. if ( indentationLeft != null )
  231. {
  232. pdfParagraph.setIndentationLeft( indentationLeft );
  233. }
  234. Float indentationRight = stylesDocument.getIndentationRight( docxParagraph );
  235. if ( indentationRight != null )
  236. {
  237. pdfParagraph.setIndentationRight( indentationRight );
  238. }
  239. Float indentationFirstLine = stylesDocument.getIndentationFirstLine( docxParagraph );
  240. if ( indentationFirstLine != null )
  241. {
  242. pdfParagraph.setFirstLineIndent( indentationFirstLine );
  243. }
  244. // spacing before
  245. Integer spacingBefore = stylesDocument.getSpacingBefore( docxParagraph );
  246. if ( spacingBefore != null )
  247. {
  248. pdfParagraph.setSpacingBefore( spacingBefore );
  249. }
  250. // spacing after
  251. Integer spacingAfter = stylesDocument.getSpacingAfter( docxParagraph );
  252. if ( spacingAfter != null )
  253. {
  254. pdfParagraph.setSpacingAfter( spacingAfter.intValue() );
  255. }
  256. CTPPr ppr = docxParagraph.getCTP().getPPr();
  257. if ( ppr != null )
  258. {
  259. CTSpacing spacing = ppr.getSpacing();
  260. if ( spacing != null )
  261. {
  262. BigInteger line = spacing.getLine();
  263. if ( line != null )
  264. {
  265. float leading = -1;
  266. // see http://officeopenxml.com/WPspacing.php
  267. // Note: If the value of the lineRule attribute is atLeast or exactly, then the value of the line
  268. // attribute is interpreted as 240th of a point. If the value of lineRule is auto, then the value of
  269. // line is interpreted as 240th of a line.
  270. LineSpacingRule lineSpacingRule = docxParagraph.getSpacingLineRule();
  271. switch ( lineSpacingRule )
  272. {
  273. case AT_LEAST:
  274. case EXACT:
  275. // FIXME : is that?
  276. leading = line.floatValue() / 240;
  277. break;
  278. case AUTO:
  279. leading = line.floatValue() / 240;
  280. break;
  281. }
  282. pdfParagraph.setMultipliedLeading( leading );
  283. }
  284. }
  285. CTNumPr numPr = ppr.getNumPr();
  286. if ( numPr != null )
  287. {
  288. // - <w:p>
  289. // - <w:pPr>
  290. // <w:pStyle w:val="style0" />
  291. // - <w:numPr>
  292. // <w:ilvl w:val="0" />
  293. // <w:numId w:val="2" />
  294. // </w:numPr>
  295. CTDecimalNumber ilvl = numPr.getIlvl();
  296. CTDecimalNumber numID = numPr.getNumId();
  297. XWPFNum num = document.getNumbering().getNum( numID.getVal() );
  298. if ( num != null )
  299. {
  300. CTDecimalNumber abstractNumID = num.getCTNum().getAbstractNumId();
  301. XWPFAbstractNum abstractNum = document.getNumbering().getAbstractNum( abstractNumID.getVal() );
  302. CTLvl lvl = abstractNum.getAbstractNum().getLvlArray( ilvl.getVal().intValue() );
  303. CTPPr lvlPPr = lvl.getPPr();
  304. if ( lvlPPr != null )
  305. {
  306. Float indLeft = ParagraphIndentationLeftValueProvider.INSTANCE.getValue( lvlPPr );
  307. if ( indLeft != null )
  308. {
  309. pdfParagraph.setIndentationLeft( indLeft );
  310. }
  311. }
  312. }
  313. }
  314. }
  315. // text-align
  316. ParagraphAlignment alignment = stylesDocument.getParagraphAlignment( docxParagraph );
  317. if ( alignment != null )
  318. {
  319. switch ( alignment )
  320. {
  321. case LEFT:
  322. pdfParagraph.setAlignment( Element.ALIGN_LEFT );
  323. break;
  324. case RIGHT:
  325. pdfParagraph.setAlignment( Element.ALIGN_RIGHT );
  326. break;
  327. case CENTER:
  328. pdfParagraph.setAlignment( Element.ALIGN_CENTER );
  329. break;
  330. case BOTH:
  331. pdfParagraph.setAlignment( Element.ALIGN_JUSTIFIED );
  332. break;
  333. default:
  334. break;
  335. }
  336. }
  337. return pdfParagraph;
  338. }
  339. private boolean hasBorder( Borders borders )
  340. {
  341. if ( borders == null )
  342. {
  343. return false;
  344. }
  345. return ( borders.getValue() != Borders.NONE.getValue() && borders.getValue() != Borders.NIL.getValue() );
  346. }
  347. @Override
  348. protected void endVisitPargraph( XWPFParagraph paragraph, IITextContainer parentContainer,
  349. IITextContainer paragraphContainer )
  350. throws Exception
  351. {
  352. // Page Break
  353. // Cannot use paragraph.isPageBreak() because it throw NPE because
  354. // pageBreak.getVal() can be null.
  355. CTPPr ppr = paragraph.getCTP().getPPr();
  356. if ( ppr.isSetPageBreakBefore() )
  357. {
  358. CTOnOff pageBreak = ppr.getPageBreakBefore();
  359. if ( pageBreak != null
  360. && ( pageBreak.getVal() == null || pageBreak.getVal().intValue() == STOnOff.INT_TRUE ) )
  361. {
  362. pdfDocument.pageBreak();
  363. }
  364. }
  365. // Paragraph
  366. ExtendedParagraph pdfParagraph = (ExtendedParagraph) paragraphContainer;
  367. parentContainer.addElement( pdfParagraph.getElement() );
  368. }
  369. @Override
  370. protected void visitEmptyRun( IITextContainer paragraphContainer )
  371. throws Exception
  372. {
  373. // ExtendedParagraph pdfParagraph = (ExtendedParagraph) paragraphContainer;
  374. // pdfParagraph.addElement( Chunk.NEWLINE );
  375. }
  376. @Override
  377. protected void visitRun( XWPFRun run, IITextContainer pdfContainer )
  378. throws Exception
  379. {
  380. CTR ctr = run.getCTR();
  381. // <w:lastRenderedPageBreak />
  382. List<CTEmpty> lastRenderedPageBreakList = ctr.getLastRenderedPageBreakList();
  383. if ( lastRenderedPageBreakList != null && lastRenderedPageBreakList.size() > 0 )
  384. {
  385. for ( CTEmpty lastRenderedPageBreak : lastRenderedPageBreakList )
  386. {
  387. pdfDocument.pageBreak();
  388. }
  389. }
  390. // Font family
  391. String fontFamily = stylesDocument.getFontFamily( run );
  392. // Get font size
  393. Integer fontSize = stylesDocument.getFontSize( run );
  394. if ( fontSize == null )
  395. {
  396. fontSize = -1;
  397. }
  398. // Get font style
  399. int fontStyle = Font.NORMAL;
  400. Boolean bold = stylesDocument.getFontStyleBold( run );
  401. if ( bold != null && bold )
  402. {
  403. fontStyle |= Font.BOLD;
  404. }
  405. Boolean italic = stylesDocument.getFontStyleItalic( run );
  406. if ( italic != null && italic )
  407. {
  408. fontStyle |= Font.ITALIC;
  409. }
  410. // Process color
  411. Color fontColor = stylesDocument.getFontColor( run );
  412. // Get font
  413. Font font =
  414. XWPFFontRegistry.getRegistry().getFont( fontFamily, options.getFontEncoding(), fontSize, fontStyle,
  415. fontColor );
  416. UnderlinePatterns underlinePatterns = run.getUnderline();
  417. boolean singleUnderlined = false;
  418. switch ( underlinePatterns )
  419. {
  420. case SINGLE:
  421. singleUnderlined = true;
  422. break;
  423. default:
  424. break;
  425. }
  426. // Loop for each element of <w:run text, tab, image etc
  427. // to keep the oder of thoses elements.
  428. XmlCursor c = ctr.newCursor();
  429. c.selectPath( "./*" );
  430. while ( c.toNextSelection() )
  431. {
  432. XmlObject o = c.getObject();
  433. if ( o instanceof CTText )
  434. {
  435. CTText ctText = (CTText) o;
  436. String tagName = o.getDomNode().getNodeName();
  437. // Field Codes (w:instrText, defined in spec sec. 17.16.23)
  438. // come up as instances of CTText, but we don't want them
  439. // in the normal text output
  440. if ( !"w:instrText".equals( tagName ) )
  441. {
  442. Chunk textChunk = new Chunk( ctText.getStringValue(), font );
  443. // underlined
  444. if ( singleUnderlined )
  445. {
  446. textChunk.setUnderline( 1, -2 );
  447. }
  448. // background color
  449. Color backgroundColor = XWPFParagraphUtils.getBackgroundColor( run );
  450. if ( backgroundColor != null )
  451. {
  452. textChunk.setBackground( backgroundColor );
  453. }
  454. pdfContainer.addElement( textChunk );
  455. }
  456. }
  457. else if ( o instanceof CTPTab )
  458. {
  459. visitTab( pdfContainer, (CTPTab) o );
  460. }
  461. else if ( o instanceof CTBr )
  462. {
  463. visitBR( pdfContainer, (CTBr) o );
  464. }
  465. else if ( o instanceof CTEmpty )
  466. {
  467. // Some inline text elements get returned not as
  468. // themselves, but as CTEmpty, owing to some odd
  469. // definitions around line 5642 of the XSDs
  470. // This bit works around it, and replicates the above
  471. // rules for that case
  472. String tagName = o.getDomNode().getNodeName();
  473. if ( "w:tab".equals( tagName ) )
  474. {
  475. visitTab( pdfContainer, null );
  476. }
  477. if ( "w:br".equals( tagName ) )
  478. {
  479. visitBR( pdfContainer, null );
  480. }
  481. if ( "w:cr".equals( tagName ) )
  482. {
  483. visitBR( pdfContainer, null );
  484. }
  485. }
  486. else if ( o instanceof CTDrawing )
  487. {
  488. visitDrawing( (CTDrawing) o, pdfContainer );
  489. }
  490. }
  491. c.dispose();
  492. }
  493. private void visitTab( IITextContainer pdfContainer, CTPTab tab )
  494. {
  495. // Chunk pdfTab = new Chunk( new DottedLineSeparator() )
  496. Chunk pdfTab = new Chunk( new VerticalPositionMark() );
  497. pdfContainer.addElement( pdfTab );
  498. }
  499. private void visitBR( IITextContainer pdfContainer, CTBr br )
  500. {
  501. pdfContainer.addElement( Chunk.NEWLINE );
  502. }
  503. // Visit table
  504. protected IITextContainer startVisitTable( XWPFTable table, IITextContainer pdfContainer )
  505. throws Exception
  506. {
  507. styleEngine.startVisitTable( table, pdfContainer );
  508. StylableTable pdfPTable = createPDFTable( table );
  509. // 3) Create PDF Table.
  510. pdfPTable.setITextContainer( pdfContainer );
  511. pdfPTable.setLockedWidth( true );
  512. // finally apply the style to the iText paragraph....
  513. applyStyles( table, pdfPTable );
  514. return pdfPTable;
  515. }
  516. private StylableTable createPDFTable( XWPFTable table )
  517. throws DocumentException
  518. {
  519. // 1) Compute colWidth
  520. float[] colWidths = XWPFTableUtil.computeColWidths( table );
  521. // 2) Compute tableWith
  522. TableWidth tableWidth = XWPFTableUtil.getTableWidth( table );
  523. StylableTable pdfPTable = pdfDocument.createTable( (IStylableContainer) null, colWidths.length );
  524. pdfPTable.setTotalWidth( colWidths );
  525. if ( tableWidth.width > 0 )
  526. {
  527. if ( tableWidth.percentUnit )
  528. {
  529. pdfPTable.setWidthPercentage( tableWidth.width );
  530. }
  531. else
  532. {
  533. pdfPTable.setTotalWidth( tableWidth.width );
  534. }
  535. }
  536. return pdfPTable;
  537. }
  538. // private StyleBorder createBorder( CTBorder docxBorder, BorderType borderType )
  539. // {
  540. // if ( docxBorder == null )
  541. // {
  542. // return null;
  543. // }
  544. // StyleBorder styleBorder = new StyleBorder( docxBorder.getVal().toString(), borderType );
  545. // // XXX semi point ?
  546. // styleBorder.setWidth( docxBorder.getSz() );
  547. // STHexColor hexColor = docxBorder.xgetColor();
  548. // Color bc = XWPFUtils.getColor( hexColor.getStringValue() );
  549. // styleBorder.setColor( bc );
  550. // return styleBorder;
  551. // }
  552. @Override
  553. protected void endVisitTable( XWPFTable table, IITextContainer parentContainer, IITextContainer tableContainer )
  554. throws Exception
  555. {
  556. parentContainer.addElement( (Element) tableContainer );
  557. }
  558. @Override
  559. protected void visitTableRow( XWPFTableRow row, IITextContainer tableContainer, boolean firstRow, boolean lastRow )
  560. throws Exception
  561. {
  562. StylableTable pdfTable = (StylableTable) tableContainer;
  563. int nbColumns = pdfTable.getNumberOfColumns();
  564. // Process cell
  565. boolean firstCell = false;
  566. boolean lastCell = false;
  567. List<XWPFTableCell> cells = row.getTableCells();
  568. if ( nbColumns > cells.size() )
  569. {
  570. // Columns number is not equal to cells number.
  571. // POI have a bug with
  572. // <w:tr w:rsidR="00C55C20">
  573. // <w:tc>
  574. // <w:tc>...
  575. // <w:sdt>
  576. // <w:sdtContent>
  577. // <w:tc> <= this tc which is a XWPFTableCell is not included in the row.getTableCells();
  578. firstCell = true;
  579. CTRow ctRow = row.getCtRow();
  580. XmlCursor c = ctRow.newCursor();
  581. c.selectPath( "./*" );
  582. while ( c.toNextSelection() )
  583. {
  584. XmlObject o = c.getObject();
  585. if ( o instanceof CTTc )
  586. {
  587. CTTc tc = (CTTc) o;
  588. XWPFTableCell cell = row.getTableCell( tc );
  589. visitCell( cell, tableContainer, firstRow, lastRow, firstCell, lastCell );
  590. firstCell = false;
  591. }
  592. else if ( o instanceof CTSdtCell )
  593. {
  594. // Fix bug of POI
  595. CTSdtCell sdtCell = (CTSdtCell) o;
  596. List<CTTc> tcList = sdtCell.getSdtContent().getTcList();
  597. for ( CTTc ctTc : tcList )
  598. {
  599. XWPFTableCell cell = new XWPFTableCell( ctTc, row, row.getTable().getBody() );
  600. visitCell( cell, tableContainer, firstRow, lastRow, firstCell, lastCell );
  601. firstCell = false;
  602. }
  603. }
  604. }
  605. c.dispose();
  606. }
  607. else
  608. {
  609. // Column number is equal to cells number.
  610. for ( int i = 0; i < cells.size(); i++ )
  611. {
  612. firstCell = ( i == 0 );
  613. lastCell = ( i == cells.size() - 1 );
  614. XWPFTableCell cell = cells.get( i );
  615. visitCell( cell, tableContainer, firstRow, lastRow, firstCell, lastCell );
  616. }
  617. }
  618. }
  619. @Override
  620. protected IITextContainer startVisitTableCell( XWPFTableCell cell, IITextContainer tableContainer,
  621. boolean firstRow, boolean lastRow, boolean firstCell,
  622. boolean lastCell )
  623. {
  624. StylableTable pdfPTable = (StylableTable) tableContainer;
  625. XWPFTableRow row = cell.getTableRow();
  626. ExtendedPdfPCell pdfPCell = pdfDocument.createTableCell( pdfPTable );
  627. pdfPCell.setITextContainer( pdfPTable );
  628. // pdfPCell.setUseAscender( true );
  629. // pdfPCell.setUseDescender( true );
  630. CTTcPr tcPr = cell.getCTTc().getTcPr();
  631. if ( tcPr != null )
  632. {
  633. // Colspan
  634. Integer colspan = null;
  635. CTDecimalNumber gridSpan = tcPr.getGridSpan();
  636. if ( gridSpan != null )
  637. {
  638. colspan = gridSpan.getVal().intValue();
  639. }
  640. if ( colspan != null )
  641. {
  642. pdfPCell.setColspan( colspan );
  643. }
  644. // Backround Color
  645. CTShd shd = tcPr.getShd();
  646. Color backgroundColor = XWPFUtils.getFillColor( shd );
  647. if ( backgroundColor != null )
  648. {
  649. pdfPCell.setBackgroundColor( backgroundColor );
  650. }
  651. // Borders
  652. // Table Properties on cells
  653. // overridden locally
  654. CTTblBorders tableStyleBorders = null;
  655. XWPFStyle tableStyle = super.getXWPFStyle( cell.getTableRow().getTable().getStyleID() );
  656. if ( tableStyle != null )
  657. {
  658. tableStyleBorders = tableStyle.getCTStyle().getTblPr().getTblBorders();
  659. }
  660. CTTblBorders tableBorders = XWPFTableUtil.getTblBorders( cell.getTableRow().getTable() );
  661. CTTcBorders cellBorders = tcPr.getTcBorders();
  662. // border-left
  663. XWPFTableUtil.setBorder( cellBorders, tableBorders, tableStyleBorders, firstRow, lastRow, firstCell,
  664. lastCell, pdfPCell, Rectangle.LEFT );
  665. // border-right
  666. XWPFTableUtil.setBorder( cellBorders, tableBorders, tableStyleBorders, firstRow, lastRow, firstCell,
  667. lastCell, pdfPCell, Rectangle.RIGHT );
  668. // border-top
  669. XWPFTableUtil.setBorder( cellBorders, tableBorders, tableStyleBorders, firstRow, lastRow, firstCell,
  670. lastCell, pdfPCell, Rectangle.TOP );
  671. // border-bottom
  672. XWPFTableUtil.setBorder( cellBorders, tableBorders, tableStyleBorders, firstRow, lastRow, firstCell,
  673. lastCell, pdfPCell, Rectangle.BOTTOM );
  674. // Text direction <w:textDirection
  675. CTTextDirection direction = tcPr.getTextDirection();
  676. if ( direction != null )
  677. {
  678. // if (direction.getVal().equals(STTextDirection.FROM_T )) {
  679. if ( "btLr".equals( direction.getVal().toString() ) )
  680. {
  681. pdfPCell.setRotation( 90 );
  682. }
  683. else if ( "tbRl".equals( direction.getVal().toString() ) )
  684. {
  685. pdfPCell.setRotation( 270 );
  686. }
  687. }
  688. // // Vertical aligment
  689. CTVerticalJc vAlign = tcPr.getVAlign();
  690. if ( vAlign != null )
  691. {
  692. Enum jc = vAlign.getVal();
  693. if ( jc != null )
  694. {
  695. switch ( jc.intValue() )
  696. {
  697. case STVerticalJc.INT_BOTTOM:
  698. pdfPCell.setVerticalAlignment( Element.ALIGN_BOTTOM );
  699. break;
  700. case STVerticalJc.INT_CENTER:
  701. pdfPCell.setVerticalAlignment( Element.ALIGN_MIDDLE );
  702. break;
  703. case STVerticalJc.INT_TOP:
  704. pdfPCell.setVerticalAlignment( Element.ALIGN_TOP );
  705. break;
  706. }
  707. }
  708. }
  709. }
  710. int height = row.getHeight();
  711. if ( height > 0 )
  712. {
  713. pdfPCell.setMinimumHeight( dxa2points( height ) );
  714. }
  715. // pdfPCell.setRunDirection( PdfWriter.RUN_DIRECTION_NO_BIDI );
  716. // pdfPCell.setRotation( 90 );
  717. // pdfPCell.setVerticalAlignment( pdfPCell.ALIGN_TOP );
  718. return pdfPCell;
  719. }
  720. @Override
  721. protected void endVisitTableCell( XWPFTableCell cell, IITextContainer tableContainer,
  722. IITextContainer tableCellContainer )
  723. {
  724. ExtendedPdfPTable pdfPTable = (ExtendedPdfPTable) tableContainer;
  725. ExtendedPdfPCell pdfPCell = (ExtendedPdfPCell) tableCellContainer;
  726. pdfPTable.addCell( pdfPCell );
  727. }
  728. @Override
  729. protected void visitPicture( CTPicture picture, IITextContainer parentContainer )
  730. {
  731. CTPositiveSize2D ext = picture.getSpPr().getXfrm().getExt();
  732. long x = ext.getCx();
  733. long y = ext.getCy();
  734. String blipId = picture.getBlipFill().getBlip().getEmbed();
  735. XWPFPictureData pictureData = super.getPictureDataByID( blipId );
  736. if ( pictureData != null )
  737. {
  738. try
  739. {
  740. Image img = Image.getInstance( pictureData.getData() );
  741. img.scaleAbsolute( dxa2points( x ) / 635, dxa2points( y ) / 635 );
  742. IITextContainer parentOfParentContainer = parentContainer.getITextContainer();
  743. if ( parentOfParentContainer != null && parentOfParentContainer instanceof PdfPCell )
  744. {
  745. parentOfParentContainer.addElement( img );
  746. }
  747. else
  748. {
  749. parentContainer.addElement( new Chunk( img, 0, 0, false ) );
  750. }
  751. }
  752. catch ( Exception e )
  753. {
  754. LOGGER.severe( e.getMessage() );
  755. }
  756. }
  757. }
  758. private void applyStyles( XWPFParagraph ele, IStylableElement<XWPFParagraph> element )
  759. {
  760. Style style = styleEngine.getStyle( ele.getStyleID() );
  761. element.applyStyles( ele, style );
  762. }
  763. private void applyStyles( XWPFTable ele, IStylableElement<XWPFTable> element )
  764. {
  765. CTString tblStyle = ele.getCTTbl().getTblPr().getTblStyle();
  766. Style style;
  767. if ( tblStyle != null )
  768. {
  769. style = styleEngine.getStyle( tblStyle.getVal() );
  770. }
  771. else
  772. {
  773. style = styleEngine.getDefaultStyle();
  774. }
  775. element.applyStyles( ele, style );
  776. }
  777. protected XWPFStyle getXWPFStyle( XWPFParagraph paragraph )
  778. {
  779. if ( paragraph == null )
  780. {
  781. return null;
  782. }
  783. return getXWPFStyle( paragraph.getStyleID() );
  784. }
  785. protected void setActiveMasterPage( StylableMasterPage masterPage )
  786. {
  787. pdfDocument.setActiveMasterPage( masterPage );
  788. }
  789. @Override
  790. protected StylableMasterPage createMasterPage( CTSectPr sectPr )
  791. {
  792. return new StylableMasterPage( sectPr );
  793. }
  794. }