// //Routine Name: // // PrintTicketHandler::ProcessPart // //Routine Description: // // Merges the Fixed Page Print Ticket with the // Fixed Document Print Ticket and caches the result. // The tickets are merged at the Page scope, so the // result contains no job-level or document-level features. // //Arguments: // // pFP - Fixed Page part // void PrintTicketHandler::ProcessPart( const IFixedPage_t &pFP ) { IPartPrintTicket_t pPrintTicket; HRESULT hr = pFP->GetPrintTicket(&pPrintTicket); // // E_ELEMENT_NOT_FOUND means that this Fixed Page // does not have a Print Ticket. Propagate the Document // Print Ticket. // All other failed HRESULTs should be thrown. // if (hr == E_ELEMENT_NOT_FOUND) { m_pPagePrintTicket = m_pDocumentPrintTicket; return; } THROW_ON_FAILED_HRESULT(hr); m_pPagePrintTicket = ProcessPrintTicket( m_pDocumentPrintTicket, pPrintTicket, kPTPageScope ); }
// //Routine Name: // // PrintTicketHandler::ProcessPrintTicket // //Routine Description: // // Gets the print ticket from the part, merges with // the base ticket, and returns the result. // //Arguments: // // pBasePrintTicket - Base Print Ticket // pDeltaPrintTicketPart - Delta Print Pipeline Print Ticket Part // scope - Scope of the merged Print Ticket // //Return Value: // // IStream_t (smart pointer) // Merged stream // IStream_t PrintTicketHandler::ProcessPrintTicket( const IStream_t &pBasePrintTicket, const IPartPrintTicket_t &pDeltaPrintTicketPart, EPrintTicketScope scope ) { IStream_t pMergedPrintTicket; IStream_t pDeltaPrintTicket; pDeltaPrintTicket = GetStreamFromPart( static_cast<IPartBase_t>(pDeltaPrintTicketPart) ); // // Before calling PTMergeAndValidatePrintTicket, both input // Print Ticket streams MUST be at position 0. The temp Print // Ticket stream is already at position 0, but the Base Print // Ticket may not be. Seek it to 0 to be sure. // LARGE_INTEGER zero; zero.QuadPart = 0; THROW_ON_FAILED_HRESULT( pBasePrintTicket->Seek(zero, SEEK_SET, NULL) ); // // Merge the delta Print Ticket with the // base Print Ticket // THROW_ON_FAILED_HRESULT( ::CreateStreamOnHGlobal( NULL, TRUE, // delete on release &pMergedPrintTicket ) ); m_pHProvider->PTMergeAndValidatePrintTicket( pBasePrintTicket, pDeltaPrintTicket, scope, pMergedPrintTicket ); return pMergedPrintTicket; }
// //Routine Name: // // XPSRasFilter::InitializeFilter_throws // //Routine Description: // // Implements IPrintPipelineFilter initialization. Gets // all necessary communication interfaces. // //Arguments: // // pICommunicator - interface to interfilter communicator // pIPropertyBag - interface to pipeline property bag // VOID XPSRasFilter::InitializeFilter_throws( const IInterFilterCommunicator_t &pICommunicator, const IPrintPipelinePropertyBag_t &pIPropertyBag ) { // // Get the pipeline communication interfaces // THROW_ON_FAILED_HRESULT( pICommunicator->RequestReader(reinterpret_cast<void**>(&m_pReader)) ); THROW_ON_FAILED_HRESULT( pICommunicator->RequestWriter(reinterpret_cast<void**>(&m_pWriter)) ); { // // Check to ensure that the provided interfaces are as expected. // That is, that the GUIDs were correctly listed in the // pipeline configuration file // IXpsDocumentProvider_t pReaderCheck; IPrintWriteStream_t pWriterCheck; THROW_ON_FAILED_HRESULT( m_pReader.QueryInterface(&pReaderCheck) ); THROW_ON_FAILED_HRESULT( m_pWriter.QueryInterface(&pWriterCheck) ); } // // Save a pointer to the Property Bag for further // initialization, later. // m_pIPropertyBag = pIPropertyBag; }
// //Routine Name: // // PrintTicketHandler::QueryPhysicalPageSize // //Routine Description: // // Queries the physical page size from the // Print Ticket using an XPath query. // //Return Value: // // XPS_SIZE // Physical page size from the Print Ticket (in XPS units). // XPS_SIZE PrintTicketHandler::QueryPhysicalPageSize() { // // Default page size: 8.5" x 11" at Xps DPI // XPS_SIZE pageSize = {11.0f * xpsDPI, 8.5f * xpsDPI}; { // // Perform the page width query on the print ticket // IXMLDOMNode_t pNode; // // See the comment in PrintTicketHandler::QueryDPI() for details // about this XPath query. // BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageMediaSize']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]" L"/*/psf:ScoredProperty[substring-after(@name,':')='MediaSizeWidth']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]" L"/psf:Value"); THROW_ON_FAILED_HRESULT( m_pDOMDoc->selectSingleNode(query, &pNode) ); if (pNode) { BSTR_t strWidth; THROW_ON_FAILED_HRESULT( pNode->get_text(&strWidth) ); LONG width; THROW_ON_FAILED_HRESULT( ::VarI4FromStr( strWidth, LOCALE_USER_DEFAULT, 0, // no custom flags &width ) ); // // the page dimensions are in microns; convert to Xps units // pageSize.width = MicronsToXpsUnits(width); } } { // // Perform the page height query on the print ticket // IXMLDOMNode_t pNode; // // See the comment in PrintTicketHandler::QueryDPI() for details // about this XPath query. // BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageMediaSize']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]" L"/*/psf:ScoredProperty[substring-after(@name,':')='MediaSizeHeight']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]" L"/psf:Value"); THROW_ON_FAILED_HRESULT( m_pDOMDoc->selectSingleNode(query, &pNode) ); if (pNode) { BSTR_t strHeight; THROW_ON_FAILED_HRESULT( pNode->get_text(&strHeight) ); LONG height; THROW_ON_FAILED_HRESULT( ::VarI4FromStr( strHeight, LOCALE_USER_DEFAULT, 0, // no custom flags &height ) ); // // the page dimensions are in microns; convert to Xps unit // pageSize.height = MicronsToXpsUnits(height); } } { // // Perform the landscape query on the print ticket // IXMLDOMNode_t pNode; // // See the comment in PrintTicketHandler::QueryDPI() for details // about this XPath query. // BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageOrientation']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]" L"/psf:Option[substring-after(@name,':')='Landscape']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]"); THROW_ON_FAILED_HRESULT( m_pDOMDoc->selectSingleNode(query, &pNode) ); if (pNode) { // // landscape. swap height and width. // FLOAT tmp; tmp = pageSize.height; pageSize.height = pageSize.width; pageSize.width = tmp; } DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Physical Page Size: %f x %f", pageSize.width, pageSize.height); } return pageSize; }
// //Routine Name: // // PrintTicketHandler::CreatePrintTicketHandler // //Routine Description: // // Static factory method that creates an instance of // PrintTicketHandler. // //Arguments: // // pPropertyBag - Property Bag // //Return Value: // // PrintTicketHandler_t (smart ptr) // The new PrintTicketHandler. // PrintTicketHandler_t PrintTicketHandler::CreatePrintTicketHandler( const IPrintPipelinePropertyBag_t &pPropertyBag ) { // // Create MSXML DOM document // IXMLDOMDocument2_t pDOMDoc; THROW_ON_FAILED_HRESULT( ::CoCreateInstance( __uuidof(DOMDocument60), NULL, CLSCTX_INPROC_SERVER, __uuidof(IXMLDOMDocument2), reinterpret_cast<LPVOID*>(&pDOMDoc) ) ); // // Get the default user Print Ticket Stream Factory // Variant_t varUserPrintTicket; THROW_ON_FAILED_HRESULT( pPropertyBag->GetProperty( XPS_FP_USER_PRINT_TICKET, &varUserPrintTicket ) ); IUnknown_t pUnk = varUserPrintTicket.punkVal; IPrintReadStreamFactory_t pStreamFactory; THROW_ON_FAILED_HRESULT( pUnk.QueryInterface(&pStreamFactory) ); // // Get the default user Print Ticket stream // and wrap it in an IStream // IPrintReadStream_t pUserPrintTicketStream; THROW_ON_FAILED_HRESULT( pStreamFactory->GetStream(&pUserPrintTicketStream) ); IStream_t pUserPrintTicket = CreateIStreamFromIPrintReadStream(pUserPrintTicketStream); // // Get the Printer Name // Variant_t varPrinterName; THROW_ON_FAILED_HRESULT( pPropertyBag->GetProperty( XPS_FP_PRINTER_NAME, &varPrinterName ) ); BSTR_t pPrinterName(varPrinterName.bstrVal); // // Get the User Security Token // Avoid CComVariant if getting the XPS_FP_USER_TOKEN property. // Please refer to http://go.microsoft.com/fwlink/?LinkID=255534 for detailed information. // SafeVariant varUserSecurityToken; THROW_ON_FAILED_HRESULT( pPropertyBag->GetProperty( XPS_FP_USER_TOKEN, &varUserSecurityToken ) ); // // Open the Print Ticket Provider // SafeHPTProvider_t pHProvider( new SafeHPTProvider( pPrinterName, varUserSecurityToken.byref ) ); PrintTicketHandler_t toReturn( new PrintTicketHandler( pDOMDoc, pHProvider, pUserPrintTicket ) ); return toReturn; }
// //Routine Name: // // PrintTicketHandler::QueryDPI // //Routine Description: // // Queries the DPI from the Print Ticket using an XPath query. // //Return Value: // // FLOAT // DPI from the Print Ticket. // FLOAT PrintTicketHandler::QueryDPI() { // // Default DPI: 96 DPI // FLOAT dpi = 96.0; // // Perform the page resolution query on the print ticket // IXMLDOMNodeList_t pNodes; // // The following XPath query is fairly straightforward, except for the // predicate attached to Feature. This is necessary to match both the // keyword AND the namespace of the "name" of the Feature as in: // // <psf:Feature name="psk:PageResolution"> // // In order to match the keyword, we match the substring after the colon: // // [substring-after(@name,':')='PageResolution'] // // We also need to ensure that the namespace refers to the correct // printschemakeywords namespace. Thus we get: // // [name(namespace::*[.=PRINTSCHEMAKEYWORDNS])=substring-before(@name,':')] // // where PRINTSCHEMAKEYWORDNS is: // // http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords // BSTR_t query(L"psf:PrintTicket/psf:Feature[substring-after(@name,':')='PageResolution']" L"[name(namespace::*[.='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'])=substring-before(@name,':')]" L"/*/*/psf:Value"); THROW_ON_FAILED_HRESULT( m_pDOMDoc->selectNodes(query, &pNodes) ); if (pNodes) { // // The Print Ticket may have both X and Y resolutions defined, but // the Xps Rasterization Service only accepts a single resolution. // We query for both X and Y resolutions and take the larger of the // two as the destination DPI. The resultant raster data could then // be scaled down in the other dimension to achieve the non-square // pixels. // LONG numResolutions; THROW_ON_FAILED_HRESULT( pNodes->get_length(&numResolutions) ); if (numResolutions != 0 && numResolutions != 1 && numResolutions != 2) { // // We expect 0, 1, or 2 resolutions to be set in the Print Ticket. // Throw if this is not the case. // THROW_ON_FAILED_HRESULT(E_UNEXPECTED); } LONG maxResolution = 0; for (INT i = 0; i < numResolutions; i++) { IXMLDOMNode_t pCurrentNode; THROW_ON_FAILED_HRESULT( pNodes->get_item(i, &pCurrentNode) ); BSTR_t strResolution; THROW_ON_FAILED_HRESULT( pCurrentNode->get_text(&strResolution) ); LONG resolution; THROW_ON_FAILED_HRESULT( ::VarI4FromStr( strResolution, LOCALE_USER_DEFAULT, 0, // no custom flags &resolution ) ); if (resolution > maxResolution) { maxResolution = resolution; } } dpi = static_cast<FLOAT>(maxResolution); } DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Got DPI: %f", dpi); return dpi; }
// //Routine Name: // // PrintTicketHandler::GetMergedPrintTicketParams // //Routine Description: // // Queries a set of parameters from the merged print ticket. // // NOTE: Relies on successful calls to all three PrintTicket // processing methods. // //Return Value: // // ParametersFromPrintTicket // The set of parameters queried from the merged // Print Ticket. // ParametersFromPrintTicket PrintTicketHandler::GetMergedPrintTicketParams() { DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Getting Print Ticket parameters"); if (!m_pPagePrintTicket) { DoTraceMessage(XPSRASFILTER_TRACE_ERROR, L"GetMergedPrintTicketParams called before ProcessPagePrintTicket"); THROW_ON_FAILED_HRESULT(E_FAIL); } ParametersFromPrintTicket params; // // Seek the Page-level Print Ticket to 0 // LARGE_INTEGER zero; zero.QuadPart = 0; THROW_ON_FAILED_HRESULT( m_pPagePrintTicket->Seek(zero, SEEK_SET, NULL) ); // // Load the print ticket stream into a DOM document // // NOTE: We are only looking for features at the Page scope for this sample, // so we only extract features from the effective page-level PrintTicket. // Variant_t varStream(m_pPagePrintTicket); VARIANT_BOOL success; THROW_ON_FAILED_HRESULT( m_pDOMDoc->load(varStream, &success) ); if (!success) { WPP_LOG_ON_FAILED_HRESULT(E_FAIL); THROW_ON_FAILED_HRESULT(E_FAIL); } // // Set the DOM Selection namespace to simplify queries // BSTR_t ns(L"xmlns:psf='http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework'"); Variant_t nsProp(ns); THROW_ON_FAILED_HRESULT( m_pDOMDoc->setProperty(L"SelectionNamespaces", nsProp) ); // // Query the print ticket for parameters of interest // params.destDPI = QueryDPI(); params.scaling = QueryScaling(); params.physicalPageSize = QueryPhysicalPageSize(); // // We simulate imageable area by assuming a constant margin of // around the entire page // params.imageableArea.x = g_pageMargin * xpsDPI; params.imageableArea.y = g_pageMargin * xpsDPI; params.imageableArea.height = params.physicalPageSize.height - 2 * g_pageMargin * xpsDPI; params.imageableArea.width = params.physicalPageSize.width - 2 * g_pageMargin * xpsDPI; return params; }
// //Routine Name: // // XPSRasFilter::StartOperation_throws // //Routine Description: // // Iterates over the 'trunk' parts of the document // and calls appropriate processing methods. // //Arguments: // // None // void XPSRasFilter::StartOperation_throws() { // // CoInitialize/CoUninitialize RAII object. // COM is inititalized for the lifetime of this method. // SafeCoInit coInit; IXpsOMObjectFactory_t pOMFactory; // // Create Xps Object Model Object Factory instance // THROW_ON_FAILED_HRESULT( ::CoCreateInstance( __uuidof(XpsOMObjectFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof(IXpsOMObjectFactory), reinterpret_cast<LPVOID*>(&pOMFactory) ) ); IOpcFactory_t pOpcFactory; // // Create Opc Object Factory instance // THROW_ON_FAILED_HRESULT( ::CoCreateInstance( __uuidof(OpcFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof(IOpcFactory), reinterpret_cast<LPVOID*>(&pOpcFactory) ) ); // // Create the rasterization interface // RasterizationInterface_t pRasInterface = RasterizationInterface::CreateRasterizationInterface( m_pIPropertyBag, m_pWriter ); // // Create the Print Ticket Handler // PrintTicketHandler_t pPrintTicketHandler = PrintTicketHandler::CreatePrintTicketHandler( m_pIPropertyBag ); IUnknown_t pUnk; // // Get first part // THROW_ON_FAILED_HRESULT(m_pReader->GetXpsPart(&pUnk)); while (m_pLiveness->IsAlive() && pUnk != NULL) { IXpsDocument_t pDoc; IFixedDocumentSequence_t pFDS; IFixedDocument_t pFD; IFixedPage_t pFP; if (SUCCEEDED(pUnk.QueryInterface(&pFP))) { DoTraceMessage(XPSRASFILTER_TRACE_VERBOSE, L"Handling a Page"); pPrintTicketHandler->ProcessPart(pFP); ParametersFromPrintTicket printTicketParams = pPrintTicketHandler->GetMergedPrintTicketParams(); pRasInterface->RasterizePage( CreateXpsOMPageFromIFixedPage(pFP, pOMFactory, pOpcFactory), printTicketParams, m_pLiveness ); } else if (SUCCEEDED(pUnk.QueryInterface(&pFD))) { pPrintTicketHandler->ProcessPart(pFD); } else if (SUCCEEDED(pUnk.QueryInterface(&pFDS))) { pPrintTicketHandler->ProcessPart(pFDS); } else if (SUCCEEDED(pUnk.QueryInterface(&pDoc))) { // // Do nothing with the XML Document part // } else { // // Any other document 'trunk' parts are ignored. // } pUnk.Release(); // // Get Next Part // THROW_ON_FAILED_HRESULT(m_pReader->GetXpsPart(&pUnk)); } pRasInterface->FinishRasterization(); }