JasperReport PDF中的Border Artifacts使用iReport 5.1.0设计 [英] Border Artifacts in JasperReport PDF Designed with iReport 5.1.0

查看:116
本文介绍了JasperReport PDF中的Border Artifacts使用iReport 5.1.0设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用JasperReports生成报告时,我看到报告引擎绘制了奇怪的边框。有时会绘制边框,使得线条以100%缩放级别突出显示,如此图所示。这意味着当我尝试绘制方形文本框时,除非我放大到150%以上,否则它看起来不像正方形。这是一张显示问题的图片。

When generating a report with JasperReports, I am seeing weird borders drawn by the reporting engine. Sometimes the borders are drawn so that the lines jut out at 100% zoom level, as seen in this image. This means that when I attempt to draw a square textbox, it will not look like a square unless I zoom in to 150% for more. Here is an image showing the issue.

在iReport中设置边框设置时我做错了什么?我该如何解决这个问题?

Am I doing something wrong when setting the border settings in iReport? How can I fix this problem?

推荐答案

我遇到了同样的问题。将表格导出为PDF并使用精细表格边框时,单元格边框线似乎会将表格的边框重叠一个像素。视觉工件仅在某些PDF查看器中可见(它们在Adobe Reader中可见),并且仅在某些缩放级别可见。在PDF查看器中打开或关闭艺术线条平滑时,工件的外观会发生变化。如果放大最大级别的重击,您会看到正确绘制线条 - 缩放文档时,PDF查看器会创建工件。

I had the same problem. When exporting tables into PDF and using thin table borders, lines of cell borders seem to overstrike borders of the table by one pixel. Visual artifacts are visible only in some PDF viewers (they are visible in the Adobe Reader) and only at some zoom levels. Appearance of artifacts changes when line art smoothing is turned on or off in PDF viewer. If you zoom on overstrike at maximal level, you see that lines are drawn correctly - the artifacts are made by the PDF viewer when scaling the document.

检查JasperReports代码时,我发现PDF导出将表格边框画成四条单行。它们是在没有帽子的情况下绘制的(线条在末尾立即被切断)。当以这种方式绘制方形边框时,角落将不会完全连接,因此每条线的绘制时间略长于边框以补偿缺失的上限。这个算法对我来说似乎是正确的,但是Adobe Reader中有一些东西,一些舍入和图像改进导致图像伪像出现。

When checking the JasperReports code, I've found that PDF export draws table border as four single lines. They are drawn with no caps (the line is cut off immediately at the end). When drawing a square border that way, the corners would not connect completely, so each line is drawn slightly longer than the border to compensate for the missing cap. The algorithm for this seems correct to me, however there is something going on in the Adobe Reader, some rounding and image "improvements" which cause image artifacts to appear.

I能够提出一个解决方案来解决我的问题。我已经将JRPdfExporter子类化并修改了绘制边框的代码。用法很简单,只需使用我的类而不是JRPdfExporter。我使用JasperReports 5.0.0。

I was able to come up with a solution which fixes this issue in my case. I have subclassed JRPdfExporter and modified the code which draws borders. Usage is simple, just use my class instead of JRPdfExporter. I use 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;
      }
    }
  }
}

这篇关于JasperReport PDF中的Border Artifacts使用iReport 5.1.0设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆