Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
it.discovery.jasperreports.jasper2word.J2WDocx4jHelper Maven / Gradle / Ivy
package it.discovery.jasperreports.jasper2word;
import it.discovery.jasperreports.jasper2word.J2WAbstractJRExporter.PageOrder;
import it.discovery.jasperreports.jasper2word.J2WAbstractPrintElementVisitorContext.DocxDocumentPart;
import it.discovery.jasperreports.jasper2word.J2WAbstractPrintElementVisitorContext.LastDocxElement;
import it.discovery.jasperreports.jasper2word.J2WGridPageLayout.ComponentPosition;
import it.discovery.jasperreports.jasper2word.J2WGridPageLayout.ComponentPositionInTable;
import it.discovery.jasperreports.jasper2word.J2WGridPageLayout.ComponentTableInfo;
import it.discovery.jasperreports.jasper2word.J2WGridPageLayout.HeaderFooterPageInfo;
import it.discovery.jasperreports.jasper2word.J2WReportConfiguration.ESpacingPolicy;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.base.JRBaseStyle;
import net.sf.jasperreports.engine.base.JRBoxPen;
import net.sf.jasperreports.engine.fill.JRTemplatePrintElement;
import net.sf.jasperreports.engine.type.*;
import net.sf.jasperreports.engine.util.JRStyledText;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.docx4j.XmlUtils;
import org.docx4j.dml.*;
import org.docx4j.dml.picture.Pic;
import org.docx4j.dml.wordprocessingDrawing.*;
import org.docx4j.jaxb.Context;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.contenttype.ContentTypes;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.*;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.relationships.Relationship;
import org.docx4j.vml.CTLine;
import org.docx4j.vml.CTOval;
import org.docx4j.vml.CTRect;
import org.docx4j.vml.STTrueFalse;
import org.docx4j.vml.officedrawing.STConnectorType;
import org.docx4j.vml.officedrawing.STHrAlign;
import org.docx4j.vml.officedrawing.STInsetMode;
import org.docx4j.wml.*;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.PPrBase.Ind;
import org.docx4j.wml.PPrBase.PBdr;
import org.docx4j.wml.PPrBase.PStyle;
import org.docx4j.wml.PPrBase.Spacing;
import org.docx4j.wml.R.LastRenderedPageBreak;
import org.docx4j.wml.SectPr.PgMar;
import org.docx4j.wml.SectPr.PgSz;
import org.docx4j.wml.Style.Aliases;
import org.docx4j.wml.Style.BasedOn;
import org.docx4j.wml.Style.Name;
import org.docx4j.wml.TcPrInner.GridSpan;
import org.docx4j.wml.TcPrInner.TcBorders;
import org.docx4j.wml.TcPrInner.VMerge;
import javax.imageio.ImageIO;
import javax.xml.bind.JAXBElement;
import java.awt.Color;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.font.TextAttribute;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;
/**
* Helper class to prodoce docx document with docx4j library.
* @author discovery
* @date 13/08/15 10.07
*/
class J2WDocx4jHelper {
/** Macro for automatic color */
private static final String COLOR_AUTO = "auto";
/**
* Hide the constructor.
*/
private J2WDocx4jHelper() {
}
/**
* Append, if necessary, a new table in the doc.
* @param tablePos The position of an element in a table.
* @param context The exporter visitor context.
* @return The metadata of the built table.
*/
static TableDocInfo buildTables(ComponentPositionInTable tablePos, J2WDocx4jPrintElementVisitorContext context) {
Map tables = context.tables;
ComponentTableInfo table = tablePos.getTableInfo();
TableDocInfo res = tables.get(table.getTableId());
// Check for pre-built table
if (res == null) {
// if the previous element in document was a table or table must be moved more down, a new space paragraph is appended
if (context.getLastDocxElement() == LastDocxElement.TABLE || context.getLastY(tablePos.getDocumentPart()) < tablePos.getTableInfo().getY()) {
R run = context.objectFactory.createR();
P paragraph = context.objectFactory.createP();
paragraph.setPPr(context.objectFactory.createPPr());
PPr pPr = paragraph.getPPr();
pPr.setPStyle(context.objectFactory.createPPrBasePStyle());
pPr.getPStyle().setVal("Normal");
run.setRPr(context.objectFactory.createRPr());
pPr.setSpacing(context.objectFactory.createPPrBaseSpacing());
Spacing spacing = pPr.getSpacing();
spacing.setBefore(BigInteger.ZERO);
spacing.setBeforeLines(BigInteger.ZERO);
spacing.setAfterLines(BigInteger.ZERO);
setParagraphMargins(paragraph, context.getLastParagraphX(), context.getLastParagraphWidth(), context);
if (context.getLastY(tablePos.getDocumentPart()) < tablePos.getTableInfo().getY()) {
BigInteger gap = EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, tablePos.getTableInfo().getY() - context.getLastY(tablePos.getDocumentPart())).divide(BigInteger.valueOf(2));
BigInteger check = BigInteger.valueOf(240);
if (gap.min(check).equals(check)) {
spacing.setAfter(BigInteger.ZERO);
spacing.setLine(gap.add(gap));
}
else {
spacing.setAfter(gap);
spacing.setLine(gap);
}
spacing.setLineRule(STLineSpacingRule.EXACT);
}
else {
spacing.setAfter(BigInteger.ZERO);
spacing.setLineRule(STLineSpacingRule.EXACT);
spacing.setLine(BigInteger.ONE);
}
paragraph.getContent().add(run);
if (tablePos.getDocumentPart() == DocxDocumentPart.HEADER)
context.headerContent.getContent().add(paragraph);
else if (tablePos.getDocumentPart() == DocxDocumentPart.FOOTER)
context.footerContent.getContent().add(paragraph);
else
context.getDocument().getMainDocumentPart().getContent().add(paragraph);
}
TableDocInfo parent = null;
if (table.getParent() instanceof ComponentPositionInTable)
parent = buildTables((ComponentPositionInTable) table.getParent(), context);
// Building the table
int[] rowsHeight = table.getRows();
int[] columnsWidth = table.getColumns();
BigInteger columnsX[] = new BigInteger[columnsWidth.length + 1];
columnsX[0] = BigInteger.ZERO;
Tbl xwpfTable = context.objectFactory.createTbl();
for (int aRowsHeight : rowsHeight) {
Tr tr = context.objectFactory.createTr();
TrPr trPr = tr.getTrPr();
if (trPr == null) {
trPr = context.objectFactory.createTrPr();
tr.setTrPr(trPr);
}
// Rows height
CTHeight ctHeight = context.objectFactory.createCTHeight();
if (table.isForceRowHeight())
ctHeight.setHRule(STHeightRule.EXACT);
else
ctHeight.setHRule(STHeightRule.AUTO);
ctHeight.setVal(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, aRowsHeight));
trPr.getCnfStyleOrDivIdOrGridBefore().add(context.objectFactory.createCTTrPrBaseTrHeight(ctHeight));
// Columns width (paragraph)
for (int aColumnsWidth : columnsWidth) {
Tc tc = context.objectFactory.createTc();
tr.getContent().add(tc);
tc.getContent().add(context.objectFactory.createP());
TcPr tcPr = tc.getTcPr();
if (tcPr == null) {
tcPr = context.objectFactory.createTcPr();
tc.setTcPr(tcPr);
}
TblWidth w = context.objectFactory.createTblWidth();
w.setType(TblWidth.TYPE_DXA);
w.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, aColumnsWidth));
tcPr.setTcW(w);
}
xwpfTable.getContent().add(tr);
}
// Table width
TblWidth tblWidth = context.objectFactory.createTblWidth();
tblWidth.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, table.getWidth()));
tblWidth.setType(TblWidth.TYPE_DXA);
// Table right margin
TblWidth tblInd = context.objectFactory.createTblWidth();
tblInd.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, table.getX()));
tblInd.setType(TblWidth.TYPE_DXA);
TblPr tblPr = context.objectFactory.createTblPr();
tblPr.setTblW(tblWidth);
tblPr.setTblInd(tblInd);
// Table borders
TblBorders tblBorders = context.objectFactory.createTblBorders();
if (table.isBordered()) {
tblBorders.setInsideH(createBorder(context.objectFactory, 1, 2, "000000", STBorder.SINGLE));
tblBorders.setInsideV(createBorder(context.objectFactory, 1, 2, "000000", STBorder.SINGLE));
tblBorders.setBottom(createBorder(context.objectFactory, 1, 2, "000000", STBorder.SINGLE));
tblBorders.setLeft(createBorder(context.objectFactory, 1, 2, "000000", STBorder.SINGLE));
tblBorders.setRight(createBorder(context.objectFactory, 1, 2, "000000", STBorder.SINGLE));
tblBorders.setTop(createBorder(context.objectFactory, 1, 2, "000000", STBorder.SINGLE));
}
else {
tblBorders.setInsideH(createBorder(context.objectFactory, 0, 0, "000000", STBorder.NONE));
tblBorders.setInsideV(createBorder(context.objectFactory, 0, 0, "000000", STBorder.NONE));
tblBorders.setBottom(createBorder(context.objectFactory, 0, 0, "000000", STBorder.NONE));
tblBorders.setLeft(createBorder(context.objectFactory, 0, 0, "000000", STBorder.NONE));
tblBorders.setRight(createBorder(context.objectFactory, 0, 0, "000000", STBorder.NONE));
tblBorders.setTop(createBorder(context.objectFactory, 0, 0, "000000", STBorder.NONE));
}
tblPr.setTblBorders(tblBorders);
// Table grid column definition
TblGrid tblGrid = context.objectFactory.createTblGrid();
for (int i = 0; i < columnsWidth.length; i++) {
int colWidth = columnsWidth[i];
TblGridCol col = context.objectFactory.createTblGridCol();
tblGrid.getGridCol().add(col);
BigInteger width = EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, colWidth);
col.setW(width);
columnsX[i + 1] = width;
}
xwpfTable.setTblPr(tblPr);
xwpfTable.setTblGrid(tblGrid);
if (parent == null) {
if (tablePos.getDocumentPart() == DocxDocumentPart.HEADER)
context.headerContent.getContent().add(xwpfTable);
else if (tablePos.getDocumentPart() == DocxDocumentPart.FOOTER)
context.footerContent.getContent().add(xwpfTable);
else
context.getDocument().getMainDocumentPart().getContent().add(xwpfTable);
}
else {
Tr row = (Tr) parent.table.getContent().get(tablePos.getRow());
Tc cell = (Tc) row.getContent().get(tablePos.getCol());
cell.getContent().clear();
cell.getContent().add(xwpfTable);
}
// Build merged cell
res = new TableDocInfo(xwpfTable);
SortedSet cellToRemove = new TreeSet<>(new CellToRemovePointComparator());
for (Rectangle mergedRegion : table.getMergedRegions()) {
Tr row = (Tr) xwpfTable.getContent().get(mergedRegion.y);
Tc cell = (Tc) row.getContent().get(mergedRegion.x);
TcPr tcPr = cell.getTcPr();
if (tcPr == null) {
tcPr = context.objectFactory.createTcPr();
cell.setTcPr(tcPr);
}
if (mergedRegion.width > 1) {
GridSpan gridSpan = context.objectFactory.createTcPrInnerGridSpan();
gridSpan.setVal(BigInteger.valueOf((long) mergedRegion.width));
tcPr.setGridSpan(gridSpan);
}
if (mergedRegion.height > 1) {
VMerge vMerge = context.objectFactory.createTcPrInnerVMerge();
vMerge.setVal("restart");
tcPr.setVMerge(vMerge);
}
TblWidth tcW = context.objectFactory.createTblWidth();
tcW.setW(columnsX[mergedRegion.x + 1].subtract(columnsX[mergedRegion.x]));
tcW.setType(TblWidth.TYPE_DXA);
tcPr.setTcW(tcW);
for (int rowIndex = mergedRegion.y; rowIndex < mergedRegion.height + mergedRegion.y; rowIndex++) {
Tr rowSpan = (Tr) xwpfTable.getContent().get(rowIndex);
for (int columnIndex = mergedRegion.x; columnIndex < mergedRegion.x + mergedRegion.width ; columnIndex++) {
if (columnIndex > mergedRegion.x)
cellToRemove.add(new Point(columnIndex, rowIndex));
if (rowIndex > mergedRegion.y && columnIndex == mergedRegion.x) {
cell = (Tc) rowSpan.getContent().get(columnIndex);
tcPr = cell.getTcPr();
if (tcPr == null) {
tcPr = context.objectFactory.createTcPr();
cell.setTcPr(tcPr);
}
if (mergedRegion.width > 1) {
GridSpan gridSpan = context.objectFactory.createTcPrInnerGridSpan();
gridSpan.setVal(BigInteger.valueOf((long) mergedRegion.width));
tcPr.setGridSpan(gridSpan);
}
if (mergedRegion.height > 1) {
VMerge vMerge = context.objectFactory.createTcPrInnerVMerge();
vMerge.setVal("continue");
tcPr.setVMerge(vMerge);
}
tcPr.setTcW(tcW);
}
}
}
}
for (Point cellCoord : cellToRemove) {
Tr rowSpan = (Tr) xwpfTable.getContent().get(cellCoord.y);
rowSpan.getContent().remove(cellCoord.x);
}
tables.put(table.getTableId(), res);
context.setLastY(tablePos.getDocumentPart(), table.getY() + table.getHeight());
}
context.setLastDocxElement(LastDocxElement.TABLE);
return res;
}
/**
* Build a table border.
* @param factory Jaxb object factory.
* @param size The border size in points.
* @param space The space between border and cell content in points.
* @param color The border color.
* @param type The border style.
* @return The built border.
*/
private static CTBorder createBorder(org.docx4j.wml.ObjectFactory factory, int size, int space, String color, STBorder type) {
CTBorder ctBorder = factory.createCTBorder();
ctBorder.setColor(color);
ctBorder.setVal(type);
ctBorder.setSz(BigInteger.valueOf(size));
ctBorder.setSpace(BigInteger.valueOf(space));
return ctBorder;
}
/**
* Format a {@link Color color} in a hexadecimal string (RRGGBB).
* @param color The java awt Color.
* @return The formatted string color.
*/
static String colorToStringFormat(Color color) {
Color base = new Color(255, 255, 255, 0);
return String.format("%6s", Integer.toHexString(color.getRGB() & base.getRGB())).replaceAll(" ", "0");
}
/**
* Parse string (or byte[]) color into a java awt Color.
* @param color It can be a hexadecimal {@link String String} like RRGGBB or a {@code byte[]} like byte[] {R, G, B}.
* @return The java awt Color.
*/
static Color stringToColorParse(Object color) {
if (color == null)
return null;
if (color instanceof String) {
String s_color = (String) color;
if (s_color.equals(COLOR_AUTO))
return null;
String tokens[] = s_color.split("(?<=\\G\\d{2})", 3);
return new Color(Integer.parseInt(tokens[0], 16), Integer.parseInt(tokens[1], 16), Integer.parseInt(tokens[2], 16), 0);
}
else if (color instanceof byte[]) {
byte c[] = (byte[]) color;
return new Color(c[0], c[1], c[2]);
}
else
throw new JRRuntimeException("Unknown color type: " + color.getClass().getName());
}
/**
* Reset document status variables and build document styles.
* @param firstReport {@code true} if first report, {@code} false otherwise.
* @param context The visitor context.
* @param report Thre report to export.
*/
static void prepareNewDocument(boolean firstReport, J2WDocx4jPrintElementVisitorContext context, JasperPrint report) {
context.resetDocumentStatus();
context.setReport(report);
if (firstReport) {
context.reportCount = 0;
context.currentSection = null;
context.sectionParagraph = null;
}
else
context.reportCount++;
buildStyles(context, report.getStylesList());
}
/**
* Prepare new page (build new section if required), set page size and (optiona) header and footer.
* @param context The visitor context.
* @param jrPage The jasper page.
* @param pageNumber The relative page number.
* @param pageOrder The absolute page position.
*/
static void prepareNewPage(J2WDocx4jPrintElementVisitorContext context, JRPrintPage jrPage, int pageNumber, PageOrder pageOrder) {
if (!pageOrder.isFirstestPage() && context.currentSection == null) {
WordprocessingMLPackage document = context.getDocument();
ObjectFactory factory = context.objectFactory;
Br breakObj = context.objectFactory.createBr();
breakObj.setType(STBrType.PAGE);
breakObj.setClear(STBrClear.ALL);
P paragraph = factory.createP();
R run = factory.createR();
run.getContent().add(breakObj);
paragraph.getContent().add(run);
document.getMainDocumentPart().getContent().add(paragraph);
}
context.currentSection = null;
context.sectionParagraph = null;
setPageSizeAndMargins(context, pageOrder);
buildHeaderFooter(context, pageNumber, pageOrder);
}
/**
* Finalize the page (add the page section, if present).
* @param context The visitor context.
* @param jrPage The jasper page.
* @param pageNumber The relative page number.
* @param pageOrder The absolute page position.
*/
static void finalizePage(J2WDocx4jPrintElementVisitorContext context, JRPrintPage jrPage, int pageNumber, PageOrder pageOrder) {
WordprocessingMLPackage document = context.getDocument();
if (context.sectionParagraph != null)
document.getMainDocumentPart().addObject(context.sectionParagraph);
}
/**
* Return the current section if exits, or create a new one.
* @param context The visitor context.
* @param pageOrder The absolute page position.
* @return The current section or new one.
*/
private static SectPr getOrCreateCurrentSection(J2WDocx4jPrintElementVisitorContext context, PageOrder pageOrder) {
WordprocessingMLPackage document = context.getDocument();
List sections = document.getDocumentModel().getSections();
// Get last section SectPr and create a new one if it doesn't exist
SectPr sectPr;
if (pageOrder.isLastestPage()) {
sectPr = sections.get(sections.size() - 1).getSectPr();
if (sectPr == null) {
sectPr = context.objectFactory.createSectPr();
sections.get(sections.size() - 1).setSectPr(sectPr);
}
}
else {
sectPr = context.currentSection;
if (sectPr == null) {
sectPr = context.objectFactory.createSectPr();
context.sectionParagraph = context.objectFactory.createP();
PPr pPr = context.objectFactory.createPPr();
pPr.setSectPr(sectPr);
context.sectionParagraph.setPPr(pPr);
LastRenderedPageBreak breakObj = context.objectFactory.createRLastRenderedPageBreak();
R run = context.objectFactory.createR();
run.getContent().add(breakObj);
context.sectionParagraph.getContent().add(run);
}
}
context.currentSection = sectPr;
return sectPr;
}
/**
* Set the page size and margins. If the report has not margins, default margins are created with 5pt size.
* @param context The visitor context.
* @param pageOrder The absolute page position.
*/
private static void setPageSizeAndMargins(J2WDocx4jPrintElementVisitorContext context, PageOrder pageOrder) {
JasperPrint report = context.getReport();
HeaderFooterPageInfo pageInfo = context.getLayout().getPageInfo();
if (context.getLastPageInfo() == null || context.getLastPageInfo().containsHeaderFooter() || pageInfo.containsHeaderFooter() || pageOrder.isLastestPage()) {
PgSz ctPageSz = context.objectFactory.createSectPrPgSz();
ctPageSz.setH(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, report.getPageHeight()));
ctPageSz.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, report.getPageWidth()));
SectPr sectPr = getOrCreateCurrentSection(context, pageOrder);
sectPr.setPgSz(ctPageSz);
int top;
int bottom;
int right = 5;
int left = 5;
int header = 0;
int footer = 0;
if (pageInfo.getRightMargin() > 0)
right = pageInfo.getRightMargin();
if (pageInfo.getLeftMargin() > 0)
left = pageInfo.getLeftMargin();
if (pageInfo.getMinHeader() != null) {
top = pageInfo.getTopMargin() + pageInfo.getMinHeader();
header = pageInfo.getMinHeader();
}
else if (pageInfo.getTopMargin() > 0)
top = pageInfo.getTopMargin();
else
top = 5;
if (pageInfo.getMaxFooter() != null) {
bottom = pageInfo.getMaxFooter() + pageInfo.getBottomMargin();
footer = pageInfo.getMaxFooter();
}
else if (pageInfo.getBottomMargin() > 0)
bottom = pageInfo.getBottomMargin();
else
bottom = 5;
PgMar ctPageMar = context.objectFactory.createSectPrPgMar();
ctPageMar.setBottom(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, bottom));
ctPageMar.setTop(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, top));
ctPageMar.setLeft(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, left));
ctPageMar.setRight(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, right));
ctPageMar.setHeader(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, header));
ctPageMar.setFooter(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, footer));
ctPageMar.setGutter(BigInteger.ZERO);
sectPr.setPgMar(ctPageMar);
}
}
/**
* Build the header and footer, if exist.
* @param context The visitor context.
* @param pageNumber The relative page number.
* @param pageOrder The absolute page position.
*/
static void buildHeaderFooter(J2WDocx4jPrintElementVisitorContext context, int pageNumber, PageOrder pageOrder) {
try {
HeaderFooterPageInfo pageInfo = context.getLayout().getPageInfo();
if (context.getLastPageInfo() == null || context.getLastPageInfo().containsHeaderFooter() || context.getLayout().getPageInfo().containsHeaderFooter()) {
WordprocessingMLPackage document = context.getDocument();
MainDocumentPart mainPart = document.getMainDocumentPart();
// Get last section SectPr and create a new one if it doesn't exist
SectPr sectPr = getOrCreateCurrentSection(context, pageOrder);
ObjectFactory factory = context.objectFactory;
Relationship content_hdr_rel = null;
Relationship content_ftr_rel = null;
if (pageInfo.getHeaderHeight() != null) {
HeaderPart headerContent = new HeaderPart(new PartName(MessageFormat.format("/word/header_{0,number,0}_{1,number,0}.xml", context.reportCount, pageNumber)));
document.getParts().put(headerContent);
context.headerContent = factory.createHdr();
// Bind the header JAXB element as representing its header part
headerContent.setJaxbElement(context.headerContent);
// Add the reference to header part to the Main Document Part
content_hdr_rel = mainPart.addTargetPart(headerContent);
}
else {
context.headerContent = null;
}
if (pageInfo.getFooterHeight() != null) {
FooterPart footerContent = new FooterPart(new PartName(MessageFormat.format("/word/footer_{0,number,0}_{1,number,0}.xml", context.reportCount, pageNumber)));
document.getParts().put(footerContent);
context.footerContent = factory.createFtr();
// Bind the footer JAXB element as representing its footer part
footerContent.setJaxbElement(context.footerContent);
// Add the reference to footer part to the Main Document Part
content_ftr_rel = mainPart.addTargetPart(footerContent);
}
else {
context.footerContent = null;
}
BooleanDefaultTrue boolanDefaultTrue = new BooleanDefaultTrue();
boolanDefaultTrue.setVal(false);
sectPr.setTitlePg(boolanDefaultTrue);
// link content headers
if (content_hdr_rel != null) {
HeaderReference hdr_ref = factory.createHeaderReference();
hdr_ref.setId(content_hdr_rel.getId());
hdr_ref.setType(HdrFtrRef.DEFAULT);
sectPr.getEGHdrFtrReferences().add(hdr_ref);
}
// link content footers
if (content_ftr_rel != null) {
FooterReference ftr_ref = factory.createFooterReference();
ftr_ref.setId(content_ftr_rel.getId());
ftr_ref.setType(HdrFtrRef.DEFAULT);
sectPr.getEGHdrFtrReferences().add(ftr_ref);
}
}
} catch (InvalidFormatException e) {
throw new JRRuntimeException(e);
}
}
/**
* Return the Style Document part (styles container) if exists, or create a new one if {@code createIfNull} is {@code true}.
* @param context The visitor context.
* @param createIfNull {@code true} create a new style document part if not exits.
* @return The style document part or {@code null} if not exists and {@code createIfNull} is {@code false}.
*/
private static StyleDefinitionsPart buildStylePart(J2WDocx4jPrintElementVisitorContext context, boolean createIfNull) {
MainDocumentPart wordDocumentPart = context.getDocument().getMainDocumentPart();
try {
StyleDefinitionsPart stylesPart = new StyleDefinitionsPart();
Relationship rel = wordDocumentPart.getRelationshipsPart().getRel(stylesPart.getPartName());
if (rel != null)
stylesPart = (StyleDefinitionsPart) wordDocumentPart.getRelationshipsPart().getPart(rel);
else if (createIfNull)
wordDocumentPart.addTargetPart(stylesPart);
else
stylesPart = null;
if (stylesPart != null) {
Styles styles = stylesPart.getContents();
if (styles == null && createIfNull) {
styles = (Styles) stylesPart.unmarshalDefaultStyles();
stylesPart.setContents(styles);
}
}
return stylesPart;
} catch (Exception e) {
throw new JRRuntimeException(e);
}
}
/**
* Update doc style with jasper style attributes.
* @param ctStyle The doc style.
* @param jrStyle The jasper style.
* @param context The visito context.
* @param update {@code true} to update doc style, {@code false} to create a new one doc style with jasper style attributes.
* @return The updated doc style.
*/
private static String updateStyle(Style ctStyle, JRStyle jrStyle, J2WDocx4jPrintElementVisitorContext context, boolean update) {
JRPen linePen = jrStyle.getLinePen();
BooleanDefaultTrue ctOnOff_ON = context.objectFactory.createBooleanDefaultTrue();
BooleanDefaultTrue ctOnOff_OFF = context.objectFactory.createBooleanDefaultTrue();
ctOnOff_ON.setVal(Boolean.TRUE);
ctOnOff_OFF.setVal(Boolean.FALSE);
String styleName = jrStyle.getName();
if (!update) {
int styleCount = 1;
while (context.allStyles.contains(styleName)) {
styleName = jrStyle.getName() + styleCount;
styleCount++;
}
context.allStyles.add(styleName);
Name name = context.objectFactory.createStyleName();
name.setVal(styleName);
ctStyle.setName(name);
ctStyle.setStyleId(styleName);
if (!styleName.equals(jrStyle.getName())) {
Aliases aliases = context.objectFactory.createStyleAliases();
aliases.setVal(jrStyle.getName());
ctStyle.setAliases(aliases);
}
ctStyle.setType("paragraph");
ctStyle.setQFormat(ctOnOff_ON);
}
// Default run settings
RPr ctrPr = ctStyle.getRPr();
if (ctrPr == null) {
ctrPr = context.objectFactory.createRPr();
ctStyle.setRPr(ctrPr);
}
// Default paragraph settings
PPr ctpPr = ctStyle.getPPr();
if (ctpPr == null) {
ctpPr = context.objectFactory.createPPr();
ctStyle.setPPr(ctpPr);
}
// Bold
if (jrStyle.isOwnBold() != null)
ctrPr.setB(jrStyle.isOwnBold() ? ctOnOff_ON : ctOnOff_OFF);
// Italic
if (jrStyle.isOwnItalic() != null)
ctrPr.setI(jrStyle.isOwnItalic() ? ctOnOff_ON : ctOnOff_OFF);
// Underline
if (jrStyle.isOwnUnderline() != null && jrStyle.isOwnUnderline()) {
U ctUnderline = context.objectFactory.createU();
if (linePen == null) {
ctUnderline.setVal(UnderlineEnumeration.SINGLE);
if (jrStyle.getForecolor() != null)
ctUnderline.setColor(colorToStringFormat(jrStyle.getForecolor()));
else
ctUnderline.setColor(COLOR_AUTO);
}
else {
if (linePen.getOwnLineStyleValue() != null) {
switch (linePen.getOwnLineStyleValue()) {
case SOLID:
ctUnderline.setVal(UnderlineEnumeration.SINGLE);
break;
case DASHED:
ctUnderline.setVal(UnderlineEnumeration.DASH);
break;
case DOTTED:
ctUnderline.setVal(UnderlineEnumeration.DOTTED);
break;
case DOUBLE:
ctUnderline.setVal(UnderlineEnumeration.DOUBLE);
break;
default:
ctUnderline.setVal(UnderlineEnumeration.SINGLE);
break;
}
}
else
ctUnderline.setVal(UnderlineEnumeration.SINGLE);
if (linePen.getLineColor() != null)
ctUnderline.setColor(colorToStringFormat(linePen.getLineColor()));
else if (jrStyle.getForecolor() != null)
ctUnderline.setColor(colorToStringFormat(jrStyle.getForecolor()));
else
ctUnderline.setColor(colorToStringFormat(Color.black));
}
ctrPr.setU(ctUnderline);
}
// Strike Through
if (jrStyle.isOwnStrikeThrough() != null)
ctrPr.setStrike(jrStyle.isOwnStrikeThrough()? ctOnOff_ON : ctOnOff_OFF);
// Fore color
org.docx4j.wml.Color foreColor = context.objectFactory.createColor();
if (jrStyle.getOwnForecolor() != null)
foreColor.setVal(colorToStringFormat(jrStyle.getOwnForecolor()));
else
foreColor.setVal(COLOR_AUTO);
ctrPr.setColor(foreColor);
// Background / Highlight
CTShd shdp = context.objectFactory.createCTShd();
shdp.setVal(STShd.CLEAR);
if (jrStyle.getOwnBackcolor() != null)
shdp.setFill(colorToStringFormat(jrStyle.getOwnBackcolor()));
else
shdp.setFill(COLOR_AUTO);
if (jrStyle.getOwnBackcolor() != null || !update)
ctpPr.setShd(shdp);
// Text alignment
org.docx4j.wml.PPrBase.TextAlignment alignment = context.objectFactory.createPPrBaseTextAlignment();
if (jrStyle.getOwnVerticalAlignmentValue() != null) {
switch (jrStyle.getOwnVerticalAlignmentValue()) {
case TOP:
alignment.setVal("top");
break;
case MIDDLE:
alignment.setVal("center");
break;
case BOTTOM:
alignment.setVal("bottom");
break;
case JUSTIFIED:
alignment.setVal("baseline");
break;
default:
alignment.setVal("auto");
break;
}
}
else
alignment.setVal("auto");
ctpPr.setTextAlignment(alignment);
if (jrStyle.getOwnHorizontalAlignmentValue() != null) {
Jc ctJc = context.objectFactory.createJc();
ctpPr.setJc(ctJc);
switch (jrStyle.getOwnHorizontalAlignmentValue()) {
case LEFT:
ctJc.setVal(JcEnumeration.LEFT);
break;
case CENTER:
ctJc.setVal(JcEnumeration.CENTER);
break;
case RIGHT:
ctJc.setVal(JcEnumeration.RIGHT);
break;
case JUSTIFIED:
ctJc.setVal(JcEnumeration.BOTH);
break;
default:
ctJc.setVal(JcEnumeration.LEFT);
break;
}
}
// Font
if (jrStyle.getOwnFontName() != null) {
RFonts ctFonts = context.objectFactory.createRFonts();
ctrPr.setRFonts(ctFonts);
ctFonts.setAscii(jrStyle.getOwnFontName());
ctFonts.setHAnsi(jrStyle.getOwnFontName());
}
if (jrStyle.getOwnFontsize() != null) {
HpsMeasure ctHpsMeasure = context.objectFactory.createHpsMeasure();
ctHpsMeasure.setVal(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.HALF_POINTS, jrStyle.getOwnFontsize()));
ctrPr.setSz(ctHpsMeasure);
}
// Paragraph advanced settings
JRParagraph paragraph = jrStyle.getParagraph();
if (paragraph != null) {
Ind ctInd = ctpPr.getInd();
if (ctInd == null) {
ctInd = context.objectFactory.createPPrBaseInd();
ctpPr.setInd(ctInd);
}
if (paragraph.getOwnFirstLineIndent() != null)
ctInd.setFirstLine(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, paragraph.getOwnFirstLineIndent()));
if (paragraph.getOwnLeftIndent() != null)
ctInd.setLeft(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, paragraph.getOwnLeftIndent()));
if (paragraph.getOwnRightIndent() != null)
ctInd.setRight(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, paragraph.getOwnRightIndent()));
ctpPr.setSpacing(buildParagraphSpacing(paragraph, ctpPr.getSpacing(), context, update));
}
if (jrStyle.getStyle() != null && ctStyle.getBasedOn() == null) {
BasedOn basedOn = context.objectFactory.createStyleBasedOn();
basedOn.setVal(jrStyle.getStyle().getName());
ctStyle.setBasedOn(basedOn);
}
return styleName;
}
/**
* Build all the jaspser styles.
* @param context The visitor context.
* @param stylesList The jasper styles.
*/
private static void buildStyles(J2WDocx4jPrintElementVisitorContext context, java.util.List stylesList) {
if (!stylesList.isEmpty()) {
StyleDefinitionsPart stylesPart = buildStylePart(context, true);
Styles styles;
try {
styles = stylesPart.getContents();
} catch (Docx4JException e) {
throw new JRRuntimeException(e);
}
for (JRStyle jrStyle : stylesList) {
Style ctStyle = context.objectFactory.createStyle();
String styleName = updateStyle(ctStyle, jrStyle, context, false);
styles.getStyle().add(ctStyle);
context.remapStylesNameByJrStyle.put(jrStyle.getName(), styleName);
}
}
}
/**
* Utility method: return {@code valOverride} if {@code useOverriding} is {@code true} and {@code valOverride} is not {@code null};
* return {@code vale} otherwise.
* @param val The default value.
* @param valOverride The overriding value.
* @param useOverriding {@code} true to use {@code valOverride}, {@code false} to use {@code val}.
* @param Type of value.
* @return {@code valOverride} if {@code useOverriding} is {@code true} and {@code valOverride} is not {@code null};
* return {@code vale} otherwise.
*/
static T getOverridingValue(T val, T valOverride, boolean useOverriding) {
if (useOverriding)
return valOverride != null? valOverride : val;
else
return val;
}
/**
* Set paragraph spacing: before, after and line spacing.
* @param paragraph The jasper paragraph.
* @param from The input/output spacing object (can be {@code null}).
* @param context The visitor context.
* @param useOverriding {@code true} to use paragraph own spacing , {@code false} otherwise.
* @return The spacing object.
* @see #getOverridingValue(Object, Object, boolean)
*/
static Spacing buildParagraphSpacing(JRParagraph paragraph, Spacing from, J2WDocx4jPrintElementVisitorContext context, boolean useOverriding) {
boolean setSpacing = false;
Spacing ctSpacing = from;
if (ctSpacing == null)
ctSpacing = context.objectFactory.createPPrBaseSpacing();
else
setSpacing = true;
Integer spacingAfter = getOverridingValue(paragraph.getSpacingAfter(), paragraph.getOwnSpacingAfter(), useOverriding);
if (spacingAfter != null) {
ctSpacing.setAfter(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, spacingAfter));
setSpacing = true;
}
else if (paragraph.getStyle() == null && useOverriding) {
ctSpacing.setAfter(BigInteger.ZERO);
ctSpacing.setAfterLines(BigInteger.ZERO);
setSpacing = true;
}
Integer spacingBefore = getOverridingValue(paragraph.getSpacingBefore(), paragraph.getOwnSpacingBefore(), useOverriding);
if (spacingBefore != null) {
ctSpacing.setBefore(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, spacingBefore));
setSpacing = true;
}
else if (paragraph.getStyle() == null && useOverriding) {
ctSpacing.setBefore(BigInteger.ZERO);
ctSpacing.setBeforeLines(BigInteger.ZERO);
setSpacing = true;
}
LineSpacingEnum lineSpacingEnum = getOverridingValue(paragraph.getLineSpacing(), paragraph.getOwnLineSpacing(), useOverriding);
if (lineSpacingEnum != null) {
Float lineSpacingSize = getOverridingValue(paragraph.getLineSpacingSize(), paragraph.getOwnLineSpacingSize(), useOverriding);
switch (lineSpacingEnum) {
case SINGLE:
ctSpacing.setLineRule(STLineSpacingRule.AUTO);
ctSpacing.setLine(EConvertMisure.toLineSpacing(null, 1D));
break;
case ONE_AND_HALF:
ctSpacing.setLineRule(STLineSpacingRule.AUTO);
ctSpacing.setLine(EConvertMisure.toLineSpacing(null, 1.5D));
break;
case DOUBLE:
ctSpacing.setLineRule(STLineSpacingRule.AUTO);
ctSpacing.setLine(EConvertMisure.toLineSpacing(null, 2D));
break;
case AT_LEAST:
ctSpacing.setLineRule(STLineSpacingRule.AT_LEAST);
if (lineSpacingSize != null)
ctSpacing.setLine(EConvertMisure.toLineSpacing(lineSpacingSize.doubleValue(), 1D));
else
ctSpacing.setLine(EConvertMisure.toLineSpacing(null, 1D));
break;
case FIXED:
ctSpacing.setLineRule(STLineSpacingRule.EXACT);
if (lineSpacingSize != null)
ctSpacing.setLine(EConvertMisure.toLineSpacing(lineSpacingSize.doubleValue(), 1D));
else
ctSpacing.setLine(EConvertMisure.toLineSpacing(null, 1D));
break;
case PROPORTIONAL:
ctSpacing.setLineRule(STLineSpacingRule.AUTO);
if (lineSpacingSize != null)
ctSpacing.setLine(EConvertMisure.toLineSpacing(lineSpacingSize.doubleValue(), 1D));
else
ctSpacing.setLine(EConvertMisure.toLineSpacing(null, 1D));
break;
}
setSpacing = true;
}
if (setSpacing)
return ctSpacing;
else
return null;
}
/**
* Set paragraph margins (left and right).
* @param paragraph The doc paragraph.
* @param x The left margin.
* @param width The paragraph width.
* @param context The visitor context.
*/
static void setParagraphMargins(P paragraph, Integer x, Integer width, J2WDocx4jPrintElementVisitorContext context) {
if (x != null && width != null) {
PPr pPr = paragraph.getPPr();
if (pPr == null) {
pPr = context.objectFactory.createPPr();
paragraph.setPPr(pPr);
}
Ind ind = pPr.getInd();
if (ind == null) {
ind = context.objectFactory.createPPrBaseInd();
pPr.setInd(ind);
}
HeaderFooterPageInfo pageInfo = context.getLayout().getPageInfo();
ind.setLeft(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, x));
ind.setRight(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, pageInfo.getPageSize().width - pageInfo.getRightMargin() - pageInfo.getLeftMargin() - x - width));
context.setLastParagraphX(x);
context.setLastParagraphWidth(width);
}
}
/**
* Set the paragraph borders.
* @param paragraph The doc baragraph.
* @param element The box element container with border infos.
* @param context The visitor context.
*/
static void setParagraphBorders(P paragraph, JRBoxContainer element, J2WDocx4jPrintElementVisitorContext context) {
if (element != null) {
JRLineBox lineBox = element.getLineBox();
if (lineBox != null) {
PPr pPr = paragraph.getPPr();
if (pPr == null) {
pPr = context.objectFactory.createPPr();
paragraph.setPPr(pPr);
}
PBdr pBdr = pPr.getPBdr();
if (pBdr == null) {
pBdr = context.objectFactory.createPPrBasePBdr();
pPr.setPBdr(pBdr);
}
pBdr.setBottom(buildBorder(lineBox.getBottomPen(), context));
pBdr.setTop(buildBorder(lineBox.getTopPen(), context));
pBdr.setRight(buildBorder(lineBox.getRightPen(), context));
pBdr.setLeft(buildBorder(lineBox.getLeftPen(), context));
}
}
}
/**
* Set table cell borders.
* @param cell A doc table cell.
* @param element The box element container with border infos.
* @param context The visitor context.
*/
static void setTableCellBorders(Tc cell, JRBoxContainer element, J2WDocx4jPrintElementVisitorContext context) {
if (element != null) {
JRLineBox lineBox = element.getLineBox();
if (lineBox != null) {
lineBox.getBottomPen();
TcPr tcPr = cell.getTcPr();
if (tcPr == null) {
tcPr = context.objectFactory.createTcPr();
cell.setTcPr(tcPr);
}
TcBorders tcBorders = tcPr.getTcBorders();
if (tcBorders == null) {
tcBorders = context.objectFactory.createTcPrInnerTcBorders();
tcPr.setTcBorders(tcBorders);
}
tcBorders.setBottom(buildBorder(lineBox.getBottomPen(), context));
tcBorders.setTop(buildBorder(lineBox.getTopPen(), context));
tcBorders.setRight(buildBorder(lineBox.getRightPen(), context));
tcBorders.setLeft(buildBorder(lineBox.getLeftPen(), context));
}
}
}
/**
* Build a single edge for a cell.
* @param pen The border style.
* @param context The visitor context.
* @return The border for cell.
*/
static CTBorder buildBorder(JRBoxPen pen, J2WDocx4jPrintElementVisitorContext context) {
if (pen == null || pen.getLineWidth() == 0f)
return null;
else {
CTBorder ctBorder = context.objectFactory.createCTBorder();
ctBorder.setColor(colorToStringFormat(pen.getPen(pen.getBox()).getLineColor()));
ctBorder.setSz(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.POINTS, pen.getLineWidth()));
switch (pen.getLineStyleValue()) {
case SOLID:
ctBorder.setVal(STBorder.SINGLE);
break;
case DASHED:
ctBorder.setVal(STBorder.DASHED);
break;
case DOTTED:
ctBorder.setVal(STBorder.DOTTED);
break;
case DOUBLE:
ctBorder.setVal(STBorder.DOUBLE);
break;
default:
ctBorder.setVal(STBorder.SINGLE);
break;
}
ctBorder.setColor(colorToStringFormat(pen.getLineColor()));
return ctBorder;
}
}
/**
* Print visitor context. This class improves the base visitor context with extra information useful to build the output document,
* like jaxb object factories, table infos, styles, etc...
*/
static class J2WDocx4jPrintElementVisitorContext extends J2WAbstractPrintElementVisitorContext {
/** Reports build till now */
private int reportCount;
/** Table infos */
private Map tables;
/** Remapped style name in document */
private Map remapStylesNameByJrStyle;
/** Built style's name */
private final Set allStyles;
/** The current header */
private Hdr headerContent;
/** The current footer */
private Ftr footerContent;
/** The current section */
private SectPr currentSection;
/** The paragraph of the current section */
private P sectionParagraph;
/** General jaxb object factory */
private final org.docx4j.wml.ObjectFactory objectFactory;
/** Pic jaxb object factory */
private final org.docx4j.vml.ObjectFactory picObjectFactory;
/** Drawing jaxb object factory */
private final org.docx4j.dml.ObjectFactory drawingObjectFactory;
/**
* Construct the context.
*/
public J2WDocx4jPrintElementVisitorContext() {
this.reportCount = 0;
this.allStyles = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
this.objectFactory = Context.getWmlObjectFactory();
this.picObjectFactory = new org.docx4j.vml.ObjectFactory();
this.drawingObjectFactory = new org.docx4j.dml.ObjectFactory();
}
/**
* Reset the document status (reset remapped style's name).
*/
private void resetDocumentStatus() {
this.remapStylesNameByJrStyle = new TreeMap<>();
}
/**
* Reset the page status (tables end last docx element).
*/
public void resetPageStatus() {
this.tables = new TreeMap<>();
this.setLastDocxElement(null);
}
}
/**
* A table informations.
*/
private static class TableDocInfo {
/** Docx table */
private final Tbl table;
/**
* Construct a table info with a docx table,
* @param table The docx table.
*/
public TableDocInfo(Tbl table) {
this.table = table;
}
}
/**
* Comparator that sorts Point from bottom to top and from right to left.
*/
private static class CellToRemovePointComparator implements Comparator {
/** Constructor */
private CellToRemovePointComparator() {
}
@Override
public int compare(Point o1, Point o2) {
if (o1.y > o2.y)
return 1;
else if (o1.y < o2.y)
return -1;
else if (o1.x > o2.x)
return -1;
else if (o1.x < o2.x)
return 1;
else
return 0;
}
}
/**
* Docx4j print element visitor. This class can "visit" every jasper report element and draw it in the
* output document.
*/
protected static class J2WDocxPrintElementVisitor implements PrintElementVisitor {
/** Attribute styled text selector (all attributes) */
protected JRStyledTextAttributeSelector allSelector;
/** Jasper context */
protected JasperReportsContext jasperReportsContext;
/**
* Construct a visitor context.
* @param allSelector The attribute selector.
* @param jasperReportsContext The jasper context.
*/
public J2WDocxPrintElementVisitor(JRStyledTextAttributeSelector allSelector, JasperReportsContext jasperReportsContext) {
this.allSelector = allSelector;
this.jasperReportsContext = jasperReportsContext;
}
/**
* Search or create the output paragraph for the current element to visit.
* @param compPosition The element position.
* @param container The element container.
* @param arg The visitor context.
* @param createParagraph {@code true} to create the missing paragraph.
* @return The paragraph for the element (both free paragraphs and table cell paragraphs).
*/
protected FoundDocParagraph findParagraph(ComponentPosition compPosition, JRBoxContainer container, J2WDocx4jPrintElementVisitorContext arg, boolean createParagraph) {
P paragraph = null;
FoundDocParagraph parent = null;
if (compPosition.getParent() != null)
parent = this.findParagraph(compPosition.getParent(), container, arg, false);
Tc cell = null;
// For element in table cell
if (compPosition instanceof ComponentPositionInTable) {
ComponentPositionInTable position = (ComponentPositionInTable) compPosition;
TableDocInfo tableDocInfo = buildTables(position, arg);
Tbl xwpfTable = tableDocInfo.table;
Tr row = (Tr) xwpfTable.getContent().get(position.getRow());
cell = (Tc) row.getContent().get(position.getCol());
if (cell.getContent().isEmpty()) {
paragraph = arg.objectFactory.createP();
cell.getContent().add(paragraph);
}
else
paragraph = (P) cell.getContent().get(0);
TcPr tcPr = cell.getTcPr();
if (tcPr == null) {
tcPr = arg.objectFactory.createTcPr();
cell.setTcPr(tcPr);
}
// Background
CTShd ctShd = arg.objectFactory.createCTShd();
ctShd.setFill(COLOR_AUTO);
ctShd.setVal(STShd.CLEAR);
tcPr.setShd(ctShd);
CTVerticalJc ctVerticalJc = arg.objectFactory.createCTVerticalJc();
ctVerticalJc.setVal(STVerticalJc.CENTER);
tcPr.setVAlign(ctVerticalJc);
if (container != null) {
setTableCellBorders(cell, container, arg);
JRLineBox lineBox = container.getLineBox();
if (lineBox != null) {
TcMar ctTcMar = tcPr.getTcMar();
if (ctTcMar == null) {
ctTcMar = arg.objectFactory.createTcMar();
tcPr.setTcMar(ctTcMar);
}
TblWidth b = arg.objectFactory.createTblWidth();
TblWidth t = arg.objectFactory.createTblWidth();
TblWidth l = arg.objectFactory.createTblWidth();
TblWidth r = arg.objectFactory.createTblWidth();
b.setType(TblWidth.TYPE_DXA);
t.setType(TblWidth.TYPE_DXA);
l.setType(TblWidth.TYPE_DXA);
r.setType(TblWidth.TYPE_DXA);
if (lineBox.getBottomPadding() != null)
b.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, lineBox.getBottomPadding()));
else
b = null;
if (lineBox.getTopPadding() != null)
t.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, lineBox.getTopPadding()));
else
t = null;
if (lineBox.getLeftPadding() != null)
l.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, lineBox.getLeftPadding()));
else
l = null;
if (lineBox.getRightPadding() != null)
r.setW(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, lineBox.getRightPadding()));
else
r = null;
ctTcMar.setBottom(b);
ctTcMar.setTop(t);
ctTcMar.setLeft(l);
ctTcMar.setRight(r);
}
}
}
if (paragraph == null && parent != null)
paragraph = parent.getParagraph();
if (paragraph == null && createParagraph) {
// Add the new paragraph in the document
paragraph = arg.objectFactory.createP();
if (compPosition.getDocumentPart() == DocxDocumentPart.HEADER)
arg.headerContent.getContent().add(paragraph);
else if (compPosition.getDocumentPart() == DocxDocumentPart.FOOTER)
arg.footerContent.getContent().add(paragraph);
else
arg.getDocument().getMainDocumentPart().getContent().add(paragraph);
}
if (paragraph != null) {
if (container != null && cell == null)
setParagraphBorders(paragraph, container, arg);
PPr pPr = paragraph.getPPr();
if (pPr == null) {
pPr = arg.objectFactory.createPPr();
paragraph.setPPr(pPr);
}
ParaRPr rPr = pPr.getRPr();
if (rPr == null) {
rPr = arg.objectFactory.createParaRPr();
pPr.setRPr(rPr);
}
if (container != null && container.getStyle() != null) {
PStyle pStyle = arg.objectFactory.createPPrBasePStyle();
pStyle.setVal(arg.remapStylesNameByJrStyle.get(container.getStyle().getName()));
pPr.setPStyle(pStyle);
}
if (cell == null) {
int leftPadding = 0;
int rightPadding = 0;
if (container != null && container.getLineBox() != null) {
JRLineBox lineBox = container.getLineBox();
if (lineBox.getLeftPadding() != null)
leftPadding = lineBox.getLeftPadding();
if (lineBox.getRightPadding() != null)
rightPadding = lineBox.getRightPadding();
}
setParagraphMargins(paragraph, compPosition.getX(), compPosition.getWidth() - rightPadding - leftPadding, arg);
}
}
int pIndex = -1;
if (paragraph != null && cell == null) {
if (compPosition.getDocumentPart() == DocxDocumentPart.HEADER)
pIndex = arg.headerContent.getContent().size() - 1;
else if (compPosition.getDocumentPart() == DocxDocumentPart.FOOTER)
pIndex = arg.footerContent.getContent().size() - 1;
else
pIndex = arg.getDocument().getMainDocumentPart().getContent().size() - 1;
}
return new FoundDocParagraph(cell, paragraph, pIndex);
}
public void visit(JRPrintText textElement, J2WDocx4jPrintElementVisitorContext arg) {
ComponentPosition compPosition = arg.getLayout().getElementPosition(textElement);
FoundDocParagraph foundDocParagraph = this.findParagraph(compPosition, textElement, arg, true);
P paragraph = foundDocParagraph.getParagraph();
boolean setInd = false;
boolean setPPr = false;
int pCount = 0;
PPr pPr = paragraph.getPPr();
if (pPr == null)
pPr = arg.objectFactory.createPPr();
Ind ind = pPr.getInd();
if (ind == null)
ind = arg.objectFactory.createPPrBaseInd();
Spacing spacing = buildParagraphSpacing(textElement.getParagraph(), pPr.getSpacing(), arg, true);
if (textElement.getOwnHorizontalAlignmentValue() != null) {
Jc jc = arg.objectFactory.createJc();
pPr.setJc(jc);
switch (textElement.getOwnHorizontalAlignmentValue()) {
case LEFT:
jc.setVal(JcEnumeration.LEFT);
break;
case CENTER:
jc.setVal(JcEnumeration.CENTER);
break;
case RIGHT:
jc.setVal(JcEnumeration.RIGHT);
break;
case JUSTIFIED:
jc.setVal(JcEnumeration.BOTH);
break;
}
setPPr = true;
}
if (textElement.getOwnVerticalAlignmentValue() != null) {
PPrBase.TextAlignment alignment = arg.objectFactory.createPPrBaseTextAlignment();
pPr.setTextAlignment(alignment);
switch (textElement.getOwnVerticalAlignmentValue()) {
case TOP:
alignment.setVal("top");
break;
case MIDDLE:
alignment.setVal("center");
break;
case BOTTOM:
alignment.setVal("bottom");
break;
case JUSTIFIED:
alignment.setVal("auto");
break;
}
setPPr = true;
}
JRParagraph jrParagraph = textElement.getParagraph();
if (jrParagraph.getOwnFirstLineIndent() != null) {
ind.setFirstLine(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, jrParagraph.getOwnFirstLineIndent()));
setInd = true;
}
if (jrParagraph.getOwnLeftIndent() != null) {
ind.setLeft(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, jrParagraph.getOwnLeftIndent()));
setInd = true;
}
if (jrParagraph.getOwnRightIndent() != null) {
ind.setRight(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, jrParagraph.getOwnRightIndent()));
setInd = true;
}
if (textElement.getOwnBackcolor() != null) {
CTShd shd = pPr.getShd();
if (shd == null) {
shd = arg.objectFactory.createCTShd();
pPr.setShd(shd);
}
shd.setFill(colorToStringFormat(textElement.getOwnBackcolor()));
shd.setVal(STShd.CLEAR);
setPPr = true;
}
if (setPPr || setInd || spacing != null)
paragraph.setPPr(pPr);
if (setInd)
pPr.setInd(ind);
pPr.setSpacing(spacing);
JRStyledText styledText = textElement.getFullStyledText(allSelector);
String fullText = styledText.getText();
AttributedCharacterIterator iterator = styledText.getAttributedString().getIterator();
int runLimit = 0;
boolean lastNewLine = false;
while(runLimit < styledText.length() && (runLimit = iterator.getRunLimit()) <= styledText.length()) {
R docRun = arg.objectFactory.createR();
paragraph.getContent().add(docRun);
this.setRunFontStyle(docRun, textElement, iterator.getAttributes(), arg);
String value = fullText.substring(iterator.getIndex(), runLimit);
StringTokenizer tkzer = new StringTokenizer(value, "\n", true);
while(tkzer.hasMoreTokens()) {
String token = tkzer.nextToken();
boolean isNewLine = "\n".equals(token);
if (lastNewLine || isNewLine) {
if (tkzer.hasMoreTokens()) {
P newParagraph = arg.objectFactory.createP();
pCount++;
if (foundDocParagraph.isTableCell())
foundDocParagraph.getCell().getContent().add(newParagraph);
else {
if (compPosition.getDocumentPart() == DocxDocumentPart.HEADER)
arg.headerContent.getContent().add(newParagraph);
else if (compPosition.getDocumentPart() == DocxDocumentPart.FOOTER)
arg.footerContent.getContent().add(newParagraph);
else
arg.getDocument().getMainDocumentPart().getContent().add(newParagraph);
}
PPr newPPr = this.cloneParagraphProperties(arg, pPr);
if (pPr.getSpacing() != null)
pPr.getSpacing().setAfter(BigInteger.ZERO);
if (newPPr.getSpacing() != null)
newPPr.getSpacing().setBefore(BigInteger.ZERO);
newParagraph.setPPr(newPPr);
paragraph = newParagraph;
docRun = arg.objectFactory.createR();
paragraph.getContent().add(docRun);
this.setRunFontStyle(docRun, textElement, iterator.getAttributes(), arg);
lastNewLine = false;
}
else
lastNewLine = true;
}
if (!isNewLine) {
Text text = arg.objectFactory.createText();
text.setValue(token);
text.setSpace("preserve");
docRun.getContent().add(text);
}
}
iterator.setIndex(runLimit);
}
if (!foundDocParagraph.isTableCell()) {
float textHeight = textElement.getTextHeight();
int realHeight = 0;
int topMargin = 0;
if (jrParagraph.getSpacingAfter() != null)
realHeight += jrParagraph.getSpacingAfter();
if (jrParagraph.getSpacingBefore() != null) {
realHeight += jrParagraph.getSpacingBefore();
topMargin = jrParagraph.getSpacingBefore();
}
JRLineBox lineBox = textElement.getLineBox();
if (lineBox != null) {
if (lineBox.getBottomPadding() != null)
realHeight += lineBox.getBottomPadding();
if (lineBox.getTopPadding() != null)
realHeight += lineBox.getTopPadding();
}
realHeight += textHeight; // EConvertMisure.HALF_POINTS.convertInto(EConvertMisure.POINTS, textHeight);
StyleDefinitionsPart stylePart = buildStylePart(arg, false);
Style style = stylePart.getStyleById("Normal");
int defaultFontSize = 12;
String defaultFontName = "Times New Roman";
if (style != null && style.getPPr() != null && style.getPPr().getRPr() != null) {
ParaRPr defaultRPr = style.getPPr().getRPr();
if (defaultRPr.getRFonts() != null && defaultRPr.getRFonts().getAscii() != null)
defaultFontName = defaultRPr.getRFonts().getAscii();
if (defaultRPr.getSz() != null && defaultRPr.getSz().getVal() != null)
defaultFontSize = (int) EConvertMisure.HALF_POINTS.convertInto(EConvertMisure.POINTS, defaultRPr.getSz().getVal().doubleValue());
}
Font newLineFont = new Font(defaultFontName, Font.PLAIN, defaultFontSize);
LineMetrics lineMetrics = newLineFont.getLineMetrics("\n", new FontRenderContext(null, false, true));
if (realHeight < compPosition.getHeight()) {
int gap = compPosition.getHeight() - realHeight;
int newLines;
if (arg.getConfiguration().getSpacingPolicy() == ESpacingPolicy.EDITABLE)
newLines = (int) (gap / lineMetrics.getHeight());
else
newLines = 0;
gap -= (newLines * defaultFontSize);
if (gap > defaultFontSize) {
Spacing spacingLast = paragraph.getPPr().getSpacing();
if (spacingLast == null) {
spacingLast = arg.objectFactory.createPPrBaseSpacing();
paragraph.getPPr().setSpacing(spacingLast);
}
Spacing spacingFirst = foundDocParagraph.getParagraph().getPPr().getSpacing();
if (spacingFirst == null) {
spacingFirst = arg.objectFactory.createPPrBaseSpacing();
foundDocParagraph.getParagraph().getPPr().setSpacing(spacingFirst);
}
BigInteger bigGap = EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, gap);
VerticalAlignEnum alignmentValue = textElement.getVerticalAlignmentValue();
if (alignmentValue == null)
alignmentValue = VerticalAlignEnum.JUSTIFIED;
switch (alignmentValue) {
case TOP:
spacingLast.setAfter(spacingLast.getAfter() != null ? spacingLast.getAfter().add(bigGap) : bigGap);
break;
case MIDDLE:
case JUSTIFIED: {
bigGap = bigGap.divide(BigInteger.valueOf(2));
spacingLast.setAfter(spacingLast.getAfter() != null ? spacingLast.getAfter().add(bigGap) : bigGap);
spacingFirst.setBefore(spacingFirst.getBefore() != null ? spacingFirst.getBefore().add(bigGap) : bigGap);
}
break;
case BOTTOM:
spacingFirst.setBefore(spacingFirst.getBefore() != null ? spacingFirst.getBefore().add(bigGap) : bigGap);
break;
}
}
this.createBeforeNewLinesParagraphs(arg, newLines, defaultFontSize, defaultFontName, foundDocParagraph.getParagraphIndexInDoc() + pCount + 1, compPosition.getDocumentPart());
}
if (arg.getLastY(compPosition.getDocumentPart()) < compPosition.getY()) {
int gap = compPosition.getY() - arg.getLastY(compPosition.getDocumentPart());
int newLines;
if (arg.getConfiguration().getSpacingPolicy() == ESpacingPolicy.EDITABLE)
newLines = (int) (gap / lineMetrics.getHeight());
else
newLines = 0;
gap -= (newLines * defaultFontSize);
if (gap > 0) {
Spacing spacingFirst = foundDocParagraph.getParagraph().getPPr().getSpacing();
if (spacingFirst == null) {
spacingFirst = arg.objectFactory.createPPrBaseSpacing();
foundDocParagraph.getParagraph().getPPr().setSpacing(spacingFirst);
}
BigInteger bigGap = EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, gap + topMargin);
spacingFirst.setBefore(spacingFirst.getBefore() != null? spacingFirst.getBefore().add(bigGap) : bigGap);
}
this.createBeforeNewLinesParagraphs(arg, newLines, defaultFontSize, defaultFontName, foundDocParagraph.getParagraphIndexInDoc(), compPosition.getDocumentPart());
}
arg.setLastY(compPosition.getDocumentPart(), compPosition.getY() + compPosition.getHeight());
arg.setLastDocxElement(LastDocxElement.TEXT_PARAGRAPH);
}
}
/**
* Add many paragraphs those indicated in {@code newLines}.
* @param arg The visitor context.
* @param newLines How many lines to add.
* @param defaultFontSize The font size.
* @param defaultFontName The font name.
* @param startIndex The index in the document objects list.
* @param part The document part.
*/
protected void createBeforeNewLinesParagraphs(J2WDocx4jPrintElementVisitorContext arg, int newLines, int defaultFontSize,
String defaultFontName, int startIndex, DocxDocumentPart part) {
for (int i = 0; i < newLines; i++) {
P newLineP = arg.objectFactory.createP();
PPr pPr = arg.objectFactory.createPPr();
pPr.setRPr(arg.objectFactory.createParaRPr());
HpsMeasure hpsMeasure = arg.objectFactory.createHpsMeasure();
hpsMeasure.setVal(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.HALF_POINTS, defaultFontSize));
pPr.getRPr().setSz(hpsMeasure);
pPr.getRPr().setRFonts(arg.objectFactory.createRFonts());
pPr.getRPr().getRFonts().setAscii(defaultFontName);
Spacing spacing = arg.objectFactory.createPPrBaseSpacing();
spacing.setAfter(BigInteger.ZERO);
spacing.setBefore(BigInteger.ZERO);
spacing.setBeforeLines(BigInteger.ZERO);
spacing.setLine(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, defaultFontSize));
spacing.setLineRule(STLineSpacingRule.EXACT);
pPr.setSpacing(spacing);
setParagraphMargins(newLineP, arg.getLastParagraphX(), arg.getLastParagraphWidth(), arg);
newLineP.setPPr(pPr);
R newLineR = arg.objectFactory.createR();
newLineR.setRPr(arg.objectFactory.createRPr());
Text text = arg.objectFactory.createText();
text.setSpace("preserve");
text.setValue("");
newLineR.getContent().add(text);
newLineP.getContent().add(newLineR);
List content;
switch (part) {
case HEADER:
content = arg.headerContent.getContent();
break;
case FOOTER:
content = arg.footerContent.getContent();
break;
default:
case BODY:
content = arg.getDocument().getMainDocumentPart().getContent();
break;
}
content.add(startIndex, newLineP);
}
}
/**
* Clone paragraphs properties.
* @param arg The visitor context.
* @param pPr The source paragraph properties.
* @return Return a clone of the {@code pPr} properties.
*/
protected PPr cloneParagraphProperties(J2WDocx4jPrintElementVisitorContext arg, PPr pPr) {
Spacing spacing = pPr.getSpacing();
PPr newPPr = arg.objectFactory.createPPr();
newPPr.setInd(pPr.getInd());
newPPr.setJc(pPr.getJc());
newPPr.setPBdr(pPr.getPBdr());
newPPr.setPStyle(pPr.getPStyle());
newPPr.setRPr(pPr.getRPr());
newPPr.setShd(pPr.getShd());
if (spacing != null) {
Spacing newSpacing = arg.objectFactory.createPPrBaseSpacing();
newSpacing.setAfter(spacing.getAfter());
newSpacing.setAfterAutospacing(spacing.isAfterAutospacing());
newSpacing.setAfterLines(spacing.getAfterLines());
newSpacing.setBefore(spacing.getBefore());
newSpacing.setBeforeAutospacing(spacing.isBeforeAutospacing());
newSpacing.setBeforeLines(spacing.getBeforeLines());
newSpacing.setLine(spacing.getLine());
newSpacing.setLineRule(spacing.getLineRule());
newPPr.setSpacing(newSpacing);
}
newPPr.setTextAlignment(pPr.getTextAlignment());
newPPr.setTextDirection(pPr.getTextDirection());
return newPPr;
}
/**
* Set the run (a text block in a paragraph) properties (font, size, colors, etc.)
* @param docRun The document run.
* @param textElement The jasper text element.
* @param attributes The global jasper text element attributes.
* @param arg The visitor context.
*/
protected void setRunFontStyle(R docRun, JRPrintText textElement, Map attributes, J2WDocx4jPrintElementVisitorContext arg) {
String styleName = textElement.getStyle() != null? textElement.getStyle().getName() : null;
boolean setRPr = false;
RPr ctrPr = docRun.getRPr();
if (ctrPr == null)
ctrPr = arg.objectFactory.createRPr();
if (textElement.isOwnBold() != null) {
BooleanDefaultTrue value = arg.objectFactory.createBooleanDefaultTrue();
value.setVal(textElement.isOwnBold());
ctrPr.setB(value);
setRPr = true;
}
if (textElement.getOwnForecolor() != null) {
org.docx4j.wml.Color color = arg.objectFactory.createColor();
color.setVal(colorToStringFormat(textElement.getOwnForecolor()));
ctrPr.setColor(color);
setRPr = true;
}
if (textElement.getOwnFontName() != null) {
RFonts rFonts = ctrPr.getRFonts();
if (rFonts == null) {
rFonts = arg.objectFactory.createRFonts();
ctrPr.setRFonts(rFonts);
}
rFonts.setAscii(textElement.getOwnFontName());
rFonts.setHAnsi(textElement.getOwnFontName());
setRPr = true;
}
if (textElement.getOwnFontsize() != null) {
HpsMeasure sz = ctrPr.getSz();
if (sz == null) {
sz = arg.objectFactory.createHpsMeasure();
ctrPr.setSz(sz);
}
sz.setVal(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.HALF_POINTS, textElement.getOwnFontsize()));
setRPr = true;
}
if (textElement.isOwnItalic() != null) {
BooleanDefaultTrue i = arg.objectFactory.createBooleanDefaultTrue();
ctrPr.setI(i);
i.setVal(textElement.isOwnItalic());
setRPr = true;
}
if (textElement.isOwnStrikeThrough() != null) {
BooleanDefaultTrue strike = arg.objectFactory.createBooleanDefaultTrue();
ctrPr.setStrike(strike);
strike.setVal(textElement.isOwnStrikeThrough());
setRPr = true;
}
if (textElement.isOwnUnderline() != null && textElement.isOwnUnderline()) {
U value = arg.objectFactory.createU();
ctrPr.setU(value);
if (textElement.getStyle() != null && textElement.getStyle().getLinePen() != null && textElement.getStyle().getLinePen().getLineStyleValue() != null) {
switch (textElement.getStyle().getLinePen().getLineStyleValue()) {
case SOLID:
value.setVal(UnderlineEnumeration.SINGLE);
break;
case DASHED:
value.setVal(UnderlineEnumeration.DASH);
break;
case DOTTED:
value.setVal(UnderlineEnumeration.DOTTED);
break;
case DOUBLE:
value.setVal(UnderlineEnumeration.DOUBLE);
break;
default:
value.setVal(UnderlineEnumeration.SINGLE);
break;
}
if (textElement.getStyle().getLinePen().getOwnLineColor() != null)
value.setColor(colorToStringFormat(textElement.getStyle().getLinePen().getOwnLineColor()));
}
else {
value.setVal(UnderlineEnumeration.SINGLE);
}
setRPr = true;
}
Map docRunAttributes = buildDocRunAttributes(docRun, styleName, arg);
if (attributes != null) {
String fontFamily = this.readAttribute(attributes, docRunAttributes, TextAttribute.FAMILY);
if (fontFamily != null) {
RFonts rFonts = ctrPr.getRFonts();
if (rFonts == null) {
rFonts = arg.objectFactory.createRFonts();
ctrPr.setRFonts(rFonts);
}
rFonts.setAscii(fontFamily);
rFonts.setHAnsi(fontFamily);
setRPr = true;
}
Number weight = this.readAttribute(attributes, docRunAttributes, TextAttribute.WEIGHT);
if (weight != null) {
BooleanDefaultTrue value = arg.objectFactory.createBooleanDefaultTrue();
value.setVal(weight.floatValue() >= TextAttribute.WEIGHT_REGULAR);
ctrPr.setB(value);
setRPr = true;
}
Paint color = this.readAttribute(attributes, docRunAttributes, TextAttribute.FOREGROUND);
if (color instanceof Color) {
org.docx4j.wml.Color color2 = arg.objectFactory.createColor();
color2.setVal(colorToStringFormat((Color) color));
ctrPr.setColor(color2);
setRPr = true;
}
Number size = this.readAttribute(attributes, docRunAttributes, TextAttribute.SIZE);
if (size != null) {
HpsMeasure sz = ctrPr.getSz();
if (sz == null) {
sz = arg.objectFactory.createHpsMeasure();
ctrPr.setSz(sz);
}
sz.setVal(EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.HALF_POINTS, size.doubleValue()));
setRPr = true;
}
Number posture = this.readAttribute(attributes, docRunAttributes, TextAttribute.POSTURE);
if (posture != null) {
BooleanDefaultTrue i = arg.objectFactory.createBooleanDefaultTrue();
ctrPr.setI(i);
i.setVal(posture.floatValue() >= TextAttribute.POSTURE_OBLIQUE);
setRPr = true;
}
Boolean strikeThrough = this.readAttribute(attributes, docRunAttributes, TextAttribute.STRIKETHROUGH);
if (strikeThrough != null) {
BooleanDefaultTrue strike = arg.objectFactory.createBooleanDefaultTrue();
ctrPr.setStrike(strike);
strike.setVal(strikeThrough);
setRPr = true;
}
Integer underline = this.readAttribute(attributes, docRunAttributes, TextAttribute.UNDERLINE);
if (underline != null) {
U value = arg.objectFactory.createU();
ctrPr.setU(value);
if (underline.equals(TextAttribute.UNDERLINE_ON))
value.setVal(UnderlineEnumeration.SINGLE);
else if (underline.equals(TextAttribute.UNDERLINE_LOW_ONE_PIXEL))
value.setVal(UnderlineEnumeration.THICK);
else if (underline.equals(TextAttribute.UNDERLINE_LOW_TWO_PIXEL))
value.setVal(UnderlineEnumeration.DOUBLE);
else if (underline.equals(TextAttribute.UNDERLINE_LOW_DOTTED))
value.setVal(UnderlineEnumeration.DOTTED_HEAVY);
else if (underline.equals(TextAttribute.UNDERLINE_LOW_GRAY))
value.setVal(UnderlineEnumeration.DOTTED);
else if (underline.equals(TextAttribute.UNDERLINE_LOW_DASHED))
value.setVal(UnderlineEnumeration.DASH);
else
value.setVal(UnderlineEnumeration.SINGLE);
setRPr = true;
}
Paint background = this.readAttribute(attributes, docRunAttributes, TextAttribute.BACKGROUND);
if (background instanceof Color) {
CTShd shd = ctrPr.getShd();
if (shd == null) {
shd = arg.objectFactory.createCTShd();
ctrPr.setShd(shd);
}
shd.setFill(colorToStringFormat(textElement.getOwnBackcolor()));
shd.setVal(STShd.CLEAR);
setRPr = true;
}
}
Locale locale = JRStyledTextAttributeSelector.getTextLocale(textElement);
if (locale != null) {
CTLanguage language = arg.objectFactory.createCTLanguage();
language.setVal(locale.toLanguageTag());
ctrPr.setLang(language);
setRPr = true;
}
if (setRPr)
docRun.setRPr(ctrPr);
}
/**
* Extract text attributes from document run.
* @param docRun The document run.
* @param styleName The style name of the run paragraph.
* @param arg The visitor context.
* @return The text attributes of the run.
*/
protected Map buildDocRunAttributes(R docRun, String styleName, J2WDocx4jPrintElementVisitorContext arg) {
Map res = new HashMap<>();
StyleDefinitionsPart stylePart = buildStylePart(arg, false);
PPr stylePPr = null;
RPr styleRPr = null;
RPr rPr = docRun.getRPr();
if (stylePart != null) {
Style style = stylePart.getStyleById(styleName);
if (style != null) {
stylePPr = style.getPPr();
styleRPr = style.getRPr();
}
}
// Font family
if (rPr != null && rPr.getRFonts() != null)
res.put(TextAttribute.FAMILY, rPr.getRFonts().getAscii());
else if (styleRPr != null && styleRPr.getRFonts() != null && styleRPr.getRFonts().getAscii() != null)
res.put(TextAttribute.FAMILY, styleRPr.getRFonts().getAscii());
// Bold
if (rPr != null && rPr.getB() != null)
res.put(TextAttribute.WEIGHT, rPr.getB().isVal() ? TextAttribute.WEIGHT_BOLD : TextAttribute.WEIGHT_REGULAR);
else if (styleRPr != null && styleRPr.getB() != null)
res.put(TextAttribute.WEIGHT, styleRPr.getB().isVal()? TextAttribute.WEIGHT_BOLD : TextAttribute.WEIGHT_REGULAR);
// Fore color
if (rPr != null && rPr.getColor() != null)
res.put(TextAttribute.FOREGROUND, stringToColorParse(rPr.getColor().getVal()));
else if (styleRPr != null && styleRPr.getColor() != null)
res.put(TextAttribute.FOREGROUND, stringToColorParse(styleRPr.getColor().getVal()));
// Font size
if (rPr != null && rPr.getSz() != null)
res.put(TextAttribute.SIZE, EConvertMisure.HALF_POINTS.convertInto(EConvertMisure.POINTS, rPr.getSz().getVal().doubleValue()));
else if (styleRPr != null && styleRPr.getSz() != null)
res.put(TextAttribute.SIZE, EConvertMisure.HALF_POINTS.convertInto(EConvertMisure.POINTS, styleRPr.getSz().getVal().doubleValue()));
// Italic
if (rPr != null && rPr.getI() != null)
res.put(TextAttribute.POSTURE, rPr.getI().isVal()? TextAttribute.POSTURE_OBLIQUE : TextAttribute.POSTURE_REGULAR);
else if (styleRPr != null && styleRPr.getI() != null)
res.put(TextAttribute.POSTURE, styleRPr.getI().isVal()? TextAttribute.POSTURE_OBLIQUE : TextAttribute.POSTURE_REGULAR);
// Strike
if (rPr != null && rPr.getStrike() != null)
res.put(TextAttribute.STRIKETHROUGH, rPr.getStrike().isVal());
else if (styleRPr != null && styleRPr.getStrike() != null)
res.put(TextAttribute.STRIKETHROUGH, styleRPr.getStrike().isVal());
// Underline
U ctUnderline = null;
if (rPr != null && rPr.getU() != null)
ctUnderline = rPr.getU();
else if (styleRPr != null && styleRPr.getU() != null)
ctUnderline = styleRPr.getU();
if (ctUnderline != null) {
UnderlineEnumeration val = ctUnderline.getVal();
switch (val) {
case SINGLE:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
break;
case DOUBLE:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_TWO_PIXEL);
break;
case THICK:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
break;
case DOTTED_HEAVY:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED);
break;
case DOTTED:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_GRAY);
break;
case DASH:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_DASHED);
break;
case NONE:
break;
default:
res.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
break;
}
}
// Background
if (rPr != null && rPr.getShd() != null)
res.put(TextAttribute.BACKGROUND, stringToColorParse(rPr.getShd().getColor()));
else if (styleRPr != null && styleRPr.getShd() != null)
res.put(TextAttribute.BACKGROUND, stringToColorParse(styleRPr.getShd().getColor()));
else if (stylePPr != null && stylePPr.getShd() != null)
res.put(TextAttribute.BACKGROUND, stringToColorParse(stylePPr.getShd().getColor()));
return res;
}
/**
* Read the text attribute difference between the two parameters map:
*
* if run has not the attribute, return the jasper attribute
* if both run and jasper have not the attribute, return {@code null}
* if both attributes are present but they are not equal, return the jasper value
* otherwise return {@code null}
*
* @param jasperAttributes The jasper attributes.
* @param runAttributes The run attributes.
* @param attributeName The attribute name.
* @param The type of attribute.
* @return The different attribute value.
*/
private V readAttribute(Map jasperAttributes, Map runAttributes, Attribute attributeName) {
@SuppressWarnings("unchecked") V jasperValue = (V) jasperAttributes.get(attributeName);
@SuppressWarnings("unchecked") V runValue = (V) runAttributes.get(attributeName);
if (runValue == null)
return jasperValue;
else if (jasperValue == null)
return null;
else if (!jasperValue.equals(runValue))
return jasperValue;
else
return null;
}
public void visit(JRPrintImage image, J2WDocx4jPrintElementVisitorContext arg) {
Renderable renderable = image.getRenderable();
if (renderable != null) {
String imageMimeType;
String imageType;
switch (renderable.getImageTypeValue()) {
case UNKNOWN:
throw new JRRuntimeException("Unknown image type: " + image.getOrigin());
case GIF:
imageMimeType = ContentTypes.IMAGE_GIF;
imageType = "gif";
break;
case JPEG:
imageMimeType = ContentTypes.IMAGE_JPEG;
imageType = "jpeg";
break;
case PNG:
imageMimeType = ContentTypes.IMAGE_PNG;
imageType = "png";
break;
case TIFF:
imageMimeType = ContentTypes.IMAGE_TIFF;
imageType = "tiff";
break;
default:
throw new JRRuntimeException("Unknown image type: (" + renderable.getImageTypeValue() + ") " + image.getOrigin());
}
try {
BufferedImage bImage = ImageIO.read(new ByteArrayInputStream(renderable.getImageData(jasperReportsContext)));
ComponentPosition position = arg.getLayout().getElementPosition(image);
ImageInfo imageInfo = new ImageInfo(null, imageMimeType);
ImageSize size = new ImageSize(bImage.getWidth(), bImage.getHeight(), bImage.getColorModel().getPixelSize());
size.calcSizeFromPixels();
imageInfo.setSize(size);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ImageIO.write(bImage, imageType, bytes);
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(arg.getDocument(), arg.getDocument().getMainDocumentPart(), bytes.toByteArray(), imageMimeType);
imagePart.setImageInfo(imageInfo);
Inline imageInline = imagePart.createImageInline(image.getRenderable().getId(), image.getKey(), image.getPrintElementId(), image.getSourceElementId(), false);
/* START default */
int leftPadding = image.getLineBox().getLeftPadding();
int topPadding = image.getLineBox().getTopPadding();
int rightPadding = image.getLineBox().getRightPadding();
int bottomPadding = image.getLineBox().getBottomPadding();
int availableImageWidth = position.getWidth() - leftPadding - rightPadding;
availableImageWidth = availableImageWidth < 0 ? 0 : availableImageWidth;
int availableImageHeight = position.getHeight() - topPadding - bottomPadding;
availableImageHeight = availableImageHeight < 0 ? 0 : availableImageHeight;
Renderable renderer = image.getRenderable();
if (
renderer != null &&
availableImageWidth > 0 &&
availableImageHeight > 0
) {
if (renderer.getTypeValue() == RenderableTypeEnum.IMAGE) {
// Non-lazy image renderers are all asked for their image data at some point.
// Better to test and replace the renderer now, in case of lazy load error.
renderer = RenderableUtil.getInstance(jasperReportsContext).getOnErrorRendererForImageData(renderer, image.getOnErrorTypeValue());
}
} else {
renderer = null;
}
if (renderer != null) {
FoundDocParagraph foundDocParagraph = this.findParagraph(position, image, arg, true);
int width = availableImageWidth;
int height = availableImageHeight;
double normalWidth = availableImageWidth;
double normalHeight = availableImageHeight;
// Image load might fail.
Renderable tmpRenderer =
RenderableUtil.getInstance(jasperReportsContext).getOnErrorRendererForDimension(renderer, image.getOnErrorTypeValue());
Dimension2D dimension = tmpRenderer == null ? null : tmpRenderer.getDimension(jasperReportsContext);
// If renderer was replaced, ignore image dimension.
if (tmpRenderer == renderer && dimension != null) {
normalWidth = dimension.getWidth();
normalHeight = dimension.getHeight();
}
double cropTop = 0;
double cropLeft = 0;
double cropBottom = 0;
double cropRight = 0;
switch (image.getScaleImageValue()) {
case FILL_FRAME: {
width = availableImageWidth;
height = availableImageHeight;
break;
}
case CLIP: {
if (normalWidth > availableImageWidth) {
switch (image.getHorizontalAlignmentValue()) {
case RIGHT: {
cropLeft = 65536 * (normalWidth - availableImageWidth) / normalWidth;
cropRight = 0;
break;
}
case CENTER: {
cropLeft = 65536 * (-availableImageWidth + normalWidth) / normalWidth / 2;
cropRight = cropLeft;
break;
}
case LEFT:
default: {
cropLeft = 0;
cropRight = 65536 * (normalWidth - availableImageWidth) / normalWidth;
break;
}
}
width = availableImageWidth;
cropLeft = cropLeft / 0.75d;
cropRight = cropRight / 0.75d;
} else {
width = (int) normalWidth;
}
if (normalHeight > availableImageHeight) {
switch (image.getVerticalAlignmentValue()) {
case TOP: {
cropTop = 0;
cropBottom = 65536 * (normalHeight - availableImageHeight) / normalHeight;
break;
}
case MIDDLE: {
cropTop = 65536 * (normalHeight - availableImageHeight) / normalHeight / 2;
cropBottom = cropTop;
break;
}
case BOTTOM:
default: {
cropTop = 65536 * (normalHeight - availableImageHeight) / normalHeight;
cropBottom = 0;
break;
}
}
height = availableImageHeight;
cropTop = cropTop / 0.75d;
cropBottom = cropBottom / 0.75d;
} else {
height = (int) normalHeight;
}
break;
}
case RETAIN_SHAPE:
default: {
if (availableImageHeight > 0) {
double ratio = normalWidth / normalHeight;
if (ratio > availableImageWidth / (double) availableImageHeight) {
width = availableImageWidth;
height = (int) (width / ratio);
} else {
height = availableImageHeight;
width = (int) (ratio * height);
}
}
}
}
// convert the inline to an anchor (xml contents are essentially the same)
String anchorXml = XmlUtils.marshaltoString(imageInline, true, false, Context.jc, Namespaces.NS_WORD12, "anchor", Inline.class);
org.docx4j.dml.ObjectFactory dmlFactory = arg.drawingObjectFactory;
org.docx4j.dml.wordprocessingDrawing.ObjectFactory wordDmlFactory = new org.docx4j.dml.wordprocessingDrawing.ObjectFactory();
Anchor anchor = (Anchor) XmlUtils.unmarshalString(anchorXml, Context.jc, Anchor.class);
anchor.setDistT(0L);
anchor.setDistB(0L);
anchor.setDistL(0L);
anchor.setDistR(0L);
anchor.setSimplePosAttr(!foundDocParagraph.isTableCell());
anchor.setRelativeHeight(0);
anchor.setBehindDoc(false);
anchor.setLocked(true);
anchor.setLayoutInCell(true);
anchor.setAllowOverlap(true);
anchor.setSimplePos(dmlFactory.createCTPoint2D());
if (!foundDocParagraph.isTableCell()) {
anchor.getSimplePos().setX((long) EConvertMisure.POINTS.convertInto(EConvertMisure.th20_POINTS, position.getX()));
anchor.getSimplePos().setY((long) EConvertMisure.POINTS.convertInto(EConvertMisure.th20_POINTS, position.getY()));
}
else {
anchor.getSimplePos().setX(0);
anchor.getSimplePos().setY(0);
}
anchor.setPositionH(wordDmlFactory.createCTPosH());
anchor.getPositionH().setRelativeFrom(STRelFromH.COLUMN);
if (image.getHorizontalAlignmentValue() != null) {
switch (image.getHorizontalAlignmentValue()) {
case RIGHT:
anchor.getPositionH().setAlign(STAlignH.RIGHT);
break;
case CENTER:
anchor.getPositionH().setAlign(STAlignH.CENTER);
break;
case JUSTIFIED:
anchor.getPositionH().setAlign(STAlignH.INSIDE);
break;
case LEFT:
default:
anchor.getPositionH().setAlign(STAlignH.LEFT);
break;
}
}
anchor.setPositionV(wordDmlFactory.createCTPosV());
anchor.getPositionV().setPosOffset(null);
anchor.getPositionV().setRelativeFrom(STRelFromV.LINE);
if (image.getVerticalAlignmentValue() != null) {
switch (image.getVerticalAlignmentValue()) {
case TOP:
anchor.getPositionV().setAlign(STAlignV.TOP);
break;
case BOTTOM:
anchor.getPositionV().setAlign(STAlignV.BOTTOM);
break;
case JUSTIFIED:
anchor.getPositionV().setAlign(STAlignV.INSIDE);
break;
case MIDDLE:
default:
anchor.getPositionV().setAlign(STAlignV.CENTER);
break;
}
}
anchor.setWrapNone(wordDmlFactory.createCTWrapNone());
Pic pic = anchor.getGraphic().getGraphicData().getPic();
CTBlipFillProperties blipFill = pic.getBlipFill();
CTRelativeRect srcRect = dmlFactory.createCTRelativeRect();
srcRect.setB((int) cropBottom);
srcRect.setL((int) cropLeft);
srcRect.setR((int) cropRight);
srcRect.setT((int) cropTop);
blipFill.setSrcRect(srcRect);
CTStretchInfoProperties stretch = dmlFactory.createCTStretchInfoProperties();
stretch.setFillRect(dmlFactory.createCTRelativeRect());
blipFill.setStretch(stretch);
CTPositiveSize2D extent = anchor.getExtent();
CTShapeProperties spPr = pic.getSpPr();
if (spPr == null) {
spPr = arg.drawingObjectFactory.createCTShapeProperties();
pic.setSpPr(spPr);
}
spPr.setBwMode(STBlackWhiteMode.AUTO);
CTTransform2D xfrm = spPr.getXfrm();
if (xfrm == null) {
xfrm = arg.drawingObjectFactory.createCTTransform2D();
spPr.setXfrm(xfrm);
}
CTPositiveSize2D ext = xfrm.getExt();
if (ext == null) {
ext = arg.drawingObjectFactory.createCTPositiveSize2D();
xfrm.setExt(ext);
}
extent.setCx((long) EConvertMisure.POINTS.convertInto(EConvertMisure.EMU, width));
extent.setCy((long) EConvertMisure.POINTS.convertInto(EConvertMisure.EMU, height));
ext.setCx(extent.getCx());
ext.setCy(extent.getCy());
CTPoint2D off = dmlFactory.createCTPoint2D();
off.setX(0);
off.setY(0);
xfrm.setOff(off);
CTPresetGeometry2D prstGeom = spPr.getPrstGeom();
if (prstGeom == null) {
prstGeom = arg.drawingObjectFactory.createCTPresetGeometry2D();
spPr.setPrstGeom(prstGeom);
}
prstGeom.setPrst(STShapeType.RECT);
if (prstGeom.getAvLst() == null) {
prstGeom.setAvLst(arg.drawingObjectFactory.createCTGeomGuideList());
}
/* END default */
Drawing drawing = arg.objectFactory.createDrawing();
drawing.getAnchorOrInline().add(anchor);
P paragraph = foundDocParagraph.getParagraph();
R run = arg.objectFactory.createR();
run.setRPr(arg.objectFactory.createRPr());
paragraph.getContent().add(run);
run.getContent().add(drawing);
// if (!foundDocParagraph.isTableCell())
// arg.setLastY(position.getDocumentPart(), position.getY() + position.getHeight());
}
} catch (JRException e) {
throw new JRRuntimeException("Unreadable image", e);
} catch (Exception e) {
throw new JRRuntimeException("Write image error", e);
}
}
}
/**
* Visiti a generic shape.
* @param drawingShape The shape jaxb object.
* @param paragraph The doc paragraph that contains the shape.
* @param position The component position.
* @param realHeight The current document y position.
* @param arg The visitor context.
*/
protected void visitDrawingShape(JAXBElement drawingShape, P paragraph, ComponentPosition position, int realHeight, J2WDocx4jPrintElementVisitorContext arg) {
R run = arg.objectFactory.createR();
paragraph.getContent().add(run);
run.getContent().add(drawingShape);
PPr pPr = paragraph.getPPr();
if (pPr == null) {
pPr = arg.objectFactory.createPPr();
paragraph.setPPr(pPr);
}
pPr.setRPr(arg.objectFactory.createParaRPr());
pPr.setPStyle(arg.objectFactory.createPPrBasePStyle());
pPr.getPStyle().setVal("Normal");
pPr.setJc(arg.objectFactory.createJc());
pPr.getJc().setVal(JcEnumeration.CENTER);
pPr.setTextAlignment(arg.objectFactory.createPPrBaseTextAlignment());
pPr.getTextAlignment().setVal("center");
Spacing spacing = pPr.getSpacing();
if (spacing == null) {
spacing = arg.objectFactory.createPPrBaseSpacing();
pPr.setSpacing(spacing);
}
if (position.getHeight() > realHeight) {
BigInteger gap = EConvertMisure.POINTS.convertIntoBigInteger(EConvertMisure.th20_POINTS, position.getHeight() - realHeight).divide(BigInteger.valueOf(2));
spacing.setAfter(gap);
spacing.setBefore(gap);
}
else {
spacing.setAfter(BigInteger.ZERO);
spacing.setAfterLines(BigInteger.ZERO);
}
spacing.setBefore(BigInteger.ZERO);
spacing.setBeforeLines(BigInteger.ZERO);
spacing.setLineRule(STLineSpacingRule.EXACT);
spacing.setLine(BigInteger.ZERO);
}
public void visit(JRPrintRectangle rectangle, J2WDocx4jPrintElementVisitorContext arg) {
if (rectangle.getLinePen() != null && (rectangle.getLinePen().getLineWidth() > 0f ||
(rectangle.getModeValue() == ModeEnum.OPAQUE && rectangle.getFillValue() == FillEnum.SOLID &&
rectangle.getBackcolor() != null && !rectangle.getBackcolor().equals(Color.white)))) {
ComponentPosition position = arg.getLayout().getElementPosition(rectangle);
FoundDocParagraph foundDocParagraph = this.findParagraph(position, rectangle.getStyle(), arg, true);
P paragraph = foundDocParagraph.getParagraph();
CTRect ctRect = arg.picObjectFactory.createCTRect();
JAXBElement rect = arg.picObjectFactory.createRect(ctRect);
Pict pict = arg.objectFactory.createPict();
pict.getAnyAndAny().add(rect);
this.visitDrawingShape(arg.objectFactory.createRPict(pict), paragraph, position, position.getHeight(), arg);
if (rectangle.getModeValue() == ModeEnum.OPAQUE && rectangle.getFillValue() == FillEnum.SOLID) {
ctRect.setFillcolor(colorToStringFormat(rectangle.getBackcolor()));
ctRect.setFilled(STTrueFalse.TRUE);
// filltemplate = "\n\t";
}
if (rectangle.getForecolor() != null) {
String color = colorToStringFormat(rectangle.getForecolor());
ctRect.setBorderbottomcolor(color);
ctRect.setBorderleftcolor(color);
ctRect.setBorderrightcolor(color);
ctRect.setBordertopcolor(color);
ctRect.setStrokecolor("#" + color);
}
Float lineWidth = rectangle.getLinePen().getLineWidth();
ctRect.setStrokeweight(String.valueOf(lineWidth) + "pt");
if (rectangle.getRadius() > 0) {
ctRect.setConnectortype(STConnectorType.CURVED);
}
else
ctRect.setConnectortype(STConnectorType.STRAIGHT);
ctRect.setVmlId("Rectangle " + rectangle.getKey());
MessageFormat format =
new MessageFormat("position:absolute;margin-left:{0,number,0.00}pt;" +
"margin-top:{1,number,0.00}pt;width:{2,number,0.00}pt;height:{3,number,0.00}pt;z-index:251661312;visibility:visible;" +
"mso-wrap-style:square;mso-wrap-distance-left:0pt;mso-wrap-distance-top:0;mso-wrap-distance-right:0pt;mso-wrap-distance-bottom:0;" +
"mso-position-horizontal:absolute;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:text;v-text-anchor:middle",
Locale.US);
ctRect.setStyle(format.format(new Object[]{position.getX(), position.getY(), position.getWidth(), position.getHeight()}));
ctRect.setSpid("_x0000_s1026");
ctRect.setInsetmode(STInsetMode.CUSTOM);
ctRect.setHralign(STHrAlign.LEFT);
if (!foundDocParagraph.isTableCell())
arg.setLastY(position.getDocumentPart(), position.getY() + position.getHeight());
}
}
public void visit(JRPrintLine line, J2WDocx4jPrintElementVisitorContext arg) {
if (line.getLinePen() != null && line.getLinePen().getLineWidth() > 0f) {
ComponentPosition position = arg.getLayout().getElementPosition(line);
FoundDocParagraph foundDocParagraph = this.findParagraph(position, line.getStyle(), arg, true);
P paragraph = foundDocParagraph.getParagraph();
CTLine ctLine = arg.picObjectFactory.createCTLine();
JAXBElement lin = arg.picObjectFactory.createLine(ctLine);
Pict pict = arg.objectFactory.createPict();
pict.getAnyAndAny().add(lin);
this.visitDrawingShape(arg.objectFactory.createRPict(pict), paragraph, position, position.getHeight(), arg);
float lineWidth = line.getLinePen().getLineWidth();
int x1, x2, y1, y2;
if (line.getHeight() == 1) { // Horizontal
x1 = 0;
y1 = (int) (position.getY() - lineWidth / 2);
x2 = x1 + position.getWidth();
y2 = y1;
}
else if (line.getWidth() == 1) { // Vertical
x1 = (int) (position.getX() - lineWidth / 2);
y1 = position.getY();
x2 = x1;
y2 = y1 + position.getHeight();
}
else { // Oblique
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN) {
x1 = position.getX();
y1 = position.getY();
x2 = x1 + position.getWidth();
y2 = y1 + position.getHeight();
}
else {
x2 = position.getX();
x1 = x2 + position.getWidth();
y1 = position.getY();
y2 = y1 + position.getHeight();
}
}
String color = colorToStringFormat(line.getLinePen().getLineColor());
ctLine.setFilled(STTrueFalse.TRUE);
MessageFormat format = new MessageFormat("{0,number,0.00}pt,{1,number,0.00}pt", Locale.US);
ctLine.setFrom(format.format(new Object[]{x1, y1}));
ctLine.setTo(format.format(new Object[]{x2, y2}));
ctLine.setStyle("style=\"position:absolute;z-index:251661312;visibility:visible;mso-wrap-style:square;mso-width-percent:0;mso-height-percent:0;mso-wrap-distance-left:0pt;mso-wrap-distance-top:0;mso-wrap-distance-right:0pt;mso-wrap-distance-bottom:0;mso-position-horizontal:absolute;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:text;mso-width-percent:0;mso-height-percent:0;mso-width-relative:margin;mso-height-relative:margin\" ");
ctLine.setVmlId("Line " + line.getKey());
ctLine.setSpid("_x0000_s1026");
ctLine.setStrokecolor("#" + color);
ctLine.setStroked(STTrueFalse.TRUE);
format = new MessageFormat("{0,number,0.00}pt", Locale.US);
ctLine.setStrokeweight(format.format(new Object[]{lineWidth}));
if (!foundDocParagraph.isTableCell())
arg.setLastY(position.getDocumentPart(), Math.max(y1, y2));
}
}
public void visit(JRPrintEllipse ellipse, J2WDocx4jPrintElementVisitorContext arg) {
if (ellipse.getLinePen() != null && (ellipse.getLinePen().getLineWidth() > 0f ||
(ellipse.getModeValue() == ModeEnum.OPAQUE && ellipse.getFillValue() == FillEnum.SOLID &&
ellipse.getBackcolor() != null && !ellipse.getBackcolor().equals(Color.white)))) {
ComponentPosition position = arg.getLayout().getElementPosition(ellipse);
FoundDocParagraph foundDocParagraph = this.findParagraph(position, ellipse.getStyle(), arg, true);
P paragraph = foundDocParagraph.getParagraph();
CTOval ctOval = arg.picObjectFactory.createCTOval();
JAXBElement rect = arg.picObjectFactory.createOval(ctOval);
Pict pict = arg.objectFactory.createPict();
pict.getAnyAndAny().add(rect);
this.visitDrawingShape(arg.objectFactory.createRPict(pict), paragraph, position, position.getHeight(), arg);
String color = colorToStringFormat(ellipse.getLinePen().getLineColor());
ctOval.setStrokecolor(color);
MessageFormat format = new MessageFormat("{0,number,0.00}", Locale.US);
ctOval.setStrokeweight(format.format(new Object[]{ellipse.getLinePen().getLineWidth()}));
if (ellipse.getModeValue() == ModeEnum.OPAQUE && ellipse.getFillValue() == FillEnum.SOLID) {
ctOval.setFillcolor(colorToStringFormat(ellipse.getLinePen().getLineColor()));
ctOval.setFilled(STTrueFalse.TRUE);
}
ctOval.setConnectortype(STConnectorType.STRAIGHT);
ctOval.setVmlId("Oval " + ellipse.getKey());
format = new MessageFormat("position:absolute;margin-left:{0,number,0.00}pt;margin-top:{1,number,0.00}pt;" +
"width:{2,number,0.00}pt;height:{3,number,0.00}pt;z-index:251660288;visibility:visible;mso-wrap-style:square;mso-wrap-distance-left:0pt;mso-wrap-distance-top:0;mso-wrap-distance-right:0pt;mso-wrap-distance-bottom:0;mso-position-horizontal:absolute;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:text;v-text-anchor:middle", Locale.US);
ctOval.setStyle(format.format(new Object[]{position.getX(), position.getY(), position.getWidth(), position.getHeight()}));
ctOval.setSpid("_x0000_s1026");
ctOval.setInsetmode(STInsetMode.CUSTOM);
ctOval.setHralign(STHrAlign.LEFT);
if (!foundDocParagraph.isTableCell())
arg.setLastY(position.getDocumentPart(), position.getY() + position.getHeight());
}
}
public void visit(JRPrintFrame frame, J2WDocx4jPrintElementVisitorContext arg) {
Collection elements = arg.getLayout().listJRPrintElements(frame);
JRStyle frameStyle = frame.getStyle();
for (JRPrintElement element : elements) {
JRStyle elementStyle = element.getStyle();
if (elementStyle == null)
element.setStyle(frameStyle);
else if (frameStyle != null) {
if (arg.getReport().getStylesMap().containsKey(elementStyle.getName())) {
JRStyle newElementStyle = (JRStyle) frameStyle.clone();
String newStyleName = arg.remapStylesNameByJrStyle.get(elementStyle.getName()) + "BasedOn" + arg.remapStylesNameByJrStyle.get(frameStyle.getName());
if (newElementStyle instanceof JRBaseStyle) {
((JRBaseStyle) newElementStyle).rename(newStyleName);
} else
throw new JRRuntimeException("Operation not supported");
if (!arg.allStyles.contains(newStyleName)) {
buildStyles(arg, Collections.singletonList(newElementStyle));
StyleDefinitionsPart stylePart = buildStylePart(arg, false);
Style style = stylePart.getStyleById(newStyleName);
BasedOn styleBasedOn = arg.objectFactory.createStyleBasedOn();
styleBasedOn.setVal(arg.remapStylesNameByJrStyle.get(frameStyle.getName()));
style.setBasedOn(styleBasedOn);
updateStyle(style, elementStyle, arg, true);
}
if (element instanceof JRTemplatePrintElement)
((JRTemplatePrintElement) element).getTemplate().setStyle(newElementStyle);
else
element.setStyle(newElementStyle);
}
}
element.accept(this, arg);
if (element instanceof JRTemplatePrintElement)
((JRTemplatePrintElement) element).getTemplate().setStyle(elementStyle);
else
element.setStyle(elementStyle);
}
}
public void visit(JRGenericPrintElement printElement, J2WDocx4jPrintElementVisitorContext arg) {
}
/**
* Found or built paragraph.
*/
protected static class FoundDocParagraph {
/** The doc paragraph */
private final P paragraph;
/** The table cell (can be {@code null}) */
private final Tc cell;
/** The index in the jaxb document list objects */
private final int paragraphIndexInDoc;
/**
* Construct the found paragraph.
* @param cell The table cell (can be {@code null}) if the paragraph is outside a table.
* @param paragraph The doc paragraph.
* @param paragraphIndexInDoc The index in the jaxb document list objects.
*/
public FoundDocParagraph(Tc cell, P paragraph, int paragraphIndexInDoc) {
this.paragraph = paragraph;
this.cell = cell;
this.paragraphIndexInDoc = paragraphIndexInDoc;
}
/**
* Return the paragraph.
* @return The paragraph.
*/
public P getParagraph() {
return paragraph;
}
/**
* Return the table cell.
* @return The table cell or {@code null}.
*/
public Tc getCell() {
return cell;
}
/**
* Return if the paragraph is inside a table.
* @return {@code true} if in table, {@code false} otherwise.
*/
public boolean isTableCell() {
return cell != null;
}
/**
* Return the index in the jaxb document list objects.
* @return The index in the jaxb document list objects.
*/
public int getParagraphIndexInDoc() {
return paragraphIndexInDoc;
}
}
}
}