我正在使用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版进行了测试。
答案 0 :(得分:1)
问题在于你认为NewPath()
意味着“我想开始画一条新路径,这是我的坐标”。相反,它更多意味着“我已经完成了绘制我的路径,任何进一步的操作员应该开始一条新路径。或者从规范:
结束路径对象而不填充或抚摸它。这个运营商 应该是一种路径绘画无操作,主要用于副作用 更改当前剪切路径(请参见8.5.4,“剪切路径” 运营商“)。
你几乎可以摆脱所有NewPath()
次呼叫,除了最需要的呼叫,直接呼叫后Clip()
content.Clip();
content.NewPath();
答案 1 :(得分:0)
这不是iText中的错误,也不是任何版本的iTextSharp中的错误。您几乎是手动地在操作符之后编写PDF语法运算符。
让我们看一下标题为“剪切路径运算符”的ISO-32000-1,第8.5.4节,更具体地说,在第2条中。我引用:
由于剪切路径是图形状态的一部分,因此其效果可以 通过封闭,可以将其本地化为特定的图形对象 修改剪切路径和绘制这些对象 在一对
q
和Q
运算符之间(见8.4.2,“图形状态” 堆栈“)。Q
运算符的执行导致剪切路径 恢复到q
运算符之前保存的值 裁剪路径被修改。
如果您想知道上述定义中q
和Q
运算符的含义:q
是保存状态运算符,Q
是恢复状态运算符。
我必须承认发生了一些奇怪的事情。可以预期剪切路径在第一个RestoreState()
之后仍然有效。如果没有正确呈现此语法,那么通过丢弃剪切路径,呈现语法的查看器可能会出错: