您正在使用ColumnText.showAligned(),这足以添加一行没有任何特殊功能的文本,但是如果您希望锚点起作用,则需要以不同的方式使用ColumnText。
这在AddLinkAnnotation2 示例中显示:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfContentByte canvas = stamper.getOverContent(1);
Font bold = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
Chunk chunk = new Chunk("The Best iText Questions on StackOverflow", bold);
chunk.setAnchor("http://pages.itextpdf.com/ebook-stackoverflow-questions.html");
Phrase p = new Phrase("Download ");
p.add(chunk);
p.add(" and discover more than 200 questions and answers.");
ColumnText ct = new ColumnText(canvas);
ct.setSimpleColumn(36, 700, 559, 750);
ct.addText(p);
ct.go();
stamper.close();
reader.close();
}
在这种情况下,我们为ColumnText 对象定义一个矩形,我们将Phrase 添加到列中,然后我们go()。
如果您检查结果,link_annotation2.pdf,您会注意到您可以单击粗体字。
ColumnText.showTextAligned() 没有计划支持此功能。这是一种方便的方法,可以用作上面显示的少数几行的快捷方式,但有一些已知的限制:不换行,忽略交互性,...
更新 1:在评论部分,您提出了一个关于旋转内容和链接的附加问题。
旋转内容并不困难。有不止一种方法可以做到这一点。旋转链接并非易事,因为链接是一种注释,而注释不是内容的一部分。
我们先来看看AddLinkAnnotation3:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AffineTransform transform = AffineTransform.getRotateInstance(Math.PI / 6);
stamper.getWriter().setPageEvent(new AddAnnotation(stamper, transform));
PdfContentByte canvas = stamper.getOverContent(1);
Font bold = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
Chunk chunk = new Chunk("The Best iText Questions on StackOverflow", bold);
chunk.setGenericTag("http://pages.itextpdf.com/ebook-stackoverflow-questions.html");
Phrase p = new Phrase("Download ");
p.add(chunk);
p.add(" and discover more than 200 questions and answers.");
canvas.saveState();
canvas.concatCTM(transform);
ColumnText ct = new ColumnText(canvas);
ct.setSimpleColumn(300, 0, 800, 400);
ct.addText(p);
ct.go();
canvas.restoreState();
stamper.close();
reader.close();
}
在本例中,我们定义了 30 度的变换 (Math.PI / 6):
AffineTransform transform = AffineTransform.getRotateInstance(Math.PI / 6);
我们在渲染列时使用这种转换:
canvas.saveState();
canvas.concatCTM(transform);
// render column
canvas.restoreState();
这会旋转内容,但我们还没有添加任何注释。相反,我们定义了一个页面事件:
stamper.getWriter().setPageEvent(new AddAnnotation(stamper, transform));
我们引入了一个通用标签:
chunk.setGenericTag("http://pages.itextpdf.com/ebook-stackoverflow-questions.html");
为了添加注解,我们在页面事件实现中使用了一些魔法:
public class AddAnnotation extends PdfPageEventHelper {
protected PdfStamper stamper;
protected AffineTransform transform;
public AddAnnotation(PdfStamper stamper, AffineTransform transform) {
this.stamper = stamper;
this.transform = transform;
}
@Override
public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) {
float[] pts = {rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()};
transform.transform(pts, 0, pts, 0, 2);
float[] dstPts = {pts[0], pts[1], pts[2], pts[3]};
rect = new Rectangle(dstPts[0], dstPts[1], dstPts[2], dstPts[3]);
PdfAnnotation annot = PdfAnnotation.createLink(writer, rect, PdfAnnotation.HIGHLIGHT_INVERT, new PdfAction(text));
stamper.addAnnotation(annot, 1);
}
}
我们创建了一个注解,但在我们这样做之前,我们对矩形进行了转换。这可以确保文本与需要可点击的文本相匹配,但是......这可能不是您所期望的:
您可能希望旋转矩形,这是可能的,但更多的是数学运算。例如:您可以创建一个更适合的多边形:ITextShape Clickable Polygon or path
幸运的是,您不需要 30 度角,您希望将文本旋转 90 度角。在这种情况下,您就没有上面屏幕截图中显示的奇怪效果了。
看看AddLinkAnnotation4
public class AddAnnotation extends PdfPageEventHelper {
protected PdfStamper stamper;
protected AffineTransform transform;
public AddAnnotation(PdfStamper stamper, AffineTransform transform) {
this.stamper = stamper;
this.transform = transform;
}
@Override
public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) {
float[] pts = {rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()};
transform.transform(pts, 0, pts, 0, 2);
float[] dstPts = {pts[0], pts[1], pts[2], pts[3]};
rect = new Rectangle(dstPts[0], dstPts[1], dstPts[2], dstPts[3]);
PdfAnnotation annot = PdfAnnotation.createLink(writer, rect, PdfAnnotation.HIGHLIGHT_INVERT, new PdfAction(text));
annot.setBorder(new PdfBorderArray(0, 0, 0));
stamper.addAnnotation(annot, 1);
}
}
如您所见,我添加了一行来移除边框(除非您重新定义 PdfBorderArray,否则边框默认存在)。
其余代码也几乎相同。我们现在定义Math.PI / 2(90 度)的角度。
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AffineTransform transform = AffineTransform.getRotateInstance(Math.PI / 2);
stamper.getWriter().setPageEvent(new AddAnnotation(stamper, transform));
PdfContentByte canvas = stamper.getOverContent(1);
Font bold = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
Chunk chunk = new Chunk("The Best iText Questions on StackOverflow", bold);
chunk.setGenericTag("http://pages.itextpdf.com/ebook-stackoverflow-questions.html");
Phrase p = new Phrase("Download ");
p.add(chunk);
p.add(" and discover more than 200 questions and answers.");
canvas.saveState();
canvas.concatCTM(transform);
ColumnText ct = new ColumnText(canvas);
ct.setSimpleColumn(36, -559, 806, -36);
ct.addText(p);
ct.go();
canvas.restoreState();
stamper.close();
reader.close();
}
注意页面的左下角是轴心点,因此我们需要调整我们添加列的坐标,否则你会旋转页面可见区域之外的所有内容。
更新 2:
在另一条评论中,您询问的是在旋转坐标系中添加文本时需要使用的坐标。
我画了这张图:
在顶部,您在页面中间添加了 MIDDLE 一词,但这不是它出现的位置:您将所有内容旋转 90 度,因此 MIDDLE 一词将在您的页面之外旋转 em>(进入阴影区域)。该词将在 PDF 中,但您永远不会看到它。
如果您查看我的代码,您会发现我使用了这些坐标:
ct.setSimpleColumn(36, -559, 806, -36);
这是可见区域之外(它低于实际页面尺寸),但是当我将所有内容旋转 90 度时,它会旋转进入可见区域。 p>
如果你看我的图,你可以看到坐标为 (0, 0), (0, -595), (842, -598) 和 (842, 0) 的页面旋转了 90 度,因此得到与坐标为 (0, 0)、(595, 0)、(595, 842) 和 (0, 842) 的页面重合。这就是我们在高中时都学过的数学类型;-)
您在crop.getLeft(10), crop.getHeight() / 2 + crop.getBottom() 位置添加文本。如果你知道文本会旋转 90 度,你应该使用crop.getHeight() / 2 + crop.getBottom(), -crop.getLeft()。
了解原因的最好方法是画一幅画。