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:


Comments (21)

  1. Fillip says:

    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]

  2. rury says:

    istalacion de programa

  3. Jo says:

    This sample DOES NOT work for landscape pages!!

    How can this be done for landscape???

  4. jun.jiang says:

    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.

  5. wfertgtr says:

    [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 …

  6. Keith says:

    Any solution for the landscape issue?

  7. Jo says:

    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);

  8. Jo says:

    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);

  9. <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,

  10. coucher says:

    <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,

  11. <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,

  12. Kiran says:

    Great snippet…

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

  13. zi says:

    How do you modify the contents on each page?

  14. Through scuttlebutt at work I hear various discussions about watermarking and its place in the rights

  15. Fragranceglamour's Beauty products and cosmetics have been used since the Egyptians and Ancient Greece and Rome. Beauty products are not essential, but they are a luxury that most of us can afford. Beauty products range from skin care products such as soaps, bath salts, creams, exfoliating scrubs, and face and body packs, to hair care products such as shampoos, conditioners, hair colours, and various perming solutions, to overall body-care products such as moisturizers