使用JasperReports生成报告时,我看到报告引擎绘制了奇怪的边框。有时会绘制边框,使得线条以100%缩放级别突出显示,如此图所示。这意味着当我尝试绘制方形文本框时,除非我放大到150%以上,否则它看起来不像正方形。这是一张显示问题的图片。
在iReport中设置边框设置时我做错了什么?我该如何解决这个问题?
答案 0 :(得分:3)
我遇到了同样的问题。将表格导出为PDF并使用薄表格边框时,单元格边框线似乎会将表格的边框重复一个像素。视觉工件仅在某些PDF查看器中可见(它们在Adobe Reader中可见),并且仅在某些缩放级别可见。在PDF查看器中打开或关闭艺术线条平滑时,工件的外观会发生变化。如果放大最大级别的重击,您会看到正确绘制了线条 - 缩放文档时,PDF查看器会创建工件。
检查JasperReports代码时,我发现PDF导出将表格边框绘制为四条单行。它们是在没有帽子的情况下绘制的(线条在末尾立即被切断)。当以这种方式绘制方形边框时,角落将不会完全连接,因此每条线的绘制时间略长于边框以补偿缺失的上限。这个算法对我来说似乎是正确的,但是Adobe Reader中有一些东西,一些舍入和图像“改进”会导致图像伪像出现。
我能够提出一个解决方案来解决我的问题。我已经将JRPdfExporter子类化并修改了绘制边框的代码。用法很简单,只需使用我的类而不是JRPdfExporter。我使用JasperReports 5.0.0。
package cz.jwa.jasper;
import java.awt.Color;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.legacy.BorderOffset;
import net.sf.jasperreports.engine.type.LineStyleEnum;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
public class JWAPdfExporter extends JRPdfExporter
{
protected void exportBox(JRLineBox box, JRPrintElement element)
{
if(!isBoxVisible(box)) return;
pdfContentByte.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE);
float x1 = element.getX() + getOffsetX();
float y1 = jasperPrint.getPageHeight() - element.getY() - getOffsetY();
float x2 = element.getX() + getOffsetX() + element.getWidth();
float y2 = jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight();
Rectangle r = new Rectangle(x1, y2, x2, y1);
int borderFlag = 0;
boolean same = true;
float lineWidth = 0;
Color lineColor = null;
if(box.getLeftPen().getLineWidth().floatValue() > 0f)
{
borderFlag |= Rectangle.LEFT;
lineWidth = box.getLeftPen().getLineWidth().floatValue();
lineColor = box.getLeftPen().getLineColor();
}
if(box.getTopPen().getLineWidth().floatValue() > 0f)
{
borderFlag |= Rectangle.TOP;
if(lineWidth == 0)
{
lineWidth = box.getTopPen().getLineWidth().floatValue();
lineColor = box.getTopPen().getLineColor();
}
else if(lineWidth != box.getTopPen().getLineWidth().floatValue()
|| !lineColor.equals(box.getTopPen().getLineColor()))
{
same = false;
}
}
if(box.getRightPen().getLineWidth().floatValue() > 0f)
{
borderFlag |= Rectangle.RIGHT;
if(lineWidth == 0)
{
lineWidth = box.getRightPen().getLineWidth().floatValue();
lineColor = box.getRightPen().getLineColor();
}
else if(lineWidth != box.getRightPen().getLineWidth().floatValue()
|| !lineColor.equals(box.getRightPen().getLineColor()))
{
same = false;
}
}
if(box.getBottomPen().getLineWidth().floatValue() > 0f)
{
borderFlag |= Rectangle.BOTTOM;
if(lineWidth == 0)
{
lineWidth = box.getBottomPen().getLineWidth().floatValue();
lineColor = box.getBottomPen().getLineColor();
}
else if(lineWidth != box.getBottomPen().getLineWidth().floatValue()
|| !lineColor.equals(box.getBottomPen().getLineColor()))
{
same = false;
}
}
if(same)
{
r.setBorder(borderFlag);
r.setBorderColor(lineColor);
r.setBorderWidth(lineWidth);
pdfContentByte.rectangle(r);
pdfContentByte.stroke();
pdfContentByte.setLineDash(0.0F);
pdfContentByte.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE);
}
else
{
super.exportBox(box, element);
}
}
private boolean isBoxVisible(JRLineBox box)
{
return box.getLeftPen().getLineWidth().floatValue() > 0f
|| box.getTopPen().getLineWidth().floatValue() > 0f
|| box.getRightPen().getLineWidth().floatValue() > 0f
|| box.getBottomPen().getLineWidth().floatValue() > 0f
;
}
protected void exportTopPen(
JRPen topPen,
JRPen leftPen,
JRPen rightPen,
JRPrintElement element)
{
if (topPen.getLineWidth().floatValue() > 0f)
{
float leftOffset = 0; //leftPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(leftPen);
float rightOffset = 0; //rightPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(rightPen);
preparePen(pdfContentByte, topPen, PdfContentByte.LINE_CAP_BUTT);
if (topPen.getLineStyleValue() == LineStyleEnum.DOUBLE)
{
float topOffset = topPen.getLineWidth().floatValue();
pdfContentByte.moveTo(
element.getX() + getOffsetX() - leftOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset / 3
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() + rightOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset / 3
);
pdfContentByte.stroke();
pdfContentByte.moveTo(
element.getX() + getOffsetX() + leftOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3
);
pdfContentByte.stroke();
}
else
{
float topOffset = BorderOffset.getOffset(topPen);
pdfContentByte.moveTo(
element.getX() + getOffsetX() - leftOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() + rightOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset
);
pdfContentByte.stroke();
}
}
}
protected void exportLeftPen(JRPen topPen, JRPen leftPen, JRPen bottomPen, JRPrintElement element)
{
if (leftPen.getLineWidth().floatValue() > 0f)
{
float topOffset = 0; //topPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(topPen);
float bottomOffset = 0; //bottomPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(bottomPen);
preparePen(pdfContentByte, leftPen, PdfContentByte.LINE_CAP_BUTT);
if (leftPen.getLineStyleValue() == LineStyleEnum.DOUBLE)
{
float leftOffset = leftPen.getLineWidth().floatValue();
pdfContentByte.moveTo(
element.getX() + getOffsetX() - leftOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() - leftOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset
);
pdfContentByte.stroke();
pdfContentByte.moveTo(
element.getX() + getOffsetX() + leftOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + leftOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3
);
pdfContentByte.stroke();
}
else
{
float leftOffset = BorderOffset.getOffset(leftPen);
pdfContentByte.moveTo(
element.getX() + getOffsetX() + leftOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + leftOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset
);
pdfContentByte.stroke();
}
}
}
/**
*
*/
protected void exportBottomPen(JRPen leftPen, JRPen bottomPen, JRPen rightPen, JRPrintElement element)
{
if (bottomPen.getLineWidth().floatValue() > 0f)
{
float leftOffset = 0; //leftPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(leftPen);
float rightOffset = 0; //rightPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(rightPen);
preparePen(pdfContentByte, bottomPen, PdfContentByte.LINE_CAP_BUTT);
if (bottomPen.getLineStyleValue() == LineStyleEnum.DOUBLE)
{
float bottomOffset = bottomPen.getLineWidth().floatValue();
pdfContentByte.moveTo(
element.getX() + getOffsetX() - leftOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset / 3
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() + rightOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset / 3
);
pdfContentByte.stroke();
pdfContentByte.moveTo(
element.getX() + getOffsetX() + leftOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3
);
pdfContentByte.stroke();
}
else
{
float bottomOffset = BorderOffset.getOffset(bottomPen);
pdfContentByte.moveTo(
element.getX() + getOffsetX() - leftOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() + rightOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset
);
pdfContentByte.stroke();
}
}
}
/**
*
*/
protected void exportRightPen(JRPen topPen, JRPen bottomPen, JRPen rightPen, JRPrintElement element)
{
if (rightPen.getLineWidth().floatValue() > 0f)
{
float topOffset = 0; //topPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(topPen);
float bottomOffset = 0; //bottomPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(bottomPen);
preparePen(pdfContentByte, rightPen, PdfContentByte.LINE_CAP_BUTT);
if (rightPen.getLineStyleValue() == LineStyleEnum.DOUBLE)
{
float rightOffset = rightPen.getLineWidth().floatValue();
pdfContentByte.moveTo(
element.getX() + getOffsetX() + element.getWidth() + rightOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() + rightOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset
);
pdfContentByte.stroke();
pdfContentByte.moveTo(
element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3
);
pdfContentByte.stroke();
}
else
{
float rightOffset = BorderOffset.getOffset(rightPen);
pdfContentByte.moveTo(
element.getX() + getOffsetX() + element.getWidth() - rightOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset
);
pdfContentByte.lineTo(
element.getX() + getOffsetX() + element.getWidth() - rightOffset,
jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset
);
pdfContentByte.stroke();
}
}
}
private static void preparePen(PdfContentByte pdfContentByte, JRPen pen, int lineCap)
{
float lineWidth = pen.getLineWidth().floatValue();
if (lineWidth <= 0)
{
return;
}
pdfContentByte.setLineWidth(lineWidth);
pdfContentByte.setLineCap(lineCap);
Color color = pen.getLineColor();
pdfContentByte.setRGBColorStroke(color.getRed(), color.getGreen(), color.getBlue());
switch (pen.getLineStyleValue())
{
case DOUBLE:
{
pdfContentByte.setLineWidth(lineWidth / 3);
pdfContentByte.setLineDash(0f);
break;
}
case DOTTED:
{
switch (lineCap)
{
case PdfContentByte.LINE_CAP_BUTT:
{
pdfContentByte.setLineDash(lineWidth, lineWidth, 0f);
break;
}
case PdfContentByte.LINE_CAP_PROJECTING_SQUARE:
{
pdfContentByte.setLineDash(0, 2 * lineWidth, 0f);
break;
}
}
break;
}
case DASHED:
{
switch (lineCap)
{
case PdfContentByte.LINE_CAP_BUTT:
{
pdfContentByte.setLineDash(5 * lineWidth, 3 * lineWidth, 0f);
break;
}
case PdfContentByte.LINE_CAP_PROJECTING_SQUARE:
{
pdfContentByte.setLineDash(4 * lineWidth, 4 * lineWidth, 0f);
break;
}
}
break;
}
case SOLID:
default:
{
pdfContentByte.setLineDash(0f);
break;
}
}
}
}