iTextSharp - 覆盖文本

时间:2014-10-21 12:22:54

标签: c# .net itextsharp

在下面的代码中,我尝试在现有文本上放置一层文本(原始现有文本为"隐藏"通过将其写成白色字体;它用作此替换的占位符处理)。下面的代码非常依赖于Chris Haas在这篇文章中提供的代码:

Getting Coordinates of string using ITextExtractionStrategy and LocationTextExtractionStrategy in Itextsharp

然而,"左"我的文字放置的位置很好,但是"底部"低于我尝试覆盖的文本(即使字体相同)。如何更改此选项以获取原始文档中文本的正确坐标?原始文档是使用表格进行布局创建的,因此这会影响这个"覆盖"过程

byte[] content;

string tmppath = @"C:\Junk\MSE_1.pdf";

using (MemoryStream output = new MemoryStream())
{
    PdfReader pdf_rdr = new PdfReader(tmppath);
    PdfStamper stamper = new PdfStamper(pdf_rdr, output);

    for (int i = 1; i < pdf_rdr.NumberOfPages; i++)
    {
        //Create an instance of our strategy
        var t = new MyLocationTextExtractionStrategy("stuff");

        if (t != null)
        {
            //Parse the page of the document above
            //(if the text was found)
            var ex = PdfTextExtractor.GetTextFromPage(pdf_rdr, i, t);

            //Loop through each chunk found
            foreach (var p in t.myPoints)
            {
                Console.WriteLine(string.Format("Found text {0} at {1} x {2} on page {3}", p.Text, p.Rect.Left, p.Rect.Bottom, i.ToString()));

                PdfContentByte pcb = stamper.GetOverContent(i);

                pcb.BeginText();

                try
                {
                    BaseFont bf = BaseFont.CreateFont(@"C:\Junk\FontFiles\georgia.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

                    pcb.SetFontAndSize(bf, 10);
                    pcb.SetTextMatrix(p.Rect.Left, p.Rect.Bottom);
                    //pcb.SetTextRise(3);
                    pcb.ShowText("STUFF");
                }
                finally
                {
                    pcb.EndText();
                }
            }
        }
    }

    // Set the flattening flag to true, as the editing is done
    stamper.FormFlattening = true;

    // close the pdf stamper
    stamper.Close();

    //close the PDF reader
    pdf_rdr.Close();

    //put the output into the byte array
    content = output.ToArray();
}

//write the content to a PDF file
using (FileStream fs = File.Create(@"C:\Junk\MSE_REPLACED.pdf"))
{
    fs.Write(content, 0, (int)content.Length);
    fs.Flush();
}

1 个答案:

答案 0 :(得分:2)

克里斯&#39; MyLocationTextExtractionStrategy只考虑文本片段的下降线和上升线,因为它对字符串使用的区域感兴趣。

但是,对于您的任务,您需要基线,因为文本绘制操作使用当前位置作为基线开始。

因此,你应该创建一个Chris&#39;的变体。除了上升和下降线之外,管理文本基线而不是/的类。

PS: OP在评论中提问

  

我担心我不熟悉使用基线。你有可以分享的任何例子吗?

如果你看克里斯&#39;您提到的代码,您将看到此RenderText实施:

public override void RenderText(TextRenderInfo renderInfo) {
    base.RenderText(renderInfo);

    //Get the bounding box for the chunk of text
    var bottomLeft = renderInfo.GetDescentLine().GetStartPoint();
    var topRight = renderInfo.GetAscentLine().GetEndPoint();

    //Create a rectangle from it
    var rect = new iTextSharp.text.Rectangle(
                                            bottomLeft[Vector.I1],
                                            bottomLeft[Vector.I2],
                                            topRight[Vector.I1],
                                            topRight[Vector.I2]
                                            );

    //Add this to our main collection
    this.myPoints.Add(new RectAndText(rect, renderInfo.GetText()));
}

如您所见,他存储的矩形的左下角位于下降线的起点,而右上角则是上升线的末端。

如果您更换

    //Get the bounding box for the chunk of text
    var bottomLeft = renderInfo.GetDescentLine().GetStartPoint();
    var topRight = renderInfo.GetAscentLine().GetEndPoint();

通过

    //Get the bounding box for the chunk of text above the baseline
    var bottomLeft = renderInfo.GetBaseline().GetStartPoint();
    var topRight = renderInfo.GetAscentLine().GetEndPoint();

你的覆盖代码应该可以正常工作。