You are on page 1of 24

OpenXPS Support in Windows Developer Preview

September 13, 2011

Abstract

This paper provides information about Support for the OpenXPS document format for Windows operating systems. It provides guidelines for application and print driver developers to help them make the most effective use of this new feature. It assumes that the reader is familiar with the XPS document format. This information applies to the following operating systems: Windows Developer Preview Windows Server Developer Preview References and resources discussed here are listed at the end of this paper. The current version of this paper is maintained on the Web at: OpenXPS Support in Windows Developer Preview

Disclaimer: This document is provided as-is. Information and views expressed in this document, including URL and other Internet website references, may change without notice. You bear the risk of using it. Some examples depicted herein are provided for illustration only and are fictitious. No real association or connection is intended or should be inferred. This document does not provide you with any legal rights to any intellectual property in any Microsoft product. You may copy and use this document for your internal, reference purposes This document is confidential and proprietary to Microsoft. It is disclosed and can be used only pursuant to a non-disclosure agreement. 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 2

Contents
A Brief Introduction to OpenXPS ............................................................................... 3 Benefits and Strategy for Supporting OpenXPS ......................................................... 3 Supported OpenXPS Scenarios .............................................................................. 3 Unsupported OpenXPS Scenarios.......................................................................... 4 Impact on Application Developers............................................................................. 5 Sending XPS to the Print System ........................................................................... 5 Sending OpenXPS to the XPS Print API .................................................................. 6 Impact on Driver Developers ..................................................................................... 7 Enabling OpenXPS in a V4 Print Driver .................................................................. 7 Updating the V4 Print Driver Manifest .................................................................. 8 Resources ................................................................................................................. 11 Appendix A .......................................................................................................... 11 Appendix B........................................................................................................... 13

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 3

A Brief Introduction to OpenXPS


OpenXPS is the XML Paper Specification document format based on the European Carton Makers Association (ECMA) standard specification. This specification, ECMA 388 Open XML Paper Specification, was published in June 2009. For the most up to date information about this specification, follow this URL: http://www.ecma-international.org/publications/standards/Ecma-388.htm This version of the specification is an international standard maintained by ECMA Technical Committee 46 and is subject to ECMAs rules for changes, edits, and revisions.

Benefits and Strategy for Supporting OpenXPS


While Microsoft has supported its original version of XPS since Windows Vista, OpenXPS support is introduced in Windows Developer Preview. As an international standard, OpenXPS has several ecosystem advantages, compared to Microsoft XPS. First, there are a number of government agencies that require standardized document formats for internal use, and that requirement has been a barrier to the adoption of MSXPS in some cases. OpenXPS removes this barrier to adoption. Additionally, Microsoft has received feedback from hardware and software developers requesting a process that prevents frequent revisions and changes to the MSXPS format to prevent the frequent rewriting of their applications and drivers to match the arbitrary changes. OpenXPS is an international standard with a formalized change processes and a wide publication of revisions. Microsoft supports OpenXPS side-by-side with existing Microsoft XPS in Windows Developer Preview, including API, driver, and viewer support. This document focuses on the application APIs and the Driver requirements for supporting OpenXPS. For more information about the differences between MSXPS and OpenXPS, see Appendix A of this paper.

Supported OpenXPS Scenarios


Windows Developer Preview provides end-to-end support for OpenXPS. Applications can present either OpenXPS or Microsoft XPS (MSXPS) to the XPS Print API interfaces (StartXpsPrintJob1() and IPrintDocumentPackageTarget ). The Windows print path will convert the submitted XPS format to match the targeted print driver. Windows also provides APIs to query the print driver, so the application can provide compatible elements and avoid any additional conversion within the print system. OpenXPS is fully supported in the version 4 (v4) print driver model. A driver can use its manifest to declare whether it supports Microsoft XPS, Open XPS, or both formats. Microsoft XPS and OpenXPS are presented to the filters in the print filter pipeline, using the existing stream and OM interfaces no new interfaces are required by drivers to support OpenXPS. The Microsoft XPS Document Writer (MXDW) is updated to a v4 driver in Windows Developer Preview. This allows the MXDW v4 to output either Microsoft XPS or
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 4

OpenXPS from any Windows desktop application. Likewise, the Microsoft XPS Viewer in Windows Developer Preview can open both XPS formats. Users can print from the XPS Viewer to MXDW in order to convert formats. (There is also a command-line XPS Converter provided in the Windows Developer Preview WDK to expedite this process. This is especially useful for converting test XPS documents to OpenXPS, or for converting archived MSXPS documents to OpenXPS in bulk.)

Unsupported OpenXPS Scenarios


Certain legacy functionality is either not supported or provides a downgraded experience when used with OpenXPS. Here is a short list of unsupported functionality: Sending OpenXPS files directly to the spooler (bypassing the XPS Print API) o o o XPS spool files sent directly to the spooler will be treated as MSXPS and handled accordingly. The results of sending an OpenXPS file directly to the spooler are undefined and will likely cause the print job to fail. No support for this scenario will be provided.

We recommend that you do not use the following techniques: Sending OpenXPS streams from applications to the XPS Print API (StartXPSPrintJob() ) o o The conversion from one flavor of XPS to another as a stream can be very expensive for performance. Use StartXPSPrintJob1() or IPrintDocumentPackageTarget() to submit the print job as XPS OM to avoid performance degradation.

Sending MSXPS direct-to-spooler targeting an OpenXPS driver o There is a conversion process provided for this scenario, solely for backward compatibility, but it is expensive for performance. If the driver supports both flavors of XPS, then MSXPS spool files sent directly to spooler will be presented to the driver as MSXPS files, even if OpenXPS is listed as the preferred format for the driver.

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 5

Impact on Application Developers


Sending XPS to the Print System
The XpsPrint.dll library provides the APIs required for sending XPS print jobs to the print system. This DLL has the following functions: StartXPSPrintJob o This function accepts the XPS document as a stream. This requires the application to generate the XPS document and package it before submitting it to the print system. Available on Vista SP1 + KB 971644 (Windows 7 client update for Windows Vista) and later Windows operating systems.

StartXpsPrintJob1 o This function accepts the print job as an IXpsOMPackageWriter interface, which allows the user to pass XPS OM to the XPS Print API instead of a packaged stream. Advantages No need to serialize the XPS in the application Serialization is pushed to the XPS Print API Serializes only if the job is going to an XPS spool file (instead of XGC for conversion to EMF for GDI printing) Application thread is relieved of serialization overhead

Faster conversion between XPS formats if required

Available on Vista SP2 + KB 2117917 (Platform Update Supplement for Windows Vista and for Windows Server 2008), Windows 7 SP1, and Windows Developer Preview Include xpsprint.h in projects using this API This interface supports printing from tailored solutions as well as desktop applications. For desktops apps, this can be used in place of StartXpsPrintJob1 if desired. Available on Window 7 SP1 + Platform Update (TBD) and Windows Developer Preview. Include DocumentTarget.h in projects to use these APIs.

o o o o o

IPrintDocumentPackageTarget

We recommend that you use StartXpsPrintJob1 and IPrintDocumentPackageTarget for sending all XPS print jobs to the print system. StartXpsPrintJob1 and IPrintDocumentPackageTarget both accept XPS OM without serialization, which improves overall performance.
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 6

Applications that consume OpenXPS documents should note that the MIME type for OpenXPS is as follows:
application\oxps

Sending OpenXPS to the XPS Print API


Specific to OpenXPS, XPS OM accepts both MSXPS and OpenXPS and provides methods for conversion and serialization to either format. This allows application developers to be agnostic of the target driver, if they want, and always submit print jobs as XPS OM to either StartXpsPrintJob1 or IDocumentPackageTarget, knowing that the print system will handle any necessary conversion. Of course, preventing conversion between XPS formats will improve end-to-end performance. From the application, the developer can check the following registry key to determine the preferred XPS format of the targeted print driver:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\[PrintDriverName]\PrintDriverData\XpsFormat

Once the preferred XPS format has been determined, the application can provide XPS OM objects that will not require conversion. Of particular note is the use of HD Photo in MSXPS and JPEGXR in OpenXPS. Converting from JPEGXR to HD Photo is relatively lightweight since the primary difference in this conversion is that HD Photo ignores 4 control bits that JPEGXR requires. However, converting from HD Photo to JPEGXR requires the entire image to be re-encoded in order to generate the required control bits. Thus, providing JPEGXR images for high-resolution images will ensure compatibility with OpenXPS and minimize the conversion cost of the image for MSXPS. The Xpsobjectmodel_1.h header defines the additional APIs and objects for OpenXPS. And the IXpsOMObjectFactory1 interface provides additional methods for image conversion:
IXpsOMObjectFactory1->ConvertHDPhotoToJpegXR(IXpsOMImageResource *imageResource); IXpsOMObjectFactory1->ConvertJpegXRToHDPhoto(IXpsOMImageResource *imageResource);

Windows Developer Preview provides the following new and updated enumerations: New enumeration
typedef enum { XPS_DOCUMENT_TYPE_UNSPECIFIED = 1, XPS_DOCUMENT_TYPE_XPS, XPS_DOCUMENT_TYPE_OPENXPS } XPS_DOCUMENT_TYPE;

Updated enumeration
typedef [v1_enum] enum { XPS_IMAGE_TYPE_JPEG = 1, XPS_IMAGE_TYPE_PNG,

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 7

XPS_IMAGE_TYPE_TIFF, XPS_IMAGE_TYPE_WDP, //HDPhoto (formerly Windows Media Photo) XPS_IMAGE_TYPE_JXR //JPEG XR } XPS_IMAGE_TYPE;

The new GetDocumentType APIs allow an application to determine the XPS format of documents. These are available in IXpsOMObjectFactory1, IXpsOMPackage1, and IXpsOMPage1.
IXpsOMObjectFactory1::GetDocumentTypeFromFile(); IXpsOMObjectFactory1::GetDocumentTypeFromStream(); IXpsOMPackage1::GetDocumentType(); IXpsOMPage1::GetDocumentType();

Windows Developer Preview provides the following new error codes in support of OpenXPS: XPS_E_MISMATCHED_NAMESPACE Defined in the OpenXPS namespace at http://schemas.openxps.org/oxps/v1.0 Defined in the MSXPS namespace at http://schemas.microsoft.com/xps/2005/06

XPS_E_ABSOLUTE_REFERENCE This error is returned if MSXPS uses absolute URIs in internal references or attempts to serialize with said references in the stream. That is because XPS OM generates relative URIs. And although MSXPS supports both relative and absolute URIs, OpenXPS requires relative URIs.

Impact on Driver Developers


Enabling OpenXPS in a V4 Print Driver
OpenXPS is supported in the v4 print driver model. The following are the basic steps for enabling OpenXPS in a v4 print driver: Add OpenXPS to the Driver Render section of the driver manifest Add oxps to the File Save section of the manifest if applicable Update print filters to handle OpenXPS elements

Using an existing stream and the appropriate object interfaces, a client can use the OpenXPS format to transfer data to the filters in the print filter pipeline. To transfer a data stream, the client uses the IID_IPrintReadStream and IID_IPrintWriteStream interfaces. To transfer data to an OM component, the client uses the IID_IXpsDocumentProvider and IID_IXpsDocumentConsumer interfaces. Drivers that declare support for OpenXPS will have to ensure that the print filters provided can correctly handle the OpenXPS format when this format is received from the pipeline manager.

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 8

Updating the V4 Print Driver Manifest


The Driver Render Section

During driver installation, the setup process checks the Driver Render section of the manifest to see if the XpsFormat entry includes OpenXPS. The XpsFormat entry may include both XPS (for Microsoft XPS) and OpenXPS, to indicate dual support. The order in which the two formats are listed in the XpsFormat entry determines the preferred format for the driver. Here are some examples of how to update the Driver Render section. Support for OpenXPS only:
[DriverRender] XpsFormat = OpenXPS

Support for MSXPS only:


[DriverRender] XpsFormat = XPS

Support for both formats, with a preference for OpenXPS:


[DriverRender] XpsFormat = OpenXPS,XPS

Support for both formats, with a preference for MSXPS:


[DriverRender] XpsFormat = XPS,OpenXPS

The driver developer determines the preferred format for their V4 print driver, and this decision is based on the functionality that the driver was designed to provide. For example, a print driver could be developed to provide JPEG XR support for highfidelity images. The setup process generates a registry key entry based on the following format:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\[PrintDriverName]\PrintDriverData\XpsFormat

This key stores integers as bytes. A value of 1 indicates XPS support, and a 2 indicates OpenXPS support. Thus, in the preceding manifest example that illustrated dual support, with a preference for the MSXPS format, the value of this key would be: 01 00 00 00 02 00 00 00. This value can be queried by applications to determine the preferred format for the driver, or to ensure that the driver supports dual format. The print system makes various decisions based on this registry key entry. Here are some examples of those decisions: GDI-based print jobs sent to v4 drivers The Microsoft XPS Document Converter (MXDC) takes GDI print job input and
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 9

converts the job to an XPS spool file. The format of that spool file will match the preferred XPS format denoted in the registry key. XPS Print API format conversion The XPS Print API will query the registry key for the target driver. If the driver supports both formats, the XPS Print API will pass the XPS Print Job to the spooler AS SUBMITTED by the application. No conversion will be performed. If the target driver only supports one or the other format, then the job will be converted to the correct format before spooling. If NO XpsFormat is provided in the manifest, the behavior will default to MSXPS only. OpenXPS input will be converted to MSXPS. This behavior provides the strongest backward compatibility for drivers. XPS files sent directly to spooler XPS files sent directly to the spooler are, by default, MSXPS. Submitting OpenXPS direct to the spooler is not supported. However, .NET prior to 4.5+ serialized its own MSXPS and submitted the job directly to the spooler. This behavior was implemented prior to the introduction of the XPS Print API (xpsprint.dll). To provide backward compatibility for these .NET applications, the print filter pipeline manager will check the spool file to determine if it was received direct-to-spooler. If so, it will be assumed to be MSXPS. The print filter pipeline manager will query the drivers XPS formats at that point. If the driver supports MSXPS, no conversion will be performed. If the driver only supports OpenXPS, the print filter pipeline manager will perform a conversion of the file. Conversion at this point in the job is performance expensive; however, it ensures that legacy .NET apps will be able to print to new v4 OpenXPS drivers.

The FileSave Section

The FileSave section of the v4 print driver manifest provides extensions for the File Save dialog used by the PORTPROMPT: port. (PORTPROMPT: should be used in lieu of FILE: in Windows Developer Preview because PORTPROMPT: will allow users to access all file locations to which they have rights, even when the application is running in low-rights mode.) The entries in the FileSave section are associated with the entries in the Driver Render section by index. Example:
[FileSave] xps=0 oxps=0 [DriverRender] XpsFormat=XPS,OpenXPS

This will ensure that when the user sends a print job to this driver and the port is set to PORTPROMPT:, the File Save dialog will display XPS and OpenXPS as file type options in the dialog, and apply .xps or .oxps respectively, as the file extension.
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 10

The following screenshot from the v4 Microsoft XPS Document Writer shows the effect of the preceding manifest entries on the File Save dialog:

Figure 1.0 File save dialog using PORTPROMPT: port with MSXPS and OpenXPS For additional information about other options for the FileSave section of the manifest, please refer to Section 6.2.1 of the Developing v4 Print Drivers whitepaper.
WDK Tools

OpenXPS support is integrated into the V4 Print Driver template in the Windows Driver Kit (WDK). Two tools are also provided to assist with OpenXPS work: XPSConverter (XPSConverter.exe) this tool allows the user to convert MSXPS to OpenXPS and vice versa. IsXPS (IsXps.exe) this tool has been updated to check validity of OpenXPS files in addition to MSXPS files as previously published. To check OpenXPS files, execute the following command:

IsXps t=OXPS f=[path to OpenXPS file]

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 11

Resources
Appendix A
Comparison of Microsoft XPS 1.0 Specification to ECMA 388 OpenXPS 1.0 Specification This appendix shows all the differences between the Microsoft XPS 1.0 specification, chapters 1 through 12, used as the base document and the differences from the comparable sections of the ECMA 388 OpenXPS 1.0 Specification, sections 8 and 19 respectively.

For example:

MSXPS Specification section 1.1 (baseline)

OpenXPS Specification section 8.1

Comparison of OpenXPS spec to MSXPS spec in Appendix A

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 12

To see a full comparison of the differences between the MSXPS and the OpenXPS specification, see the specification comparison document.

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 13

Appendix B
Code example using the StartXpsPrintJob1 XPS Print API
/* * Copyright (c) Microsoft Corporation. All rights reserved. */ // XPSPrintAPISample.cpp : Defines the entry point for the console application. //

#include #include #include #include for font

"stdafx.h" <xpsprint.h> <xpsobjectmodel_1.h> <t2embapi.h> example

//XPS Print API //XPS OM APIs //true type embedding APIs used

//function declaration void SampleStartXpsPrintJob1(); HRESULT CreateXpsOMPrintJob(IOpcPartUri** documentSequencePartUri, IXpsOMDocumentSequence** documentSequence , IOpcPartUri** documentPartUri, IOpcPartUri** discardControlPartName, IXpsOMPage1** page, XPS_SIZE pageSize, IXpsOMFontResource** fontResource); HRESULT CreateFontResourceForFont(IXpsOMObjectFactory1* xpsFactory, LPCTSTR fontName,IXpsOMFontResource **fontResource); HRESULT PrintHelloWorld(IXpsOMObjectFactory1 *xpsFactory, IXpsOMFontResource* fontResource, IXpsOMVisualCollection *pageVisuals, XPS_SIZE pageSize); int _tmain(int argc, _TCHAR* argv[]) { SampleStartXpsPrintJob1(); return 0; } void SampleStartXpsPrintJob1() { //variables required for StartXpsPrintJob1 HRESULT resultStartPrintJob; LPCWSTR printerName = TEXT("Microsoft XPS Document Writer"); LPCWSTR jobName = TEXT("XpsPrintAPITest"); LPCWSTR outputFileName = TEXT("c:\\users\\bclubb.ntdev\\desktop\\XpsPrintAPITest.oxps"); HANDLE progressEvent = CreateEvent(NULL, FALSE, FALSE, NULL); HANDLE completionEvent = CreateEvent(NULL, TRUE, FALSE, NULL); IXpsPrintJob* xpsPrintJob; IXpsOMPackageTarget* xpsOMPackageTarget; //variables required for CreateXpsOMPackageWriter HRESULT resultCreateXpsOMPackageWriter;

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 14

IOpcPartUri* IXpsOMPackageWriter*

discardControlPartName = NULL; packageWriter = NULL;

//variables required for XPS OM print job XPS_SIZE pageSize = {816, 1056}; //US Letter 8.5X11 page XPS units are 1/96" IOpcPartUri* documentSequencePartName = NULL; IXpsOMDocumentSequence* documentSequence = NULL; IXpsOMPrintTicketResource* documentSequencePrintTicket = NULL; IOpcPartUri* documentPartUri = NULL; IXpsOMPage1* page = NULL; IXpsOMFontResource* fontResource = NULL; HRESULT resultCreateXpsOMPrintJob; //variables for PackageWriter HRESULT resultAddPage; HRESULT resultClose;

//this helper function is a very basic simulation of what an app would do to generate a print job. Using the xpsFactory, they would create a document and add visuals to pages. These can be sent to the Package Writer without serializing to an XPS stream resultCreateXpsOMPrintJob = CreateXpsOMPrintJob(&documentSequencePartName,&documentSequence,&document PartUri,&discardControlPartName,&page,pageSize,&fontResource); /* StartXpsPrintJob1 (MSDN Link: http://msdn.microsoft.com/enus/library/ff970306(VS.85).aspx) */ //Call StartXpsPrintJob1. This will initialize the print job with the XPS Print API and return a pointer to an IXpsOMPackageTarget (MSDN Link: http://msdn.microsoft.com/en-us/library/ff970304.aspx). if(SUCCEEDED(resultCreateXpsOMPrintJob)) { resultStartPrintJob = StartXpsPrintJob1(printerName,jobName,outputFileName,progressEvent,comple tionEvent,&xpsPrintJob,&xpsOMPackageTarget); }

/* CreateXpsOMPackageWriter (MSDN Link: http://msdn.microsoft.com/en-us/library/ff970305.aspx) */ //Use the IXpsOMPackageTarget returned from StartXpsPrintJob1 to create an IXpsOmPackageWriter if(SUCCEEDED(resultStartPrintJob)) { resultCreateXpsOMPackageWriter = xpsOMPackageTarget>CreateXpsOMPackageWriter(documentSequencePartName,documentSequencePrintT icket,discardControlPartName,&packageWriter); }

/* IXpsOmPackageWriter (MSDN Link: http://msdn.microsoft.com/en-us/library/dd372619.aspx) */ if(SUCCEEDED(resultCreateXpsOMPackageWriter))


September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 15

{ resultStartPrintJob = packageWriter>StartNewDocument(documentPartUri,NULL,NULL,NULL,NULL); if(SUCCEEDED(resultStartPrintJob)) { resultAddPage = packageWriter>AddPage(page,&pageSize,NULL,NULL,NULL,NULL); } if(SUCCEEDED(resultAddPage)) { resultClose = packageWriter->Close(); packageWriter->Release(); } } /* clean up tasks */ if(xpsPrintJob != NULL) { xpsPrintJob->Release(); } if(xpsOMPackageTarget != NULL) { xpsOMPackageTarget->Release(); } if(documentSequencePartName != NULL) { documentSequencePartName->Release(); } if(documentSequence != NULL) { documentSequence->Release(); } if(documentSequencePrintTicket != NULL) { documentSequencePrintTicket->Release(); } if(documentPartUri != NULL) { documentPartUri->Release(); } if(page != NULL) { page->Release(); } if(fontResource != NULL) { fontResource->Release(); }

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 16

if(discardControlPartName != NULL) { discardControlPartName->Release(); }

CloseHandle(progressEvent); CloseHandle(completionEvent); return; } HRESULT CreateXpsOMPrintJob(IOpcPartUri** documentSequencePartUri, IXpsOMDocumentSequence** documentSequence , IOpcPartUri** documentPartUri, IOpcPartUri** discardControlPartName, IXpsOMPage1** page, XPS_SIZE pageSize, IXpsOMFontResource** fontResource) { IXpsOMObjectFactory1* xpsFactory = NULL; HRESULT hr; //generic, reusable HRESULT //variables for XPS document IXpsOMDocument* //variables for XPS page IOpcPartUri*

document = NULL;

pagePartUri = NULL;

//variables for XPS page visuals IXpsOMVisualCollection* pageVisuals = NULL;

//call CoInitializeEx if (FAILED(hr = CoInitializeEx(0, COINIT_MULTITHREADED))) { //CoInitializeEx failed } //create an instance of IXpsOMObjectFactory11. this will be used to generate the XPSOM objects for the print job that will be submitted to the package writer if(SUCCEEDED(hr)) { hr = CoCreateInstance(__uuidof(IXpsOMObjectFactory1),NULL,CLSCTX_INPROC_SERVER ,__uuidof(IXpsOMObjectFactory1),reinterpret_cast<void**>(&xpsFactory)); } /* create an XPS Document Sequence part */ if(SUCCEEDED(hr)) { hr = xpsFactory>CreatePartUri(TEXT("/FixedDocumentSequence.fdseq"),documentSequencePartU ri); hr = xpsFactory>CreateDocumentSequence(*documentSequencePartUri,documentSequence); }

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 17

/* create XPS discard control part names */ if(SUCCEEDED(hr)) { hr = xpsFactory->CreatePartUri(TEXT("/DiscardControl.xml"), discardControlPartName); } /* create an XPS Document */ //this will be used with packageWriter->StartNewDocument(); if(SUCCEEDED(hr)) { hr = xpsFactory>CreatePartUri(TEXT("/Documents/1/FixedDocument.fdoc"),documentPartUri); hr = xpsFactory>CreateDocument(*documentPartUri,&document); } else { //add error handling here } /* create an XPS Page */ if(SUCCEEDED(hr)) { hr = xpsFactory>CreatePartUri(TEXT("Documents/1/Pages/1.fpage"),&pagePartUri); hr = xpsFactory->CreatePage1(&pageSize, L"en-us", pagePartUri, page); } else { //add error handling here } /* get page visuals collection pointer */ //the visuals collection holds all the graphic elements to be drawn on the page if(SUCCEEDED(hr)) { hr = (*page)->GetVisuals(&pageVisuals); } else { //add error handling here } /* create font resource */ //the XPS OM Object Factory call for creating a font resource is hr = xpsFactory->CreateFontResource(); Due to the fact that there is quite a bit of work to obfuscate and embed a font, I have used a helper function to simplify this part of the sample. if(SUCCEEDED(hr)) { hr = CreateFontResourceForFont(xpsFactory,TEXT("Verdana"),fontResource); } else {
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 18

//add error handling here } /* add text to XPS page */ //adding text requires multiple steps that I did not want to show in this part of the sample code. I have used a helper function to simplify this part of the sample. if(SUCCEEDED(hr)) { hr = PrintHelloWorld(xpsFactory,*fontResource,pageVisuals,pageSize); } else { //add error handling here } return hr; } HRESULT CreateFontResourceForFont(IXpsOMObjectFactory1* xpsFactory, LPCTSTR fontName,IXpsOMFontResource **fontResource) { HRESULT hr = S_OK; HDC hDC = NULL; LOGFONT logFont = {}; HGDIOBJ hFont = NULL; ULONG privStatus = 0; LONG ttStatus; XPS_FONT_EMBEDDING embedding = XPS_FONT_EMBEDDING_NORMAL; DWORD fontDataLen = GDI_ERROR; HGLOBAL hGlobal = NULL; LPVOID ptr = NULL; IStream *fontStream = NULL; GUID fontObfuscationGuid = {}; IOpcPartUri* partUri = NULL; wchar_t fontPartName[60]; //create device context hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL); if (!hDC) { hr = E_UNEXPECTED; } //copy font name into LOGFONT structure if (SUCCEEDED(hr)) { if (wcscpy_s(logFont.lfFaceName, fontName) != 0) { hr = E_UNEXPECTED; } } //create font if (SUCCEEDED(hr)) { hFont = CreateFontIndirect(&logFont); if (!hFont)
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 19

{ hr = E_UNEXPECTED; } } //select font object if (SUCCEEDED(hr)) { if (!SelectObject(hDC, hFont)) { hr = E_UNEXPECTED; } } //get true type font info (MSXPS and OpenXPS require that producers/consumers support OpenType fonts) if (SUCCEEDED(hr)) { if ((ttStatus = TTGetEmbeddingType(hDC, &privStatus)) != E_NONE) { //font is not a TrueType font if (ttStatus == E_NOTATRUETYPEFONT) { //add handler here } //font embedding type could not be retrieve else { //add handler here } hr = E_UNEXPECTED; } } //set embedding value based on info retrieved from TrueType font if (SUCCEEDED(hr)) { switch (privStatus) { case EMBED_PREVIEWPRINT: // Restricted font embedding = XPS_FONT_EMBEDDING_RESTRICTED; break; case EMBED_EDITABLE: // Editable font - MUST obfuscate embedding = XPS_FONT_EMBEDDING_OBFUSCATED; break; case EMBED_INSTALLABLE: // Installable font - SHOULD obfuscate embedding = XPS_FONT_EMBEDDING_OBFUSCATED; break; case EMBED_NOEMBEDDING: //font not allowed to be embedded hr = E_UNEXPECTED; break; default: //undefined result in embedding info hr = E_UNEXPECTED; break; } }
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 20

//get font data length if (SUCCEEDED(hr)) { fontDataLen = GetFontData(hDC, 0, 0, NULL, 0); //could not get length of font data if (fontDataLen == GDI_ERROR) { hr = E_UNEXPECTED; } } //allocate memory for font using GlobalAlloc if (SUCCEEDED(hr)) { hGlobal = GlobalAlloc(GMEM_MOVEABLE, fontDataLen); //Could not allocate memory with GlobalAlloc if (!hGlobal) { hr = E_OUTOFMEMORY; } } //lock the memory allocated above if (SUCCEEDED(hr)) { ptr = GlobalLock(hGlobal); //could nto lock global memory object if (!ptr) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { //could not get font data if (GetFontData(hDC, 0, 0, ptr, fontDataLen) == GDI_ERROR) { hr = E_UNEXPECTED; } GlobalUnlock(hGlobal); } } // Could perform font subsetting with CreateFontPackage here.

//create font stream if (SUCCEEDED(hr)) { //could not create font stream if (FAILED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, &fontStream))) { //add error handler } else {

September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 21

// If CreateStreamOnHGlobal succeeded, the stream now controls the lifetime of the // HGLOBAL. hGlobal = NULL; } } //create GUID for font obfuscation if (SUCCEEDED(hr)) { //Could not create GUID for obfuscation if (FAILED(hr = CoCreateGuid(&fontObfuscationGuid))) { //add error handler } } //output to stream writer if (SUCCEEDED(hr)) { if (swprintf_s( fontPartName, sizeof(fontPartName)/sizeof(wchar_t), L"/Resources/Fonts/%08lX-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X.odttf", fontObfuscationGuid.Data1, fontObfuscationGuid.Data2, fontObfuscationGuid.Data3, fontObfuscationGuid.Data4[0], fontObfuscationGuid.Data4[1], fontObfuscationGuid.Data4[2], fontObfuscationGuid.Data4[3], fontObfuscationGuid.Data4[4], fontObfuscationGuid.Data4[5], fontObfuscationGuid.Data4[6], fontObfuscationGuid.Data4[7] ) == -1) { //Could not format GUID into part name hr = E_UNEXPECTED; } } //create part URI for font if (SUCCEEDED(hr)) { if (FAILED(hr = xpsFactory->CreatePartUri( fontPartName, &partUri))) { //Could not create part URI } } //create the font resource object in XPSOM if (SUCCEEDED(hr)) { if (FAILED(hr = xpsFactory->CreateFontResource( fontStream,
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 22

embedding, partUri, FALSE, fontResource ))) { //Could not create font resource } } //clean up objects if (fontStream) { fontStream->Release(); fontStream = NULL; } if (partUri) { partUri->Release(); partUri = NULL; } if (hGlobal) { GlobalFree(hGlobal); } if (hFont) { DeleteObject(hFont); } if (hDC) { DeleteDC(hDC); } //return HRESULT return hr; } HRESULT PrintHelloWorld(IXpsOMObjectFactory1 *xpsFactory, IXpsOMFontResource* fontResource, IXpsOMVisualCollection *pageVisuals, XPS_SIZE pageSize) { HRESULT hr = S_OK; IXpsOMGlyphs* glyph = NULL; IXpsOMGlyphsEditor* glyphEditor = NULL; IXpsOMSolidColorBrush* brush = NULL; IXpsOMMatrixTransform* matrixTransform = NULL; //create glyphs object if (SUCCEEDED(hr)) { if (FAILED(hr = xpsFactory->CreateGlyphs(fontResource, &glyph))) { //Could not create glyphs }
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 23

} //create glyphs editor object if (SUCCEEDED(hr)) { if (FAILED(hr = glyph->GetGlyphsEditor(&glyphEditor))) { //Could not get glyphs editor } } //add unicode string if (SUCCEEDED(hr)) { if (FAILED(hr = glyphEditor->SetUnicodeString(L"Hello World"))) { //Could not set unicode string } } //apply the changes to the glyph editor if (SUCCEEDED(hr)) { if (FAILED(hr = glyphEditor->ApplyEdits())) { //Could not apply glyph edits } } //set font rendering em size if (SUCCEEDED(hr)) { if (FAILED(hr = glyph->SetFontRenderingEmSize(50.0f))) { //Could not set font rendering size } } //create and set glyph origin point XPS_POINT point; point.x = 100.0; point.y = 100.0; if (SUCCEEDED(hr)) { if (FAILED(hr = glyph->SetOrigin(&point))) { //Could not set origin } } //create black solid color brush if (SUCCEEDED(hr)) { //black brush XPS_COLOR color; color.colorType = XPS_COLOR_TYPE_SRGB; color.value.sRGB.alpha = 255; color.value.sRGB.blue = 0;
September 13, 2011 2011 Microsoft. All rights reserved.

OpenXPS Support in Windows Developer Preview - 24

color.value.sRGB.green = 0; color.value.sRGB.red = 0; if (FAILED(hr = xpsFactory->CreateSolidColorBrush(&color, NULL, &brush))) { //Could not create solid color brush } } //apply the newly created black solid color brush if (SUCCEEDED(hr)) { if (FAILED(hr = glyph->SetFillBrushLocal(brush))) { //Could not set local fill brush } } //set style simulations (in this case, none) if (SUCCEEDED(hr)) { if (FAILED(hr = glyph>SetStyleSimulations(XPS_STYLE_SIMULATION_NONE))) { //Could not set style simulations } }

//append text/glyphs to page visuals if (SUCCEEDED(hr)) { if (FAILED(hr = pageVisuals->Append(glyph))) { //Could not add Hello World glyph to page visuals: 0x%X"), hr); } } // Clean up objects if (brush) { brush->Release(); brush = NULL; } if (glyphEditor) { glyphEditor->Release(); glyphEditor = NULL; } if (glyph) { glyph->Release(); glyph = NULL; } return hr;}
September 13, 2011 2011 Microsoft. All rights reserved.

You might also like