Tuesday, 14 May 2013

XPS Observations

All these observations were made printing an XPS document which seems to have a problem with the embedded subsetted font. The printer was a non-XPS printer (the Xerox Phaser 8560) but the problems affected the Microsoft PostScript driver as much as the Xerox driver.

Code to test printing XPS using the native API can be found on Logos Bible Software Code Blog

If your text looks blurry / fuzzy in print, it could be because the print path has converted your text to bitmaps.

The font problem which hadn’t upset .net 3.5 caused .net 4.5 to render each word rasterized as an individual png.

Try printing to the Microsoft Xps Document Writer and looking inside the XPS document (below).

.net 4.5 is more fussy than .net 3.5

Compiling the same code for a different target framework can change the results you’ll get.

The native API (with raw spooling) is fussier still

A problematic XPS document could cause reams of pages with random junk at the top, or event have documents be reordered in the print queue.

The native API (with metafile spooling) behaves unpredictably with bad input

You might get pages of junk, you might get a complete document, you might get nothing at all.

The XPS format is pretty easy to mess with manually, once you’ve generated your document

  • Make a test harness that can print the XPS document, using

LocalPrintServer.GetDefaultPrintQueue().AddJob("PrintJob", file, false);

or the native code referenced above.

  • Extract the files from the XPS package by treating it as a zip (I used 7zip to extract the contents into a folder).

  • Have a look around the extracted Resource folders for images (.png) and embedded obfuscated fonts (.odttf).

  • Document text and references to the resources can be changed by editing the xml format file.

  • Select all the files and subfolders in the top level of the extracted package, and add them to a zip file named like “MyHackedUpDocument.xps” (i.e. use the zip format, but .xps extension).

  • You’ve got a new XPS document to try printing.

The obfuscated fonts can be deobfuscated if you want to see what they were originally, using code like this StackOverflow answer but be aware that they will usually have had any unused glyphs stripped out (subsetted).

XPS Packages can contain multiple documents with different (per-document) print tickets

But the .net API ignores them.

You need to feed the tickets to the print job’s document writer.

  • Pick the tickets out of the fixed documents using its FixedDocumentSequenceReader.

  • Create a writer with System.Printing.PrintQueue.CreateXpsDocumentWriter(queue) and handle WritingPrintTicketRequired to supply the ticket based on CurrentPrintTicketLevel and Sequence (which is 1-based).

  • Use MergeAndValidatePrintTicket with the queue’s DefaultPrintTicket to get a valid ticket with the settings for that document.