我有一些代码可以创建一个红色"戳"使用红色字体颜色:
string StampDate = DateTime.Now.ToString("MM/dd/yyyy");
string FontPath = Server.MapPath("/assets/Fonts");
string OrigFile = Server.MapPath("/test.pdf");
const int OpacityPercent = 80;
const float PDFPaidFontSize = 28;
const float PDFCopyX = 170;
const float PDFPaidX = 385;
const float PDFY = 20;
const float PDFDateXOffset = 7;
const float PDFDateYOffset = 12;
const float PDFDateFontSize = 10;
const string PaidStampTxt = "PAID";
const string CopyStampTxt = "COPY";
const string ArialFilename = "arialbd.ttf";
PdfStamper stamper = null;
PdfReader reader = null;
PdfReader.unethicalreading = true;
MemoryStream streamPDF;
try
{
reader = new PdfReader(OrigFile);
streamPDF = new MemoryStream();
stamper = new PdfStamper(reader, streamPDF);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfGState gstate = new PdfGState();
gstate.FillOpacity = gstate.StrokeOpacity = OpacityPercent / 100F;
PdfContentByte overContent = stamper.GetOverContent(i);
overContent.SaveState();
overContent.SetGState(gstate);
overContent.SetColorFill(BaseColor.RED);
overContent.BeginText();
BaseFont font = BaseFont.CreateFont(BaseFont.TIMES_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
overContent.SetFontAndSize(font, PDFPaidFontSize);
overContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, CopyStampTxt, PDFCopyX, PDFY, 0);
overContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, PaidStampTxt, PDFPaidX, PDFY, 0);
overContent.SetColorFill(BaseColor.BLACK);
font = BaseFont.CreateFont(Path.Combine(FontPath, ArialFilename), BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
overContent.SetFontAndSize(font, PDFDateFontSize);
overContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, StampDate, PDFPaidX + PDFDateXOffset, PDFY - PDFDateYOffset, 0);
overContent.EndText();
overContent.RestoreState();
}
}
finally
{
if (stamper != null)
{
stamper.Close();
}
if (reader != null)
{
reader.Close();
}
}
byte[] pdf = streamPDF.ToArray();
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Buffer = false;
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Charset = string.Empty;
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", pdf.Length.ToString());
Response.AddHeader("Content-Disposition", "inline;filename=test.pdf;");
Response.BinaryWrite(pdf);
Response.Close();
生成的pdf文本为灰色而不是红色。 当我恢复到版本5.5.3时,它再次显示为红色。我尝试过5.5.4和5.5.5,他们似乎都有同样的问题。
我的问题是:这是一个错误还是我需要将我的代码更改为更新的代码?
编辑:这似乎只是某些pdf文件的问题。更改字体和pdf文件版本似乎没有效果。
比较有效的pdf和不起作用的pdf(我都不能公开分享)我注意到不起作用的pdf是带标记的pdf,启用了快速Web视图,并由adobe pdf库生成。工作的pdf不是标记的pdf,没有启用快速Web视图,并且是由itextsharp创建的。
由于我无法控制源pdf文件的内容,因此我恢复到了似乎一直有效的早期版本的itextsharp。
答案 0 :(得分:4)
我刚刚执行了这些值的代码:
int OpacityPercent = 70;
int PDFPaidFontSize = 20;
string CopyStampTxt = "COPY";
string PaidStampTxt = "PAID";
int PDFCopyX = 100;
int PDFPaidX = 250;
int PDFY = 500;
string FontPath = @"C:\Windows\Fonts";
string ArialFilename = "ariali.ttf";
int PDFDateFontSize = 30;
string StampDate = "TODAY";
int PDFDateXOffset = 0;
int PDFDateYOffset = 35;
使用简单的源PDF,结果PDF如下所示:
与你的观察相反
生成的pdf文字为灰色而不是红色。
生成的文本颜色偏红(白色部分透明的红色)。
我使用iTextSharp 5.5.5测试。
要获得灰色而不是红色,因此,您的变量值或源PDF必须有一些特殊内容,这不是一般的iTextSharp问题。
在第一次尝试重现该问题后,OP提供了一个示例文件Test.pdf,实际上,对于此文件,相同代码的结果是:
因此,确实存在一个问题。
两种情况下添加的内容流操作的比较显示:
首次尝试使用我的示例PDF:
/Xi0 gs
1 0 0 rg
BT
/Xi1 20 Tf
1 0 0 1 100 500 Tm
(COPY) Tj
使用OP的示例文件进行第二次尝试:
/Xi0 gs
1 0 0 rg
BT
0 g
/Xi1 20 Tf
1 0 0 1 100 500 Tm
(COPY) Tj
因此,尽管使用了相同的代码,但在后一种情况下还有一个0 g
操作,并且操作选择黑色作为填充颜色。
这令人非常惊讶。因此,我查看了iText代码和代码历史记录以获得解释(我选择了iText / Java代码,因为这是原始开发发生的地方,可以更彻底地检查更改)。
事实上,PdfContentByte.beginText
以:
if (isTagged()) {
try {
restoreColor();
} catch (IOException ioe) {
}
}
因此,在标记PDF的情况下,该方法“重置颜色”。为什么?
查看代码历史记录会给出一些提示
修订版5499 标记PDF支持:将图形和文本保存在一个画布中。尚未准备好......
修订版5515 现在iText可以将文本和图形写入1个画布。为此,您应将PdfDocument.putTextAndGraphicsTogether设置为true。
此处上面的块首先出现略有差异
if (autoControlTextBlocks) {
try {
restoreColor();
} catch (IOException ioe) {
}
}
即。此处仅在autoControlTextBlocks
为true
时才会恢复颜色。
...
修订版5533 writer.isTagged属性现在决定是将所有内容写入一个画布还是单独写入。
此处标志autoControlTextBlocks
已被关联作者的isTagged
调用所取代。
我的解释:
为了正确支持标记的PDF,将图形和文本保存在一个画布中是必要的或者至少是有利的(以前它们是在不同的画布中创建的,最终被连接起来,所以相关的图形
为了在高级代码中保持图形和文本的最小开销,在PdfContentByte
中添加了一个新的 autoControlTextBlocks 模式,可以根据需要自动启动和停止文本对象。为文本保存和恢复单独的颜色集。
这种模式似乎已被选为支持iText中标记内容的手段,而它似乎并未被认为对其他上下文有用。因此,此模式现在自动用于标记文件。
在我看来,这种选择不是最佳选择。 PdfContentByte
是公开发布的iText API的一部分,并且公开宣传(作为“内容过多”),用于对生成的或预先存在的PDF进行低级调整。引入这样的副作用违反了API合同,至少这会让人们无法升级。
只需使用
切换颜色设置和文本对象启动操作的顺序...
overContent.BeginText();
overContent.SetColorFill(BaseColor.RED);
...
结果
如果我正确解释了最终签到,则应在iText版本5.5.6中修复此问题。
提交 301a45b57dcef37ae0ec3625fbdd6caaf4004a3a
删除了PdfContentByte类(DEV-1371)中已标记的pdf文档的保存和恢复颜色的弃用逻辑。