PDFClown:创建TextMarkup会导致TextMarkup的Box不准确

时间:2017-08-31 14:34:07

标签: java pdfclown

我正在使用PDFClown来分析和处理PDF文档。我的目标是突出表格中的所有数字。对于所有属于一起的数字(例如:表格的一列中的所有数字),我将创建一个带有四边形列表的TextMarkup。首先,看起来每个方面都很好用:左边的所有高光都属于一个TextMarkup,右边的所有高光都属于另一个TextMarkup。

HighlightedText

但是在分析TextMarkup的大小时,它的大小比它看起来的大。因此,当在左侧TextMarkup框中绘制一个矩形时,矩形与另一列相交,尽管没有高亮显示左侧TextMarkup与另一列相交。有没有办法优化TextMarkup的Box?我认为盒子有一个球状结尾,所以盒子与另一个TextMarkup相交

这是创建TextMarkup的代码:

List<Quad> highlightQuads = new ArrayList<Quad>();
for (TextMarkup textMarkup : textMarkupsForOneAnnotation) {
    Rectangle2D textBox = textMarkup.getBox();
    Rectangle2D.Double rectangle = new Rectangle2D.Double(textBox.getX(), textBox.getY(), textBox.getWidth(), textBox.getHeight());
    highlightQuads.add(Quad.get(rectangle));
}

if (highlightQuads.size() > 0) {

    TextMarkup _textMarkup = new TextMarkup(pagesOfNewFile.get(lastFoundNewFilePage).getPage(), highlightQuads,"", MarkupTypeEnum.Highlight);       
    _textMarkup.setColor(DeviceRGBColor.get(Color.GREEN));
    _textMarkup.setVisible(true);
    allTextMarkUps.add(_textMarkup);
}

以下是一个示例文件Example

谢谢!!

1 个答案:

答案 0 :(得分:1)

您的代码并非真正自包含(我无法运行它,因为它特别错过了输入数据),因此我只能进行一些PDF Clown代码分析。但是,该代码分析确实提供了一个PDF Clown实现细节,可以解释您的观察结果。

PDF Clown如何计算标记注释的尺寸?

标记注释矩形必须足够大,以包括所有四边形以及开始和结束装饰(标记矩形上的左右圆角)。

PDF Clown在TextMarkup

中按如下方式计算此矩形
  public void setMarkupBoxes(
    List<Quad> value
    )
  {
    PdfArray quadPointsObject = new PdfArray();
    double pageHeight = getPage().getBox().getHeight();
    Rectangle2D box = null;
    for(Quad markupBox : value)
    {
      /*
        NOTE: Despite the spec prescription, Point 3 and Point 4 MUST be inverted.
      */
      Point2D[] markupBoxPoints = markupBox.getPoints();
      quadPointsObject.add(PdfReal.get(markupBoxPoints[0].getX())); // x1.
      quadPointsObject.add(PdfReal.get(pageHeight - markupBoxPoints[0].getY())); // y1.
      quadPointsObject.add(PdfReal.get(markupBoxPoints[1].getX())); // x2.
      quadPointsObject.add(PdfReal.get(pageHeight - markupBoxPoints[1].getY())); // y2.
      quadPointsObject.add(PdfReal.get(markupBoxPoints[3].getX())); // x4.
      quadPointsObject.add(PdfReal.get(pageHeight - markupBoxPoints[3].getY())); // y4.
      quadPointsObject.add(PdfReal.get(markupBoxPoints[2].getX())); // x3.
      quadPointsObject.add(PdfReal.get(pageHeight - markupBoxPoints[2].getY())); // y3.
      if(box == null)
      {box = markupBox.getBounds2D();}
      else
      {box.add(markupBox.getBounds2D());}
    }
    getBaseDataObject().put(PdfName.QuadPoints, quadPointsObject);

    /*
      NOTE: Box width is expanded to make room for end decorations (e.g. rounded highlight caps).
    */
    double markupBoxMargin = getMarkupBoxMargin(box.getHeight());
    box.setRect(box.getX() - markupBoxMargin, box.getY(), box.getWidth() + markupBoxMargin * 2, box.getHeight());
    setBox(box);

    refreshAppearance();
  }

  private static double getMarkupBoxMargin(
    double boxHeight
    )
  {return boxHeight * .25;}

所以它需要所有四边形的边界框,并添加左右边距,每个边距宽度为整个边界框高度的四分之一

您案件的结果是什么?

如果只有一个四边形,这个增加的边距宽度是合理的,如果你的标记注释包含许多四边形,这会导致一个巨大的,不必要的边缘。

如何改进代码?

由于添加的上限取决于各个上限而不是它们的组合边界框,因此可以通过使用各个四边形的最大高度而不是所有四边形的边界框的高度来改进代码,例如:像这样:

Rectangle2D box = null;
double maxQuadHeight = 0;
for(Quad markupBox : value)
{
  double quadHeight = markupBox.getBounds2D().getHeight();
  if (quadHeight > maxQuadHeight)
    maxQuadHeight = quadHeight;
  ...
}
...
double markupBoxMargin = getMarkupBoxMargin(maxQuadHeight);
box.setRect(box.getX() - markupBoxMargin, box.getY(), box.getWidth() + markupBoxMargin * 2, box.getHeight());
setBox(box);

如果您不想为此修补PDF Clown,您也可以在构建TextMarkup _textMarkup后执行此代码(稍作调整)以更正预先计算的注释矩形。

这是修复PDF小丑错误吗?

这不是错误,因为文本标记注释矩形不需要最小化;对于每个这样的注释,PDF Clown也可以始终使用整个裁剪框。

我认为,代码的作者想要计算一个有点最小的矩形,但只针对单行优化,所以在某种程度上不符合他自己的期望。

此代码中是否还有其他问题?

是。标记注释标记的文本不需要是水平的,它可以是一个角度,甚至可以是垂直的。在这种情况下,注释矩形的顶部和底部也需要一些边距,而不是(仅)在左侧和右侧。