我正在使用 Windows 10 或更高版本中的
Print to PDF
功能生成带水印的 PDF,但我遇到了打印或查看时水印翻转或出现镜像的问题。我正在使用 iText7 库向 PDF 添加水印,以下代码用于水印生成:
try
{
using var inputStream = new MemoryStream(pdfBytes);
using var outputStream = new MemoryStream();
var writerProperties = password != null ? CreateEncryptedWriterProperties(password) : new WriterProperties();
using var reader = new PdfReader(inputStream);
using var writer = new PdfWriter(outputStream, writerProperties);
using var document = new PdfDocument(reader, writer);
var pageCount = document.GetNumberOfPages();
for (int i = 1; i <= pageCount; i++)
{
var page = document.GetPage(i);
var canvas = new PdfCanvas(page.NewContentStreamAfter(), page.GetResources(), document);
DrawWatermark(canvas, watermarkText, document, page);
}
document.Close();
return outputStream.ToArray();
}
catch (Exception ex)
{
_logger?.LogError(ex, "Error watermarking PDF bytes");
return null;
}
private void DrawWatermark(PdfCanvas canvas, string watermarkText, PdfDocument document, PdfPage page)
{
var pageSize = page.GetPageSize();
var (pageWidth, pageHeight) = (pageSize.GetWidth(), pageSize.GetHeight());
var dateText = _options.IncludeDate ? DateTime.Now.ToString(_options.DateFormat) : string.Empty;
var font = string.IsNullOrEmpty(_options.FontPath) ? PdfFontFactory.CreateFont() : PdfFontFactory.CreateFont(_options.FontPath);
var position = CalculateWatermarkPosition(watermarkText, dateText, pageWidth, pageHeight, _options.FontSize, font);
ApplyWatermark(canvas, watermarkText, dateText, position, font, pageWidth, pageHeight);
}
private (float TextX, float TextY, float DateX, float DateY, float TextWidth, float DateWidth) CalculateWatermarkPosition(
string watermarkText,
string dateText,
float pageWidth,
float pageHeight,
float fontSize,
PdfFont font)
{
var textWidth = (font.GetWidth(watermarkText) * fontSize) / 1000;
var dateWidth = (font.GetWidth(dateText) * (fontSize / 2)) / 1000;
var centerX = pageWidth / 2f;
var centerY = pageHeight / 2f;
float verticalSpacing = fontSize / 4;
return (
TextX: centerX - textWidth / 2f,
TextY: centerY,
DateX: centerX - dateWidth / 2f,
DateY: centerY - fontSize - verticalSpacing,
TextWidth: textWidth,
DateWidth: dateWidth
);
}
private void ApplyWatermark(
PdfCanvas canvas,
string watermarkText,
string dateText,
(float TextX, float TextY, float DateX, float DateY, float TextWidth, float DateWidth) position,
PdfFont font,
float pageWidth,
float pageHeight)
{
var centerX = pageWidth / 2f;
var centerY = pageHeight / 2f;
var angleInRadians = (float)(_options.RotationAngle * Math.PI / 180);
canvas.SaveState();
var gs = new PdfExtGState().SetFillOpacity(_options.Opacity);
canvas.SetExtGState(gs);
canvas.BeginText()
.SetFontAndSize(font, _options.FontSize)
.SetFillColor(_options.Color)
.SetTextRenderingMode(PdfCanvasConstants.TextRenderingMode.FILL_STROKE);
var cosAngle = (float)Math.Cos(angleInRadians);
var sinAngle = (float)Math.Sin(angleInRadians);
var tx = position.TextX - centerX;
var ty = position.TextY - centerY;
var finalX = centerX + (tx * cosAngle - ty * sinAngle);
var finalY = centerY + (tx * sinAngle + ty * cosAngle);
canvas.SetTextMatrix(
cosAngle, sinAngle,
-sinAngle, cosAngle,
finalX, finalY
)
.ShowText(watermarkText);
canvas.EndText()
.RestoreState();
}
此问题似乎仅发生在使用 Windows 10 或更高版本的“打印到 PDF”功能生成的 PDF 中。通过其他方式生成的 PDF 不会出现此问题。
你使用
var canvas = new PdfCanvas(page.NewContentStreamAfter(), page.GetResources(), document);
构建
PdfCanvas
。
考虑使用
var canvas = new PdfCanvas(page, true);
相反。
bool
参数值true
使iText将现有内容包装在保存图形状态/恢复图形状态信封中。