Welcome to MSDN Blogs Sign in | Join | Help

Modifying XPS Document: Add Watermark

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:

Published Wednesday, August 23, 2006 6:19 PM by fyuan

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Wednesday, September 06, 2006 11:10 AM by Fillip

# Fillip

Cool site! Thanks!
<a href="http://topperfumes.free20.com/topperfumes/lancome-perfume.html">lancome perfume</a> <a href="http:// topperfumes.free20.com/topperfumes/womens-perfume.html ">womens perfume</a>
[url=http:// topperfumes.free20.com/topperfumes/dolce-gabbana-perfume.html ]dolce gabbana perfume[/url] [url=http:// topperfumes.free20.com/topperfumes/perfume-oil.html ]perfume oil[/url]
Wednesday, September 13, 2006 4:36 AM by rury

# re: Modifying XPS Document: Add Watermark

istalacion de programa
Saturday, December 02, 2006 8:19 AM by Jo

# re: Modifying XPS Document: Add Watermark

This sample DOES NOT work for landscape pages!!

How can this be done for landscape???

Tuesday, January 09, 2007 1:54 AM by jun.jiang

# re: Modifying XPS Document: Add Watermark

Thank you for your explanation.

But I have another question. Now our team want to develop XPS printer driver for our OEM products. The sample of XPS driver in Vista DDK is written based on Unidrv. And I happen to know if we can write similar code for XPS driver to GDI-based monolithic driver. And the new XPS driver does not use any utilities of Unidrv.

Wednesday, June 06, 2007 10:10 AM by wfertgtr

# recipes

[url=http://artmam.net/Dir-Chicken_Recipe.htm]easy chicken recipe[/url]

Of The Month One way to boost your fruit intake is to add apples to salads and cooked dishes

instead of eating them solely as snacks. Peak season for apples is September ...

Wednesday, June 27, 2007 10:11 AM by Keith

# re: Modifying XPS Document: Add Watermark

Any solution for the landscape issue?

Wednesday, June 27, 2007 3:27 PM by Jo

# re: Modifying XPS Document: Add Watermark

Hi,

if you want to have the pages in correct size (also in the xps-viewer) then just add a simple printticket with the PageMediaSize set to the size of the FixedPage...

regards,

Jo

...

// Write out modified page

PrintTicket pt = new PrintTicket();

pt.PageMediaSize = new PageMediaSize(width, height);

vxpsd.Write(newpage, pt);

...

Thursday, June 28, 2007 9:45 AM by Jo

# re: Modifying XPS Document: Add Watermark

for printing you need also the PageOrientation in PrintTicket:

...

// Write out modified page

PrintTicket pt = new PrintTicket();

pt.PageMediaSize = new PageMediaSize(width, height);

pt.PageOrientation = (width > height) ? PageOrientation.Landscape : PageOrientation.Portrait;

vxpsd.Write(newpage, pt);

...

Tuesday, July 31, 2007 4:26 PM by b2kfanfictionstoriesatsony

# b2kfanfictionstoriesatsony

<a href="httpwwwigenqmvhcnpage3html">debrawhalengeorgia</a> debrawhalengeorgia,<a href="httpwwwigenqmvhcnpage4html">matthewstaffordcindynelsonwedding</a> matthewstaffordcindynelsonwedding,<a href="httpwwwigenqmvhcnpage18html">blondesamp</a> blondesamp,<a href="httpwwwigenqmvhcnpage4html">weddingshopslancashire</a> weddingshopslancashire,<a href="httpwwwtyxotwjecnpage98html">tradingspacesideasforbedroomvanitytable</a> tradingspacesideasforbedroomvanitytable,<a href="httpwwwigenqmvhcnpage15html">samsclubmemberbenefits</a> samsclubmemberbenefits,<a href="httpwwwtyxotwjecnpage97html">listofstateswithpowerballjackpotwinners</a> listofstateswithpowerballjackpotwinners,<a href="httpwwwigenqmvhcnpage19html">grillzdirtynellylyrics</a> grillzdirtynellylyrics,<a href="httpwwwigenqmvhcnpage4html">whitetulipweddingbouquets</a> whitetulipweddingbouquets,<a href="httpwwwigenqmvhcnpage18html">funneykidsblondejokes</a> funneykidsblondejokes,

Tuesday, July 31, 2007 8:12 PM by coucher

# coucher

<a href="httpwwwevzvhqkucnpage8html">hotelmayfairpaphoscyprus</a> hotelmayfairpaphoscyprus,<a href="httpwwwevzvhqkucnpage12html">antiquebusinessesamp</a> antiquebusinessesamp,<a href="httpwwwihamuicscnpage98html">vendre</a> vendre,<a href="httpwwwevzvhqkucnpage12html">owningadeli</a> owningadeli,<a href="httpwwwihamuicscnpage92html">gigabeatos</a> gigabeatos,<a href="httpwwwevzvhqkucnpage12html">owningahomeincanaga</a> owningahomeincanaga,<a href="httpwwwevzvhqkucnpage13html">vanhelsingwerewolfpictures</a> vanhelsingwerewolfpictures,<a href="httpwwwevzvhqkucnpage6html">caribbeanflavoredchewsticks</a> caribbeanflavoredchewsticks,<a href="httpwwwihamuicscnpage92html">osuruguay</a> osuruguay,<a href="httpwwwevzvhqkucnpage13html">livingnightmarewerewolfmakeupkit</a> livingnightmarewerewolfmakeupkit,

Wednesday, August 01, 2007 2:07 PM by choiceisyoursrevised

# choiceisyoursrevised

<a href="httpwwwyleaqeaacnpage59html">girlsuseingdildos</a> girlsuseingdildos,<a href="httpwwwyleaqeaacnpage47html">saru14deviantart</a> saru14deviantart,<a href="httpwwwyleaqeaacnpage41html">fiskclarkflagghaberdasherfirm</a> fiskclarkflagghaberdasherfirm,<a href="httpwwwyleaqeaacnpage61html">madonnakissingbritny</a> madonnakissingbritny,<a href="httpwwwyleaqeaacnpage55html">forchheim</a> forchheim,<a href="httpwwwyleaqeaacnpage61html">winmadonnaticket</a> winmadonnaticket,<a href="httpwwwyleaqeaacnpage44html">fujis5000camera</a> fujis5000camera,<a href="httpwwwyleaqeaacnpage42html">1967classicvwsale</a> 1967classicvwsale,<a href="httpwwwyleaqeaacnpage40html">glittergraphis</a> glittergraphis,<a href="httpwwwyleaqeaacnpage43html">listofshrubsforacottagegarden</a> listofshrubsforacottagegarden,

Thursday, September 06, 2007 2:26 AM by Kiran

# re: Modifying XPS Document: Add Watermark

Great snippet...

?? How to write to FixedDocumentSequence rather than to a file [vxpsd.Write(newpage);]

Monday, November 26, 2007 2:02 PM by Modifying XPS Document: Add Watermark

# Modifying XPS Document: Add Watermark

Wednesday, June 11, 2008 2:28 PM by zi

# re: Modifying XPS Document: Add Watermark

How do you modify the contents on each page?

# car insurance &raquo; Modifying XPS Document: Add Watermark

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker