/*++ Routine Name: CBookletFilter::CreatePadPage Routine Description: Method to create a pad page which is required for odd page counts to ensure pages are correctly ordered for presentation as a booklet Arguments: ppNewPage - Pointer to a pointer to the newly created fixed page Return Value: HRESULT S_OK - On success E_* - On error --*/ HRESULT CBookletFilter::CreatePadPage( _Outptr_ IFixedPage** ppNewPage ) { HRESULT hr = S_OK; // // Validate parameters and members before proceeding // if (SUCCEEDED(hr = CHECK_POINTER(ppNewPage, E_POINTER)) && SUCCEEDED(hr = CHECK_POINTER(m_pXDWriter, E_PENDING))) { *ppNewPage = NULL; PCWSTR pszPageName = NULL; try { // // Create a unique name for the pad page for this print session // CStringXDW szNewPageName; szNewPageName.Format(L"/Pad_page_%u.xaml", GetUniqueNumber()); pszPageName = szNewPageName.GetBuffer(); // // Create a new empty page and retrieve a writer. Also get a // reader from the first page so we can copy the FixedPage root // element. This ensures the page sizes match. // CComPtr<IPrintWriteStream> pWriter(NULL); CComPtr<ISAXXMLReader> pSaxRdr(NULL); if (SUCCEEDED(hr) && SUCCEEDED(hr = m_pXDWriter->GetNewEmptyPart(pszPageName, IID_IFixedPage, reinterpret_cast<PVOID*>(ppNewPage), &pWriter)) && SUCCEEDED(hr = pSaxRdr.CoCreateInstance(CLSID_SAXXMLReader60))) { // // We use a simple SAX handler which copies only the root // element and discards all other content. // CBkSaxHandler bkSaxHndlr(pWriter); CComPtr<IPrintReadStream> pReader(NULL); IFixedPage* pFP = NULL; pFP = m_cacheFP[0]; if (SUCCEEDED(hr) && SUCCEEDED(hr = pSaxRdr->putContentHandler(&bkSaxHndlr)) && SUCCEEDED(hr = pFP->GetStream(&pReader))) { CComPtr<ISequentialStream> pReadStreamToSeq(NULL); pReadStreamToSeq.Attach(new(std::nothrow) pfp::PrintReadStreamToSeqStream(pReader)); if (SUCCEEDED(hr = CHECK_POINTER(pReadStreamToSeq, E_OUTOFMEMORY))) { hr = pSaxRdr->parse(CComVariant(static_cast<ISequentialStream*>(pReadStreamToSeq))); } } pWriter->Close(); } } catch (CXDException& e) { hr = e; } } ERR_ON_HR(hr); return hr; }
/*++ Routine Name: CRasterWatermark::CreateXMLElement Routine Description: Method to create the XML markup which describes the transform and properties used to present the watermark correctly on the page Arguments: None Return Value: HRESULT S_OK - On success E_* - On error --*/ HRESULT CRasterWatermark::CreateXMLElement( VOID ) { ASSERTMSG(m_pDOMDoc != NULL, "NULL DOM document detected whilst creating text watermark\n"); ASSERTMSG(m_bstrImageURI.Length() > 0, "Invalid image URI detected whilst creating text watermark\n"); HRESULT hr = S_OK; if (SUCCEEDED(hr = CHECK_POINTER(m_pDOMDoc, E_PENDING))) { if (m_bstrImageURI.Length() == 0) { hr = E_PENDING; } } // // We need to retrieve the bitmap bounds to calculate // the correct render transform for the watermark // SizeF bmpDims; CComBSTR bstrWMOpacity; if (SUCCEEDED(hr) && SUCCEEDED(hr = m_wmBMP.GetImageDimensions(&bmpDims)) && SUCCEEDED(hr = m_WMProps.GetOpacity(&bstrWMOpacity))) { // // The markup will look like this (square bracketed values "[]" // describes content): // // <Path // RenderTransform="[appropriate to scale, translate and rotate to the PT settings]" // Data="M [corner coords of image] z"> // <Path.Fill> // <ImageBrush // ImageSource="[image URI from cache]" // Opacity="[opacity value from PT]" // ViewboxUnits="Absolute" // Viewbox="[image bounds]" // ViewportUnits="Absolute" // Viewport="[image bounds]" /> // </Path.Fill> // </Path> // CComPtr<IXMLDOMElement> pPathFill(NULL); CComPtr<IXMLDOMElement> pImageBrush(NULL); CComPtr<IXMLDOMNode> pInsertNode(NULL); CStringXDW strPathData; CStringXDW strViewbox; CStringXDW strViewport; CComBSTR bstrMatrixXForm; // // Create the transform and elements and add attributes // try { strPathData.Format(L"M 0,0 L 0,%.2f %.2f,%.2f %.2f,0 z", bmpDims.Height, bmpDims.Width, bmpDims.Height, bmpDims.Width); strViewbox.Format(L"0,0,%.2f,%.2f", bmpDims.Width, bmpDims.Height); strViewport.Format(L"0,0,%.2f,%.2f", bmpDims.Width, bmpDims.Height); if (SUCCEEDED(hr = CreateWMTransform(RectF(0, 0, bmpDims.Width, bmpDims.Height), &bstrMatrixXForm)) && SUCCEEDED(hr = m_pDOMDoc->createElement(CComBSTR(L"Path"), &m_pWMElem)) && SUCCEEDED(hr = m_pDOMDoc->createElement(CComBSTR(L"Path.Fill"), &pPathFill)) && SUCCEEDED(hr = m_pDOMDoc->createElement(CComBSTR(L"ImageBrush"), &pImageBrush)) && SUCCEEDED(hr = m_pWMElem->setAttribute(CComBSTR(L"RenderTransform"), CComVariant(bstrMatrixXForm))) && SUCCEEDED(hr = m_pWMElem->setAttribute(CComBSTR(L"Data"), CComVariant(strPathData.GetBuffer()))) && SUCCEEDED(hr = pImageBrush->setAttribute(CComBSTR(L"ImageSource"), CComVariant(m_bstrImageURI))) && SUCCEEDED(hr = pImageBrush->setAttribute(CComBSTR(L"Opacity"), CComVariant(bstrWMOpacity))) && SUCCEEDED(hr = pImageBrush->setAttribute(CComBSTR(L"ViewboxUnits"), CComVariant(L"Absolute"))) && SUCCEEDED(hr = pImageBrush->setAttribute(CComBSTR(L"Viewbox"), CComVariant(strViewbox.GetBuffer()))) && SUCCEEDED(hr = pImageBrush->setAttribute(CComBSTR(L"ViewportUnits"), CComVariant(L"Absolute"))) && SUCCEEDED(hr = pImageBrush->setAttribute(CComBSTR(L"Viewport"), CComVariant(strViewport.GetBuffer()))) && SUCCEEDED(hr = pPathFill->appendChild(pImageBrush, &pInsertNode)) && SUCCEEDED(hr = m_pWMElem->appendChild(pPathFill, &pInsertNode))) { hr = m_pWMElem->appendChild(pPathFill, &pInsertNode); } } catch (CXDException& e) { hr = e; } } ERR_ON_HR(hr); return hr; }