/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2009 Jaspersoft Corporation. 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 <http://www.gnu.org/licenses/>.
*/
/*
* Contributors:
* Alex Parfenov - aparfeno@users.sourceforge.net
* Adrian Jackson - iapetus@users.sourceforge.net
* David Taylor - exodussystems@users.sourceforge.net
* Lars Kristensen - llk@users.sourceforge.net
*/
package net.sf.jasperreports.engine.export;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.font.TextAttribute;
import java.awt.geom.Dimension2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.AttributedCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import net.sf.jasperreports.crosstabs.JRCellContents;
import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRImageMapRenderer;
import net.sf.jasperreports.engine.JRImageRenderer;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintElementIndex;
import net.sf.jasperreports.engine.JRPrintEllipse;
import net.sf.jasperreports.engine.JRPrintFrame;
import net.sf.jasperreports.engine.JRPrintGraphicElement;
import net.sf.jasperreports.engine.JRPrintHyperlink;
import net.sf.jasperreports.engine.JRPrintHyperlinkParameter;
import net.sf.jasperreports.engine.JRPrintImage;
import net.sf.jasperreports.engine.JRPrintImageArea;
import net.sf.jasperreports.engine.JRPrintImageAreaHyperlink;
import net.sf.jasperreports.engine.JRPrintLine;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JRPrintRectangle;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JRRenderable;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JRWrappingSvgRenderer;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.base.JRBasePrintFrame;
import net.sf.jasperreports.engine.fonts.FontFamily;
import net.sf.jasperreports.engine.fonts.FontInfo;
import net.sf.jasperreports.engine.type.HyperlinkTypeEnum;
import net.sf.jasperreports.engine.type.LineDirectionEnum;
import net.sf.jasperreports.engine.type.ModeEnum;
import net.sf.jasperreports.engine.type.RunDirectionEnum;
import net.sf.jasperreports.engine.type.ScaleImageEnum;
import net.sf.jasperreports.engine.util.JRColorUtil;
import net.sf.jasperreports.engine.util.JRFontUtil;
import net.sf.jasperreports.engine.util.JRProperties;
import net.sf.jasperreports.engine.util.JRStringUtil;
import net.sf.jasperreports.engine.util.JRStyledText;
import net.sf.jasperreports.engine.util.JRTextAttribute;
import net.sf.jasperreports.engine.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Exports a JasperReports document to HTML format. It has character output type and exports the document to a
* grid-based layout.
*
* @author Teodor Danciu (teodord@users.sourceforge.net)
* @version $Id: JRHtmlExporter.java 4297 2011-04-18 15:23:50Z teodord $
*/
public class JRHtmlExporter extends JRAbstractExporter
{
private static final Log log = LogFactory.getLog(JRHtmlExporter.class);
private static final String HTML_EXPORTER_PROPERTIES_PREFIX = JRProperties.PROPERTY_PREFIX + "export.html.";
/**
* The exporter key, as used in
* {@link GenericElementHandlerEnviroment#getHandler(net.sf.jasperreports.engine.JRGenericElementType, String)}.
*/
public static final String HTML_EXPORTER_KEY = JRProperties.PROPERTY_PREFIX + "html";
/**
* @deprecated Replaced by {@link JRHtmlExporterParameter#PROPERTY_FRAMES_AS_NESTED_TABLES}.
*/
public static final String PROPERTY_FRAMES_AS_NESTED_TABLES = JRHtmlExporterParameter.PROPERTY_FRAMES_AS_NESTED_TABLES;
/**
*
*/
public static final String PROPERTY_HTML_CLASS = HTML_EXPORTER_PROPERTIES_PREFIX + "class";
/**
*
*/
public static final String PROPERTY_HTML_ID = HTML_EXPORTER_PROPERTIES_PREFIX + "id";
/**
* Configuration property that determines the exporter to produce accessible HTML.
*/
public static final String PROPERTY_ACCESSIBLE = HTML_EXPORTER_PROPERTIES_PREFIX + "accessible";
/**
*
*/
protected static final String JR_PAGE_ANCHOR_PREFIX = "JR_PAGE_ANCHOR_";
protected static final float DEFAULT_ZOOM = 1f;
/**
*
*/
protected static final String CSS_TEXT_ALIGN_LEFT = "left";
protected static final String CSS_TEXT_ALIGN_RIGHT = "right";
protected static final String CSS_TEXT_ALIGN_CENTER = "center";
protected static final String CSS_TEXT_ALIGN_JUSTIFY = "justify";
/**
*
*/
protected static final String HTML_VERTICAL_ALIGN_TOP = "top";
protected static final String HTML_VERTICAL_ALIGN_MIDDLE = "middle";
protected static final String HTML_VERTICAL_ALIGN_BOTTOM = "bottom";
public static final String IMAGE_NAME_PREFIX = "img_";
protected static final int IMAGE_NAME_PREFIX_LEGTH = IMAGE_NAME_PREFIX.length();
protected class ExporterContext extends BaseExporterContext implements JRHtmlExporterContext
{
public String getExportPropertiesPrefix()
{
return HTML_EXPORTER_PROPERTIES_PREFIX;
}
public String getHyperlinkURL(JRPrintHyperlink link)
{
return JRHtmlExporter.this.getHyperlinkURL(link);
}
}
/**
*
*/
protected Writer writer;
protected JRExportProgressMonitor progressMonitor;
protected Map rendererToImagePathMap;
protected Map imageMaps;
protected Map imageNameToImageDataMap;
protected List imagesToProcess;
protected boolean isPxImageLoaded;
protected int reportIndex;
protected int pageIndex;
/**
*
*/
protected File imagesDir;
protected String imagesURI;
protected boolean isOutputImagesToDir;
protected boolean isRemoveEmptySpace;
protected boolean isWhitePageBackground;
protected String encoding;
protected String sizeUnit;
protected float zoom = DEFAULT_ZOOM;
protected boolean isUsingImagesToAlign;
protected boolean isWrapBreakWord;
protected boolean isIgnorePageMargins;
protected boolean accessibleHtml;
protected boolean flushOutput;
/**
*
*/
protected String htmlHeader;
protected String betweenPagesHtml;
protected String htmlFooter;
protected StringProvider emptyCellStringProvider;
/**
* @deprecated
*/
protected Map fontMap;
private LinkedList backcolorStack;
private Color backcolor;
protected JRHyperlinkTargetProducerFactory targetProducerFactory = new DefaultHyperlinkTargetProducerFactory();
protected boolean hyperlinkStarted;
protected int thDepth;
protected ExporterNature nature;
protected JRHtmlExporterContext exporterContext = new ExporterContext();
public JRHtmlExporter()
{
backcolorStack = new LinkedList();
backcolor = null;
}
/**
*
*/
public void exportReport() throws JRException
{
progressMonitor = (JRExportProgressMonitor)parameters.get(JRExporterParameter.PROGRESS_MONITOR);
/* */
setOffset();
try
{
/* */
setExportContext();
/* */
setInput();
if (!parameters.containsKey(JRExporterParameter.FILTER))
{
filter = createFilter(HTML_EXPORTER_PROPERTIES_PREFIX);
}
/* */
if (!isModeBatch)
{
setPageRange();
}
htmlHeader = (String)parameters.get(JRHtmlExporterParameter.HTML_HEADER);
betweenPagesHtml = (String)parameters.get(JRHtmlExporterParameter.BETWEEN_PAGES_HTML);
htmlFooter = (String)parameters.get(JRHtmlExporterParameter.HTML_FOOTER);
imagesDir = (File)parameters.get(JRHtmlExporterParameter.IMAGES_DIR);
if (imagesDir == null)
{
String dir = (String)parameters.get(JRHtmlExporterParameter.IMAGES_DIR_NAME);
if (dir != null)
{
imagesDir = new File(dir);
}
}
isRemoveEmptySpace =
getBooleanParameter(
JRHtmlExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
JRHtmlExporterParameter.PROPERTY_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
false
);
isWhitePageBackground =
getBooleanParameter(
JRHtmlExporterParameter.IS_WHITE_PAGE_BACKGROUND,
JRHtmlExporterParameter.PROPERTY_WHITE_PAGE_BACKGROUND,
true
);
Boolean isOutputImagesToDirParameter = (Boolean)parameters.get(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR);
if (isOutputImagesToDirParameter != null)
{
isOutputImagesToDir = isOutputImagesToDirParameter.booleanValue();
}
String uri = (String)parameters.get(JRHtmlExporterParameter.IMAGES_URI);
if (uri != null)
{
imagesURI = uri;
}
encoding =
getStringParameterOrDefault(
JRExporterParameter.CHARACTER_ENCODING,
JRExporterParameter.PROPERTY_CHARACTER_ENCODING
);
rendererToImagePathMap = new HashMap();
imageMaps = new HashMap();
imagesToProcess = new ArrayList();
isPxImageLoaded = false;
//backward compatibility with the IMAGE_MAP parameter
imageNameToImageDataMap = (Map)parameters.get(JRHtmlExporterParameter.IMAGES_MAP);
// if (imageNameToImageDataMap == null)
// {
// imageNameToImageDataMap = new HashMap();
// }
//END - backward compatibility with the IMAGE_MAP parameter
isWrapBreakWord =
getBooleanParameter(
JRHtmlExporterParameter.IS_WRAP_BREAK_WORD,
JRHtmlExporterParameter.PROPERTY_WRAP_BREAK_WORD,
false
);
sizeUnit =
getStringParameterOrDefault(
JRHtmlExporterParameter.SIZE_UNIT,
JRHtmlExporterParameter.PROPERTY_SIZE_UNIT
);
Float zoomRatio = (Float)parameters.get(JRHtmlExporterParameter.ZOOM_RATIO);
if (zoomRatio != null)
{
zoom = zoomRatio.floatValue();
if (zoom <= 0)
{
throw new JRException("Invalid zoom ratio : " + zoom);
}
}
else
{
zoom = DEFAULT_ZOOM;
}
isUsingImagesToAlign =
getBooleanParameter(
JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,
JRHtmlExporterParameter.PROPERTY_USING_IMAGES_TO_ALIGN,
true
);
if (isUsingImagesToAlign)
{
emptyCellStringProvider =
new StringProvider()
{
public String getStringForCollapsedTD(Object value, int width, int height)
{
return "><img alt=\"\" src=\"" + value + "px\" style=\"width: " + toSizeUnit(width) + "; height: " + toSizeUnit(height) + ";\"/>";
}
public String getStringForEmptyTD(Object value)
{
return "<img alt=\"\" src=\"" + value + "px\" border=\"0\"/>";
}
public String getReportTableStyle()
{
return null;
}
};
loadPxImage();
}
else
{
emptyCellStringProvider =
new StringProvider()
{
public String getStringForCollapsedTD(Object value, int width, int height)
{
return " style=\"width: " + toSizeUnit(width) + "; height: " + toSizeUnit(height) + ";\">";
}
public String getStringForEmptyTD(Object value)
{
return "";
}
public String getReportTableStyle()
{
// required for lines and rectangles, but doesn't work in IE
// border-collapse: collapse seems to take care of this though
return "empty-cells: show";
}
};
}
isIgnorePageMargins =
getBooleanParameter(
JRExporterParameter.IGNORE_PAGE_MARGINS,
JRExporterParameter.PROPERTY_IGNORE_PAGE_MARGINS,
false
);
accessibleHtml =
JRProperties.getBooleanProperty(
jasperPrint,
PROPERTY_ACCESSIBLE,
false
);
fontMap = (Map) parameters.get(JRExporterParameter.FONT_MAP);
setHyperlinkProducerFactory();
//FIXMENOW check all exporter properties that are supposed to work at report level
boolean deepGrid =
!getBooleanParameter(
JRHtmlExporterParameter.FRAMES_AS_NESTED_TABLES,
JRHtmlExporterParameter.PROPERTY_FRAMES_AS_NESTED_TABLES,
true
);
nature = new JRHtmlExporterNature(filter, deepGrid, isIgnorePageMargins);
flushOutput = getBooleanParameter(JRHtmlExporterParameter.FLUSH_OUTPUT,
JRHtmlExporterParameter.PROPERTY_FLUSH_OUTPUT,
true);
StringBuffer sb = (StringBuffer)parameters.get(JRExporterParameter.OUTPUT_STRING_BUFFER);
if (sb != null)
{
try
{
writer = new StringWriter();
exportReportToWriter();
sb.append(writer.toString());
}
catch (IOException e)
{
throw new JRException("Error writing to StringBuffer writer : " + jasperPrint.getName(), e);
}
finally
{
if (writer != null)
{
try
{
writer.close();
}
catch(IOException e)
{
}
}
}
}
else
{
writer = (Writer)parameters.get(JRExporterParameter.OUTPUT_WRITER);
if (writer != null)
{
try
{
exportReportToWriter();
}
catch (IOException e)
{
throw new JRException("Error writing to writer : " + jasperPrint.getName(), e);
}
}
else
{
OutputStream os = (OutputStream)parameters.get(JRExporterParameter.OUTPUT_STREAM);
if (os != null)
{
try
{
writer = new OutputStreamWriter(os, encoding);
exportReportToWriter();
}
catch (IOException e)
{
throw new JRException("Error writing to OutputStream writer : " + jasperPrint.getName(), e);
}
}
else
{
File destFile = (File)parameters.get(JRExporterParameter.OUTPUT_FILE);
if (destFile == null)
{
String fileName = (String)parameters.get(JRExporterParameter.OUTPUT_FILE_NAME);
if (fileName != null)
{
destFile = new File(fileName);
}
else
{
throw new JRException("No output specified for the exporter.");
}
}
try
{
os = new FileOutputStream(destFile);
writer = new OutputStreamWriter(os, encoding);
}
catch (IOException e)
{
throw new JRException("Error creating to file writer : " + jasperPrint.getName(), e);
}
if (imagesDir == null)
{
imagesDir = new File(destFile.getParent(), destFile.getName() + "_files");
}
if (isOutputImagesToDirParameter == null)
{
isOutputImagesToDir = true;
}
if (imagesURI == null)
{
imagesURI = imagesDir.getName() + "/";
}
try
{
exportReportToWriter();
}
catch (IOException e)
{
throw new JRException("Error writing to file writer : " + jasperPrint.getName(), e);
}
finally
{
if (writer != null)
{
try
{
writer.close();
}
catch(IOException e)
{
}
}
}
}
}
}
if (isOutputImagesToDir)
{
if (imagesDir == null)
{
throw new JRException("The images directory was not specified for the exporter.");
}
if (isPxImageLoaded || (imagesToProcess != null && imagesToProcess.size() > 0))
{
if (!imagesDir.exists())
{
imagesDir.mkdir();
}
if (isPxImageLoaded)
{
JRRenderable pxRenderer =
JRImageRenderer.getInstance("net/sf/jasperreports/engine/images/pixel.GIF");
byte[] imageData = pxRenderer.getImageData();
File imageFile = new File(imagesDir, "px");
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(imageFile);
fos.write(imageData, 0, imageData.length);
}
catch (IOException e)
{
throw new JRException("Error writing to image file : " + imageFile, e);
}
finally
{
if (fos != null)
{
try
{
fos.close();
}
catch(IOException e)
{
}
}
}
}
for(Iterator it = imagesToProcess.iterator(); it.hasNext();)
{
JRPrintElementIndex imageIndex = (JRPrintElementIndex)it.next();
JRPrintImage image = getImage(jasperPrintList, imageIndex);
JRRenderable renderer = image.getRenderer();
if (renderer.getType() == JRRenderable.TYPE_SVG)
{
renderer =
new JRWrappingSvgRenderer(
renderer,
new Dimension(image.getWidth(), image.getHeight()),
ModeEnum.OPAQUE == image.getModeValue() ? image.getBackcolor() : null
);
}
byte[] imageData = renderer.getImageData();
File imageFile = new File(imagesDir, getImageName(imageIndex));
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(imageFile);
fos.write(imageData, 0, imageData.length);
}
catch (IOException e)
{
throw new JRException("Error writing to image file : " + imageFile, e);
}
finally
{
if (fos != null)
{
try
{
fos.close();
}
catch(IOException e)
{
}
}
}
}
}
}
}
finally
{
resetExportContext();
}
}
public static JRPrintImage getImage(List jasperPrintList, String imageName)
{
return getImage(jasperPrintList, getPrintElementIndex(imageName));
}
public static JRPrintImage getImage(List jasperPrintList, JRPrintElementIndex imageIndex)
{
JasperPrint report = (JasperPrint)jasperPrintList.get(imageIndex.getReportIndex());
JRPrintPage page = (JRPrintPage)report.getPages().get(imageIndex.getPageIndex());
Integer[] elementIndexes = imageIndex.getAddressArray();
Object element = page.getElements().get(elementIndexes[0].intValue());
for (int i = 1; i < elementIndexes.length; ++i)
{
JRPrintFrame frame = (JRPrintFrame) element;
element = frame.getElements().get(elementIndexes[i].intValue());
}
return (JRPrintImage) element;
}
/**
*
*/
protected void exportReportToWriter() throws JRException, IOException
{
if (htmlHeader == null)
{
// no doctype because of bug 1430880
// writer.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n");
// writer.write("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n");
writer.write("<html>\n");
writer.write("<head>\n");
writer.write(" <title></title>\n");
writer.write(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + encoding + "\"/>\n");
writer.write(" <style type=\"text/css\">\n");
writer.write(" a {text-decoration: none}\n");
writer.write(" </style>\n");
writer.write("</head>\n");
writer.write("<body text=\"#000000\" link=\"#000000\" alink=\"#000000\" vlink=\"#000000\">\n");
writer.write("<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n");
writer.write("<tr><td width=\"50%\"> </td><td align=\"center\">\n");
writer.write("\n");
}
else
{
writer.write(htmlHeader);
}
for(reportIndex = 0; reportIndex < jasperPrintList.size(); reportIndex++)
{
setJasperPrint((JasperPrint)jasperPrintList.get(reportIndex));
List pages = jasperPrint.getPages();
if (pages != null && pages.size() > 0)
{
if (isModeBatch)
{
startPageIndex = 0;
endPageIndex = pages.size() - 1;
}
JRPrintPage page = null;
for(pageIndex = startPageIndex; pageIndex <= endPageIndex; pageIndex++)
{
if (Thread.interrupted())
{
throw new JRException("Current thread interrupted.");
}
page = (JRPrintPage)pages.get(pageIndex);
writer.write("<a name=\"" + JR_PAGE_ANCHOR_PREFIX + reportIndex + "_" + (pageIndex + 1) + "\"></a>\n");
/* */
exportPage(page);
if (reportIndex < jasperPrintList.size() - 1 || pageIndex < endPageIndex)
{
if (betweenPagesHtml == null)
{
writer.write("<br/>\n<br/>\n");
}
else
{
writer.write(betweenPagesHtml);
}
}
writer.write("\n");
}
}
}
if (htmlFooter == null)
{
writer.write("</td><td width=\"50%\"> </td></tr>\n");
writer.write("</table>\n");
writer.write("</body>\n");
writer.write("</html>\n");
}
else
{
writer.write(htmlFooter);
}
if (flushOutput)
{
writer.flush();
}
}
/**
*
*/
protected void exportPage(JRPrintPage page) throws JRException, IOException
{
List elements = null;
if (accessibleHtml)
{
JRBasePrintFrame frame = new JRBasePrintFrame(jasperPrint.getDefaultStyleProvider());
new JRHtmlExporterHelper(jasperPrint).createNestedFrames(page.getElements().listIterator(), frame);
elements = frame.getElements();
}
else
{
elements = page.getElements();
}
JRGridLayout layout =
new JRGridLayout(
nature,
elements,
jasperPrint.getPageWidth(),
jasperPrint.getPageHeight(),
globalOffsetX,
globalOffsetY,
null //address
);
exportGrid(layout, isWhitePageBackground);
if (progressMonitor != null)
{
progressMonitor.afterPageExport();
}
}
/**
*
*/
protected void exportGrid(JRGridLayout gridLayout, boolean whitePageBackground) throws IOException, JRException
{
CutsInfo xCuts = gridLayout.getXCuts();
JRExporterGridCell[][] grid = gridLayout.getGrid();
String tableStyle = "width: " + toSizeUnit(gridLayout.getWidth()) + "; border-collapse: collapse";
String additionalTableStyle = emptyCellStringProvider.getReportTableStyle();
if (additionalTableStyle != null)
{
tableStyle += "; " + additionalTableStyle;
}
writer.write("<table style=\"" + tableStyle + "\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"");
if (whitePageBackground)
{
writer.write(" bgcolor=\"white\"");
}
writer.write(">\n");
if (whitePageBackground)
{
setBackcolor(Color.white);
}
writer.write("<tr>\n");
int width = 0;
for(int i = 1; i < xCuts.size(); i++)
{
width = xCuts.getCut(i) - xCuts.getCut(i - 1);
writer.write(" <td" + emptyCellStringProvider.getStringForCollapsedTD(imagesURI, width, 1) + "</td>\n");
}
writer.write("</tr>\n");
thDepth = 0;
for(int y = 0; y < grid.length; y++)
{
if (gridLayout.getYCuts().isCutSpanned(y) || !isRemoveEmptySpace)
{
JRExporterGridCell[] gridRow = grid[y];
int rowHeight = JRGridLayout.getRowHeight(gridRow);
boolean hasEmptyCell = hasEmptyCell(gridRow);
writer.write("<tr valign=\"top\"");
if (!hasEmptyCell)
{
writer.write(" style=\"height:" + toSizeUnit(rowHeight) + "\"");
}
writer.write(">\n");
for(int x = 0; x < gridRow.length; x++)
{
JRExporterGridCell gridCell = gridRow[x];
if(gridCell.getWrapper() == null)
{
writeEmptyCell(gridCell, rowHeight);
}
else
{
JRPrintElement element = gridCell.getWrapper().getElement();
String thTag = null;
if (
element != null
&& element.hasProperties()
)
{
thTag = element.getPropertiesMap().getProperty(JRPdfExporterTagHelper.PROPERTY_TAG_TH);
}
if (thTag != null && (JRPdfExporterTagHelper.TAG_START.equals(thTag) || JRPdfExporterTagHelper.TAG_FULL.equals(thTag)))
{
thDepth++;
}
if (element instanceof JRPrintLine)
{
exportLine((JRPrintLine)element, gridCell);
}
else if (element instanceof JRPrintRectangle)
{
exportRectangle((JRPrintRectangle)element, gridCell);
}
else if (element instanceof JRPrintEllipse)
{
exportRectangle((JRPrintEllipse)element, gridCell);
}
else if (element instanceof JRPrintImage)
{
exportImage((JRPrintImage)element, gridCell);
}
else if (element instanceof JRPrintText)
{
exportText((JRPrintText)element, gridCell);
}
else if (element instanceof JRPrintFrame)
{
exportFrame((JRPrintFrame) element, gridCell);
}
else if (element instanceof JRGenericPrintElement)
{
exportGenericElement((JRGenericPrintElement) element,
gridCell, rowHeight);
}
if (thTag != null && (JRPdfExporterTagHelper.TAG_END.equals(thTag) || JRPdfExporterTagHelper.TAG_FULL.equals(thTag)))
{
thDepth--;
}
}
x += gridCell.getColSpan() - 1;
}
writer.write("</tr>\n");
}
}
if (whitePageBackground)
{
restoreBackcolor();
}
writer.write("</table>\n");
}
private boolean hasEmptyCell(JRExporterGridCell[] gridRow)
{
if (gridRow[0].getWrapper() == null) // quick exit
{
return true;
}
boolean hasEmptyCell = false;
for(int x = 1; x < gridRow.length; x++)
{
if (gridRow[x].getWrapper() == null)
{
hasEmptyCell = true;
break;
}
}
return hasEmptyCell;
}
protected void writeEmptyCell(JRExporterGridCell cell, int rowHeight) throws IOException
{
String cellTag = getCellTag(cell);
writer.write(" <" + cellTag);
if (cell.getColSpan() > 1)
{
writer.write(" colspan=\"" + cell.getColSpan() + "\"");
}
StringBuffer styleBuffer = new StringBuffer();
appendBackcolorStyle(cell, styleBuffer);
appendBorderStyle(cell.getBox(), styleBuffer);
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(emptyCellStringProvider.getStringForCollapsedTD(imagesURI, cell.getWidth(), rowHeight));
writer.write("</" + cellTag + ">\n");
}
/**
*
*/
protected void exportLine(JRPrintLine line, JRExporterGridCell gridCell) throws IOException
{
writeCellStart(gridCell);
StringBuffer styleBuffer = new StringBuffer();
appendBackcolorStyle(gridCell, styleBuffer);
String side = null;
float ratio = line.getWidth() / line.getHeight();
if (ratio > 1)
{
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN)
{
side = "top";
}
else
{
side = "bottom";
}
}
else
{
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN)
{
side = "left";
}
else
{
side = "right";
}
}
appendPen(
styleBuffer,
line.getLinePen(),
side
);
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(">");
writer.write(emptyCellStringProvider.getStringForEmptyTD(imagesURI));
writeCellEnd(gridCell);
}
/**
*
*/
protected void writeCellStart(JRExporterGridCell gridCell) throws IOException
{
writer.write(" <" + getCellTag(gridCell));
if (gridCell.getColSpan() > 1)
{
writer.write(" colspan=\"" + gridCell.getColSpan() +"\"");
}
if (gridCell.getRowSpan() > 1)
{
writer.write(" rowspan=\"" + gridCell.getRowSpan() + "\"");
}
if (gridCell.getWrapper() != null)
{
JRPrintElement element = gridCell.getWrapper().getElement();
if (element != null)
{
String id = JRProperties.getProperty(element, PROPERTY_HTML_ID);
if (id != null)
{
writer.write(" id=\"" + id +"\"");
}
String clazz = JRProperties.getProperty(element, PROPERTY_HTML_CLASS);
if (clazz != null)
{
writer.write(" class=\"" + clazz +"\"");
}
}
}
}
/**
*
*/
protected void writeCellEnd(JRExporterGridCell gridCell) throws IOException
{
writer.write("</" + getCellTag(gridCell) + ">\n");
}
/**
*
*/
protected String getCellTag(JRExporterGridCell gridCell)
{
if (accessibleHtml)
{
if (thDepth > 0)
{
return "th"; //FIXMEHTML th tags have center alignment by default
}
else
{
ElementWrapper wrapper = gridCell.getWrapper();
OccupiedGridCell occupiedCell = gridCell instanceof OccupiedGridCell ? (OccupiedGridCell)gridCell : null;
if (occupiedCell != null)
{
wrapper = occupiedCell.getOccupier().getWrapper();
}
if (wrapper != null)
{
String cellContentsType = wrapper.getProperty(JRCellContents.PROPERTY_TYPE);
if (
JRCellContents.TYPE_CROSSTAB_HEADER.equals(cellContentsType)
|| JRCellContents.TYPE_COLUMN_HEADER.equals(cellContentsType)
|| JRCellContents.TYPE_ROW_HEADER.equals(cellContentsType)
)
{
return "th";
}
}
}
}
return "td";
}
/**
*
*/
protected void exportRectangle(JRPrintGraphicElement element, JRExporterGridCell gridCell) throws IOException
{
writeCellStart(gridCell);
StringBuffer styleBuffer = new StringBuffer();
appendBackcolorStyle(gridCell, styleBuffer);
appendPen(
styleBuffer,
element.getLinePen(),
null
);
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(">");
writer.write(emptyCellStringProvider.getStringForEmptyTD(imagesURI));
writeCellEnd(gridCell);
}
/**
*
*/
protected void exportStyledText(JRStyledText styledText, Locale locale) throws IOException
{
exportStyledText(styledText, null, locale);
}
/**
*
*/
protected void exportStyledText(JRStyledText styledText, String tooltip, Locale locale) throws IOException
{
String text = styledText.getText();
int runLimit = 0;
AttributedCharacterIterator iterator = styledText.getAttributedString().getIterator();
boolean first = true;
boolean startedSpan = false;
while(runLimit < styledText.length() && (runLimit = iterator.getRunLimit()) <= styledText.length())
{
//if there are several text runs, write the tooltip into a parent <span>
if (first && runLimit < styledText.length() && tooltip != null)
{
startedSpan = true;
writer.write("<span title=\"");
writer.write(JRStringUtil.xmlEncode(tooltip));
writer.write("\">");
//reset the tooltip so that inner <span>s to not use it
tooltip = null;
}
first = false;
exportStyledTextRun(
iterator.getAttributes(),
text.substring(iterator.getIndex(), runLimit),
tooltip,
locale
);
iterator.setIndex(runLimit);
}
if (startedSpan)
{
writer.write("</span>");
}
}
/**
*
*/
protected void exportStyledTextRun(Map attributes, String text, Locale locale) throws IOException
{
exportStyledTextRun(attributes, text, null, locale);
}
/**
*
*/
protected void exportStyledTextRun(
Map attributes,
String text,
String tooltip,
Locale locale
) throws IOException
{
String fontFamilyAttr = (String)attributes.get(TextAttribute.FAMILY);
String fontFamily = fontFamilyAttr;
if (fontMap != null && fontMap.containsKey(fontFamilyAttr))
{
fontFamily = (String) fontMap.get(fontFamilyAttr);
}
else
{
FontInfo fontInfo = JRFontUtil.getFontInfo(fontFamilyAttr, locale);
if (fontInfo != null)
{
//fontName found in font extensions
FontFamily family = fontInfo.getFontFamily();
String exportFont = family.getExportFont(getExporterKey());
if (exportFont != null)
{
fontFamily = exportFont;
}
}
}
boolean localHyperlink = false;
JRPrintHyperlink hyperlink = (JRPrintHyperlink)attributes.get(JRTextAttribute.HYPERLINK);
if (!hyperlinkStarted && hyperlink != null)
{
startHyperlink(hyperlink);
localHyperlink = true;
}
writer.write("<span style=\"font-family: ");
writer.write(fontFamily);
writer.write("; ");
Color forecolor = (Color)attributes.get(TextAttribute.FOREGROUND);
if (!hyperlinkStarted || !Color.black.equals(forecolor))
{
writer.write("color: #");
writer.write(JRColorUtil.getColorHexa(forecolor));
writer.write("; ");
}
Color runBackcolor = (Color)attributes.get(TextAttribute.BACKGROUND);
if (runBackcolor != null)
{
writer.write("background-color: #");
writer.write(JRColorUtil.getColorHexa(runBackcolor));
writer.write("; ");
}
writer.write("font-size: ");
writer.write(toSizeUnit(((Float)attributes.get(TextAttribute.SIZE)).intValue()));
writer.write(";");
/*
if (!horizontalAlignment.equals(CSS_TEXT_ALIGN_LEFT))
{
writer.write(" text-align: ");
writer.write(horizontalAlignment);
writer.write(";");
}
*/
if (TextAttribute.WEIGHT_BOLD.equals(attributes.get(TextAttribute.WEIGHT)))
{
writer.write(" font-weight: bold;");
}
if (TextAttribute.POSTURE_OBLIQUE.equals(attributes.get(TextAttribute.POSTURE)))
{
writer.write(" font-style: italic;");
}
if (TextAttribute.UNDERLINE_ON.equals(attributes.get(TextAttribute.UNDERLINE)))
{
writer.write(" text-decoration: underline;");
}
if (TextAttribute.STRIKETHROUGH_ON.equals(attributes.get(TextAttribute.STRIKETHROUGH)))
{
writer.write(" text-decoration: line-through;");
}
if (TextAttribute.SUPERSCRIPT_SUPER.equals(attributes.get(TextAttribute.SUPERSCRIPT)))
{
writer.write(" vertical-align: super;");
}
else if (TextAttribute.SUPERSCRIPT_SUB.equals(attributes.get(TextAttribute.SUPERSCRIPT)))
{
writer.write(" vertical-align: sub;");
}
writer.write("\"");
if (tooltip != null)
{
writer.write(" title=\"");
writer.write(JRStringUtil.xmlEncode(tooltip));
writer.write("\"");
}
writer.write(">");
writer.write(
JRStringUtil.htmlEncode(text)
);
writer.write("</span>");
if (localHyperlink)
{
endHyperlink();
}
}
/**
*
*/
protected void exportText(JRPrintText text, JRExporterGridCell gridCell) throws IOException
{
JRStyledText styledText = getStyledText(text);
int textLength = 0;
if (styledText != null)
{
textLength = styledText.length();
}
writeCellStart(gridCell);//FIXME why dealing with cell style if no text to print (textLength == 0)?
if (text.getRunDirectionValue() == RunDirectionEnum.RTL)
{
writer.write(" dir=\"rtl\"");
}
StringBuffer styleBuffer = new StringBuffer();
String verticalAlignment = HTML_VERTICAL_ALIGN_TOP;
switch (text.getVerticalAlignmentValue())
{
case BOTTOM :
{
verticalAlignment = HTML_VERTICAL_ALIGN_BOTTOM;
break;
}
case MIDDLE :
{
verticalAlignment = HTML_VERTICAL_ALIGN_MIDDLE;
break;
}
case TOP :
default :
{
verticalAlignment = HTML_VERTICAL_ALIGN_TOP;
}
}
if (!verticalAlignment.equals(HTML_VERTICAL_ALIGN_TOP))
{
styleBuffer.append(" vertical-align: ");
styleBuffer.append(verticalAlignment);
styleBuffer.append(";");
}
appendBackcolorStyle(gridCell, styleBuffer);
appendBorderStyle(gridCell.getBox(), styleBuffer);
appendPaddingStyle(text.getLineBox(), styleBuffer);
String horizontalAlignment = CSS_TEXT_ALIGN_LEFT;
if (textLength > 0)
{
switch (text.getHorizontalAlignmentValue())
{
case RIGHT :
{
horizontalAlignment = CSS_TEXT_ALIGN_RIGHT;
break;
}
case CENTER :
{
horizontalAlignment = CSS_TEXT_ALIGN_CENTER;
break;
}
case JUSTIFIED :
{
horizontalAlignment = CSS_TEXT_ALIGN_JUSTIFY;
break;
}
case LEFT :
default :
{
horizontalAlignment = CSS_TEXT_ALIGN_LEFT;
}
}
if (
(text.getRunDirectionValue() == RunDirectionEnum.LTR
&& !horizontalAlignment.equals(CSS_TEXT_ALIGN_LEFT))
|| (text.getRunDirectionValue() == RunDirectionEnum.RTL
&& !horizontalAlignment.equals(CSS_TEXT_ALIGN_RIGHT))
)
{
styleBuffer.append("text-align: ");
styleBuffer.append(horizontalAlignment);
styleBuffer.append(";");
}
}
if (isWrapBreakWord)
{
styleBuffer.append("width: " + toSizeUnit(gridCell.getWidth()) + "; ");
styleBuffer.append("word-wrap: break-word; ");
}
if (text.getLineBreakOffsets() != null)
{
//if we have line breaks saved in the text, set nowrap so that
//the text only wraps at the explicit positions
styleBuffer.append("white-space: nowrap; ");
}
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(">");
writer.write("<p style=\"overflow: hidden; ");
switch (text.getParagraph().getLineSpacing())
{
case SINGLE:
default:
{
writer.write("line-height: 1.0; ");
break;
}
case ONE_AND_HALF:
{
writer.write("line-height: 1.5; ");
break;
}
case DOUBLE:
{
writer.write("line-height: 2.0; ");
break;
}
case PROPORTIONAL:
{
writer.write("line-height: " + (int)(100 * text.getParagraph().getLineSpacingSize().floatValue()) + "%; ");
break;
}
case AT_LEAST:
case FIXED:
{
writer.write("line-height: " + text.getParagraph().getLineSpacingSize().floatValue() + "px; ");
break;
}
}
writer.write("text-indent: " + text.getParagraph().getFirstLineIndent().intValue() + "px; ");
// writer.write("margin-left: " + text.getParagraph().getLeftIndent().intValue() + "px; ");
// writer.write("margin-right: " + text.getParagraph().getRightIndent().intValue() + "px; ");
// writer.write("margin-top: " + text.getParagraph().getSpacingBefore().intValue() + "px; ");
// writer.write("margin-bottom: " + text.getParagraph().getSpacingAfter().intValue() + "px; ");
writer.write("\">");
if (text.getAnchorName() != null)
{
writer.write("<a name=\"");
writer.write(text.getAnchorName());
writer.write("\"/>");
}
startHyperlink(text);
if (textLength > 0)
{
//only use text tooltip when no hyperlink present
String textTooltip = hyperlinkStarted ? null : text.getHyperlinkTooltip();
exportStyledText(styledText, textTooltip, getTextLocale(text));
}
else
{
writer.write(emptyCellStringProvider.getStringForEmptyTD(imagesURI));
}
endHyperlink();
writer.write("</p>");
writeCellEnd(gridCell);
}
protected boolean startHyperlink(JRPrintHyperlink link) throws IOException
{
String href = getHyperlinkURL(link);
if (href != null)
{
writer.write("<a href=\"");
writer.write(href);
writer.write("\"");
String target = getHyperlinkTarget(link);
if (target != null)
{
writer.write(" target=\"");
writer.write(target);
writer.write("\"");
}
if (link.getHyperlinkTooltip() != null)
{
writer.write(" title=\"");
writer.write(JRStringUtil.xmlEncode(link.getHyperlinkTooltip()));
writer.write("\"");
}
writer.write(">");
}
hyperlinkStarted = href != null;
return hyperlinkStarted;
}
protected String getHyperlinkTarget(JRPrintHyperlink link)
{
String target = null;
JRHyperlinkTargetProducer producer = targetProducerFactory.getHyperlinkTargetProducer(link.getLinkTarget());
if (producer == null)
{
switch(link.getHyperlinkTargetValue())
{
case BLANK :
{
target = "_blank";//FIXME make reverse for html markup hyperlinks
break;
}
case PARENT :
{
target = "_parent";
break;
}
case TOP :
{
target = "_top";
break;
}
case CUSTOM :
{
boolean paramFound = false;
List parameters = link.getHyperlinkParameters() == null ? null : link.getHyperlinkParameters().getParameters();
if (parameters != null)
{
for(Iterator it = parameters.iterator(); it.hasNext();)
{
JRPrintHyperlinkParameter parameter = (JRPrintHyperlinkParameter)it.next();
if (link.getLinkTarget().equals(parameter.getName()))
{
target = parameter.getValue() == null ? null : parameter.getValue().toString();
paramFound = true;
break;
}
}
}
if (!paramFound)
{
target = link.getLinkTarget();
}
break;
}
case SELF :
default :
{
}
}
}
else
{
target = producer.getHyperlinkTarget(link);
}
return target;
}
protected String getHyperlinkURL(JRPrintHyperlink link)
{
String href = null;
JRHyperlinkProducer customHandler = getCustomHandler(link);
if (customHandler == null)
{
switch(link.getHyperlinkTypeValue())
{
case REFERENCE :
{
if (link.getHyperlinkReference() != null)
{
href = link.getHyperlinkReference();
}
break;
}
case LOCAL_ANCHOR :
{
if (link.getHyperlinkAnchor() != null)
{
href = "#" + link.getHyperlinkAnchor();
}
break;
}
case LOCAL_PAGE :
{
if (link.getHyperlinkPage() != null)
{
href = "#" + JR_PAGE_ANCHOR_PREFIX + reportIndex + "_" + link.getHyperlinkPage().toString();
}
break;
}
case REMOTE_ANCHOR :
{
if (
link.getHyperlinkReference() != null &&
link.getHyperlinkAnchor() != null
)
{
href = link.getHyperlinkReference() + "#" + link.getHyperlinkAnchor();
}
break;
}
case REMOTE_PAGE :
{
if (
link.getHyperlinkReference() != null &&
link.getHyperlinkPage() != null
)
{
href = link.getHyperlinkReference() + "#" + JR_PAGE_ANCHOR_PREFIX + "0_" + link.getHyperlinkPage().toString();
}
break;
}
case NONE :
default :
{
break;
}
}
}
else
{
href = customHandler.getHyperlink(link);
}
return href;
}
protected void endHyperlink() throws IOException
{
if (hyperlinkStarted)
{
writer.write("</a>");
}
hyperlinkStarted = false;
}
protected boolean appendBorderStyle(JRLineBox box, StringBuffer styleBuffer)
{
boolean addedToStyle = false;
if (box != null)
{
addedToStyle |= appendPen(
styleBuffer,
box.getTopPen(),
"top"
);
addedToStyle |= appendPen(
styleBuffer,
box.getLeftPen(),
"left"
);
addedToStyle |= appendPen(
styleBuffer,
box.getBottomPen(),
"bottom"
);
addedToStyle |= appendPen(
styleBuffer,
box.getRightPen(),
"right"
);
}
return addedToStyle;
}
protected boolean appendPaddingStyle(JRLineBox box, StringBuffer styleBuffer)
{
boolean addedToStyle = false;
if (box != null)
{
addedToStyle |= appendPadding(
styleBuffer,
box.getTopPadding(),
"top"
);
addedToStyle |= appendPadding(
styleBuffer,
box.getLeftPadding(),
"left"
);
addedToStyle |= appendPadding(
styleBuffer,
box.getBottomPadding(),
"bottom"
);
addedToStyle |= appendPadding(
styleBuffer,
box.getRightPadding(),
"right"
);
}
return addedToStyle;
}
protected Color appendBackcolorStyle(JRExporterGridCell gridCell, StringBuffer styleBuffer)
{
Color cellBackcolor = gridCell.getCellBackcolor();
if (cellBackcolor != null && (backcolor == null || cellBackcolor.getRGB() != backcolor.getRGB()))
{
styleBuffer.append("background-color: #");
styleBuffer.append(JRColorUtil.getColorHexa(cellBackcolor));
styleBuffer.append("; ");
return cellBackcolor;
}
return null;
}
/**
*
*/
protected void exportImage(JRPrintImage image, JRExporterGridCell gridCell) throws JRException, IOException
{
writeCellStart(gridCell);
StringBuffer styleBuffer = new StringBuffer();
String horizontalAlignment = CSS_TEXT_ALIGN_LEFT;
switch (image.getHorizontalAlignmentValue())
{
case RIGHT :
{
horizontalAlignment = CSS_TEXT_ALIGN_RIGHT;
break;
}
case CENTER :
{
horizontalAlignment = CSS_TEXT_ALIGN_CENTER;
break;
}
case LEFT :
default :
{
horizontalAlignment = CSS_TEXT_ALIGN_LEFT;
}
}
if (!horizontalAlignment.equals(CSS_TEXT_ALIGN_LEFT))
{
styleBuffer.append("text-align: ");
styleBuffer.append(horizontalAlignment);
styleBuffer.append(";");
}
String verticalAlignment = HTML_VERTICAL_ALIGN_TOP;
switch (image.getVerticalAlignmentValue())
{
case BOTTOM :
{
verticalAlignment = HTML_VERTICAL_ALIGN_BOTTOM;
break;
}
case MIDDLE :
{
verticalAlignment = HTML_VERTICAL_ALIGN_MIDDLE;
break;
}
case TOP :
default :
{
verticalAlignment = HTML_VERTICAL_ALIGN_TOP;
}
}
if (!verticalAlignment.equals(HTML_VERTICAL_ALIGN_TOP))
{
styleBuffer.append(" vertical-align: ");
styleBuffer.append(verticalAlignment);
styleBuffer.append(";");
}
appendBackcolorStyle(gridCell, styleBuffer);
boolean addedToStyle = appendBorderStyle(gridCell.getBox(), styleBuffer);
if (!addedToStyle)
{
appendPen(
styleBuffer,
image.getLinePen(),
null
);
}
appendPaddingStyle(image.getLineBox(), styleBuffer);
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(">");
if (image.getAnchorName() != null)
{
writer.write("<a name=\"");
writer.write(image.getAnchorName());
writer.write("\"/>");
}
JRRenderable renderer = image.getRenderer();
JRRenderable originalRenderer = renderer;
boolean imageMapRenderer = renderer != null
&& renderer instanceof JRImageMapRenderer
&& ((JRImageMapRenderer) renderer).hasImageAreaHyperlinks();
boolean hasHyperlinks = false;
if(renderer != null || isUsingImagesToAlign)
{
if (imageMapRenderer)
{
hasHyperlinks = true;
hyperlinkStarted = false;
}
else
{
hasHyperlinks = startHyperlink(image);
}
writer.write("<img");
String imagePath = null;
String imageMapName = null;
List imageMapAreas = null;
ScaleImageEnum scaleImage = image.getScaleImageValue();
if (renderer != null)
{
if (renderer.getType() == JRRenderable.TYPE_IMAGE && rendererToImagePathMap.containsKey(renderer.getId()))
{
imagePath = (String)rendererToImagePathMap.get(renderer.getId());
}
else
{
if (image.isLazy())
{
imagePath = ((JRImageRenderer)renderer).getImageLocation();
}
else
{
JRPrintElementIndex imageIndex = getElementIndex(gridCell);
imagesToProcess.add(imageIndex);
String imageName = getImageName(imageIndex);
imagePath = imagesURI + imageName;
//backward compatibility with the IMAGE_MAP parameter
if (imageNameToImageDataMap != null)
{
if (renderer.getType() == JRRenderable.TYPE_SVG)
{
renderer =
new JRWrappingSvgRenderer(
renderer,
new Dimension(image.getWidth(), image.getHeight()),
ModeEnum.OPAQUE == image.getModeValue() ? image.getBackcolor() : null
);
}
imageNameToImageDataMap.put(imageName, renderer.getImageData());
}
//END - backward compatibility with the IMAGE_MAP parameter
}
rendererToImagePathMap.put(renderer.getId(), imagePath);
}
if (imageMapRenderer)
{
Rectangle renderingArea = new Rectangle(image.getWidth(), image.getHeight());
if (renderer.getType() == JRRenderable.TYPE_IMAGE)
{
imageMapName = (String) imageMaps.get(new Pair(renderer.getId(), renderingArea));
}
if (imageMapName == null)
{
imageMapName = "map_" + getElementIndex(gridCell).toString();
imageMapAreas = ((JRImageMapRenderer) originalRenderer).getImageAreaHyperlinks(renderingArea);//FIXMECHART
if (renderer.getType() == JRRenderable.TYPE_IMAGE)
{
imageMaps.put(new Pair(renderer.getId(), renderingArea), imageMapName);
}
}
}
}
else // ie: if(isUsingImagesToAlign)
{
loadPxImage();
imagePath = imagesURI + "px";
scaleImage = ScaleImageEnum.FILL_FRAME;
}
writer.write(" src=\"");
if (imagePath != null)
{
writer.write(imagePath);
}
writer.write("\"");
int imageWidth = image.getWidth() - image.getLineBox().getLeftPadding().intValue() - image.getLineBox().getRightPadding().intValue();
if (imageWidth < 0)
{
imageWidth = 0;
}
int imageHeight = image.getHeight() - image.getLineBox().getTopPadding().intValue() - image.getLineBox().getBottomPadding().intValue();
if (imageHeight < 0)
{
imageHeight = 0;
}
switch (scaleImage)
{
case FILL_FRAME :
{
writer.write(" style=\"width: ");
writer.write(toSizeUnit(imageWidth));
writer.write("; height: ");
writer.write(toSizeUnit(imageHeight));
writer.write("\"");
break;
}
case CLIP : //FIXMEIMAGE image clip could be achieved by cutting the image and preserving the image type
case RETAIN_SHAPE :
default :
{
double normalWidth = imageWidth;
double normalHeight = imageHeight;
if (!image.isLazy())
{
// Image load might fail.
JRRenderable tmpRenderer =
JRImageRenderer.getOnErrorRendererForDimension(renderer, image.getOnErrorTypeValue());
Dimension2D dimension = tmpRenderer == null ? null : tmpRenderer.getDimension();
// If renderer was replaced, ignore image dimension.
if (tmpRenderer == renderer && dimension != null)
{
normalWidth = dimension.getWidth();
normalHeight = dimension.getHeight();
}
}
if (imageHeight > 0)
{
double ratio = normalWidth / normalHeight;
if( ratio > (double)imageWidth / (double)imageHeight )
{
writer.write(" style=\"width: ");
writer.write(toSizeUnit(imageWidth));
writer.write("\"");
}
else
{
writer.write(" style=\"height: ");
writer.write(toSizeUnit(imageHeight));
writer.write("\"");
}
}
}
}
if (imageMapName != null)
{
writer.write(" usemap=\"#" + imageMapName + "\"");
}
writer.write(" alt=\"\"");
if (hasHyperlinks)
{
writer.write(" border=\"0\"");
}
if (image.getHyperlinkTooltip() != null)
{
writer.write(" title=\"");
writer.write(JRStringUtil.xmlEncode(image.getHyperlinkTooltip()));
writer.write("\"");
}
writer.write("/>");
endHyperlink();
if (imageMapAreas != null)
{
writer.write("\n");
writeImageMap(imageMapName, image, imageMapAreas);
}
}
writeCellEnd(gridCell);
}
protected JRPrintElementIndex getElementIndex(JRExporterGridCell gridCell)
{
JRPrintElementIndex imageIndex =
new JRPrintElementIndex(
reportIndex,
pageIndex,
gridCell.getWrapper().getAddress()
);
return imageIndex;
}
protected void writeImageMap(String imageMapName, JRPrintImage image, List imageMapAreas) throws IOException
{
writer.write("<map name=\"" + imageMapName + "\">\n");
for (ListIterator it = imageMapAreas.listIterator(imageMapAreas.size()); it.hasPrevious();)
{
JRPrintImageAreaHyperlink areaHyperlink = (JRPrintImageAreaHyperlink) it.previous();
JRPrintImageArea area = areaHyperlink.getArea();
writer.write(" <area shape=\"" + JRPrintImageArea.getHtmlShape(area.getShape()) + "\"");
writeImageAreaCoordinates(area.getCoordinates());
writeImageAreaHyperlink(areaHyperlink.getHyperlink());
writer.write("/>\n");
}
if (image.getHyperlinkTypeValue() != HyperlinkTypeEnum.NONE)
{
writer.write(" <area shape=\"default\"");
writeImageAreaCoordinates(new int[]{0, 0, image.getWidth(), image.getHeight()});//for IE
writeImageAreaHyperlink(image);
writer.write("/>\n");
}
writer.write("</map>\n");
}
protected void writeImageAreaCoordinates(int[] coords) throws IOException
{
if (coords != null && coords.length > 0)
{
StringBuffer coordsEnum = new StringBuffer(coords.length * 4);
coordsEnum.append(toZoom(coords[0]));
for (int i = 1; i < coords.length; i++)
{
coordsEnum.append(',');
coordsEnum.append(toZoom(coords[i]));
}
writer.write(" coords=\"" + coordsEnum + "\"");
}
}
protected void writeImageAreaHyperlink(JRPrintHyperlink hyperlink) throws IOException
{
String href = getHyperlinkURL(hyperlink);
if (href == null)
{
writer.write(" nohref=\"nohref\"");
}
else
{
writer.write(" href=\"" + href + "\"");
String target = getHyperlinkTarget(hyperlink);
if (target != null)
{
writer.write(" target=\"");
writer.write(target);
writer.write("\"");
}
}
if (hyperlink.getHyperlinkTooltip() != null)
{
writer.write(" title=\"");
writer.write(JRStringUtil.xmlEncode(hyperlink.getHyperlinkTooltip()));
writer.write("\"");
}
}
/**
*
*/
protected void loadPxImage() throws JRException
{
isPxImageLoaded = true;
//backward compatibility with the IMAGE_MAP parameter
if (imageNameToImageDataMap != null && !imageNameToImageDataMap.containsKey("px"))
{
JRRenderable pxRenderer =
JRImageRenderer.getInstance("net/sf/jasperreports/engine/images/pixel.GIF");
rendererToImagePathMap.put(pxRenderer.getId(), imagesURI + "px");
imageNameToImageDataMap.put("px", pxRenderer.getImageData());
}
//END - backward compatibility with the IMAGE_MAP parameter
}
/**
*
*/
protected static interface StringProvider
{
/**
*
*/
public String getStringForCollapsedTD(Object value, int width, int height);
/**
*
*/
public String getStringForEmptyTD(Object value);
public String getReportTableStyle();
}
/**
*
*/
private boolean appendPadding(StringBuffer sb, Integer padding, String side)
{
boolean addedToStyle = false;
if (padding.intValue() > 0)
{
sb.append("padding");
if (side != null)
{
sb.append("-");
sb.append(side);
}
sb.append(": ");
sb.append(toSizeUnit(padding.intValue()));
sb.append("; ");
addedToStyle = true;
}
return addedToStyle;
}
/**
*
*/
private boolean appendPen(StringBuffer sb, JRPen pen, String side)
{
boolean addedToStyle = false;
float borderWidth = pen.getLineWidth().floatValue();
if (0f < borderWidth && borderWidth < 1f)
{
borderWidth = 1f;
}
String borderStyle = null;
switch (pen.getLineStyleValue())
{
case DOUBLE :
{
borderStyle = "double";
break;
}
case DOTTED :
{
borderStyle = "dotted";
break;
}
case DASHED :
{
borderStyle = "dashed";
break;
}
case SOLID :
default :
{
borderStyle = "solid";
break;
}
}
if (borderWidth > 0f)
{
sb.append("border");
if (side != null)
{
sb.append("-");
sb.append(side);
}
sb.append("-style: ");
sb.append(borderStyle);
sb.append("; ");
sb.append("border");
if (side != null)
{
sb.append("-");
sb.append(side);
}
sb.append("-width: ");
sb.append(toSizeUnit((int)borderWidth));
sb.append("; ");
sb.append("border");
if (side != null)
{
sb.append("-");
sb.append(side);
}
sb.append("-color: #");
sb.append(JRColorUtil.getColorHexa(pen.getLineColor()));
sb.append("; ");
addedToStyle = true;
}
return addedToStyle;
}
/**
*
*/
public static String getImageName(JRPrintElementIndex printElementIndex)
{
return IMAGE_NAME_PREFIX + printElementIndex.toString();
}
/**
*
*/
public static JRPrintElementIndex getPrintElementIndex(String imageName)
{
if (!imageName.startsWith(IMAGE_NAME_PREFIX))
{
throw new JRRuntimeException("Invalid image name: " + imageName);
}
return JRPrintElementIndex.parsePrintElementIndex(imageName.substring(IMAGE_NAME_PREFIX_LEGTH));
}
protected void exportFrame(JRPrintFrame frame, JRExporterGridCell gridCell) throws IOException, JRException
{
writeCellStart(gridCell);
StringBuffer styleBuffer = new StringBuffer();
Color frameBackcolor = appendBackcolorStyle(gridCell, styleBuffer);
appendBorderStyle(gridCell.getBox(), styleBuffer);
//no padding style for frames, because padding is in the grid
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(">\n");
if (frameBackcolor != null)
{
setBackcolor(frameBackcolor);
}
try
{
exportGrid(gridCell.getLayout(), false);
}
finally
{
if (frameBackcolor != null)
{
restoreBackcolor();
}
}
writeCellEnd(gridCell);
}
protected void setBackcolor(Color color)
{
backcolorStack.addLast(backcolor);
backcolor = color;
}
protected void restoreBackcolor()
{
backcolor = (Color) backcolorStack.removeLast();
}
protected void exportGenericElement(JRGenericPrintElement element,
JRExporterGridCell gridCell, int rowHeight) throws IOException
{
GenericElementHtmlHandler handler = (GenericElementHtmlHandler)
GenericElementHandlerEnviroment.getHandler(
element.getGenericType(), HTML_EXPORTER_KEY);
if (handler == null)
{
if (log.isDebugEnabled())
{
log.debug("No HTML generic element handler for "
+ element.getGenericType());
}
writeEmptyCell(gridCell, rowHeight);
}
else
{
writeCellStart(gridCell);
StringBuffer styleBuffer = new StringBuffer();
appendBackcolorStyle(gridCell, styleBuffer);
appendBorderStyle(gridCell.getBox(), styleBuffer);
if (styleBuffer.length() > 0)
{
writer.write(" style=\"");
writer.write(styleBuffer.toString());
writer.write("\"");
}
writer.write(">");
String htmlFragment = handler.getHtmlFragment(exporterContext, element);
if (htmlFragment != null)
{
writer.write(htmlFragment);
}
writeCellEnd(gridCell);
}
}
public Map getExportParameters()
{
return parameters;
}
public String getExportPropertiesPrefix()
{
return HTML_EXPORTER_PROPERTIES_PREFIX;
}
protected String getExporterKey()
{
return HTML_EXPORTER_KEY;
}
public JasperPrint getExportedReport()
{
return jasperPrint;
}
public String toSizeUnit(int size)
{
return String.valueOf(toZoom(size)) + sizeUnit;
}
public int toZoom(int size)
{
return (int)(zoom * size);
}
protected JRStyledText getStyledText(JRPrintText textElement,
boolean setBackcolor)
{
JRStyledText styledText = super.getStyledText(textElement, setBackcolor);
if (styledText != null)
{
short[] lineBreakOffsets = textElement.getLineBreakOffsets();
if (lineBreakOffsets != null && lineBreakOffsets.length > 0)
{
//insert new lines at the line break positions saved at fill time
//cloning the text first
styledText = styledText.cloneText();
styledText.insert("\n", lineBreakOffsets);
}
}
return styledText;
}
}