共用方式為


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

  • Anonymous
    September 06, 2006
    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]

  • Anonymous
    September 12, 2006
    istalacion de programa

  • Anonymous
    December 02, 2006
    This sample DOES NOT work for landscape pages!! How can this be done for landscape???

  • Anonymous
    January 08, 2007
    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.

  • Anonymous
    June 06, 2007
    The comment has been removed

  • Anonymous
    June 27, 2007
    Any solution for the landscape issue?

  • Anonymous
    June 27, 2007
    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); ...

  • Anonymous
    June 28, 2007
    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); ...

  • Anonymous
    July 31, 2007
    <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,

  • Anonymous
    July 31, 2007
    <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,

  • Anonymous
    August 01, 2007
    <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,

  • Anonymous
    September 05, 2007
    Great snippet... ?? How to write to FixedDocumentSequence rather than to a file [vxpsd.Write(newpage);]

  • Anonymous
    November 26, 2007
    PingBack from http://feeds.maxblog.eu/item_996524.html

  • Anonymous
    June 11, 2008
    How do you modify the contents on each page?

  • Anonymous
    August 11, 2008
    PingBack from http://hoursfunnywallpaper.cn/?p=916

  • Anonymous
    December 04, 2008
    Through scuttlebutt at work I hear various discussions about watermarking and its place in the rights

  • Anonymous
    January 20, 2009
    PingBack from http://www.hilpers.com/1031485-nachtraegliches-aendern-von-xps-dateien

  • Anonymous
    May 26, 2009
    PingBack from http://castironbakeware.info/story.php?title=feng-yuan-modifying-xps-document-add-watermark

  • Anonymous
    June 07, 2009
    PingBack from http://greenteafatburner.info/story.php?id=3728

  • Anonymous
    June 16, 2009
    PingBack from http://lowcostcarinsurances.info/story.php?id=6085

  • Anonymous
    June 06, 2010
    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