📄 xpsproc.cpp
字号:
/*++
Copyright (c) 2005 Microsoft Corporation
All rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
File Name:
xpsproc.cpp
Abstract:
Implementation of the XPS processor. This class is responsible for handling
the logical document and page structure of the XPS container. The class starts
with the content types part and .rels part to find the Fixed Document Sequence.
It then parses the FDS to find the Fixed Documents and finally the FDs to find
each Fixed Page. Each fixed page is then reported to a client FixedPageProcessor
to interpret the mark-up and write out modifications as required. The class is
additionally responsible for ensuring all XPS parts and accompanying resources are
sent on to the PK archive handler to be written out.
--*/
#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdstring.h"
#include "xdexcept.h"
#include "xpsproc.h"
#include "xpsfilew.h"
static PCSTR szContentTypes = "[Content_Types].xml";
static PCSTR szRelsPre = "_rels/";
static PCSTR szRelsPost = ".rels";
/*++
Routine Name:
CXPSProcessor::CXPSProcessor
Routine Description:
CXPSProcessor class constructor
Arguments:
pReadStream - Pointer to the print read stream
pWriteStream - Pointer to the print write stream
pPageProcessor - Pointer to the page processor interface
pPropertyBag - Pointer to the filter pipeline property bag
Return Value:
None
Throws CXDException(HRESULT) on an error
--*/
CXPSProcessor::CXPSProcessor(
__in IPrintReadStream* pReadStream,
__in IPrintWriteStream* pWriteStream,
__in IFixedPageProcessor* pPageProcessor,
__in IPrintPipelinePropertyBag* pPropertyBag,
__in CPTManager* pPtManager
) :
m_xpsArchive(pReadStream, pWriteStream),
m_pSaxRdr(NULL),
m_pPageProcessor(pPageProcessor),
m_pPrintPropertyBag(pPropertyBag),
m_pPtManager(pPtManager)
{
HRESULT hr = S_OK;
CComPtr<ISequentialStream> pFileReader(NULL);
//
// Setup the SAX reader and extract the content types
//
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = CHECK_POINTER(pReadStream, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(pWriteStream, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(m_pPageProcessor, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(m_pPtManager, E_POINTER)) &&
SUCCEEDED(hr = m_pSaxRdr.CoCreateInstance(CLSID_SAXXMLReader60)) &&
SUCCEEDED(hr = m_xpsArchive.GetFileStream(szContentTypes, &pFileReader)) &&
SUCCEEDED(hr = m_pSaxRdr->putContentHandler(&m_contentTypes)) &&
SUCCEEDED(hr = m_pSaxRdr->parse(CComVariant(pFileReader))))
{
//
// We've got all the data we need - send it on
//
hr = m_xpsArchive.SendCurrentFile();
}
//
// Close the curent file ready for the next
//
m_xpsArchive.CloseCurrent();
if (FAILED(hr))
{
throw CXDException(hr);
}
}
/*++
Routine Name:
CXPSProcessor::~CXPSProcessor
Routine Description:
CXPSProcessor class destructor
Arguments:
None
Return Value:
None
--*/
CXPSProcessor::~CXPSProcessor()
{
}
/*++
Routine Name:
CXPSProcessor::Start
Routine Description:
This routine kicks off the processing of the XPS archive struture. The
routine parses the Fixed Document Sequence mark-up to find the Fixed
Document parts, then parses the Fixed Document mark-up to find the Fixed
Page parts before passing these on to the Fixed Page processor. Additionally
the routine handles indentifying, processing and sending resources and part
relationships. Note: This limits the XPS document processing to only modifying
the fixed page data; the client is not presented the opportunity to modify any
other parts.
Arguments:
None
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::Start(
VOID
)
{
HRESULT hr = S_OK;
try
{
//
// Get the start part list and iterate over all parts
//
FileList fixedDocumentSequenceParts;
if (SUCCEEDED(hr = GetFixedDocumentSequenceParts(&fixedDocumentSequenceParts)))
{
FileList::const_iterator iterFDS = fixedDocumentSequenceParts.begin();
for (;
iterFDS != fixedDocumentSequenceParts.end() &&
SUCCEEDED(hr) &&
SUCCEEDED(hr = ProcessRelsParts(*iterFDS, ContentFixedDocumentSequence));
iterFDS++)
{
//
// Parse the start part retrieving the FD list - iterate over all FDs
//
FileList fixedDocumentParts;
if (SUCCEEDED(hr = GetFixedDocumentParts(*iterFDS, &fixedDocumentParts)))
{
FileList::const_iterator iterFD = fixedDocumentParts.begin();
for (;
iterFD != fixedDocumentParts.end() &&
SUCCEEDED(hr) &&
SUCCEEDED(hr = ProcessRelsParts(*iterFD, ContentFixedDocument));
iterFD++)
{
//
// Parse the FD retrieving the FP list - iterate over all FPs
//
FileList fixedPageParts;
if (SUCCEEDED(hr = GetFixedPageParts(*iterFD, &fixedPageParts)))
{
FileList::const_iterator iterFP = fixedPageParts.begin();
for (;
iterFP != fixedPageParts.end() &&
SUCCEEDED(hr) &&
SUCCEEDED(hr = ProcessRelsParts(*iterFP, ContentFixedPage));
iterFP++)
{
//
// Process the fixed page - this calls on to the IFixedPageProcessor
// interface for the client to do the work
//
hr = ProcessFixedPage(*iterFP);
}
}
}
}
}
}
}
catch (CXDException& e)
{
hr = e;
}
catch (exception& DBG_ONLY(e))
{
ERR(e.what());
hr = E_FAIL;
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CXPSProcessor::GetFixedDocumentSequenceParts
Routine Description:
This routine retrieves the Fixed Document Sequence from the root
relationships part.
Arguments:
pFixedDocumentSequencePartsList - List of fixed document sequences found to be populated
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::GetFixedDocumentSequenceParts(
__out FileList* pFixedDocumentSequencePartsList
)
{
HRESULT hr = S_OK;
//
// Extract the .rels part to find the start part
//
if (SUCCEEDED(hr = CHECK_POINTER(pFixedDocumentSequencePartsList, E_POINTER)) &&
SUCCEEDED(hr = GetRelsForPart("")))
{
CONST RelsTypeList* pRelsTypeList = NULL;
hr = m_rels.GetRelsTypeList("", &pRelsTypeList);
RelsTypeList::const_iterator iterRels = pRelsTypeList->begin();
for (;iterRels != pRelsTypeList->end() && SUCCEEDED(hr); iterRels++)
{
if (iterRels->second == RelsStartPart)
{
//
// We have a start part add it to the part list
//
pFixedDocumentSequencePartsList->push_back(iterRels->first);
}
else
{
//
// Send any other part on
//
if (SUCCEEDED(hr = m_xpsArchive.InitialiseFile(iterRels->first)) &&
SUCCEEDED(hr = m_xpsArchive.SendCurrentFile()))
{
m_xpsArchive.CloseCurrent();
}
}
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CXPSProcessor::GetFixedDocumentParts
Routine Description:
This routine retrieves the list of fixed documents from the fixed document
sequence
Arguments:
szFixedDocSeq - The name of the FDS part to parse
pFixedDocumentParts - Pointer to the document list to be populated
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::GetFixedDocumentParts(
__in PCSTR szFixedDocSeq,
__out FileList* pFixedDocumentParts
)
{
HRESULT hr = S_OK;
CComPtr<ISequentialStream> pFileReader(NULL);
//
// Set up the fixed document sequence as the current file in the
// XPS archive and parse the file stream using the FDS SAX content
// handler to retrieve all fixed documents in the sequence
//
if (SUCCEEDED(hr = CHECK_POINTER(szFixedDocSeq, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(pFixedDocumentParts, E_POINTER)) &&
SUCCEEDED(hr = m_contentTypes.ValidateContentType(szFixedDocSeq, ContentFixedDocumentSequence)) &&
SUCCEEDED(hr = m_xpsArchive.GetFileStream(szFixedDocSeq, &pFileReader)) &&
SUCCEEDED(hr = m_fixedDocSeq.Clear()) &&
SUCCEEDED(hr = m_pSaxRdr->putContentHandler(&m_fixedDocSeq)) &&
SUCCEEDED(hr = m_pSaxRdr->parse(CComVariant(pFileReader))) &&
SUCCEEDED(hr = m_fixedDocSeq.GetFixedDocumentList(pFixedDocumentParts)))
{
//
// We are done with the FDS - send it on
//
hr = m_xpsArchive.SendCurrentFile();
}
//
// Close the curent file ready for the next
//
m_xpsArchive.CloseCurrent();
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CXPSProcessor::GetFixedPageParts
Routine Description:
This routine retrieves the list of fixed pages from the Fixed Document
Arguments:
szFixedDoc - The name of the FD part to parse
pFixedPageParts - Pointer to the page list to be populated
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::GetFixedPageParts(
__in PCSTR szFixedDoc,
__out FileList* pFixedPageParts
)
{
HRESULT hr = S_OK;
CComPtr<ISequentialStream> pFileReader(NULL);
//
// Set up the fixed document as the current file in the XPS
// archive and parse the file stream using the FD SAX content
// handler to retrieve all fixed pages in the document
//
if (SUCCEEDED(hr = CHECK_POINTER(szFixedDoc, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(pFixedPageParts, E_POINTER)) &&
SUCCEEDED(hr = m_contentTypes.ValidateContentType(szFixedDoc, ContentFixedDocument)) &&
SUCCEEDED(hr = m_xpsArchive.GetFileStream(szFixedDoc, &pFileReader)) &&
SUCCEEDED(hr = m_fixedDoc.Clear()) &&
SUCCEEDED(hr = m_pSaxRdr->putContentHandler(&m_fixedDoc)) &&
SUCCEEDED(hr = m_pSaxRdr->parse(CComVariant(pFileReader))) &&
SUCCEEDED(hr = m_fixedDoc.GetFixedPageList(pFixedPageParts)))
{
//
// We are done with the FD - send it on
//
hr = m_xpsArchive.SendCurrentFile();
}
//
// Close the curent file ready for the next
//
m_xpsArchive.CloseCurrent();
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CXPSProcessor::GetRelsForPart
Routine Description:
This routine retrieves and populates the rels object with the relationships
for the specified part
Arguments:
szPartName - The name of the part to retrieve the relationships for
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::GetRelsForPart(
__in PCSTR szPartName
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(szPartName, E_POINTER)))
{
try
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -