C# 版本5.5.4+中的ItextSharp字体颜色问题;
我有一些使用红色字体颜色创建红色“戳记”的代码:C# 版本5.5.4+中的ItextSharp字体颜色问题;,c#,itext,C#,Itext,我有一些使用红色字体颜色创建红色“戳记”的代码: 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 PDFPaidF
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();
string StampDate=DateTime.Now.ToString(“MM/dd/yyyy”);
字符串FontPath=Server.MapPath(“/assets/Fonts”);
字符串OrigFile=Server.MapPath(“/test.pdf”);
常数不透明度=80;
常量浮点PDFPaidFontSize=28;
常量浮点PDFCopyX=170;
常量浮点PDFPaidX=385;
常数浮点PDFY=20;
常量浮点PDFDateXOffset=7;
常量浮点PDFDateYOffset=12;
常量浮点PDFDateFontSize=10;
const string PaidStampTxt=“已付款”;
常量字符串copyStampText=“复制”;
常量字符串ArialFilename=“arialbd.ttf”;
PdfStamper压模=null;
PdfReader reader=null;
PdfReader.unethicalreading=true;
MemoryStream streamPDF;
尝试
{
读卡器=新的PDF读卡器(原始文件);
streamPDF=新的MemoryStream();
压模=新的PdfStamper(读卡器,streamPDF);
对于(int i=1;i)首次尝试重现问题
我刚刚为这些值执行了您的代码:
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必须有一些特殊之处,这不是一个一般问题
使用OP提供的文件复制问题
在首次尝试重现问题后,OP提供了一个示例文件,实际上,对于该文件,相同代码的结果是:
因此,确实存在一个问题
分析
两种情况下添加的内容流操作的比较显示:
- 对于第一次尝试使用我的示例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
因此,尽管使用了相同的代码,在后一种情况下还有一个附加的0g
操作,并且该操作选择黑色作为填充颜色
因此,我查看了iText代码和代码历史以获得解释(我选择了iText/Java代码,因为它是原始开发的地方,可以更彻底地检查更改)
实际上,PdfContentByte.beginext
以以下内容结尾:
if (isTagged()) {
try {
restoreColor();
} catch (IOException ioe) {
}
}
背景
因此,在标记PDF的情况下,此方法“重置颜色”。为什么
查看代码历史记录会给出一些提示
- 修订版5499标记的PDF支持:将图形和文本保留在一个画布中。尚未准备就绪
- 修订版5515现在iText可以将文本和图形写入1个画布。为此,应将PdfDocument.puttextandgraphics设置为true
这里,上面的块首先出现,略有不同
if (autoControlTextBlocks) {
try {
restoreColor();
} catch (IOException ioe) {
}
}
i、 e.仅当autoControlTextBlocks
为true
时,颜色才会恢复
- 修订版5533 writer.istaged属性现在决定是将所有内容写入一个画布还是写入单独的画布
这里,标志
autoControlTextBlocks
被相关写入程序的istaged
调用所取代
我的解释是:
- 为了正确地支持带标签的PDF,将图形和文本保存在一个画布中是必要的,或者至少是有利的(以前它们是在不同的画布中创建的,最终被连接在一起,因此相关的图形和文本在内容中彼此距离较远)
- 为了使图形和文本在高级代码中保持在一起,并将开销降至最低,在
PdfContentByte
中添加了一个新的autoControlTextBlocks模式,可根据需要自动启动和停止文本对象,并保存和恢复文本的单独颜色集
- 此模式似乎已被选为iText中支持标记内容的方式,但似乎对其他上下文没有用处。因此,此模式现在自动用于标记文件
在我看来,这种选择不是最优的。PdfContentByte
是公开可用的iText API的一部分,它被公开宣传(称为“过度内容”),用于对生成的或预先存在的PDF进行低级调整。引入这种副作用违反了API合同,至少是阻碍人们升级的麻烦
变通
只需切换颜色设置和文本对象启动操作的顺序,使用
...
overContent.BeginText();
overContent.SetColorFill(BaseColor.RED);
...
导致
决议
如果我正确解释了最终签入,这个问题应该在iText版本5.5.6中解决
提交301a45b57dcef37ae0ec3625fbdd6caaf4004a3a
删除了PdfContentByte类(DEV-1371)中已标记pdf文档保存和恢复颜色的不推荐逻辑。请显示更完整的代码示例,还包括文本绘图说明。编辑以显示完整的代码示例。“红色”代码为:overContent.SetColorFill(BaseColor.Red);乍一看还可以。但是,代码中有许多未知实体,尤其是源PDF和外部设置的许多值。因此,您能否完成示例以使其独立?或者至少提供一个示例输出PDF以进行分析?我认为这与源PDF属性有更大关系。我编辑以显示v可变值,以及在比较有效的pdf文件和无效的pdf文件时我可以确定的内容。您能否创建一个源文件来说明您可以共享的问题?非常感谢您的帮助!非常棒的深入分析!:O