1

我正在使用 iTextSharp 生成 PDF 文件。我遇到了一个问题,如果我在做之后SaveState(),那么我的剪切路径会丢失并且不会剪切进一步的绘图。RestoreState()Clip()

我不知道这是否是 iText/iTextSharp 中的错误,或者我做错了什么。下面是示例 C# 代码。

using (var fileStream = System.IO.File.OpenWrite(@"Problem.PDF"))
{
    var doc = new iTextSharp.text.Document();
    var writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, fileStream);

    doc.Open();

    var content = writer.DirectContent;

    // Stroke where the blue box will be drawn
    content.NewPath();
    content.MoveTo(250, 250);
    content.LineTo(250, 350);
    content.LineTo(350, 350);
    content.LineTo(350, 250);
    content.LineTo(250, 250);
    content.SetRGBColorStroke(0, 0, 255);
    content.Stroke();

    // Stroke where the red box will be drawn
    content.NewPath();
    content.MoveTo(250, 150);
    content.LineTo(250, 250);
    content.LineTo(350, 250);
    content.LineTo(350, 150);
    content.LineTo(250, 150);
    content.SetRGBColorStroke(255, 0, 0);
    content.Stroke();

    // Set the clipping box
    content.NewPath();
    content.MoveTo(200, 200);
    content.LineTo(200, 300);
    content.LineTo(300, 300);
    content.LineTo(300, 200);
    content.LineTo(200, 200);
    content.Clip();

    // Save state, then fill the blue box (will be clipped)
    content.SaveState();

    content.NewPath();
    content.MoveTo(250, 250);
    content.LineTo(250, 350);
    content.LineTo(350, 350);
    content.LineTo(350, 250);
    content.LineTo(250, 250);
    content.SetRGBColorFill(0, 0, 255);
    content.Fill();

    // Restore state
    content.RestoreState();

    // Save state again, then fill the red box (will not be clipped... why not?)
    content.SaveState();

    content.NewPath();
    content.MoveTo(250, 150);
    content.LineTo(250, 250);
    content.LineTo(350, 250);
    content.LineTo(350, 150);
    content.LineTo(250, 150);
    content.SetRGBColorFill(255, 0, 0);
    content.Fill();

    content.RestoreState();

    doc.Close();
}

在上面的代码中,我用一个红色的框和一个蓝色的框来表示剪切框将被绘制在哪里(用于验证)。那些被描边的盒子不应该被剪掉。填充的蓝色框被正确剪裁。 红色的填充框没有被剪掉,但应该是我的理解。

我已添加ClosePath()到各种路径(剪切、填充、描边等),而对结果没有任何更改。

由于设置了各种 gstate 值(不透明度、混合模式等),我需要在SaveState()/RestoreState()之后进行Clip()

我已经使用 iTextSharp 5.5.3 和 LGPL 版本 4.1.6 进行了测试。

4

2 回答 2

1

问题是您认为这NewPath()意味着“我想开始绘制一条新路径,这是我的坐标”。相反,它更多地意味着“我已经完成了我的路径,任何进一步的操作员都应该开始一条新路径。或者从规范:

结束路径对象而不填充或抚摸它。这个操作符应该是一个路径绘制无操作,主要用于改变当前剪切路径的副作用(见 8.5.4,“剪切路径操作符”)。

您几乎可以摆脱所有NewPath()呼叫,除了最需要的呼叫,即在呼叫后直接呼叫Clip()

content.Clip();
content.NewPath();
于 2013-04-24T13:37:53.200 回答
0

这不是 iText 中的错误,也不是任何版本的 iTextSharp 中的错误。您几乎手动地在运算符之后编写 PDF 语法运算符。

让我们看一下 ISO-32000-1,第 8.5.4 节,标题为“剪切路径运算符”,更具体地说,在注 2 中。我引用:

由于剪切路径是图形状态的一部分,它的效果可以通过在一对qQ运算符之间封闭剪切路径的修改和那些对象的绘制来定位到特定的图形对象(参见 8.4.2,“图形状态堆栈”)。运算符的执行Q会导致剪切路径恢复为q修改剪切路径之前运算符保存的值。

如果您想知道上述定义中的qand运算符是什么:是保存状态运算符,是恢复状态运算符。QqQ

我必须承认发生了一些奇怪的事情。人们会期望剪切路径在第一个之后仍然处于活动状态RestoreState()。如果此语法未正确呈现,则呈现语法的查看器可能会通过丢弃剪切路径来做错事......

于 2013-04-24T06:58:21.003 回答