Java tutorial
/** * Copyright (C) 2011-2015 The XDocReport Team <xdocreport@googlegroups.com> * * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package fr.opensagres.poi.xwpf.converter.pdf.internal; import static fr.opensagres.poi.xwpf.converter.core.utils.DxaUtil.emu2points; import java.io.OutputStream; import java.math.BigInteger; import java.util.List; import java.util.logging.Logger; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.UnderlinePatterns; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.STRelFromH; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.STRelFromV; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.STWrapText; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPTab; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTabs; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText; import com.lowagie.text.Chunk; import com.lowagie.text.DocumentException; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.Image; import com.lowagie.text.Paragraph; import com.lowagie.text.pdf.PdfPCell; import com.lowagie.text.pdf.PdfPTable; import fr.opensagres.poi.xwpf.converter.core.Color; import fr.opensagres.poi.xwpf.converter.core.ListItemContext; import fr.opensagres.poi.xwpf.converter.core.ParagraphLineSpacing; import fr.opensagres.poi.xwpf.converter.core.TableWidth; import fr.opensagres.poi.xwpf.converter.core.openxmlformats.IOpenXMLFormatsPartProvider; import fr.opensagres.poi.xwpf.converter.core.openxmlformats.OpenXMlFormatsVisitor; import fr.opensagres.poi.xwpf.converter.core.utils.DxaUtil; import fr.opensagres.poi.xwpf.converter.core.utils.StringUtils; import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableAnchor; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableDocument; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableHeaderFooter; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableMasterPage; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableParagraph; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableTable; import fr.opensagres.poi.xwpf.converter.pdf.internal.elements.StylableTableCell; import fr.opensagres.xdocreport.itext.extension.ExtendedChunk; import fr.opensagres.xdocreport.itext.extension.ExtendedImage; import fr.opensagres.xdocreport.itext.extension.ExtendedParagraph; import fr.opensagres.xdocreport.itext.extension.ExtendedPdfPCell; import fr.opensagres.xdocreport.itext.extension.ExtendedPdfPTable; import fr.opensagres.xdocreport.itext.extension.IITextContainer; import fr.opensagres.xdocreport.itext.extension.font.FontGroup; public class FastPdfMapper extends OpenXMlFormatsVisitor<IITextContainer, PdfOptions, StylableMasterPage> { private static final String TAB = "\t"; /** * Logger for this class */ private static final Logger LOGGER = Logger.getLogger(FastPdfMapper.class.getName()); private final OutputStream out; // Instance of PDF document private StylableDocument pdfDocument; private Font currentRunFontAscii; private Font currentRunFontEastAsia; private Font currentRunFontHAnsi; private UnderlinePatterns currentRunUnderlinePatterns; private Color currentRunBackgroundColor; private Float currentRunX; private Float currentPageWidth; public FastPdfMapper(IOpenXMLFormatsPartProvider provider, OutputStream out, PdfOptions options) throws Exception { super(provider, options != null ? options : PdfOptions.getDefault()); this.out = out; } // ------------------------- Document @Override protected IITextContainer startVisitDocument() throws Exception { // Create instance of PDF document this.pdfDocument = new StylableDocument(out, options.getConfiguration()); this.pdfDocument.setMasterPageManager(getMasterPageManager()); return pdfDocument; } @Override protected void endVisitDocument() throws Exception { pdfDocument.close(); out.close(); } public void setActiveMasterPage(StylableMasterPage masterPage) { pdfDocument.setActiveMasterPage(masterPage); } public StylableMasterPage createMasterPage(CTSectPr sectPr) { return new StylableMasterPage(sectPr); } @Override protected void pageBreak() throws Exception { pdfDocument.pageBreak(); } @Override protected IITextContainer startVisitParagraph(CTP paragraph, ListItemContext itemContext, IITextContainer pdfParentContainer) throws Exception { // create PDF paragraph StylableParagraph pdfParagraph = pdfDocument.createParagraph(pdfParentContainer); CTTbl parentTable = super.getParentTable(); // indentation left Float indentationLeft = stylesDocument.getIndentationLeft(paragraph, parentTable); if (indentationLeft != null) { pdfParagraph.setIndentationLeft(indentationLeft); } // indentation right Float indentationRight = stylesDocument.getIndentationRight(paragraph, parentTable); if (indentationRight != null) { pdfParagraph.setIndentationRight(indentationRight); } // indentation first line Float indentationFirstLine = stylesDocument.getIndentationFirstLine(paragraph, parentTable); if (indentationFirstLine != null) { pdfParagraph.setFirstLineIndent(indentationFirstLine); } // indentation hanging (remove first line) Float indentationHanging = stylesDocument.getIndentationHanging(paragraph, parentTable); if (indentationHanging != null) { pdfParagraph.setFirstLineIndent(-indentationHanging); } // // spacing before Float spacingBefore = stylesDocument.getSpacingBefore(paragraph, parentTable); if (spacingBefore != null) { pdfParagraph.setSpacingBefore(spacingBefore); } // spacing after // one more pargraph, spacing after should be applied. Float spacingAfter = stylesDocument.getSpacingAfter(paragraph, parentTable); if (spacingAfter != null) { pdfParagraph.setSpacingAfter(spacingAfter); } ParagraphLineSpacing lineSpacing = stylesDocument.getParagraphSpacing(paragraph, parentTable); if (lineSpacing != null) { if (lineSpacing.getLeading() != null && lineSpacing.getMultipleLeading() != null) { pdfParagraph.setLeading(lineSpacing.getLeading(), lineSpacing.getMultipleLeading()); } else { if (lineSpacing.getLeading() != null) { pdfParagraph.setLeading(lineSpacing.getLeading()); } if (lineSpacing.getMultipleLeading() != null) { pdfParagraph.setMultipliedLeading(lineSpacing.getMultipleLeading()); } } } // text-align ParagraphAlignment alignment = stylesDocument.getParagraphAlignment(paragraph, parentTable); if (alignment != null) { switch (alignment) { case LEFT: pdfParagraph.setAlignment(Element.ALIGN_LEFT); break; case RIGHT: pdfParagraph.setAlignment(Element.ALIGN_RIGHT); break; case CENTER: pdfParagraph.setAlignment(Element.ALIGN_CENTER); break; case BOTH: pdfParagraph.setAlignment(Element.ALIGN_JUSTIFIED); break; default: break; } } return pdfParagraph; } @Override protected void endVisitParagraph(CTP paragraph, IITextContainer pdfParentContainer, IITextContainer pdfParagraphContainer) throws Exception { // add the iText paragraph in the current parent container. ExtendedParagraph pdfParagraph = (ExtendedParagraph) pdfParagraphContainer; pdfParentContainer.addElement(pdfParagraph.getElement()); } @Override protected void visitRun(CTR run, CTP paragraph, boolean pageNumber, String url, IITextContainer pdfParagraphContainer) throws Exception { // Font family String fontFamilyAscii = stylesDocument.getFontFamilyAscii(run, paragraph); String fontFamilyEastAsia = stylesDocument.getFontFamilyEastAsia(run, paragraph); String fontFamilyHAnsi = stylesDocument.getFontFamilyHAnsi(run, paragraph); // Get font size Float fontSize = stylesDocument.getFontSize(run, paragraph); if (fontSize == null) { fontSize = -1f; } // Get font style int fontStyle = Font.NORMAL; Boolean bold = stylesDocument.getFontStyleBold(run, paragraph); if (bold != null && bold) { fontStyle |= Font.BOLD; } Boolean italic = stylesDocument.getFontStyleItalic(run, paragraph); if (italic != null && italic) { fontStyle |= Font.ITALIC; } Boolean strike = stylesDocument.getFontStyleStrike(run, paragraph); if (strike != null && strike) { fontStyle |= Font.STRIKETHRU; } // Font color Color fontColor = stylesDocument.getFontColor(run, paragraph); // Font this.currentRunFontAscii = getFont(fontFamilyAscii, fontSize, fontStyle, fontColor); this.currentRunFontEastAsia = getFont(fontFamilyEastAsia, fontSize, fontStyle, fontColor); this.currentRunFontHAnsi = getFont(fontFamilyHAnsi, fontSize, fontStyle, fontColor); // Underline patterns this.currentRunUnderlinePatterns = stylesDocument.getUnderline(run, paragraph); // background color this.currentRunBackgroundColor = stylesDocument.getBackgroundColor(run, paragraph); // highlight if (currentRunBackgroundColor == null) { this.currentRunBackgroundColor = stylesDocument.getTextHighlighting(run, paragraph); } StylableParagraph pdfParagraph = (StylableParagraph) pdfParagraphContainer; pdfParagraph.adjustMultipliedLeading(currentRunFontAscii); // addd symbol list item chunk if needed. String listItemText = pdfParagraph.getListItemText(); if (StringUtils.isNotEmpty(listItemText)) { // FIXME: add some space after the list item listItemText += " "; String listItemFontFamily = pdfParagraph.getListItemFontFamily(); Float listItemFontSize = pdfParagraph.getListItemFontSize(); int listItemFontStyle = pdfParagraph.getListItemFontStyle(); java.awt.Color listItemFontColor = pdfParagraph.getListItemFontColor(); Font listItemFont = options.getFontProvider().getFont( listItemFontFamily != null ? listItemFontFamily : fontFamilyAscii, options.getFontEncoding(), listItemFontSize != null ? listItemFontSize : fontSize, listItemFontStyle != Font.NORMAL ? listItemFontStyle : fontStyle, listItemFontColor != null ? listItemFontColor : Converter.toAwtColor(fontColor)); Chunk symbol = createTextChunk(listItemText, false, listItemFont, currentRunUnderlinePatterns, currentRunBackgroundColor); pdfParagraph.add(symbol); pdfParagraph.setListItemText(null); } IITextContainer container = pdfParagraphContainer; if (url != null) { // URL is not null, generate a PDF hyperlink. StylableAnchor pdfAnchor = new StylableAnchor(); pdfAnchor.setReference(url); pdfAnchor.setITextContainer(container); container = pdfAnchor; } super.visitRun(run, paragraph, pageNumber, url, pdfParagraphContainer); if (url != null) { // URL is not null, add the PDF hyperlink in the PDF paragraph pdfParagraphContainer.addElement((StylableAnchor) container); } this.currentRunFontAscii = null; this.currentRunFontEastAsia = null; this.currentRunFontHAnsi = null; this.currentRunUnderlinePatterns = null; this.currentRunBackgroundColor = null; } private Font getFont(String fontFamily, Float fontSize, int fontStyle, Color fontColor) { String fontToUse = stylesDocument.getFontNameToUse(fontFamily); if (StringUtils.isNotEmpty(fontToUse)) { return options.getFontProvider().getFont(fontToUse, options.getFontEncoding(), fontSize, fontStyle, Converter.toAwtColor(fontColor)); } Font font = options.getFontProvider().getFont(fontFamily, options.getFontEncoding(), fontSize, fontStyle, Converter.toAwtColor(fontColor)); if (!isFontExists(font)) { // font is not found try { List<String> altNames = stylesDocument.getFontsAltName(fontFamily); if (altNames != null) { // Loop for each alternative names font (from the fontTable.xml) to find the well font. for (String altName : altNames) { // check if the current font name is not the same that original (o avoid StackOverFlow : see // https://code.google.com/p/xdocreport/issues/detail?id=393) if (!fontFamily.equals(altName)) { font = getFont(altName, fontSize, fontStyle, fontColor); if (isFontExists(font)) { stylesDocument.setFontNameToUse(fontFamily, altName); return font; } } } } } catch (Exception e) { LOGGER.severe(e.getMessage()); } } return font; } /** * Returns true if the iText font exists and false otherwise. * * @param font * @return */ private boolean isFontExists(Font font) { // FIXME : is it like this to test that font exists? return font != null && font.getBaseFont() != null; } @Override protected void visitText(CTText docxText, boolean pageNumber, IITextContainer pdfParagraphContainer) throws Exception { Font font = currentRunFontAscii; Font fontAsian = currentRunFontEastAsia; Font fontComplex = currentRunFontHAnsi; createAndAddChunks(pdfParagraphContainer, docxText.getStringValue(), currentRunUnderlinePatterns, currentRunBackgroundColor, pageNumber, font, fontAsian, fontComplex); } private Chunk createTextChunk(String text, boolean pageNumber, Font currentRunFont, UnderlinePatterns currentRunUnderlinePatterns, Color currentRunBackgroundColor) { Chunk textChunk = pageNumber ? new ExtendedChunk(pdfDocument, true, currentRunFont) : new Chunk(text, currentRunFont); if (currentRunUnderlinePatterns != null) { // underlined boolean singleUnderlined = false; switch (currentRunUnderlinePatterns) { case SINGLE: singleUnderlined = true; break; default: break; } if (singleUnderlined) { textChunk.setUnderline(1, -2); } } // background color if (currentRunBackgroundColor != null) { textChunk.setBackground(Converter.toAwtColor(currentRunBackgroundColor)); } if (currentRunX != null) { this.currentRunX += textChunk.getWidthPoint(); } return textChunk; } private void createAndAddChunks(IITextContainer parent, String textContent, UnderlinePatterns underlinePatterns, Color backgroundColor, boolean pageNumber, Font font, Font fontAsian, Font fontComplex) { StringBuilder sbuf = new StringBuilder(); FontGroup currentGroup = FontGroup.WESTERN; for (int i = 0; i < textContent.length(); i++) { char ch = textContent.charAt(i); FontGroup group = FontGroup.getUnicodeGroup(ch, font, fontAsian, fontComplex); if (sbuf.length() == 0 || currentGroup.equals(group)) { // continue current chunk sbuf.append(ch); } else { // end chunk Font chunkFont = getFont(font, fontAsian, fontComplex, currentGroup); Chunk chunk = createTextChunk(sbuf.toString(), pageNumber, chunkFont, underlinePatterns, backgroundColor); parent.addElement(chunk); // start new chunk sbuf.setLength(0); sbuf.append(ch); } currentGroup = group; } // end chunk Font chunkFont = getFont(font, fontAsian, fontComplex, currentGroup); Chunk chunk = createTextChunk(sbuf.toString(), pageNumber, chunkFont, underlinePatterns, backgroundColor); parent.addElement(chunk); } private Font getFont(Font font, Font fontAsian, Font fontComplex, FontGroup group) { switch (group) { case WESTERN: return font; case ASIAN: return fontAsian; case COMPLEX: return fontComplex; } return font; } @Override protected void visitTab(CTPTab o, IITextContainer paragraphContainer) throws Exception { // TODO Auto-generated method stub } @Override protected void visitTabs(CTTabs tabs, IITextContainer paragraphContainer) throws Exception { // TODO Auto-generated method stub } @Override protected void visitBookmark(CTBookmark bookmark, CTP paragraph, IITextContainer paragraphContainer) throws Exception { // TODO Auto-generated method stub } @Override protected void addNewLine(CTBr br, IITextContainer paragraphContainer) throws Exception { paragraphContainer.addElement(Chunk.NEWLINE); } @Override protected void visitHeader(CTHdrFtr currentHeader, CTHdrFtrRef headerRef, CTSectPr sectPr, StylableMasterPage masterPage) throws Exception { BigInteger headerY = sectPr.getPgMar() != null ? sectPr.getPgMar().getHeader() : null; this.currentPageWidth = sectPr.getPgMar() != null ? DxaUtil.dxa2points(sectPr.getPgSz().getW()) : null; StylableHeaderFooter pdfHeader = new StylableHeaderFooter(pdfDocument, headerY, false); StylableTableCell tableCell = pdfHeader.getTableCell(); visitBodyElements(currentHeader, tableCell); masterPage.setHeader(pdfHeader); this.currentPageWidth = null; } @Override protected void visitFooter(CTHdrFtr currentFooter, CTHdrFtrRef footerRef, CTSectPr sectPr, StylableMasterPage masterPage) throws Exception { BigInteger footerY = sectPr.getPgMar() != null ? sectPr.getPgMar().getFooter() : null; this.currentPageWidth = sectPr.getPgMar() != null ? DxaUtil.dxa2points(sectPr.getPgSz().getW()) : null; StylableHeaderFooter pdfFooter = new StylableHeaderFooter(pdfDocument, footerY, false); StylableTableCell tableCell = pdfFooter.getTableCell(); visitBodyElements(currentFooter, tableCell); masterPage.setFooter(pdfFooter); this.currentPageWidth = null; } // ----------------- Table @Override protected IITextContainer startVisitTable(CTTbl table, float[] colWidths, IITextContainer pdfParentContainer) throws Exception { StylableTable pdfPTable = createPDFTable(table, colWidths, pdfParentContainer); return pdfPTable; } private StylableTable createPDFTable(CTTbl table, float[] colWidths, IITextContainer pdfParentContainer) throws DocumentException { // 2) Compute tableWith TableWidth tableWidth = stylesDocument.getTableWidth(table); StylableTable pdfPTable = pdfDocument.createTable(pdfParentContainer, colWidths.length); pdfPTable.setTotalWidth(colWidths); if (tableWidth != null && tableWidth.width > 0) { if (tableWidth.percentUnit) { pdfPTable.setWidthPercentage(tableWidth.width); } else { pdfPTable.setTotalWidth(tableWidth.width); } } pdfPTable.setLockedWidth(true); // Table alignment ParagraphAlignment alignment = stylesDocument.getTableAlignment(table); if (alignment != null) { switch (alignment) { case LEFT: pdfPTable.setHorizontalAlignment(Element.ALIGN_LEFT); break; case RIGHT: pdfPTable.setHorizontalAlignment(Element.ALIGN_RIGHT); break; case CENTER: pdfPTable.setHorizontalAlignment(Element.ALIGN_CENTER); break; case BOTH: pdfPTable.setHorizontalAlignment(Element.ALIGN_JUSTIFIED); break; default: break; } } // Table indentation Float indentation = stylesDocument.getTableIndentation(table); if (indentation != null) { pdfPTable.setPaddingLeft(indentation); } return pdfPTable; } @Override protected void endVisitTable(CTTbl table, IITextContainer parentContainer, IITextContainer tableContainer) throws Exception { parentContainer.addElement(((ExtendedPdfPTable) tableContainer).getElement()); } // ------------------------- Table Row @Override protected void startVisitTableRow(CTRow row, IITextContainer tableContainer, boolean headerRow) throws Exception { if (headerRow) { PdfPTable table = (PdfPTable) tableContainer; table.setHeaderRows(table.getHeaderRows() + 1); } } @Override protected IITextContainer startVisitTableCell(CTTc cell, IITextContainer tableContainer) throws Exception { StylableTable pdfPTable = (StylableTable) tableContainer; StylableTableCell pdfPCell = pdfDocument.createTableCell(pdfPTable); // Background Color Color backgroundColor = stylesDocument.getTableCellBackgroundColor(cell); if (backgroundColor != null) { pdfPCell.setBackgroundColor(Converter.toAwtColor(backgroundColor)); } return pdfPCell; } @Override protected void endVisitTableCell(CTTc cell, IITextContainer tableContainer, IITextContainer tableCellContainer) throws Exception { ExtendedPdfPTable pdfPTable = (ExtendedPdfPTable) tableContainer; ExtendedPdfPCell pdfPCell = (ExtendedPdfPCell) tableCellContainer; pdfPTable.addCell(pdfPCell); } // ------------------------- Image @Override protected void visitPicture(CTPicture picture, Float offsetX, org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.STRelFromH.Enum relativeFromH, Float offsetY, org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.STRelFromV.Enum relativeFromV, STWrapText.Enum wrapText, IITextContainer pdfParentContainer) throws Exception { CTPositiveSize2D ext = picture.getSpPr().getXfrm().getExt(); long x = ext.getCx(); long y = ext.getCy(); byte[] pictureData = super.getPictureBytes(picture); if (pictureData != null) { try { Image img = Image.getInstance(pictureData); img.scaleAbsolute(emu2points(x), emu2points(y)); IITextContainer parentOfParentContainer = pdfParentContainer.getITextContainer(); if (parentOfParentContainer != null && parentOfParentContainer instanceof PdfPCell) { parentOfParentContainer.addElement(img); } else { float chunkOffsetX = 0; if (offsetX != null) { if (STRelFromH.CHARACTER.equals(relativeFromH)) { chunkOffsetX = offsetX; } else if (STRelFromH.COLUMN.equals(relativeFromH)) { chunkOffsetX = offsetX; } else if (STRelFromH.INSIDE_MARGIN.equals(relativeFromH)) { chunkOffsetX = offsetX; } else if (STRelFromH.LEFT_MARGIN.equals(relativeFromH)) { chunkOffsetX = offsetX; } else if (STRelFromH.MARGIN.equals(relativeFromH)) { chunkOffsetX = pdfDocument.left() + offsetX; } else if (STRelFromH.OUTSIDE_MARGIN.equals(relativeFromH)) { chunkOffsetX = offsetX; } else if (STRelFromH.PAGE.equals(relativeFromH)) { chunkOffsetX = offsetX - pdfDocument.left(); } } float chunkOffsetY = 0; boolean useExtendedImage = false; if (STRelFromV.PARAGRAPH.equals(relativeFromV)) { useExtendedImage = true; } if (useExtendedImage) { ExtendedImage extImg = new ExtendedImage(img, -offsetY); if (STRelFromV.PARAGRAPH.equals(relativeFromV)) { chunkOffsetY = -extImg.getScaledHeight(); } Chunk chunk = new Chunk(extImg, chunkOffsetX, chunkOffsetY, false); pdfParentContainer.addElement(chunk); } /* * float chunkOffsetY = 0; if ( wrapText != null ) { chunkOffsetY = -img.getScaledHeight(); } * boolean useExtendedImage = offsetY != null; // if ( STRelFromV.PARAGRAPH.equals( relativeFromV ) * ) // { // useExtendedImage = true; // } // if ( useExtendedImage ) { float imgY = -offsetY; if ( * pdfHeader != null ) { float headerY = pdfHeader.getY() != null ? pdfHeader.getY() : 0; imgY += - * img.getScaledHeight() + headerY; } ExtendedImage extImg = new ExtendedImage( img, imgY ); // if ( * STRelFromV.PARAGRAPH.equals( relativeFromV ) ) // { // chunkOffsetY = -extImg.getScaledHeight(); * // } Chunk chunk = new Chunk( extImg, chunkOffsetX, chunkOffsetY, false ); * pdfParentContainer.addElement( chunk ); } */ else { if (pdfParentContainer instanceof Paragraph) { // I don't know why but we need add some spacing before in the paragraph // otherwise the image cut the text of the below paragraph (see FormattingTests JUnit)? Paragraph paragraph = (Paragraph) pdfParentContainer; paragraph.setSpacingBefore(paragraph.getSpacingBefore() + 5f); } pdfParentContainer.addElement(new Chunk(img, chunkOffsetX, chunkOffsetY, false)); } } } catch (Exception e) { LOGGER.severe(e.getMessage()); } } } }