All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jasperreports.engine.export.oasis.JROdsExporter Maven / Gradle / Ivy

There is a newer version: 6.21.3
Show newest version
/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2022 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.ExifOrientationEnum;
import net.sf.jasperreports.engine.util.ImageUtil;
import net.sf.jasperreports.engine.util.ImageUtil.Insets;
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.DataRenderable;
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 ExifOrientationEnum exifOrientation = ExifOrientationEnum.NORMAL; if (renderer instanceof DataRenderable) { byte[] imageData = ((DataRenderable)renderer).getData(jasperReportsContext); exifOrientation = ImageUtil.getExifOrientation(imageData); } 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 (ImageUtil.getRotation(imageElement.getRotation(), exifOrientation)) { 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 (ImageUtil.getRotation(imageElement.getRotation(), exifOrientation)) { 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; } Insets exifCrop = ImageUtil.getExifCrop(imageElement, exifOrientation, cropTop, cropLeft, cropBottom, cropRight); cropLeft = exifCrop.left; cropRight = exifCrop.right; cropTop = exifCrop.top; cropBottom = exifCrop.bottom; 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 (ImageUtil.getRotation(imageElement.getRotation(), exifOrientation)) { 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; } Insets exifCrop = ImageUtil.getExifCrop(imageElement, exifOrientation, cropTop, cropLeft, cropBottom, cropRight); cropLeft = exifCrop.left; cropRight = exifCrop.right; cropTop = exifCrop.top; cropBottom = exifCrop.bottom; } } 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 } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy