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

我正在尝试使用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。 没有什么对我有用

谢谢。

实际上iText(Sharp)也为旋转单元格中的锚点创建了一个Link注释,但它的坐标完全错误:

 /Rect[-0.003 0 53.34 12] 

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

原因

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

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

 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); } 

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

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

 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); 

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

因此,上面要求旋转锚块的PdfDocument代码将位于通常完全错误的位置。

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


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

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

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

我已经validation了创建本地链接,当链接和目标都在表中时(即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);