Java tutorial
/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved. * http://www.jaspersoft.com * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is part of JasperReports. * * JasperReports is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JasperReports is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JasperReports. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.jasperreports.engine.fill; import java.awt.Image; import java.awt.geom.Dimension2D; import java.io.File; import java.io.InputStream; import java.net.URL; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExpression; import net.sf.jasperreports.engine.JRExpressionCollector; import net.sf.jasperreports.engine.JRGroup; import net.sf.jasperreports.engine.JRHyperlinkParameter; import net.sf.jasperreports.engine.JRImage; import net.sf.jasperreports.engine.JRLineBox; import net.sf.jasperreports.engine.JRPrintElement; import net.sf.jasperreports.engine.JRPrintHyperlinkParameters; import net.sf.jasperreports.engine.JRPrintImage; import net.sf.jasperreports.engine.JRVisitor; import net.sf.jasperreports.engine.type.EvaluationTimeEnum; import net.sf.jasperreports.engine.type.HorizontalImageAlignEnum; import net.sf.jasperreports.engine.type.HyperlinkTypeEnum; import net.sf.jasperreports.engine.type.ModeEnum; import net.sf.jasperreports.engine.type.OnErrorTypeEnum; import net.sf.jasperreports.engine.type.ScaleImageEnum; import net.sf.jasperreports.engine.type.VerticalImageAlignEnum; import net.sf.jasperreports.engine.util.Pair; import net.sf.jasperreports.engine.util.StyleUtil; import net.sf.jasperreports.renderers.DimensionRenderable; 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; import net.sf.jasperreports.repo.RepositoryContext; import net.sf.jasperreports.repo.RepositoryUtil; import net.sf.jasperreports.repo.ResourceInfo; import net.sf.jasperreports.repo.ResourcePathKey; /** * @author Teodor Danciu (teodord@users.sourceforge.net) */ public class JRFillImage extends JRFillGraphicElement implements JRImage { private static final Log log = LogFactory.getLog(JRFillImage.class); public static final String EXCEPTION_MESSAGE_KEY_UNKNOWN_SOURCE_CLASS = "fill.image.unknown.source.class"; /** * */ private JRGroup evaluationGroup; /** * */ private Renderable renderer; private Renderable oldRenderer; private Object prevSource; private Renderable prevRenderer; private boolean usedCache; private boolean hasOverflowed; private Integer imageHeight; private Integer imageWidth; private Integer imageX; private String anchorName; private String hyperlinkReference; private Boolean hyperlinkWhen; private String hyperlinkAnchor; private Integer hyperlinkPage; private String hyperlinkTooltip; private JRPrintHyperlinkParameters hyperlinkParameters; protected final JRLineBox initLineBox; protected JRLineBox lineBox; /** * */ protected JRFillImage(JRBaseFiller filler, JRImage image, JRFillObjectFactory factory) { super(filler, image, factory); initLineBox = image.getLineBox().clone(this); evaluationGroup = factory.getGroup(image.getEvaluationGroup()); } protected JRFillImage(JRFillImage image, JRFillCloneFactory factory) { super(image, factory); initLineBox = image.getLineBox().clone(this); evaluationGroup = image.evaluationGroup; } @Override protected void evaluateStyle(byte evaluation) throws JRException { super.evaluateStyle(evaluation); lineBox = null; if (providerStyle != null) { lineBox = initLineBox.clone(this); StyleUtil.appendBox(lineBox, providerStyle.getLineBox()); } } @Override public ModeEnum getModeValue() { return getStyleResolver().getMode(this, ModeEnum.TRANSPARENT); } @Override public ScaleImageEnum getScaleImageValue() { return getStyleResolver().getScaleImageValue(this); } @Override public ScaleImageEnum getOwnScaleImageValue() { return providerStyle == null || providerStyle.getOwnScaleImageValue() == null ? ((JRImage) this.parent).getOwnScaleImageValue() : providerStyle.getOwnScaleImageValue(); } @Override public void setScaleImage(ScaleImageEnum scaleImage) { throw new UnsupportedOperationException(); } @Override public HorizontalImageAlignEnum getHorizontalImageAlign() { return getStyleResolver().getHorizontalImageAlign(this); } @Override public HorizontalImageAlignEnum getOwnHorizontalImageAlign() { return providerStyle == null || providerStyle.getOwnHorizontalImageAlign() == null ? ((JRImage) this.parent).getOwnHorizontalImageAlign() : providerStyle.getOwnHorizontalImageAlign(); } @Override public void setHorizontalImageAlign(HorizontalImageAlignEnum horizontalAlignment) { throw new UnsupportedOperationException(); } @Override public VerticalImageAlignEnum getVerticalImageAlign() { return getStyleResolver().getVerticalImageAlign(this); } @Override public VerticalImageAlignEnum getOwnVerticalImageAlign() { return providerStyle == null || providerStyle.getOwnVerticalImageAlign() == null ? ((JRImage) this.parent).getOwnVerticalImageAlign() : providerStyle.getOwnVerticalImageAlign(); } @Override public void setVerticalImageAlign(VerticalImageAlignEnum verticalAlignment) { throw new UnsupportedOperationException(); } /** * @deprecated Replaced by {@link #getUsingCache()}. */ @Override public boolean isUsingCache() { return ((JRImage) this.parent).isUsingCache(); } /** * @deprecated Replaced by {@link #getUsingCache()}. */ @Override public Boolean isOwnUsingCache() { return ((JRImage) this.parent).isOwnUsingCache(); } @Override public Boolean getUsingCache() { return ((JRImage) this.parent).getUsingCache(); } /** * @deprecated Replaced by {@link #setUsingCache(Boolean)}. */ @Override public void setUsingCache(boolean isUsingCache) { } @Override public void setUsingCache(Boolean isUsingCache) { } @Override public boolean isLazy() { return ((JRImage) this.parent).isLazy(); } @Override public void setLazy(boolean isLazy) { } @Override public OnErrorTypeEnum getOnErrorTypeValue() { return ((JRImage) this.parent).getOnErrorTypeValue(); } @Override public void setOnErrorType(OnErrorTypeEnum onErrorType) { throw new UnsupportedOperationException(); } @Override public EvaluationTimeEnum getEvaluationTimeValue() { return ((JRImage) this.parent).getEvaluationTimeValue(); } @Override public JRGroup getEvaluationGroup() { return this.evaluationGroup; } @Override public JRLineBox getLineBox() { return lineBox == null ? initLineBox : lineBox; } /** * @deprecated Replaced by {@link #getHyperlinkTypeValue()}. */ public byte getHyperlinkType() { return getHyperlinkTypeValue().getValue(); } @Override public HyperlinkTypeEnum getHyperlinkTypeValue() { return ((JRImage) parent).getHyperlinkTypeValue(); } @Override public byte getHyperlinkTarget() { return ((JRImage) this.parent).getHyperlinkTarget(); } @Override public String getLinkTarget() { return ((JRImage) this.parent).getLinkTarget(); } @Override public JRExpression getExpression() { return ((JRImage) this.parent).getExpression(); } @Override public JRExpression getAnchorNameExpression() { return ((JRImage) this.parent).getAnchorNameExpression(); } @Override public JRExpression getHyperlinkReferenceExpression() { return ((JRImage) this.parent).getHyperlinkReferenceExpression(); } @Override public JRExpression getHyperlinkWhenExpression() { return ((JRImage) this.parent).getHyperlinkWhenExpression(); } @Override public JRExpression getHyperlinkAnchorExpression() { return ((JRImage) this.parent).getHyperlinkAnchorExpression(); } @Override public JRExpression getHyperlinkPageExpression() { return ((JRImage) this.parent).getHyperlinkPageExpression(); } /** * */ protected Renderable getRenderable() { return this.renderer; } /** * */ protected String getAnchorName() { return this.anchorName; } /** * */ protected String getHyperlinkReference() { return this.hyperlinkReference; } /** * */ protected String getHyperlinkAnchor() { return this.hyperlinkAnchor; } /** * */ protected Integer getHyperlinkPage() { return this.hyperlinkPage; } protected String getHyperlinkTooltip() { return this.hyperlinkTooltip; } /** * */ protected JRTemplateImage getJRTemplateImage() { return (JRTemplateImage) getElementTemplate(); } @Override protected JRTemplateElement createElementTemplate() { JRTemplateImage template = new JRTemplateImage(getElementOrigin(), filler.getJasperPrint().getDefaultStyleProvider(), this); if (getScaleImageValue() == ScaleImageEnum.REAL_HEIGHT || getScaleImageValue() == ScaleImageEnum.REAL_SIZE) { template.setScaleImage(ScaleImageEnum.RETAIN_SHAPE); } return template; } @Override protected void evaluate(byte evaluation) throws JRException { initDelayedEvaluations(); reset(); evaluatePrintWhenExpression(evaluation); if (isPrintWhenExpressionNull() || isPrintWhenTrue()) { if (isEvaluateNow()) { hasOverflowed = false; evaluateImage(evaluation); } } } /** * */ protected void evaluateImage(byte evaluation) throws JRException { evaluateProperties(evaluation); evaluateStyle(evaluation); JRExpression expression = this.getExpression(); Renderable newRenderer = null; Boolean isUsingCache = getUsingCache(); usedCache = isUsingCache == null ? true : isUsingCache; Object source = null; try { source = evaluateExpression(expression, evaluation); } catch (Exception e) { source = RendererUtil.getInstance(filler.getJasperReportsContext()).handleImageError(e, getOnErrorTypeValue()); } if (source != null) { if (isUsingCache == null) { usedCache = isUsingCache = source instanceof String; //FIXME the flag determined based on the expression type is lost in print images //hence the isUsingCache test in exporters yields false positives for images that did not come from Strings } boolean lazy = isLazy(); RepositoryContext repositoryContext = filler.getRepositoryContext(); Object srcKey = source; if (source instanceof String) { ResourcePathKey pathKey = ResourcePathKey.inContext(lazy ? null : repositoryContext, (String) source); srcKey = new Pair<>(lazy, pathKey); } if (isUsingCache && filler.fillContext.hasLoadedRenderer(srcKey)) { newRenderer = filler.fillContext.getLoadedRenderer(srcKey); } else { @SuppressWarnings("deprecation") net.sf.jasperreports.engine.JRRenderable deprecatedRenderable = source instanceof net.sf.jasperreports.engine.JRRenderable ? (net.sf.jasperreports.engine.JRRenderable) source : null; if (source instanceof String) { String strSource = (String) source; if (lazy)//TODO lucianc resolve within repository context? { newRenderer = ResourceRenderer.getInstance(strSource, true); } else { ResourceInfo resourceInfo = RepositoryUtil.getInstance(repositoryContext) .getResourceInfo((String) source); if (resourceInfo == null) { newRenderer = RendererUtil.getInstance(repositoryContext) .getNonLazyRenderable(strSource, getOnErrorTypeValue()); } else { String absoluteLocation = resourceInfo.getRepositoryResourceLocation(); if (log.isDebugEnabled()) { log.debug("image " + source + " resolved to " + absoluteLocation); } ResourcePathKey absolutePathKey = ResourcePathKey.absolute(absoluteLocation); Object absoluteKey = new Pair<>(lazy, absolutePathKey); if (isUsingCache && filler.fillContext.hasLoadedRenderer(absoluteKey)) { newRenderer = filler.fillContext.getLoadedRenderer(absoluteKey); } else { newRenderer = RendererUtil.getInstance(repositoryContext) .getNonLazyRenderable(absoluteLocation, getOnErrorTypeValue()); if (isUsingCache) { filler.fillContext.registerLoadedRenderer(absoluteKey, newRenderer); } } } } } else if (source instanceof Image) { Image img = (Image) source; newRenderer = RendererUtil.getInstance(filler.getJasperReportsContext()).getRenderable(img, getOnErrorTypeValue()); } else if (source instanceof byte[]) { byte[] data = (byte[]) source; newRenderer = RendererUtil.getInstance(filler.getJasperReportsContext()).getRenderable(data); } else if (source instanceof InputStream) { if (this.prevSource != null && source == this.prevSource)//testing for object identity { //the image can be evaluated twice when the band is prevented to split //if the image source is a stream, we can't read it again //TODO do the same thing for other source types (file, url, string) too? newRenderer = this.prevRenderer; } else { InputStream is = (InputStream) source; newRenderer = RendererUtil.getInstance(filler.getJasperReportsContext()).getRenderable(is, getOnErrorTypeValue()); } } else if (source instanceof URL) { URL url = (URL) source; newRenderer = RendererUtil.getInstance(filler.getJasperReportsContext()).getRenderable(url, getOnErrorTypeValue()); } else if (source instanceof File) { File file = (File) source; newRenderer = RendererUtil.getInstance(filler.getJasperReportsContext()).getRenderable(file, getOnErrorTypeValue()); } else if (source instanceof Renderable) { newRenderer = (Renderable) source; } else if (deprecatedRenderable != null) { @SuppressWarnings("deprecation") Renderable wrappingRenderable = net.sf.jasperreports.engine.RenderableUtil .getWrappingRenderable(deprecatedRenderable); newRenderer = wrappingRenderable; } else { newRenderer = RendererUtil.getInstance(filler.getJasperReportsContext()).getOnErrorRenderer( getOnErrorTypeValue(), new JRException(EXCEPTION_MESSAGE_KEY_UNKNOWN_SOURCE_CLASS, new Object[] { source.getClass().getName() })); } if (isUsingCache) { filler.fillContext.registerLoadedRenderer(srcKey, newRenderer); } } } Renderable crtRenderer = getRenderable(); this.oldRenderer = renderer; this.renderer = newRenderer; this.prevSource = source; this.prevRenderer = renderer; setValueRepeating(crtRenderer == newRenderer); this.anchorName = (String) evaluateExpression(this.getAnchorNameExpression(), evaluation); this.hyperlinkReference = (String) evaluateExpression(this.getHyperlinkReferenceExpression(), evaluation); this.hyperlinkWhen = (Boolean) evaluateExpression(this.getHyperlinkWhenExpression(), evaluation); this.hyperlinkAnchor = (String) evaluateExpression(this.getHyperlinkAnchorExpression(), evaluation); this.hyperlinkPage = (Integer) evaluateExpression(this.getHyperlinkPageExpression(), evaluation); this.hyperlinkTooltip = (String) evaluateExpression(this.getHyperlinkTooltipExpression(), evaluation); hyperlinkParameters = JRFillHyperlinkHelper.evaluateHyperlinkParameters(this, expressionEvaluator, evaluation); } @Override public void rewind() { super.rewind(); @SuppressWarnings("deprecation") boolean isLegacyBandEvaluationEnabled = filler.getFillContext().isLegacyBandEvaluationEnabled(); if (!isLegacyBandEvaluationEnabled) { this.renderer = this.oldRenderer; } } @Override protected boolean prepare(int availableHeight, boolean isOverflow) throws JRException { boolean willOverflow = false; if (this.isPrintWhenExpressionNull() || (!this.isPrintWhenExpressionNull() && this.isPrintWhenTrue())) { this.setToPrint(true); } else { this.setToPrint(false); } if (!this.isToPrint()) { return willOverflow; } boolean isToPrint = true; boolean isReprinted = false; if (isEvaluateNow()) { if (isOverflow && this.isAlreadyPrinted() && !this.isPrintWhenDetailOverflows()) { isToPrint = false; } if (isToPrint && this.isPrintWhenExpressionNull() && !this.isPrintRepeatedValues() && isValueRepeating()) { if ((!this.isPrintInFirstWholeBand() || !this.getBand().isFirstWholeOnPageColumn()) && (this.getPrintWhenGroupChanges() == null || !this.getBand().isNewGroup(this.getPrintWhenGroupChanges())) && (!isOverflow || !this.isPrintWhenDetailOverflows())) { isToPrint = false; } } if (isToPrint && this.isRemoveLineWhenBlank() && this.getRenderable() == null) { isToPrint = false; } if (isToPrint) { if (availableHeight < getRelativeY() + getHeight()) { isToPrint = false; willOverflow = true; } else if (!isLazy() && (getScaleImageValue() == ScaleImageEnum.REAL_HEIGHT || getScaleImageValue() == ScaleImageEnum.REAL_SIZE)) { int padding = getLineBox().getBottomPadding() + getLineBox().getTopPadding(); boolean reprinted = isOverflow && (this.isPrintWhenDetailOverflows() && (this.isAlreadyPrinted() || (!this.isAlreadyPrinted() && !this.isPrintRepeatedValues()))); boolean imageOverflowAllowed = filler.isBandOverFlowAllowed() && !reprinted && !hasOverflowed; if (renderer == null) { // if renderer is null, it means the isRemoveLineWhenBlank was false further up; // no need to do anything here } else { // image fill does not normally produce non-lazy ResourceRenderer instances, // so we do not need to attempt load resource renderers from cache here, as we do in the catch below RenderersCache renderersCache = usedCache ? filler.fillContext.getRenderersCache() : new RenderersCache(filler.getJasperReportsContext()); DimensionRenderable dimensionRenderer = renderersCache.getDimensionRenderable(renderer); if (dimensionRenderer != null) { try { dimensionRenderer.getDimension(filler.getJasperReportsContext()); } catch (Exception e) { renderer = RendererUtil.getInstance(filler.getJasperReportsContext()) .handleImageError(e, getOnErrorTypeValue()); if (renderer instanceof ResourceRenderer) { renderer = renderersCache.getLoadedRenderer((ResourceRenderer) renderer); } dimensionRenderer = renderersCache.getDimensionRenderable(renderer); } if (dimensionRenderer == null) // OnErrorTypeEnum.BLANK can return null above { isToPrint = !isRemoveLineWhenBlank(); } else { boolean fits = true; Dimension2D imageSize = dimensionRenderer .getDimension(filler.getJasperReportsContext()); if (imageSize != null) { fits = fitImage(imageSize, availableHeight - getRelativeY() - padding, imageOverflowAllowed, getHorizontalImageAlign()); } if (fits) { if (imageHeight != null) { setPrepareHeight(imageHeight + padding); } } else { hasOverflowed = true; isToPrint = false; willOverflow = true; setPrepareHeight(availableHeight - getRelativeY() - padding); } } } } } } if (isToPrint && isOverflow && //(this.isAlreadyPrinted() || !this.isPrintRepeatedValues()) (this.isPrintWhenDetailOverflows() && (this.isAlreadyPrinted() || (!this.isAlreadyPrinted() && !this.isPrintRepeatedValues())))) { isReprinted = true; } } else { if (isOverflow && this.isAlreadyPrinted() && !this.isPrintWhenDetailOverflows()) { isToPrint = false; } if (isToPrint && availableHeight < this.getRelativeY() + getHeight()) { isToPrint = false; willOverflow = true; } if (isToPrint && isOverflow && //(this.isAlreadyPrinted() || !this.isPrintRepeatedValues()) (this.isPrintWhenDetailOverflows() && (this.isAlreadyPrinted() || (!this.isAlreadyPrinted() && !this.isPrintRepeatedValues())))) { isReprinted = true; } } this.setToPrint(isToPrint); this.setReprinted(isReprinted); return willOverflow; } @Override protected void reset() { imageHeight = null; imageWidth = null; imageX = null; super.reset(); } protected boolean fitImage(Dimension2D imageSize, int availableHeight, boolean overflowAllowed, HorizontalImageAlignEnum hAlign) throws JRException { imageHeight = null; imageWidth = null; imageX = null; int realHeight = (int) imageSize.getHeight(); int realWidth = (int) imageSize.getWidth(); boolean fitted; int reducedHeight = realHeight; int reducedWidth = realWidth; if (realWidth > getWidth()) { double wRatio = ((double) getWidth()) / realWidth; reducedHeight = (int) (wRatio * realHeight); reducedWidth = getWidth(); } if (reducedHeight <= availableHeight) { imageHeight = reducedHeight; if (getScaleImageValue() == ScaleImageEnum.REAL_SIZE) { imageWidth = reducedWidth; } fitted = true; } else if (overflowAllowed) { fitted = false; } else { imageHeight = availableHeight; if (getScaleImageValue() == ScaleImageEnum.REAL_SIZE) { double hRatio = ((double) availableHeight) / realHeight; imageWidth = (int) (hRatio * realWidth); } fitted = true; } if (imageWidth != null && imageWidth != getWidth()) { switch (hAlign) { case RIGHT: imageX = getX() + getWidth() - imageWidth; break; case CENTER: imageX = getX() + (getWidth() - imageWidth) / 2; break; default: break; } } if (log.isDebugEnabled()) { log.debug("Fitted image of dimension " + imageSize + " on " + availableHeight + ", overflow allowed " + overflowAllowed + ": " + fitted); } return fitted; } @Override protected JRPrintElement fill() throws JRException { EvaluationTimeEnum evaluationTime = this.getEvaluationTimeValue(); JRTemplatePrintImage printImage; JRRecordedValuesPrintImage recordedValuesImage; if (isEvaluateAuto()) { printImage = recordedValuesImage = new JRRecordedValuesPrintImage(getJRTemplateImage(), printElementOriginator); } else { printImage = new JRTemplatePrintImage(getJRTemplateImage(), printElementOriginator); recordedValuesImage = null; } printImage.setUUID(this.getUUID()); printImage.setX(this.getX()); printImage.setY(this.getRelativeY()); printImage.setWidth(getWidth()); printImage.setHeight(this.getStretchHeight()); printImage.setBookmarkLevel(getBookmarkLevel()); if (isEvaluateNow()) { this.copy(printImage); } else if (isEvaluateAuto()) { initDelayedEvaluationPrint(recordedValuesImage); } else { filler.addBoundElement(this, printImage, evaluationTime, getEvaluationGroup(), band); } return printImage; } /** * */ protected void copy(JRPrintImage printImage) { printImage.setUUID(getUUID()); if (imageX != null) { printImage.setX(imageX); } if (imageWidth != null) { printImage.setWidth(imageWidth); } printImage.setRenderer(getRenderable()); printImage.setAnchorName(getAnchorName()); if (getHyperlinkWhenExpression() == null || Boolean.TRUE.equals(hyperlinkWhen)) { printImage.setHyperlinkReference(getHyperlinkReference()); printImage.setHyperlinkAnchor(getHyperlinkAnchor()); printImage.setHyperlinkPage(getHyperlinkPage()); printImage.setHyperlinkTooltip(getHyperlinkTooltip()); printImage.setHyperlinkParameters(hyperlinkParameters); } else { if (printImage instanceof JRTemplatePrintImage)//this is normally the case { ((JRTemplatePrintImage) printImage).setHyperlinkOmitted(true); } printImage.setHyperlinkReference(null); } transferProperties(printImage); } @Override public void collectExpressions(JRExpressionCollector collector) { collector.collect(this); } @Override public void visit(JRVisitor visitor) { visitor.visitImage(this); } @Override protected void resolveElement(JRPrintElement element, byte evaluation) throws JRException { evaluateImage(evaluation); JRPrintImage printImage = (JRPrintImage) element; if (getScaleImageValue() == ScaleImageEnum.REAL_SIZE)//to avoid get dimension and thus unnecessarily load the image { // image fill does not normally produce non-lazy ResourceRenderer instances, // so we do not need to attempt load resource renderers from cache here, as we do in the catch below RenderersCache renderersCache = usedCache ? filler.fillContext.getRenderersCache() : new RenderersCache(filler.getJasperReportsContext()); DimensionRenderable dimensionRenderer = renderersCache.getDimensionRenderable(renderer); if (dimensionRenderer != null) { try { dimensionRenderer.getDimension(filler.getJasperReportsContext()); } catch (Exception e) { renderer = RendererUtil.getInstance(filler.getJasperReportsContext()).handleImageError(e, getOnErrorTypeValue()); if (renderer instanceof ResourceRenderer) { renderer = renderersCache.getLoadedRenderer((ResourceRenderer) renderer); } dimensionRenderer = renderersCache.getDimensionRenderable(renderer); } if (dimensionRenderer != null) // OnErrorTypeEnum.BLANK can return null above { Dimension2D imageSize = dimensionRenderer.getDimension(filler.getJasperReportsContext()); if (imageSize != null) { int padding = printImage.getLineBox().getBottomPadding() + printImage.getLineBox().getTopPadding(); fitImage(imageSize, getHeight() - padding, false, printImage.getHorizontalImageAlign()); } } } } copy(printImage); filler.updateBookmark(element); } @Override public int getBookmarkLevel() { return ((JRImage) this.parent).getBookmarkLevel(); } @Override public JRFillCloneable createClone(JRFillCloneFactory factory) { return new JRFillImage(this, factory); } @Override protected void collectDelayedEvaluations() { super.collectDelayedEvaluations(); collectDelayedEvaluations(getExpression()); collectDelayedEvaluations(getAnchorNameExpression()); collectDelayedEvaluations(getHyperlinkReferenceExpression()); collectDelayedEvaluations(getHyperlinkWhenExpression()); collectDelayedEvaluations(getHyperlinkAnchorExpression()); collectDelayedEvaluations(getHyperlinkPageExpression()); } @Override public JRHyperlinkParameter[] getHyperlinkParameters() { return ((JRImage) parent).getHyperlinkParameters(); } @Override public String getLinkType() { return ((JRImage) parent).getLinkType(); } @Override public JRExpression getHyperlinkTooltipExpression() { return ((JRImage) parent).getHyperlinkTooltipExpression(); } }