我想在叠加文字中添加一个链接。我已经读过,使用Anchor
只适用于从头开始制作的文档,但不适用于现有的pdf文件。我的代码是为每个页面添加叠加文本。我的目标是使该文本的一部分可以点击。我不知道如何制作链接注释,这是一个短语的一部分。
这是我的代码:
int n = reader.getNumberOfPages();
// step 4: we add content
PdfImportedPage page;
PdfCopy.PageStamp stamp;
for (int j = 0; j < n; )
{
++j;
page = writer.getImportedPage(reader, j);
if (i == 1) {
stamp = writer.createPageStamp(page);
Rectangle mediabox = reader.getPageSize(j);
Rectangle crop = new Rectangle(mediabox);
writer.setCropBoxSize(crop);
// add overlay text
Paragraph p = new Paragraph();
p.setAlignment(Element.ALIGN_CENTER);
FONT_URL_OVERLAY.setColor(0, 191, 255);
// get current user
EPerson loggedin = context.getCurrentUser();
String eperson = null;
if (loggedin != null)
{
eperson = loggedin.getFullName();
}
else eperson = "Anonymous";
Phrase downloaded = new Phrase();
Chunk site = new Chunk("My Website",FONT_URL_OVERLAY);
site.setAction(new PdfAction("http://www.mywebsite.com"));
downloaded.add(new Chunk("Downloaded by [" + eperson + "] from ", FONT_OVERLAY));
downloaded.add(site);
downloaded.add(new Chunk(" on ", FONT_OVERLAY));
downloaded.add(new Chunk(new SimpleDateFormat("MMMM d, yyyy").format(new Date()), FONT_OVERLAY));
downloaded.add(new Chunk(" at ", FONT_OVERLAY));
downloaded.add(new Chunk(new SimpleDateFormat("h:mm a z").format(new Date()), FONT_OVERLAY));
p.add(downloaded);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, p,
crop.getLeft(10), crop.getHeight() / 2 + crop.getBottom(), 90);
stamp.alterContents();
}
writer.addPage(page);
}
所以我的叠加层看起来像这样:
于2015年2月17日中部标准时间上午1:20从[strong>我的网站下载[匿名]
如何将我的网站转换为链接注释?在SO中搜索,我发现了post,但我不知道如何在我的叠加文字的一部分中添加链接注释。
提前致谢。
编辑:如何添加带有链接注释的旋转叠加文字到现有的pdf?
感谢Bruno Lowagie在回答我的问题时不遗余力。虽然我最初询问如何在叠加文本中添加链接注释到现有的pdf,但他也在他的答案的评论部分提供了我的问题,如果旋转叠加文本,则正确设置坐标。
答案 0 :(得分:2)
您使用的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度的角度旋转文本。在这种情况下,您没有上面屏幕截图中显示的奇怪效果。
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一词将在页面外旋转 (进入阴影区域)。这个词将在PDF中,但你永远不会看到它。
如果查看我的代码,您会看到我使用这些坐标:
ct.setSimpleColumn(36, -559, 806, -36);
这是在可见区域之外(它在实际页面尺寸之下),但是当我将所有内容旋转90度时,它会将旋转到可见区域。
如果查看我的绘图,可以看到坐标为(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()
。
了解原因的最佳方法是制作图纸。