在iTextSharp中的旋转PdfPCell中创建本地链接

时间:2015-12-22 05:04:34

标签: c# pdf hyperlink itextsharp itext

我正在尝试使用iTextSharp在我的pdf中添加指向另一个页面的链接。 旋转单元格中的链接不起作用。其他细胞按预期工作:

FileStream fs = new FileStream("TestPDF.pdf", FileMode.Create, FileAccess.Write, FileShare.None);
Document doc = new Document();
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();

PdfPTable linkTable = new PdfPTable(2);
PdfPCell linkCell = new PdfPCell();

linkCell.HorizontalAlignment = Element.ALIGN_CENTER;
linkCell.Rotation = 90;
linkCell.FixedHeight = 70;

Anchor linkAnchor = new Anchor("Click here");
linkAnchor.Reference = "#target";
Paragraph linkPara = new Paragraph();
linkPara.Add(linkAnchor);
linkCell.AddElement(linkPara);
linkTable.AddCell(linkCell);

PdfPCell linkCell2 = new PdfPCell();
Anchor linkAnchor2 = new Anchor("Click here 2");
linkAnchor2.Reference = "#target";
Paragraph linkPara2 = new Paragraph();
linkPara2.Add(linkAnchor2);
linkCell2.AddElement(linkPara2);
linkTable.AddCell(linkCell2);

linkTable.AddCell(new PdfPCell(new Phrase("cell 3")));
linkTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(linkTable);

doc.NewPage();

Anchor destAnchor = new Anchor("top");
destAnchor.Name = "target";
PdfPTable destTable = new PdfPTable(1);
PdfPCell destCell = new PdfPCell();
Paragraph destPara = new Paragraph();
destPara.Add(destAnchor);
destCell.AddElement(destPara);
destTable.AddCell(destCell);
destTable.AddCell(new PdfPCell(new Phrase("cell 2")));
destTable.AddCell(new PdfPCell(new Phrase("cell 3")));
destTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(destTable);

doc.Close();

我正在使用'iTextSharp 5.5.8'。我尝试过使用Chunk.SetAction PdfAction.GotoLocalPage和Chunk.SetLocalGoto。什么都不适合我

谢谢。

2 个答案:

答案 0 :(得分:3)

实际上iText(夏普)确实为旋转单元格中的锚点创建了链接注释,但其坐标完全错误:

/Rect[-0.003 0 53.34 12]

这些坐标甚至部分偏离页面,这可能解释了一些PDF查看器的特殊行为。

原因

(我分析了具有相同问题的iText Java代码,因为我更喜欢使用Java。匹配的iTextSharp C#代码非常相似。)

原因是处理PdfDocument的{​​{1}}代码假定当前坐标系是使用 MediaBox 数据初始化的原始用户空间坐标系。因此,它使用当前坐标而不进行任何转换来生成本地链接注释:

PdfChunk

(PdfDocument.writeLineToContent(PdfLine,PdfContentByte,PdfContentByte,Object [],float))

然而,不幸的是,通过用户坐标系变化来实现单元旋转,例如,旋转90°:

float xMarker = text.getXTLM();
float baseXMarker = xMarker;
float yMarker = text.getYTLM();
...
if (chunk.isAttribute(Chunk.LOCALGOTO)) {
    float subtract = lastBaseFactor;
    if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALGOTO))
        subtract = 0;
    if (nextChunk == null)
        subtract += hangingCorrection;
    localGoto((String)chunk.getAttribute(Chunk.LOCALGOTO), xMarker, yMarker, xMarker + width - subtract, yMarker + fontSize);
}

(PdfPRow.writeCells(int,int,float,float,PdfContentByte [],boolean))

因此,上面调用旋转锚点的ct.setSimpleColumn(-0.003f, -0.001f, netWidth + 0.003f, calcHeight); ... pivotY = cell.getTop() + yPos - currentMaxHeight + cell.getEffectivePaddingBottom(); switch (cell.getVerticalAlignment()) { case Element.ALIGN_BOTTOM: pivotX = cell.getLeft() + xPos + cell.getWidth() - cell.getEffectivePaddingRight(); break; case Element.ALIGN_MIDDLE: pivotX = cell.getLeft() + xPos + (cell.getWidth() + cell.getEffectivePaddingLeft() - cell.getEffectivePaddingRight() + calcHeight) / 2; break; default: //top pivotX = cell.getLeft() + xPos + cell.getEffectivePaddingLeft() + calcHeight; break; } saveAndRotateCanvases(canvases, 0, 1, -1, 0, pivotX, pivotY); 代码将位于一个完全错误的位置。

顺便说一句,这不仅涉及本地链接注释,还涉及为块生成的各种注释。一个特别邪恶的情况是泛型标记的情况:如果页面事件监听器对PdfDocument事件做出反应,它可以在调用期间使用坐标进行某些绘制操作,但不能作为相对于 MediaBox <的坐标/强>

对此的修复很可能需要发信号通知GenericTag的任何坐标系更改并更新其中的代码,以便在将坐标用于不受这些转换影响的目的时将此信息考虑在内。特别是PdfDocument事件应该扩展为接收转换坐标和原始坐标。

我建议将此修复程序留给iText开发。

答案 1 :(得分:2)

包含不适合您的代码会非常有用,因此人们可以专注于特定的问题。

当链接和目的地都在表格中时(PdfPCell),我已经验证了通常创建本地链接。此代码按预期工作:

PdfPTable linkTable = new PdfPTable(2);
PdfPCell linkCell = new PdfPCell();
Anchor linkAnchor = new Anchor("Click here to go to top of next page.");
linkAnchor.Reference = "#target";
Paragraph linkPara = new Paragraph();
linkPara.Add(linkAnchor);
linkCell.AddElement(linkPara);
linkTable.AddCell(linkCell);
linkTable.AddCell(new PdfPCell(new Phrase("cell 2")));
linkTable.AddCell(new PdfPCell(new Phrase("cell 3")));
linkTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(linkTable);

doc.NewPage();

Anchor destAnchor = new Anchor("top");
destAnchor.Name = "target";
PdfPTable destTable = new PdfPTable(1);
PdfPCell destCell = new PdfPCell();
Paragraph destPara = new Paragraph();
destPara.Add(destAnchor);
destCell.AddElement(destPara);
destTable.AddCell(destCell);
destTable.AddCell(new PdfPCell(new Phrase("cell 2")));
destTable.AddCell(new PdfPCell(new Phrase("cell 3")));
destTable.AddCell(new PdfPCell(new Phrase("cell 4")));
doc.Add(destTable);