PDFClown:创建 TextMarkup 会导致 TextMarkup 的框不准确
PDFClown: Creating a TextMarkup leads to an inaccurate Box of the TextMarkup
我正在与 PDFClown 一起分析和使用 PDFDocuments。我的目标是突出显示 table 中的所有数字。对于属于一起的所有数字(例如:table 的一列中的所有数字)我将创建一个带有四边形列表的 TextMarkup。首先,everythink 看起来效果很好:左侧的所有高亮显示都属于一个 TextMarkup,右侧的所有高亮显示都属于另一个 TextMarkup。
但是在分析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
谢谢!!
您的代码并不是真正独立的(我不能 运行 因为它特别遗漏了输入数据),所以我只能做一些 PDF Clown 代码分析。不过,该代码分析确实发现了一个 PDF Clown 实现细节,可以解释您的观察结果。
PDF小丑如何计算标记标注的尺寸?
标记注释矩形必须足够大以包含所有四边形以及开始和结束装饰(标记矩形上的左右圆角大写字母)。
PDF小丑在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 也可以始终为每个此类注释使用整个裁剪框。
不过,我假设代码的作者 想要计算一个最小的矩形 但只针对单行进行了优化,因此在某种程度上没有达到他自己的期望...
这段代码还有其他问题吗?
是的。标记注释标记的文本不需要是水平的,它可以倾斜,甚至可以是垂直的。在这种情况下,注释矩形的顶部和底部也需要一些边距,而不仅仅是左侧和右侧。
我正在与 PDFClown 一起分析和使用 PDFDocuments。我的目标是突出显示 table 中的所有数字。对于属于一起的所有数字(例如:table 的一列中的所有数字)我将创建一个带有四边形列表的 TextMarkup。首先,everythink 看起来效果很好:左侧的所有高亮显示都属于一个 TextMarkup,右侧的所有高亮显示都属于另一个 TextMarkup。
但是在分析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
谢谢!!
您的代码并不是真正独立的(我不能 运行 因为它特别遗漏了输入数据),所以我只能做一些 PDF Clown 代码分析。不过,该代码分析确实发现了一个 PDF Clown 实现细节,可以解释您的观察结果。
PDF小丑如何计算标记标注的尺寸?
标记注释矩形必须足够大以包含所有四边形以及开始和结束装饰(标记矩形上的左右圆角大写字母)。
PDF小丑在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 也可以始终为每个此类注释使用整个裁剪框。
不过,我假设代码的作者 想要计算一个最小的矩形 但只针对单行进行了优化,因此在某种程度上没有达到他自己的期望...
这段代码还有其他问题吗?
是的。标记注释标记的文本不需要是水平的,它可以倾斜,甚至可以是垂直的。在这种情况下,注释矩形的顶部和底部也需要一些边距,而不仅仅是左侧和右侧。