Modifying XPS Document: Add Watermark

本文介绍了一种在XPS文档中每一页添加水印的方法。通过使用WPF将XPS文档转换为Visual对象,然后在每一页上叠加水印,并最终重新序列化为新的XPS文档。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Windows Platform Foundation has provided easy APIs and solutions for XPS document generation, visualization and printing. But often time, after XPS documents are generated, we would like to modify it in certain way. The scenario I'm trying to demonstrate here is adding a watermark to each page within an XPS document.

There are multiple ways to modify an XPS document. The lowest level would be working from container and XPS markup directly. But if you're changing font/image resources, it can get quite complicated.

Another way is using WPF to load each page in an XPS document as a Visual, modify the Visual, and then write it back as a new XPS document. We will take the second approach here.

The first step is to create a Visual for watermak:

Visual CreateWatermark(double width, double height, string message)

{

DrawingVisual watermark = new DrawingVisual();

 

using (DrawingContext ctx = watermark.RenderOpen())

{

FormattedText text = new FormattedText(message,

System.Globalization.CultureInfo.CurrentCulture,

FlowDirection.LeftToRight,

new Typeface("Times New Roman"), 96 * 1.5,

new SolidColorBrush(Color.FromScRgb(0.3f, 1f, 0f, 0f))

);

 

// Rotate transform, keep center

{

double diag = Math.Sqrt(width * width + height * height);

double cX = width / 2;

double cY = height / 2;

double sin = height / diag;

double cos = width / diag;

double dx = (cX * (1.0 - cos)) + (cY * sin);

double dy = (cY * (1.0 - cos)) - (cX * sin);

Transform mat = new MatrixTransform(cos, sin, -sin, cos, dx, dy);

 

ctx.PushTransform(mat);

}

 

// Centerlize

double x = (width - text.Width) / 2;

double y = (height - text.Height) / 2;

ctx.DrawText(text, new Point(x, y));

ctx.Pop();

}

 

return watermark;

}

The CreateWatermark routine accepts three parameters, page width, page height, and a text string. It creates a DrawingVisual by drawing to the DrawingContext interface. To make it more like a real watermark, text is rotated according to page dimension and centered.

Once we have code for watermark, we can use XPS-related API to load a document and create a new document:

void AddWatermark(string filename)

{

// Open original XPS document

XpsDocument xpsOld = new XpsDocument(filename, FileAccess.Read);

FixedDocumentSequence seqOld = xpsOld.GetFixedDocumentSequence();

 

// Create new XPS document

Package container = Package.Open("new_" + filename, FileMode.Create);

XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(new XpsDocument(container));

 

// Needed for writing multiple pages

SerializerWriterCollator vxpsd = writer.CreateVisualsCollator();

 

int pageno = 1;

 

foreach (DocumentReference r in seqOld.References)

{

FixedDocument d = r.GetDocument(false);

 

// Walk through each page

foreach (PageContent pc in d.Pages)

{

FixedPage fixedPage = pc.GetPageRoot(false);

 

double width = fixedPage.Width;

double height = fixedPage.Height;

Size sz = new Size(width, height);

 

// Convert to WPF Visual

fixedPage.Measure(sz);

fixedPage.Arrange(new Rect(new Point(), sz));

fixedPage.UpdateLayout();

 

ContainerVisual newpage = new ContainerVisual();

newpage.Children.Add(fixedPage);

newpage.Children.Add(CreateWatermark(width, height, "Confidential (" + pageno + ")"));

 

pageno ++;

 

// Write out modified page

vxpsd.Write(newpage);

}

}

 

vxpsd.EndBatchWrite();

 

container.Close();

xpsOld.Close();

}

There are a few things to notice here:

  • SerializerWriteCollator is used to write multiple Visuals out, each as a FixedPage
  • Measure, Arrange, and UpdateLayout are used to convert FixedPage to a WPF Visual.
  • ContainerVisual is used to combine the original page with the watermark.
  • The contains of the document is re-serialized, so markup and resource may not be the same as in original document.

Finally, here is a sample output:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值