JasperReport PDF中的Border Artifacts使用iReport 5.1.0设计

时间:2013-08-08 02:15:44

标签: jasper-reports ireport

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

Bad Table

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

1 个答案:

答案 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;
      }
    }
  }
}