Advanced Color
Configuration
Notifications
Assumes familiarity with XPSDrv architecture and interfaces
Generic filters
Configuration DLL
New DrvDocumentEvents events
PrintTicket control
Filter service publishing
Notification
Custom Inter Filter Communicators (IFC)
Win32 App WPF App
Win32
Monitoring
Application
MS Component
ISV Component
IHV Component
Win32 Print
APIs
WPF Print
APIs
Print Subsystem
XPS Doc
(Spool File)
Conversion
Render Module
Configuration
Module
Sample XPSDrv Print Driver
Filter Pipeline
Advanced
Color Filter
Configuration
Filter
Notification
Filter
XPS Doc
(PDL
Stream)
Printer
Windows Photo Gallery prints Windows Media Photo image to XPSDrv print driver for 8-color inkjet photo printer
XPS Documents support high dynamic range, wide gamut vector and image content
Using system services, filters can process rich color data to best match printed output to user intent and device capabilities
Windows Color System (WCS) – Enables extensive color conversion
Windows Imaging Components (WIC) – Image format support for Windows Media Photo and other
XPS image formats
PrintTicket – Supports an array of color processing keywords to enable consistent and unambiguous color control between app and device
Windows Photo Gallery allows user selection of print settings
MXDW driver encapsulates Windows Media
Photo image and print settings (as PrintTicket) in XPS Document
Filter process XPS file, decoding/transforming image, saving image to JPG format
Print Subsystem
XPS Doc
(Spool File)
Filter Pipeline
Advanced Color Filter
Identify All
Images in
XPS File
Convert
Images into Device
Color
Space
Convert
Images into JPGs
MS Component
ISV Component
IHV Component
Device Color
Profile
Windows Color
System
Windows
Imaging
Codecs
HRESULT CColorFilter::StartOperation(void)
{
HRESULT hr = SetupColorTransform(L“wsRGB.cdmp") ;
CComPtr<IUnknown> pUnk; while (SUCCEEDED(hr = m_pProvider-> GetXpsPart(&pUnk) ))
{
CComPtr<IXpsDocument> pXD;
CComPtr<IFixedPage> pFP; if (SUCCEEDED(pUnk.QueryInterface(&pXD))) { hr = m_pConsumer->SendXpsDocument(pXD);
} else if ...
else if (SUCCEEDED(pUnk.
QueryInterface(&pFP) )) { hr = ProcessFixedPage(pFP) ; hr = m_pConsumer-> SendFixedPage(pFP) ;
}
} m_pConsumer->CloseSender(); m_pPrintPipeManager->FilterFinished();
DeleteColorTransform(m_hColorTrans) ; return hr;
}
HPROFILE OpenColorProfile(const WCHAR * pszProfileName)
{
PROFILE profile = { PROFILE_FILENAME, (PVOID) pszProfileName,
(DWORD) (wcslen(pszProfileName) * sizeof(WCHAR)) }; return WcsOpenColorProfile(&profile, NULL, NULL, PROFILE_READ,
FILE_SHARE_READ, OPEN_EXISTING, 0);
}
HRESULT SetupColorTransform(const WCHAR * pszDestProfileName)
{
HRESULT hr = S_OK; HPROFILE hProfile[2]; hProfile[0] = OpenColorProfile(L"wscRGB.cdmp"); hProfile[1] = OpenColorProfile(pszDestProfileName);
DWORD intents = INTENT_ABSOLUTE_COLORIMETRIC; m_hColorTrans = CreateMultiProfileTransform(hProfile, 2, &intents, 1,
WCS_ALWAYS | BEST_MODE, INDEX_DONT_CARE) ;
CloseColorProfile(hProfile[0]);
CloseColorProfile(hProfile[1]); return hr;
}
HRESULT CColorFilter::ProcessFixedPage(IFixedPage* pFP)
{
HRESULT hr = S_OK;
CComPtr<IPrintWriteStream> pWriter; if (SUCCEEDED(hr = pFP-> GetWriteStream(&pWriter) )) {
CComPtr<IPrintReadStream> pReader; if (SUCCEEDED(hr = pFP-> GetStream(&pReader) )) {
CXmlFilter filter(pWriter, pReader) ; // XML filter while ( filter.GetToken() ) if ( wcscmp(filter.m_token, L"ImageSource") == 0 ) { filter.GetToken(); // = filter.GetToken(); // URI for ImageSource
ConvertImage(filter.m_token, filter.m_tokenlen,
COUNTOF(filter.m_token), pFP) ;
}
}
} pWriter->Close();
} return hr;
}
HRESULT ConvertWriteImage(pStream, imageUri, pFixedPage)
{
HRESULT hr = S_OK;
CComPtr<IUnknown> pRead;
CComPtr<IPartImage> pImagePart;
CComPtr<IPrintReadStream> pImageStream; if (SUCCEEDED(hr = pFixedPage->GetPagePart(imageUri, &pRead) ) &&
SUCCEEDED(hr = pRead.QueryInterface(&pImagePart)) &&
SUCCEEDED(hr = pImagePart->GetStream(&pImageStream) )) {
CImage src; CImage dst;
CPrintStream2IStream readStream(pImageStream, NULL); hr = src.Load(& readStream, m_pImagingFactory) ; hr = dst.Create(src.m_Width,src.m_Height,BM_BGRTRIPLETS) ;
TranslateBitmapBits(m_hColorTrans, src.m_pBuffer, src.m_icmFormat, src.m_Width, src.m_Height, src.m_Stride, dst.m_pBuffer, dst.m_icmFormat, dst.m_Stride, NULL, NULL) ;
}
CPrintStream2IStream writeStream(NULL, pStream); hr = dst.Save(& writeStream, m_pImagingFactory) ;
} return hr;
During printing, XPSDrv configuration module optimizes
PrintTicket settings and provides additional services to
XPSDrv filters
DrvDocumentEvents – Using new document events, XPSDrv configuration modules can pre-process PrintTicket setting sent by
Windows Presentation Foundation
(WPF) applications
Filter Services – The configuration module can publish helper services for use at print time by filters
User prints from a WPF application
DocumentEvents are intercepted by the configuration module and PrintTickets are added or modified
When filters are processing the XPS file, the filter queries a configuration service to assist in constraint resolution
WPF Print
APIs
XPS Spool
File
Sample XPSDrv Print Driver
Configuration Module
Implement and
Register for PT
DrvDocum entEvents
Overwrite
FDS
PrintTicket
Remove
FD/FP
PrintTicket
(s)
Filter Pipeline
Configuration Filter
Extract all settings from embedded
PrintTicket
Retrieve
Control
Strings
MS Component
ISV Component
IHV Component
Print Subsystem
Add
Control
String to
Content
IPrintCoreHelper
Filter Service
DOCEVENT_FILTER * p = (DOCEVENT_FILTER*) pvOut; switch (iEsc) { case DOCUMENTEVENT_XPS_QUERYFILTER : if (p->cElementsAllocated >= 7) { p->aDocEventCall[0] =
DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE ; p->aDocEventCall[1] =
DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPOST ;
...
p->cElementsReturned = 7;
} else { p->cElementsNeeded = 7; } break; case DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE :
*((PrintPropertiesCollection **) pvOut) =
ReplacePT((PrintPropertiesCollection *) pvIn); break; case DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPOST :
DeleteCollection(*((PrintPropertiesCollection **) pvIn)); break;
}
HRESULT STDMETHODCALLTYPE StartOperation(VOID)
{
HRESULT hr;
CComPtr<IPartPrintTicket> pPrintTicket; while (SUCCEEDED(hr = m_pProvider->GetXpsPart(&pUnk)) {
CComPtr<IXpsDocument> pXD;
CComPtr<IFixedDocumentSequence> pFDS; if (SUCCEEDED(pUnk.QueryInterface(&pXD))) { hr = m_pConsumer->SendXpsDocument(pXD);
} else if (SUCCEEDED(pUnk.QueryInterface(&pFDS))) { if (pPrintTicket == NULL) { pFDS->GetPrintTicket(& pPrintTicket);
} hr = m_pConsumer->SendFixedDocumentSequence(pFDS);
}
...
}
AddPage(pPrintTicket);
...
return hr;
}
HRESULT CConfigurationFilter::AddPage(IPartPrintTicket * pPrintTicket)
{
CComPtr<IFixedPage> pNewPage;
CComPtr<IPrintWriteStream> pNewPageMarkupStream;
CComPtr<IPartFont> pNewFont;
CComPtr<IPrintWriteStream> pNewFontStream; m_pConsumer->GetNewEmptyPart(L"newpage.xaml", IID_IFixedPage, reinterpret_cast<void **>(&pNewPage), &pNewPageMarkupStream); m_pConsumer->GetNewEmptyPart(L"new.ttf", IID_IPartFont, reinterpret_cast<void **>(&pNewFont), &pNewFontStream);
AddFontToPage(L"new.ttf", pNewFont, pNewFontStream, pNewPage);
CComPtr<IPrintReadStream> ptStream; pPrintTicket->GetStream(& ptStream);
AddTextToPage(pNewPageMarkupStream, ptStream, m_pCoreHelper, "new.ttf"); return S_OK;
}
HRESULT AddTextToPage(IPrintWriteStream *pPageMarkupStream,
IPrintReadStream * ptStream, IPrintCoreHelperUni * pPrintHelper, const char * pFont)
{
CXpsWriter writer(pPageMarkupStream); writer.Write("<FixedPage Width=\"816\" Height=\"1056\" xmlns="
"\"http://schemas.microsoft.com/xps/2005/06\" xml:lang=\"en-US\">");
{ CPrintTicketSaxHandler sax(writer, pFont, black);
CComPtr<ISAXXMLReader> pSaxRdr; pSaxRdr.CoCreateInstance(CLSID_SAXXMLReader60); pSaxRdr->putContentHandler(& sax); pfp::PrintReadStreamToSeqStream reader(ptStream); pSaxRdr->parse(CComVariant(& reader));
}
{ CComPtr<IStream> pStream; pPrintHelper->CreateDefaultGDLSnapshot(0, & pStream);
CGDLSaxHandler sax(writer, pFont, black);
CComPtr<ISAXXMLReader> pSaxRdr; pSaxRdr.CoCreateInstance(CLSID_SAXXMLReader60); pSaxRdr->putContentHandler(& sax); pSaxRdr->parse(CComVariant(pStream);
} return writer.Write("</FixedPage>");
}
While processing a print job, a filter sends async notifications to a custom status monitor
Async Notification – The Windows Vista spooler includes an async notification engine for communication and UI messages
XPS IFC – The structured nature of the
XPS Document and the XPS Inter-filter
Communicator identify key steps in document processing
As an XPS Document is rendered in filters, rendering progress is communicated through notification events dispatched by the filter
MS Component
ISV Component
IHV Component
Print Subsystem
XPS Doc
(Spool File)
Filter Pipeline
Notification Filter
Send Job
Processing via
ReportJob
Progress
STDMETHODIMP XpsFilter::InitializeFilter(
__in IInterFilterCommunicator *pIfc,
__in IPrintPipelinePropertyBag *pIPropertyBag,
__in IPrintPipelineManagerControl *pIPipelineControl
)
{
...
VARIANT var;
VariantInit(&var); pIPropertyBag->GetProperty(XPS_FP_PROGRESS_REPORT, &var);
Tools::SmartPtr<IUnknown> pUnk = V_UNKNOWN(&var);
VariantClear(&var); pUnk->QueryInterface(IID_IPrintPipelineProgressReport, reinterpret_cast<void **>(&m_pProgressReport));
...
}
HRESULT XpsFilter::ProcessFixedDoc(__in void *pVoid)
{
Tools::SmartPtr<IFixedDocument> pIFixedDocument; pIFixedDocument.Attach(static_cast<IFixedDocument *>(pVoid));
HRESULT hRes = m_pXpsConsumer->SendFixedDocument(pIFixedDocument); if (SUCCEEDED(hRes))
{ m_pProgressReport->ReportProgress(XpsJob_FixedDocumentAdded);
} return hRes;
}
HRESULT XpsFilter::ProcessFixedPage(__in void *pVoid)
{
Tools::SmartPtr<IFixedPage> pIFixedPage; pIFixedPage.Attach(static_cast<IFixedPage *>(pVoid));
HRESULT hRes = m_pXpsConsumer->SendFixedPage(pIFixedPage); if (SUCCEEDED(hRes))
{ m_pProgressReport->ReportProgress(XpsJob_FixedPageAdded);
} return hRes;
}
Test the GDI Print Path, XPS Print Path and compatibility paths
Report problems immediately
Host-based printers
Pass-through XPSDrv drivers for XPScapable devices (direct consumption)
Aim for Windows Vista launch availability
Understand your company logo goals and review new logo requirements
Basic and Premium
At WinHEC
Practice driver dev and testing skills in XPS Printing hands on labs
Ask the Experts at lunch today
Visit the Microsoft Pavilion to see XPS demos
Read XPSDrv Print Drivers and the Windows Color System on http://www.microsoft.com/whdc/device/print/default.mspx
Attend related sessions
PRI050 Inside Printer Installation on Windows Vista
PRI039 Using the Windows Color System in Device Drivers
PRI077 Print Driver and XPSDrv Testing in Windows Vista
PRI019 Developing XPSDrv Print Drivers
PRI115 Windows Media Photo: A New Format for
End-to-End Digital Imaging
Technical advice
XPSinfo @ microsoft.com
Prninfo @ microsoft.com
mscolor @ microsoft.com
WDK and SDK
Online
XPS Portal http://www.microsoft.com/xps , links to relevant blogs, white papers, specs
WHDC Printing documents http://www.microsoft.com/whdc/device/print/default.mspx
WHDC Color documents http://www.microsoft.com/whdc/device/display/color/default.mspx
Windows Digital Documents Platform Team Newsletter https://profile.microsoft.com/RegSysProfileCenter/subscriptionwizard.aspx
?wizid=77d9786e-9500-40a4-ba20-a4c7504d83ca&lcid=1033
© 2006 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.
The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation.
MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.