2013-04-23 76 views
1

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

我不知道它是否是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()添加到各种路径(裁剪,填充,描边等),而不会对结果做任何更改。

我需要做Clip()SaveState()/RestoreState()由于各种gstate值(不透明度,混合模式等)

我已经使用iTextSharp的5.5.3和LGPL版本4.1.6测试的设置。

回答

1

问题是您在考虑NewPath()的含义是“我想开始绘制新路径,这里是我的坐标“。相反,它更多的意思是“我已经完成了我的路径,任何进一步的操作员都应该开始一条新的路径,或者从规格:

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

你几乎可以摆脱所有NewPath()呼叫的除了一个最需要而这直接调用后Clip()

content.Clip(); 
content.NewPath(); 
+0

添加'NEWPATH()'剪辑后'()'工作。 – 2013-04-24 17:53:19

+0

很高兴这个工作,我不得不阅读规范10次才终于点击它所说的。幸运的是,我之前并不习惯看到'NewPath()'命令,所以至少给了我一个提示! – 2013-04-24 18:21:11

+0

我习惯了EPS语法,其中'NewPath'用于开始一个新路径。执行描边或填充不会重置当前路径,因此您可以填充,描边,剪裁相同的路径而无需重新启动或重新定义路径。 – 2013-04-24 18:29:45

0

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

让我们来看看ISO-32000-1,8.5.4节题为“裁减路线运营商”,更具体的注2:我引述:

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

如果你想知道什么qQ运营商都在上面定义:q保存状态操作,Q恢复状态运营商。

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