Generating XPS Document from Win32 Applications: the XPS Document Writer

At Winhec 2005, Microsoft announced a new file format code named Metro (Modular Content Framework and Document Format). The name Metro has since been retired and replaced with the official name XPS which stands for XML Paper Specification.


XPS is a set of conventions for the use of XML and other widely available technologies to describe the content and appearance of paginated documents. For details about XPS, check the following:


If you’re writing a WPF (Windows Presentation Foundation, previously known as Avalon) application, generating XPS Document is already supported by the new API. If you’re using or writing Win32 based applications, or non WPF-based .Net applications, there is an easy way to generate XPS Documents too, as long as your applications support printing.


With Windows Vista and WPF, Microsoft has provided a GDI/DDI based printer driver which can capture GDI/DDI command sequence and generate a XPS Document from it. The name of the printer driver is Microsoft XPS Document Writer (previously known as MDDW driver). The XPS Documents generated can then be viewed by XpsViewer or other XPS-aware applications and devices.


So let’s try out the XPS Document Writer. First let’s create a simple Microsoft Word document with two shapes overlapping each other, a pink ellipse on top of a yellow rectangle, with the ellipse set to be 50% transparent.


Now we can print it to the XPS Document Writer, hit ‘Print’, select ‘XPS Document Writer’ as your printer, and hit ‘Ok’. A file save dialog box will appear for you to select the file name. XPS Documents uses “.container” as file extension. If you set your printer option to be ‘Open the new XPS Document automatically”, an IE window will pop up showing the new container generated. Otherwise, you can locate the file and double check to open it.


For the document, the WPF rendering is almost exactly the same as Microsoft Word rendering, but they are using two totally different rendering engines. WPF is using a new hardware-accelerated rendering engine based on D3D, while Microsoft Word is using software-based rendering engine known as GDI+.



As XPS Document is packaged in ZIP format and its contents are XML-based, we can easily crack open a XPS Document and see what’s inside. Rename your container to use the zip file extension, double click to open it using WinZip. There are a bunch of files in the zip container. You can find XML files for PrintTicket, image files, font files, XML files for defining the relationship between those files. The file we are interested in here is named FixedPage_1.fpage. This is the XPS representation of the first page of our print job.


Open it up using your favorite XML viewer/editor, mine being the ever-powerful Microsoft Visual Studio.


<FixedPage Width="816" Height="1056"

    xmlns="" xml:lang="en-US">

    <Glyphs Fill="#ff000000" FontUri="/font_0.TTF"


    StyleSimulations="None" OriginX="576" OriginY="336.16"

    Indices="3" UnicodeString=" " />

    <Path Data="F1 M 48,36 L 192,36 192,192 48,192 z" Fill="#ffffff00" />

    <Path Data="F1 M 48,36 L 48,192 192,192 192,36 z"

    Stroke="#ff0000ff" StrokeThickness="0.96" StrokeLineJoin="Miter"

    StrokeStartLineCap="Round" StrokeEndLineCap="Round"

    StrokeMiterLimit="8" Clip="M 0,0 L 0,1056 816,1056 816,0 z" />

    <Path Data="F0 M 216,84 C 149.76,84 96,124.32 96,173.92 96,223.68

    149.76,264 216,264 282.24,264 336,223.68 336,173.92 336,124.32

    282.24,84 216,84 z" Opacity="0.5"

    Clip="M 0,0 L 0,1056 816,1056 816,0 z" Fill="#ffff00ff" />

    <Path Data="F1 M 216,84 C 149.76,84 96,124.32 96,173.92 96,223.68

    149.76,264 216,264 282.24,264 336,223.68 336,173.92 336,124.32

    282.24,84 216,84" Stroke="#ff000000" StrokeThickness="0.96"

    StrokeLineJoin="Round" StrokeStartLineCap="Round"

    StrokeEndLineCap="Round" Clip="M 0,0 L 0,1056 816,1056 816,0 z" />




For the official XPS specification, check


Here is a crash course on XPS syntax:


  • A page in XPS is stored in FixedPage element.
  • XPS base unit is 96-dpi, so 816 x 1056 is just 8.5 inch x 11 inch.
  • XPS uses schema.
  • All text is represented using Glyphs element, unless it has been converted to vector graphic or image.
  • All vector graphic and image is represented using Path element. Images are represented using image brushes.
  • Brush is specified using Fill attribute, which can solid color brush, linear gradient brush, radial gradient brush, image brush, or visual brush.
  • Pen is represented using a few attributes which start with “Stroke”. The “Stroke” attribute itself specifies the brush for stroking, StrokeTickness is for width, and other attributes control the shape of stroking.
  • Transparency (opacity, alpha channel) can be in lots of places in XPS. It can be in colors, images, on a single element, or on a bunch of elements grouped in a Canvas element. Transparency can be also used as opacity mask. The only place with transparency in this example is on the 3rd path, the pink ellipse.

There are five elements in this XPS page:


  • The first is a Glyphs element with a single character. I’m not sure why it’s generated by Microsoft Word.
  • The second is the yellow rectangle.
  • The 3rd is the blue outline of the rectangle. It’s possible to combine 2 and 3 into a single element.
  • The 4th is the 50% transparent pink ellipse. Note that the ellipse has been converted into 4 pieces of Bezier curves.
  • The last one is the black outline of ellipse. Again it can be combined with 4 to save some space, provided we push the opacity into the filling brush first.

The XPS Document Writer does a quite good job of converting GDI/DDI commands into XPS. One of the things it put special handling is optimzation of GDI raster operation sequences into real transparency. When GDI+, which is used by Microsoft Word under the cover, prints shapes with transparency, it normally uses a sequence of GDI commands with GDI raster operation to simulate transparency. Raster operations basically mask off certain pixels off on the source and destination and then combine the remaining to give the impression that two things are blended together.


Here is the actual sequence of commands generated by GDI+ to print the 50% transparent pink ellipse:



    SelectObject(hDC, hObj[2]);


    SetROP2(hDC, R2_MASKPEN);

    SetTextColor(hDC, RGB(0xFF,0xFF,0xFF));


    static KDIB Dib_1(_TEXT("fp00001_1.bmp"));// 16x16x1


    SelectObject(hDC, hObj[3]);

    SetPolyFillMode(hDC, ALTERNATE);



static const POINT Points_2[]={ 378, 208, 171, 208, 3, 334, 3,

   489, 3, 645, 171, 771, 378, 771, 585, 771, 753, 645, 753,

    489, 753, 334, 585, 208, 378, 208 };

    PolyBezier(hDC, Points_2, 13);



    SetPolyFillMode(hDC, ALTERNATE);

    SelectObject(hDC, hObj[2]);

    SetTextColor(hDC, PALETTERGB(0,0,0));

    SetROP2(hDC, R2_COPYPEN);


    SelectObject(hDC, GetStockObject(WHITE_BRUSH));



The main GDI commands used are:


  • PatBlt with PATINVERT rop.
  • FillPath with R2_MASKPEN rop, using a 16 x 16 bit bitmap brush simulating 50% transparency,
  • PatBlt again with PATINVERT rop.

Now you’re ready to explore XPS Document Writer on your own.