iTextSharp:RestoreState后丢失的剪切路径

时间:2013-04-23 19:37:11

标签: c# pdf itextsharp itext

我正在使用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版进行了测试。

2 个答案:

答案 0 :(得分:1)

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

  

结束路径对象而不填充或抚摸它。这个运营商   应该是一种路径绘画无操作,主要用于副作用   更改当前剪切路径(请参见8.5.4,“剪切路径”   运营商“)。

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

content.Clip();
content.NewPath();

答案 1 :(得分:0)

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

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

  

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

如果您想知道上述定义中qQ运算符的含义:q保存状态运算符,Q恢复状态运算符。

我必须承认发生了一些奇怪的事情。可以预期剪切路径在第一个RestoreState()之后仍然有效。如果没有正确呈现此语法,那么通过丢弃剪切路径,呈现语法的查看器可能会出错: