net.sf.jasperreports.engine.export.draw.ImageDrawer Maven / Gradle / Ivy
The newest version!
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, 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 .
*/
/*
* Contributors:
* Eugene D - [email protected]
* Adrian Jackson - [email protected]
* David Taylor - [email protected]
* Lars Kristensen - [email protected]
*/
package net.sf.jasperreports.engine.export.draw;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPrintImage;
import net.sf.jasperreports.engine.JasperReportsContext;
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.renderers.DataRenderable;
import net.sf.jasperreports.renderers.DimensionRenderable;
import net.sf.jasperreports.renderers.Graphics2DRenderable;
import net.sf.jasperreports.renderers.Renderable;
import net.sf.jasperreports.renderers.RenderersCache;
import net.sf.jasperreports.renderers.ResourceRenderer;
import net.sf.jasperreports.renderers.util.RendererUtil;
/**
* @author Teodor Danciu ([email protected])
*/
public class ImageDrawer extends ElementDrawer
{
private final RenderersCache renderersCache;
/**
* @deprecated Replaced by {@link #ImageDrawer(JasperReportsContext, RenderersCache)}.
*/
public ImageDrawer(JasperReportsContext jasperReportsContext)
{
this(
jasperReportsContext,
new RenderersCache(jasperReportsContext)
);
}
/**
*
*/
public ImageDrawer(
JasperReportsContext jasperReportsContext,
RenderersCache renderersCache
)
{
super(jasperReportsContext);
this.renderersCache = renderersCache;
}
@Override
public void draw(Graphics2D grx, JRPrintImage printImage, int offsetX, int offsetY) throws JRException
{
if (printImage.getModeValue() == ModeEnum.OPAQUE)
{
grx.setColor(printImage.getBackcolor());
grx.fillRect(
printImage.getX() + offsetX,
printImage.getY() + offsetY,
printImage.getWidth(),
printImage.getHeight()
);
}
InternalImageDrawer internalImageDrawer =
new InternalImageDrawer(
printImage,
offsetX,
offsetY
);
Renderable renderer = printImage.getRenderer();
if (
renderer != null
&& internalImageDrawer.availableImageWidth > 0
&& internalImageDrawer.availableImageHeight > 0
)
{
try
{
internalImageDrawer.draw(grx, renderer);
}
catch (Exception e)
{
Renderable onErrorRenderer = RendererUtil.getInstance(getJasperReportsContext()).handleImageError(e, printImage.getOnErrorTypeValue());
if (onErrorRenderer != null)
{
internalImageDrawer.draw(grx, onErrorRenderer);
}
}
}
if (
printImage.getLineBox().getTopPen().getLineWidth() <= 0f &&
printImage.getLineBox().getLeftPen().getLineWidth() <= 0f &&
printImage.getLineBox().getBottomPen().getLineWidth() <= 0f &&
printImage.getLineBox().getRightPen().getLineWidth() <= 0f
)
{
if (printImage.getLinePen().getLineWidth() != 0)
{
drawPen(
grx,
printImage.getLinePen(),
printImage,
offsetX,
offsetY
);
}
}
else
{
drawBox(grx, printImage.getLineBox(), printImage, offsetX, offsetY);
}
}
private class InternalImageDrawer
{
private final JRPrintImage printImage;
private final int offsetX;
private final int offsetY;
private final int availableImageWidth;
private final int availableImageHeight;
private final int topPadding;
private final int leftPadding;
private final int bottomPadding;
private final int rightPadding;
protected InternalImageDrawer(
JRPrintImage printImage,
int offsetX,
int offsetY
)
{
this.printImage = printImage;
this.offsetX = offsetX;
this.offsetY = offsetY;
topPadding = printImage.getLineBox().getTopPadding();
leftPadding = printImage.getLineBox().getLeftPadding();
bottomPadding = printImage.getLineBox().getBottomPadding();
rightPadding = printImage.getLineBox().getRightPadding();
int tmpAvailableImageWidth = printImage.getWidth() - leftPadding - rightPadding;
availableImageWidth = tmpAvailableImageWidth < 0 ? 0 : tmpAvailableImageWidth;
int tmpAvailableImageHeight = printImage.getHeight() - topPadding - bottomPadding;
availableImageHeight = tmpAvailableImageHeight < 0 ? 0 : tmpAvailableImageHeight;
}
protected void draw(
Graphics2D grx,
Renderable renderer
) throws JRException
{
if (renderer instanceof ResourceRenderer)
{
renderer = renderersCache.getLoadedRenderer((ResourceRenderer)renderer);
}
Graphics2DRenderable grxRenderer = renderersCache.getGraphics2DRenderable(renderer);//FIXME honor isUsingCache
switch (printImage.getScaleImageValue())
{
case CLIP :
{
drawClip(grx, grxRenderer);
break;
}
case FILL_FRAME :
{
drawFillFrame(grx, grxRenderer);
break;
}
case RETAIN_SHAPE :
default :
{
drawRetainShape(grx, grxRenderer);
}
}
}
private void drawClip(
Graphics2D grx,
Graphics2DRenderable renderer
) throws JRException
{
int translateX = 0;
int translateY = 0;
int renderWidth = 0;
int renderHeight = 0;
double angle = 0;
Dimension2D dimension =
renderer instanceof DimensionRenderable
? ((DimensionRenderable)renderer).getDimension(getJasperReportsContext())
: null;
if (dimension == null)
{
renderWidth = availableImageWidth;
renderHeight = availableImageHeight;
}
else
{
renderWidth = (int)dimension.getWidth();
renderHeight = (int)dimension.getHeight();
}
ExifOrientationEnum exifOrientation = ExifOrientationEnum.NORMAL;
DataRenderable dataRenderable = renderer instanceof DataRenderable ? (DataRenderable)renderer : null;
if (dataRenderable != null)
{
exifOrientation = ImageUtil.getExifOrientation(dataRenderable.getData(getJasperReportsContext()));
}
if (
ExifOrientationEnum.LEFT == exifOrientation
|| ExifOrientationEnum.RIGHT == exifOrientation
)
{
int t = renderWidth;
renderWidth = renderHeight;
renderHeight = t;
}
switch (printImage.getRotation())
{
case LEFT :
{
translateX = (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageWidth - renderHeight));
translateY = availableImageHeight - (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageHeight - renderWidth));
angle = - Math.PI / 2;
break;
}
case RIGHT :
{
translateX = availableImageWidth - (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageWidth - renderHeight));
translateY = (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageHeight - renderWidth));
angle = Math.PI / 2;
break;
}
case UPSIDE_DOWN :
{
translateX = availableImageWidth - (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageWidth - renderWidth));
translateY = availableImageHeight - (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageHeight - renderHeight));
angle = Math.PI;
break;
}
case NONE :
default :
{
translateX = (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageWidth - renderWidth));
translateY = (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageHeight - renderHeight));
angle = 0;
}
}
Shape oldClipShape = grx.getClip();
grx.clip(
new Rectangle(
printImage.getX() + leftPadding + offsetX,
printImage.getY() + topPadding + offsetY,
availableImageWidth,
availableImageHeight
)
);
AffineTransform oldTransform = grx.getTransform();
grx.translate(
printImage.getX() + leftPadding + offsetX + translateX,
printImage.getY() + topPadding + offsetY + translateY
);
grx.rotate(angle);
try
{
renderer.render(
getJasperReportsContext(),
grx,
new Rectangle(
0,
0,
renderWidth,
renderHeight
)
);
}
finally
{
grx.setTransform(oldTransform);
grx.setClip(oldClipShape);
}
}
/**
*
*/
private void drawFillFrame(
Graphics2D grx,
Graphics2DRenderable renderer
) throws JRException
{
int translateX = 0;
int translateY = 0;
int renderWidth = availableImageWidth;
int renderHeight = availableImageHeight;
double angle = 0;
switch (printImage.getRotation())
{
case LEFT :
{
translateX = 0;
translateY = availableImageHeight;
renderWidth = availableImageHeight;
renderHeight = availableImageWidth;
angle = - Math.PI / 2;
break;
}
case RIGHT :
{
translateX = availableImageWidth;
translateY = 0;
renderWidth = availableImageHeight;
renderHeight = availableImageWidth;
angle = Math.PI / 2;
break;
}
case UPSIDE_DOWN :
{
translateX = availableImageWidth;
translateY = availableImageHeight;
renderWidth = availableImageWidth;
renderHeight = availableImageHeight;
angle = Math.PI;
break;
}
case NONE :
default :
{
}
}
AffineTransform oldTransform = grx.getTransform();
grx.translate(
printImage.getX() + leftPadding + offsetX + translateX,
printImage.getY() + topPadding + offsetY + translateY
);
grx.rotate(angle);
try
{
renderer.render(
getJasperReportsContext(),
grx,
new Rectangle(
0,
0,
renderWidth,
renderHeight
)
);
}
finally
{
grx.setTransform(oldTransform);
}
}
/**
*
*/
private void drawRetainShape(
Graphics2D grx,
Graphics2DRenderable renderer
) throws JRException
{
float normalWidth = 0;
float normalHeight = 0;
float ratioX = 1f;
float ratioY = 1f;
int translateX = 0;
int translateY = 0;
float renderWidth = 0;
float renderHeight = 0;
double angle = 0;
Dimension2D dimension =
renderer instanceof DimensionRenderable
? ((DimensionRenderable)renderer).getDimension(getJasperReportsContext())
: null;
if (dimension == null)
{
normalWidth = availableImageWidth;
normalHeight = availableImageHeight;
}
else
{
normalWidth = (int)dimension.getWidth();
normalHeight = (int)dimension.getHeight();
}
ExifOrientationEnum exifOrientation = ExifOrientationEnum.NORMAL;
DataRenderable dataRenderable = renderer instanceof DataRenderable ? (DataRenderable)renderer : null;
if (dataRenderable != null)
{
exifOrientation = ImageUtil.getExifOrientation(dataRenderable.getData(getJasperReportsContext()));
}
if (
ExifOrientationEnum.LEFT == exifOrientation
|| ExifOrientationEnum.RIGHT == exifOrientation
)
{
float t = normalWidth;
normalWidth = normalHeight;
normalHeight = t;
}
switch (printImage.getRotation())
{
case LEFT :
{
ratioX = availableImageWidth / normalHeight;
ratioY = availableImageHeight / normalWidth;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
renderWidth = normalWidth * ratioX;
renderHeight = normalHeight * ratioY;
translateX = (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageWidth - renderHeight));
translateY = availableImageHeight - (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageHeight - renderWidth));
angle = - Math.PI / 2;
break;
}
case RIGHT :
{
ratioX = availableImageWidth / normalHeight;
ratioY = availableImageHeight / normalWidth;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
renderWidth = normalWidth * ratioX;
renderHeight = normalHeight * ratioY;
translateX = availableImageWidth - (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageWidth - renderHeight));
translateY = (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageHeight - renderWidth));
angle = Math.PI / 2;
break;
}
case UPSIDE_DOWN :
{
ratioX = availableImageWidth / normalWidth;
ratioY = availableImageHeight / normalHeight;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
renderWidth = normalWidth * ratioX;
renderHeight = normalHeight * ratioY;
translateX = availableImageWidth - (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageWidth - renderWidth));
translateY = availableImageHeight - (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageHeight - renderHeight));
angle = Math.PI;
break;
}
case NONE :
default :
{
ratioX = availableImageWidth / normalWidth;
ratioY = availableImageHeight / normalHeight;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
renderWidth = normalWidth * ratioX;
renderHeight = normalHeight * ratioY;
translateX = (int)(ImageUtil.getXAlignFactor(printImage) * (availableImageWidth - renderWidth));
translateY = (int)(ImageUtil.getYAlignFactor(printImage) * (availableImageHeight - renderHeight));
angle = 0;
}
}
AffineTransform oldTransform = grx.getTransform();
grx.translate(
printImage.getX() + leftPadding + offsetX + translateX,
printImage.getY() + topPadding + offsetY + translateY
);
grx.rotate(angle);
try
{
renderer.render(
getJasperReportsContext(),
grx,
new Rectangle(
0,
0,
(int)renderWidth,
(int)renderHeight
)
);
}
finally
{
grx.setTransform(oldTransform);
}
}
}
}