net.sf.jasperreports.engine.export.oasis.JROdsExporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
/*
* Special thanks to Google 'Summer of Code 2005' program for supporting this development
*
* Contributors:
* Majid Ali Khan - [email protected]
* Frank Schönheit - [email protected]
*/
package net.sf.jasperreports.engine.export.oasis;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.Dimension2D;
import java.io.IOException;
import java.io.OutputStream;
import java.text.AttributedCharacterIterator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRGenericElementType;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.JRPrintFrame;
import net.sf.jasperreports.engine.JRPrintGraphicElement;
import net.sf.jasperreports.engine.JRPrintHyperlink;
import net.sf.jasperreports.engine.JRPrintImage;
import net.sf.jasperreports.engine.JRPrintLine;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.PrintPageFormat;
import net.sf.jasperreports.engine.base.JRBaseLineBox;
import net.sf.jasperreports.engine.export.Cut;
import net.sf.jasperreports.engine.export.CutsInfo;
import net.sf.jasperreports.engine.export.ElementGridCell;
import net.sf.jasperreports.engine.export.GenericElementHandlerEnviroment;
import net.sf.jasperreports.engine.export.HyperlinkUtil;
import net.sf.jasperreports.engine.export.JRExporterGridCell;
import net.sf.jasperreports.engine.export.JRGridLayout;
import net.sf.jasperreports.engine.export.JRHyperlinkProducer;
import net.sf.jasperreports.engine.export.JRXlsAbstractExporter;
import net.sf.jasperreports.engine.export.LengthUtil;
import net.sf.jasperreports.engine.export.OccupiedGridCell;
import net.sf.jasperreports.engine.export.XlsRowLevelInfo;
import net.sf.jasperreports.engine.export.zip.ExportZipEntry;
import net.sf.jasperreports.engine.export.zip.FileBufferedZipEntry;
import net.sf.jasperreports.engine.type.LineDirectionEnum;
import net.sf.jasperreports.engine.type.ModeEnum;
import net.sf.jasperreports.engine.util.ImageUtil;
import net.sf.jasperreports.engine.util.JRStringUtil;
import net.sf.jasperreports.engine.util.JRStyledText;
import net.sf.jasperreports.export.OdsExporterConfiguration;
import net.sf.jasperreports.export.OdsReportConfiguration;
import net.sf.jasperreports.export.XlsReportConfiguration;
import net.sf.jasperreports.renderers.DimensionRenderable;
import net.sf.jasperreports.renderers.Renderable;
import net.sf.jasperreports.renderers.RenderersCache;
import net.sf.jasperreports.renderers.ResourceRenderer;
/**
* Exports a JasperReports document to Open Document Spreadsheet format. It has character output type
* and exports the document to a grid-based layout.
*
* The {@link net.sf.jasperreports.engine.export.oasis.JROdsExporter} exporter
* implementation produces documents that comply with the Open Document Format for
* Office Applications specifications for spreadsheets. These documents use the
* .ods
file extension.
*
* Because spreadsheet documents are made of sheets containing cells, this exporter is a
* grid exporter, as well, therefore having the known limitations of grid exporters.
*
* Special exporter configuration settings, that can be applied to a
* {@link net.sf.jasperreports.engine.export.oasis.JROdsExporter} instance
* to control its behavior, can be found in {@link net.sf.jasperreports.export.OdsReportConfiguration}
* and in its {@link net.sf.jasperreports.export.XlsReportConfiguration} superclass.
*
* @see net.sf.jasperreports.export.OdsReportConfiguration
* @see net.sf.jasperreports.export.XlsReportConfiguration
* @author Teodor Danciu ([email protected])
*/
public class JROdsExporter extends JRXlsAbstractExporter
{
/**
*
*/
protected static final String JR_PAGE_ANCHOR_PREFIX = "JR_PAGE_ANCHOR_";
protected static final String DEFAULT_COLUMN = "A";
protected static final String DEFAULT_ADDRESS = "$A$1";
/**
*
*/
protected OasisZip oasisZip;
protected ExportZipEntry tempBodyEntry;
protected ExportZipEntry tempStyleEntry;
protected WriterHelper tempBodyWriter;
protected WriterHelper tempStyleWriter;
protected WriterHelper stylesWriter;
protected StyleCache styleCache;
protected DocumentBuilder documentBuilder;
protected TableBuilder tableBuilder;
protected StyleBuilder styleBuilder;
protected boolean startPage;
protected PrintPageFormat oldPageFormat;
protected int pageFormatIndex;
protected StringBuilder namedExpressions;
protected Map rowStyles = new HashMap();
protected Map columnStyles = new HashMap();
@Override
protected void openWorkbook(OutputStream os) throws JRException, IOException
{
oasisZip = new OdsZip();
tempBodyEntry = new FileBufferedZipEntry(null);
tempStyleEntry = new FileBufferedZipEntry(null);
tempBodyWriter = new WriterHelper(jasperReportsContext, tempBodyEntry.getWriter());
tempStyleWriter = new WriterHelper(jasperReportsContext, tempStyleEntry.getWriter());
rowStyles.clear();
columnStyles.clear();
documentBuilder = new OdsDocumentBuilder(oasisZip);
styleCache = new StyleCache(jasperReportsContext, tempStyleWriter, getExporterKey());
stylesWriter = new WriterHelper(jasperReportsContext, oasisZip.getStylesEntry().getWriter());
styleBuilder = new StyleBuilder(stylesWriter);
styleBuilder.buildBeforeAutomaticStyles(jasperPrint);
namedExpressions = new StringBuilder("\n");
pageFormatIndex = -1;
maxColumnIndex = 1023;
}
@Override
protected int exportPage(JRPrintPage page, CutsInfo xCuts, int startRow, String defaultSheetName) throws JRException
{
if (oldPageFormat != pageFormat)
{
styleBuilder.buildPageLayout(++pageFormatIndex, pageFormat);
oldPageFormat = pageFormat;
}
return super.exportPage(page, xCuts, startRow, defaultSheetName);
}
@Override
protected void createSheet(CutsInfo xCuts, SheetInfo sheetInfo)
{
startPage = true;
// CutsInfo xCuts = gridLayout.getXCuts();
// JRExporterGridCell[][] grid = gridLayout.getGrid();
// TableBuilder tableBuilder = frameIndex == null
// ? new TableBuilder(reportIndex, pageIndex, tempBodyWriter, tempStyleWriter)
// : new TableBuilder(frameIndex.toString(), tempBodyWriter, tempStyleWriter);
tableBuilder = new OdsTableBuilder(
documentBuilder,
jasperPrint,
pageFormatIndex,
pageIndex,
tempBodyWriter,
tempStyleWriter,
styleCache,
rowStyles,
columnStyles,
sheetInfo.sheetName,
sheetInfo.tabColor);
// tableBuilder.buildTableStyle(gridLayout.getWidth());
tableBuilder.buildTableStyle(xCuts.getLastCutOffset());//FIXMEODS
tableBuilder.buildTableHeader();
// for(int col = 1; col < xCuts.size(); col++)
// {
// tableBuilder.buildColumnStyle(
// col - 1,
// xCuts.getCutOffset(col) - xCuts.getCutOffset(col - 1)
// );
// tableBuilder.buildColumnHeader(col - 1);
// tableBuilder.buildColumnFooter();
// }
}
@Override
protected void closeSheet()
{
if (tableBuilder != null)
{
tableBuilder.buildRowFooter();
tableBuilder.buildTableFooter();
}
}
@Override
protected void closeWorkbook(OutputStream os) throws JRException, IOException
{
styleBuilder.buildMasterPages(pageFormatIndex);
stylesWriter.flush();
tempBodyWriter.flush();
tempStyleWriter.flush();
stylesWriter.close();
tempBodyWriter.close();
tempStyleWriter.close();
namedExpressions.append(" \n");
/* */
ContentBuilder contentBuilder =
new ContentBuilder(
oasisZip.getContentEntry(),
tempStyleEntry,
tempBodyEntry,
styleCache.getFontFaces(),
OasisZip.MIME_TYPE_ODS,
namedExpressions
);
contentBuilder.build();
tempStyleEntry.dispose();
tempBodyEntry.dispose();
oasisZip.zipEntries(os);
oasisZip.dispose();
}
@Override
protected void setColumnWidth(int col, int width, boolean autoFit)
{
tableBuilder.buildColumnStyle(col - 1, width);
tableBuilder.buildColumnHeader(width);
tableBuilder.buildColumnFooter();
}
@Override
protected void setRowHeight(
int rowIndex,
int lastRowHeight,
Cut yCut,
XlsRowLevelInfo levelInfo
) throws JRException
{
boolean isFlexibleRowHeight = getCurrentItemConfiguration().isFlexibleRowHeight();
tableBuilder.buildRowStyle(rowIndex, isFlexibleRowHeight ? -1 : lastRowHeight);
tableBuilder.buildRow(rowIndex, isFlexibleRowHeight ? -1 : lastRowHeight);
}
@Override
protected void addRowBreak(int rowIndex)
{
//FIXMEODS sheet.setRowBreak(rowIndex);
}
// @Override
// protected void setCell(
// JRExporterGridCell gridCell,
// int colIndex,
// int rowIndex)
// {
// //nothing to do
// }
@Override
protected void addBlankCell(
JRExporterGridCell gridCell,
int colIndex,
int rowIndex
)
{
tempBodyWriter.write(" 1)
// {
// tempBodyWriter.write(" table:number-columns-spanned=\"" + emptyCellColSpan + "\"");
// }
tempBodyWriter.write("/>\n");
//
// exportOccupiedCells(emptyCellColSpan - 1);
}
@Override
protected void addOccupiedCell(
OccupiedGridCell occupiedGridCell,
int colIndex,
int rowIndex
) throws JRException
{
ElementGridCell elementGridCell = (ElementGridCell)occupiedGridCell.getOccupier();
addBlankCell(elementGridCell, colIndex, rowIndex);
}
@Override
public void exportText(
JRPrintText text,
JRExporterGridCell gridCell,
int colIndex,
int rowIndex
) throws JRException
{
tableBuilder.exportText(text, gridCell, isShrinkToFit(text), isWrapText(text), isIgnoreTextFormatting(text));
XlsReportConfiguration configuration = getCurrentItemConfiguration();
if (!configuration.isIgnoreAnchors() && text.getAnchorName() != null)
{
String cellAddress = "$'" + tableBuilder.getTableName() + "'." + getCellAddress(rowIndex, colIndex);
int lastCol = Math.max(0, colIndex + gridCell.getColSpan() -1);
String cellRangeAddress = getCellAddress(rowIndex + gridCell.getRowSpan() - 1, lastCol);
namedExpressions.append(" \n");
}
}
@Override
public void exportImage(
JRPrintImage image,
JRExporterGridCell gridCell,
int colIndex,
int rowIndex,
int emptyCols,
int yCutsRow,
JRGridLayout layout
) throws JRException
{
int topPadding =
Math.max(image.getLineBox().getTopPadding(), Math.round(image.getLineBox().getTopPen().getLineWidth()));
int leftPadding =
Math.max(image.getLineBox().getLeftPadding(), Math.round(image.getLineBox().getLeftPen().getLineWidth()));
int bottomPadding =
Math.max(image.getLineBox().getBottomPadding(), Math.round(image.getLineBox().getBottomPen().getLineWidth()));
int rightPadding =
Math.max(image.getLineBox().getRightPadding(), Math.round(image.getLineBox().getRightPen().getLineWidth()));
int availableImageWidth = image.getWidth() - leftPadding - rightPadding;
availableImageWidth = availableImageWidth < 0 ? 0 : availableImageWidth;
int availableImageHeight = image.getHeight() - topPadding - bottomPadding;
availableImageHeight = availableImageHeight < 0 ? 0 : availableImageHeight;
tableBuilder.buildCellHeader(styleCache.getCellStyle(gridCell), gridCell.getColSpan(), gridCell.getRowSpan());
Renderable renderer = image.getRenderer();
if (
renderer != null
&& availableImageWidth > 0
&& availableImageHeight > 0
)
{
InternalImageProcessor imageProcessor =
new InternalImageProcessor(
image,
gridCell,
availableImageWidth,
availableImageHeight//,
// documentBuilder,
// jasperReportsContext
);
InternalImageProcessorResult imageProcessorResult = null;
try
{
imageProcessorResult = imageProcessor.process(renderer);
}
catch (Exception e)
{
Renderable onErrorRenderer = getRendererUtil().handleImageError(e, image.getOnErrorTypeValue());
if (onErrorRenderer != null)
{
imageProcessorResult = imageProcessor.process(onErrorRenderer);
}
}
if (imageProcessorResult != null)
{
XlsReportConfiguration configuration = getCurrentItemConfiguration();
boolean isOnePagePerSheet = configuration.isOnePagePerSheet();
// tempBodyWriter.write("");
documentBuilder.insertPageAnchor(tableBuilder);
if (!configuration.isIgnoreAnchors() && image.getAnchorName() != null)
{
tableBuilder.exportAnchor(JRStringUtil.xmlEncode(image.getAnchorName()));
String cellAddress = "$'" + tableBuilder.getTableName() + "'." + getCellAddress(rowIndex, colIndex);
int lastCol = Math.max(0, colIndex + gridCell.getColSpan() - 1);
String cellRangeAddress = getCellAddress(rowIndex + gridCell.getRowSpan() - 1, lastCol);
namedExpressions.append(" \n");
}
boolean startedHyperlink = tableBuilder.startHyperlink(image,false, isOnePagePerSheet);
//String cellAddress = getCellAddress(rowIndex + gridCell.getRowSpan(), colIndex + gridCell.getColSpan() - 1);
String cellAddress = getCellAddress(rowIndex + gridCell.getRowSpan(), colIndex + gridCell.getColSpan());
cellAddress = cellAddress == null ? "" : "table:end-cell-address=\"" + cellAddress + "\" ";
// tempBodyWriter.write(
// ""
// );
tempBodyWriter.write(
""
);
tempBodyWriter.write(" \n");
tempBodyWriter.write(" ");
if (startedHyperlink)
{
tableBuilder.endHyperlink(false);
}
// tempBodyWriter.write(" ");
}
}
tableBuilder.buildCellFooter();
}
private class InternalImageProcessor
{
private final JRPrintImage imageElement;
private final RenderersCache imageRenderersCache;
private final JRExporterGridCell cell;
private final int availableImageWidth;
private final int availableImageHeight;
protected InternalImageProcessor(
JRPrintImage imageElement,
JRExporterGridCell cell,
int availableImageWidth,
int availableImageHeight
)
{
this.imageElement = imageElement;
this.imageRenderersCache = imageElement.isUsingCache() ? documentBuilder.getRenderersCache()
: new RenderersCache(getJasperReportsContext());
this.cell = cell;
this.availableImageWidth = availableImageWidth;
this.availableImageHeight = availableImageHeight;
}
private InternalImageProcessorResult process(Renderable renderer) throws JRException
{
// boolean isLazy = RendererUtil.isLazy(renderer);
//
// if (!isLazy)
// {
if (renderer instanceof ResourceRenderer)
{
renderer = imageRenderersCache.getLoadedRenderer((ResourceRenderer)renderer);
}
// }
// check dimension first, to avoid caching renderers that might not be used eventually, due to their dimension errors
int imageWidth = availableImageWidth;
int imageHeight = availableImageHeight;
int xoffset = 0;
int yoffset = 0;
double cropTop = 0;
double cropLeft = 0;
double cropBottom = 0;
double cropRight = 0;
double angle = 0;
switch (imageElement.getScaleImageValue())
{
case FILL_FRAME :
{
switch (imageElement.getRotation())
{
case LEFT:
imageWidth = availableImageHeight;
imageHeight = availableImageWidth;
xoffset = 0;
yoffset = availableImageHeight;
angle = Math.PI / 2;
break;
case RIGHT:
imageWidth = availableImageHeight;
imageHeight = availableImageWidth;
xoffset = availableImageWidth;
yoffset = 0;
angle = - Math.PI / 2;
break;
case UPSIDE_DOWN:
imageWidth = availableImageWidth;
imageHeight = availableImageHeight;
xoffset = availableImageWidth;
yoffset = availableImageHeight;
angle = Math.PI;
break;
case NONE:
default:
imageWidth = availableImageWidth;
imageHeight = availableImageHeight;
xoffset = 0;
yoffset = 0;
angle = 0;
break;
}
break;
}
case CLIP :
{
double normalWidth = availableImageWidth;
double normalHeight = availableImageHeight;
DimensionRenderable dimensionRenderer = imageRenderersCache.getDimensionRenderable(renderer);
Dimension2D dimension = dimensionRenderer == null ? null : dimensionRenderer.getDimension(getJasperReportsContext());
if (dimension != null)
{
normalWidth = dimension.getWidth();
normalHeight = dimension.getHeight();
}
switch (imageElement.getRotation())
{
case LEFT:
if (dimension == null)
{
normalWidth = availableImageHeight;
normalHeight = availableImageWidth;
}
imageWidth = availableImageHeight;
imageHeight = availableImageWidth;
switch (imageElement.getHorizontalImageAlign())
{
case RIGHT :
cropLeft = normalWidth - availableImageHeight;
cropRight = 0;
yoffset = imageWidth;
break;
case CENTER :
cropLeft = (normalWidth - availableImageHeight) / 2;
cropRight = cropLeft;
yoffset = availableImageHeight - (availableImageHeight - imageWidth) / 2;
break;
case LEFT :
default :
cropLeft = 0;
cropRight = normalWidth - availableImageHeight;
yoffset = availableImageHeight;
break;
}
switch (imageElement.getVerticalImageAlign())
{
case TOP :
cropTop = 0;
cropBottom = normalHeight - availableImageWidth;
xoffset = 0;
break;
case MIDDLE :
cropTop = (normalHeight - availableImageWidth) / 2;
cropBottom = cropTop;
xoffset = (availableImageWidth - imageHeight) / 2;
break;
case BOTTOM :
default :
cropTop = normalHeight - availableImageWidth;
cropBottom = 0;
xoffset = availableImageWidth - imageHeight;
break;
}
angle = Math.PI / 2;
break;
case RIGHT:
if (dimension == null)
{
normalWidth = availableImageHeight;
normalHeight = availableImageWidth;
}
imageWidth = availableImageHeight;
imageHeight = availableImageWidth;
switch (imageElement.getHorizontalImageAlign())
{
case RIGHT :
cropLeft = normalWidth - availableImageHeight;
cropRight = 0;
yoffset = availableImageHeight - imageWidth;
break;
case CENTER :
cropLeft = (normalWidth - availableImageHeight) / 2;
cropRight = cropLeft;
yoffset = (availableImageHeight - imageWidth) / 2;
break;
case LEFT :
default :
cropLeft = 0;
cropRight = normalWidth - availableImageHeight;
yoffset = 0;
break;
}
switch (imageElement.getVerticalImageAlign())
{
case TOP :
cropTop = 0;
cropBottom = normalHeight - availableImageWidth;
xoffset = availableImageWidth;
break;
case MIDDLE :
cropTop = (normalHeight - availableImageWidth) / 2;
cropBottom = cropTop;
xoffset = availableImageWidth - (availableImageWidth - imageHeight) / 2;
break;
case BOTTOM :
default :
cropTop = normalHeight - availableImageWidth;
cropBottom = 0;
xoffset = imageHeight;
break;
}
angle = - Math.PI / 2;
break;
case UPSIDE_DOWN:
imageWidth = availableImageWidth;
imageHeight = availableImageHeight;
switch (imageElement.getHorizontalImageAlign())
{
case RIGHT :
cropLeft = normalWidth - availableImageWidth;
cropRight = 0;
xoffset = imageWidth;
break;
case CENTER :
cropLeft = (normalWidth - availableImageWidth) / 2;
cropRight = cropLeft;
xoffset = availableImageWidth - (availableImageWidth - imageWidth) / 2;
break;
case LEFT :
default :
cropLeft = 0;
cropRight = normalWidth - availableImageWidth;
xoffset = availableImageWidth;
break;
}
switch (imageElement.getVerticalImageAlign())
{
case TOP :
cropTop = 0;
cropBottom = normalHeight - availableImageHeight;
yoffset = availableImageHeight;
break;
case MIDDLE :
cropTop = (normalHeight - availableImageHeight) / 2;
cropBottom = cropTop;
yoffset = availableImageHeight - (availableImageHeight - imageHeight) / 2;
break;
case BOTTOM :
default :
cropTop = normalHeight - availableImageHeight;
cropBottom = 0;
yoffset = imageHeight;
break;
}
angle = Math.PI;
break;
case NONE:
default:
imageWidth = availableImageWidth;
imageHeight = availableImageHeight;
switch (imageElement.getHorizontalImageAlign())
{
case RIGHT :
cropLeft = normalWidth - availableImageWidth;
cropRight = 0;
xoffset = availableImageWidth - imageWidth;
break;
case CENTER :
cropLeft = (normalWidth - availableImageWidth) / 2;
cropRight = cropLeft;
xoffset = (availableImageWidth - imageWidth) / 2;
break;
case LEFT :
default :
cropLeft = 0;
cropRight = normalWidth - availableImageWidth;
xoffset = 0;
break;
}
switch (imageElement.getVerticalImageAlign())
{
case TOP :
cropTop = 0;
cropBottom = normalHeight - availableImageHeight;
yoffset = 0;
break;
case MIDDLE :
cropTop = (normalHeight - availableImageHeight) / 2;
cropBottom = cropTop;
yoffset = (availableImageHeight - imageHeight) / 2;
break;
case BOTTOM :
default :
cropTop = normalHeight - availableImageHeight;
cropBottom = 0;
yoffset = availableImageHeight - imageHeight;
break;
}
angle = 0;
break;
}
break;
}
case RETAIN_SHAPE :
default :
{
double normalWidth = availableImageWidth;
double normalHeight = availableImageHeight;
Dimension2D dimension = null;
// if (!isLazy)
// {
DimensionRenderable dimensionRenderer = imageRenderersCache.getDimensionRenderable(renderer);
dimension = dimensionRenderer == null ? null : dimensionRenderer.getDimension(getJasperReportsContext());
if (dimension != null)
{
normalWidth = dimension.getWidth();
normalHeight = dimension.getHeight();
}
// }
double ratioX = 1f;
double ratioY = 1f;
switch (imageElement.getRotation())
{
case LEFT:
if (dimension == null)
{
normalWidth = availableImageHeight;
normalHeight = availableImageWidth;
}
imageWidth = availableImageHeight;
imageHeight = availableImageWidth;
ratioX = availableImageWidth / normalHeight;
ratioY = availableImageHeight / normalWidth;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
xoffset = 0;
yoffset = availableImageHeight;
cropLeft = (int)(ImageUtil.getXAlignFactor(imageElement) * (normalWidth - availableImageHeight / ratioX));
cropRight = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (normalWidth - availableImageHeight / ratioX));
cropTop = (int)(ImageUtil.getYAlignFactor(imageElement) * (normalHeight - availableImageWidth / ratioY));
cropBottom = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (normalHeight - availableImageWidth / ratioY));
angle = Math.PI / 2;
break;
case RIGHT:
if (dimension == null)
{
normalWidth = availableImageHeight;
normalHeight = availableImageWidth;
}
imageWidth = availableImageHeight;
imageHeight = availableImageWidth;
ratioX = availableImageWidth / normalHeight;
ratioY = availableImageHeight / normalWidth;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
xoffset = availableImageWidth;
yoffset = 0;
cropLeft = (int)(ImageUtil.getXAlignFactor(imageElement) * (normalWidth - availableImageHeight / ratioX));
cropRight = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (normalWidth - availableImageHeight / ratioX));
cropTop = (int)(ImageUtil.getYAlignFactor(imageElement) * (normalHeight - availableImageWidth / ratioY));
cropBottom = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (normalHeight - availableImageWidth / ratioY));
angle = - Math.PI / 2;
break;
case UPSIDE_DOWN:
imageWidth = availableImageWidth;
imageHeight = availableImageHeight;
ratioX = availableImageWidth / normalWidth;
ratioY = availableImageHeight / normalHeight;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
xoffset = availableImageWidth;
yoffset = availableImageHeight;
cropLeft = (int)(ImageUtil.getXAlignFactor(imageElement) * (normalWidth - availableImageWidth / ratioX));
cropRight = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (normalWidth - availableImageWidth / ratioX));
cropTop = (int)(ImageUtil.getYAlignFactor(imageElement) * (normalHeight - availableImageHeight / ratioY));
cropBottom = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (normalHeight - availableImageHeight / ratioY));
angle = Math.PI;
break;
case NONE:
default:
imageWidth = availableImageWidth;
imageHeight = availableImageHeight;
ratioX = availableImageWidth / normalWidth;
ratioY = availableImageHeight / normalHeight;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
xoffset = 0;
yoffset = 0;
cropLeft = (int)(ImageUtil.getXAlignFactor(imageElement) * (normalWidth - availableImageWidth / ratioX));
cropRight = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (normalWidth - availableImageWidth / ratioX));
cropTop = (int)(ImageUtil.getYAlignFactor(imageElement) * (normalHeight - availableImageHeight / ratioY));
cropBottom = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (normalHeight - availableImageHeight / ratioY));
angle = 0;
break;
}
}
}
String imagePath =
documentBuilder.getImagePath(
renderer,
new Dimension(imageWidth, imageHeight),
ModeEnum.OPAQUE == imageElement.getModeValue() ? imageElement.getBackcolor() : null,
cell,
// isLazy,
imageRenderersCache
);
return
new InternalImageProcessorResult(
imagePath,
imageWidth,
imageHeight,
xoffset,
yoffset,
cropTop,
cropLeft,
cropBottom,
cropRight,
angle
);
}
}
private class InternalImageProcessorResult
{
protected final String imagePath;
protected final int width;
protected final int height;
protected final int xoffset;
protected final int yoffset;
protected final double cropTop;
protected final double cropLeft;
protected final double cropBottom;
protected final double cropRight;
protected final double angle;
protected InternalImageProcessorResult(
String imagePath,
int width,
int height,
int xoffset,
int yoffset,
double cropTop,
double cropLeft,
double cropBottom,
double cropRight,
double angle
)
{
this.imagePath = imagePath;
this.width = width;
this.height = height;
this.xoffset = xoffset;
this.yoffset = yoffset;
this.cropTop = cropTop;
this.cropLeft = cropLeft;
this.cropBottom = cropBottom;
this.cropRight = cropRight;
this.angle = angle;
}
}
protected String getCellAddress(int row, int col)
{
String address = null;
if(row > -1 && row < 1048577 && col > -1 && col < maxColumnIndex)
{
address = "$" + getColumIndexName(col, maxColumnIndex) + "$" + (row + 1);
}
return address == null ? DEFAULT_ADDRESS : address;
}
@Override
protected void exportRectangle(
JRPrintGraphicElement rectangle,
JRExporterGridCell gridCell,
int colIndex,
int rowIndex
) throws JRException
{
tableBuilder.exportRectangle(rectangle, gridCell);
}
@Override
protected void exportLine(
JRPrintLine line,
JRExporterGridCell gridCell,
int colIndex,
int rowIndex
) throws JRException
{
JRLineBox box = new JRBaseLineBox(null);
JRPen pen = null;
float ratio = line.getWidth() / line.getHeight();
if (ratio > 1)
{
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN)
{
pen = box.getTopPen();
}
else
{
pen = box.getBottomPen();
}
}
else
{
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN)
{
pen = box.getLeftPen();
}
else
{
pen = box.getRightPen();
}
}
pen.setLineColor(line.getLinePen().getLineColor());
pen.setLineStyle(line.getLinePen().getLineStyleValue());
pen.setLineWidth(line.getLinePen().getLineWidth());
gridCell.setBox(box);//CAUTION: only some exporters set the cell box
tableBuilder.buildCellHeader(styleCache.getCellStyle(gridCell), gridCell.getColSpan(), gridCell.getRowSpan());
// double x1, y1, x2, y2;
//
// if (line.getDirection() == JRLine.DIRECTION_TOP_DOWN)
// {
// x1 = Utility.translatePixelsToInches(0);
// y1 = Utility.translatePixelsToInches(0);
// x2 = Utility.translatePixelsToInches(line.getWidth() - 1);
// y2 = Utility.translatePixelsToInches(line.getHeight() - 1);
// }
// else
// {
// x1 = Utility.translatePixelsToInches(0);
// y1 = Utility.translatePixelsToInches(line.getHeight() - 1);
// x2 = Utility.translatePixelsToInches(line.getWidth() - 1);
// y2 = Utility.translatePixelsToInches(0);
// }
tempBodyWriter.write("");
//FIXMEODS insertPageAnchor();
// tempBodyWriter.write(
// ""
// //+ " "
// + " "
// );
tempBodyWriter.write(" ");
tableBuilder.buildCellFooter();
}
@Override
protected void exportFrame(
JRPrintFrame frame,
JRExporterGridCell cell,
int colIndex,
int rowIndex
) throws JRException
{
addBlankCell(cell, colIndex, rowIndex);
}
@Override
protected void exportGenericElement(
JRGenericPrintElement element,
JRExporterGridCell gridCell,
int colIndex,
int rowIndex,
int emptyCols,
int yCutsRow,
JRGridLayout layout
) throws JRException
{
GenericElementOdsHandler handler = (GenericElementOdsHandler)
GenericElementHandlerEnviroment.getInstance(getJasperReportsContext()).getElementHandler(
element.getGenericType(), ODS_EXPORTER_KEY);
if (handler != null)
{
JROdsExporterContext exporterContext = new ExporterContext(tableBuilder);
handler.exportElement(exporterContext, element, gridCell, colIndex, rowIndex, emptyCols, yCutsRow, layout);
}
else
{
if (log.isDebugEnabled())
{
log.debug("No ODS generic element handler for "
+ element.getGenericType());
}
}
}
@Override
protected void setFreezePane(int rowIndex, int colIndex) {
// nothing to do here
}
@Override
protected void setSheetName(String sheetName) {
// TODO Auto-generated method stub
}
@Override
protected void setAutoFilter(String autoFilterRange) {
// TODO Auto-generated method stub
}
@Override
protected void setRowLevels(XlsRowLevelInfo levelInfo, String level) {
// TODO Auto-generated method stub
}
private static final Log log = LogFactory.getLog(JROdsExporter.class);
protected static final String ODS_EXPORTER_PROPERTIES_PREFIX = JRPropertiesUtil.PROPERTY_PREFIX + "export.ods.";
/**
* The exporter key, as used in
* {@link GenericElementHandlerEnviroment#getElementHandler(JRGenericElementType, String)}.
*/
public static final String ODS_EXPORTER_KEY = JRPropertiesUtil.PROPERTY_PREFIX + "ods";
protected class ExporterContext extends BaseExporterContext implements JROdsExporterContext
{
TableBuilder tableBuilder = null;
public ExporterContext(TableBuilder tableBuidler)
{
this.tableBuilder = tableBuidler;
}
@Override
public TableBuilder getTableBuilder()
{
return tableBuilder;
}
}
protected class OdsDocumentBuilder extends DocumentBuilder
{
public OdsDocumentBuilder(OasisZip oasisZip)
{
super(oasisZip);
}
@Override
public JRStyledText getStyledText(JRPrintText text)
{
return JROdsExporter.this.getStyledText(text);
}
@Override
public Locale getTextLocale(JRPrintText text)
{
return JROdsExporter.this.getTextLocale(text);
}
@Override
public String getInvalidCharReplacement()
{
return JROdsExporter.this.invalidCharReplacement;
}
@Override
protected void insertPageAnchor(TableBuilder tableBuilder)
{
JROdsExporter.this.insertPageAnchor(tableBuilder);
}
@Override
protected JRHyperlinkProducer getHyperlinkProducer(JRPrintHyperlink link)
{
return JROdsExporter.this.getHyperlinkProducer(link);
}
@Override
protected JasperReportsContext getJasperReportsContext()
{
return JROdsExporter.this.getJasperReportsContext();
}
@Override
protected int getReportIndex()
{
return JROdsExporter.this.reportIndex;
}
@Override
protected int getPageIndex()
{
return JROdsExporter.this.pageIndex;
}
}
protected class OdsTableBuilder extends TableBuilder
{
protected OdsTableBuilder(
DocumentBuilder documentBuilder,
JasperPrint jasperPrint,
int pageFormatIndex,
int pageIndex,
WriterHelper bodyWriter,
WriterHelper styleWriter,
StyleCache styleCache,
Map rowStyles,
Map columnStyles,
Color tabColor)
{
super(
documentBuilder,
jasperPrint,
pageFormatIndex,
pageIndex,
bodyWriter,
styleWriter,
styleCache,
rowStyles,
columnStyles,
tabColor);
}
protected OdsTableBuilder(
DocumentBuilder documentBuilder,
JasperPrint jasperPrint,
int pageFormatIndex,
int pageIndex,
WriterHelper bodyWriter,
WriterHelper styleWriter,
StyleCache styleCache,
Map rowStyles,
Map columnStyles,
String sheetName,
Color tabColor)
{
super(
documentBuilder,
jasperPrint,
pageFormatIndex,
pageIndex,
bodyWriter,
styleWriter,
styleCache,
rowStyles,
columnStyles,
tabColor);
this.tableName = sheetName;
}
@Override
protected String getIgnoreHyperlinkProperty()
{
return XlsReportConfiguration.PROPERTY_IGNORE_HYPERLINK;
}
@Override
protected void exportTextContents(JRPrintText textElement)
{
String href = null;
String ignLnkPropName = getIgnoreHyperlinkProperty();
Boolean ignoreHyperlink = HyperlinkUtil.getIgnoreHyperlink(ignLnkPropName, textElement);
boolean isIgnoreTextFormatting = isIgnoreTextFormatting(textElement);
if (ignoreHyperlink == null)
{
ignoreHyperlink = getPropertiesUtil().getBooleanProperty(jasperPrint, ignLnkPropName, false);
}
if (!ignoreHyperlink)
{
href = documentBuilder.getHyperlinkURL(textElement, getCurrentItemConfiguration().isOnePagePerSheet());
}
if (href == null)
{
exportStyledText(textElement, false, isIgnoreTextFormatting);
}
else
{
JRStyledText styledText = getStyledText(textElement);
if (styledText != null && styledText.length() > 0)
{
String text = styledText.getText();
Locale locale = getTextLocale(textElement);
int runLimit = 0;
AttributedCharacterIterator iterator = styledText.getAttributedString().getIterator();
while(runLimit < styledText.length() && (runLimit = iterator.getRunLimit()) <= styledText.length())
{
// ODS does not like text:span inside text:a
// writing one text:a inside text:span for each style run
String runText = text.substring(iterator.getIndex(), runLimit);
startTextSpan(
iterator.getAttributes(),
runText,
locale,
isIgnoreTextFormatting);
writeHyperlink(textElement, href, true);
writeText(runText);
endHyperlink(true);
endTextSpan();
iterator.setIndex(runLimit);
}
}
}
}
}
/**
* @see #JROdsExporter(JasperReportsContext)
*/
public JROdsExporter()
{
this(DefaultJasperReportsContext.getInstance());
}
/**
*
*/
public JROdsExporter(JasperReportsContext jasperReportsContext)
{
super(jasperReportsContext);
exporterContext = new ExporterContext(null);
}
@Override
protected Class getConfigurationInterface()
{
return OdsExporterConfiguration.class;
}
@Override
protected Class getItemConfigurationInterface()
{
return OdsReportConfiguration.class;
}
@Override
protected void initExport()
{
super.initExport();
// macroTemplate = macroTemplate == null ? getPropertiesUtil().getProperty(jasperPrint, PROPERTY_MACRO_TEMPLATE) : macroTemplate;
//
// password =
// getStringParameter(
// JRXlsAbstractExporterParameter.PASSWORD,
// JRXlsAbstractExporterParameter.PROPERTY_PASSWORD
// );
}
@Override
protected void initReport()
{
super.initReport();
XlsReportConfiguration configuration = getCurrentItemConfiguration();
//FIXMEODS setBackground()
nature =
new JROdsExporterNature(
jasperReportsContext,
filter,
configuration.isIgnoreGraphics(),
configuration.isIgnorePageMargins()
);
}
// /**
// *
// */
// protected void exportEllipse(TableBuilder tableBuilder, JRPrintEllipse ellipse, JRExporterGridCell gridCell) throws IOException
// {
// JRLineBox box = new JRBaseLineBox(null);
// JRPen pen = box.getPen();
// pen.setLineColor(ellipse.getLinePen().getLineColor());
// pen.setLineStyle(ellipse.getLinePen().getLineStyleValue());
// pen.setLineWidth(ellipse.getLinePen().getLineWidth());
//
// gridCell.setBox(box);//CAUTION: only some exporters set the cell box
//
// tableBuilder.buildCellHeader(styleCache.getCellStyle(gridCell), gridCell.getColSpan(), gridCell.getRowSpan());
// tempBodyWriter.write("");
// insertPageAnchor();
//// tempBodyWriter.write(
//// ""
//// + " "
//// );
// tempBodyWriter.write(" ");
// tableBuilder.buildCellFooter();
// }
@Override
public String getExporterKey()
{
return ODS_EXPORTER_KEY;
}
@Override
public String getExporterPropertiesPrefix()
{
return ODS_EXPORTER_PROPERTIES_PREFIX;
}
/**
*
*/
protected void insertPageAnchor(TableBuilder tableBuilder)
{
if(startPage)
{
String pageName = DocumentBuilder.JR_PAGE_ANCHOR_PREFIX + reportIndex + "_" + (sheetIndex - sheetsBeforeCurrentReport);
String cellAddress = "$'" + tableBuilder.getTableName() + "'.$A$1";
tableBuilder.exportAnchor(pageName);
namedExpressions.append(" \n");
startPage = false;
}
}
@Override
protected void exportEmptyReport() throws JRException, IOException
{
// does nothing in ODS export
}
}