📄 xpsproc.cpp
字号:
{
CStringXDA cstrRelsPartName;
CComPtr<ISequentialStream> pFileReader(NULL);
//
// Construct the rels part from the parent part name and parse for
// relationships
//
if (SUCCEEDED(hr = MakeRelsPartName(szPartName, &cstrRelsPartName)) &&
SUCCEEDED(hr = m_contentTypes.ValidateContentType(cstrRelsPartName, ContentRelationships)) &&
SUCCEEDED(hr = m_xpsArchive.GetFileStream(cstrRelsPartName, &pFileReader)) &&
SUCCEEDED(hr = m_pSaxRdr->putContentHandler(&m_rels)) &&
SUCCEEDED(hr = m_rels.SetCurrentFileName(szPartName)) &&
SUCCEEDED(hr = m_pSaxRdr->parse(CComVariant(pFileReader))))
{
//
// We are done with the .rels part - send it on
//
hr = m_xpsArchive.SendCurrentFile();
}
//
// Close the curent file ready for the next
//
m_xpsArchive.CloseCurrent();
}
catch (CXDException& e)
{
hr = e;
}
}
ERR_ON_HR_EXC(hr, E_ELEMENT_NOT_FOUND);
return hr;
}
/*++
Routine Name:
CXPSProcessor::MakeRelsPartName
Routine Description:
This routine converts a part name into the appropriate .rels name.
The rules for naming are:
rels parts are stored in a directory named _rels relative to the current part
rels parts always end in .rels
e.g. \Documents\FixedDoc.fdseq has rels part \Documents\_rels\FixedDoc.fdseq.rels
Arguments:
szPartName - The name of the part to be converted
pcstrRelsPartName - Pointer to a CStringXDA that recieves the new name
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::MakeRelsPartName(
__in PCSTR szPartName,
__out CStringXDA* pcstrRelsPartName
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(szPartName, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(pcstrRelsPartName, E_POINTER)))
{
try
{
*pcstrRelsPartName = szPartName;
//
// Find the slash that splits the directory and part name
//
INT cLastSlash = -1;
for (;;)
{
INT cSlash = pcstrRelsPartName->Find("/", cLastSlash + 1);
if (cSlash != -1)
{
cLastSlash = cSlash;
}
else
{
break;
}
}
cLastSlash++;
//
// Insert "_rels/" after the slash and append ".rels"
//
pcstrRelsPartName->Insert(cLastSlash, szRelsPre);
pcstrRelsPartName->Append(szRelsPost);
}
catch (CXDException& e)
{
hr = e;
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CXPSProcessor::ProcessRelsParts
Routine Description:
This routine processes the related parts for a given part
Arguments:
szPartName - The name of the part
eContentType - The type of the part to be processed. This must be either an FDS, FD or FP.
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::ProcessRelsParts(
__in PCSTR szPartName,
__in CONST EContentType eContentType
)
{
HRESULT hr = S_OK;
BOOL bPrintTicketSent = FALSE;
if (SUCCEEDED(hr = CHECK_POINTER(szPartName, E_POINTER)))
{
if (eContentType != ContentFixedDocumentSequence &&
eContentType != ContentFixedDocument &&
eContentType != ContentFixedPage)
{
hr = E_INVALIDARG;
}
}
if (SUCCEEDED(hr))
{
try
{
//
// Validate the part content type
// Get the rels and handle any print tickets
//
CONST RelsTypeList* pRelsTypeList;
if (SUCCEEDED(hr = m_contentTypes.ValidateContentType(szPartName, eContentType)) &&
SUCCEEDED(hr = GetRelsForPart(szPartName)) &&
SUCCEEDED(hr = m_rels.GetRelsTypeList(szPartName, &pRelsTypeList)))
{
RelsTypeList::const_iterator iterRels = pRelsTypeList->begin();
for (;iterRels != pRelsTypeList->end() && SUCCEEDED(hr); iterRels++)
{
//
// Strip any leading "/"
//
CStringXDA cstrName(iterRels->first);
if (cstrName.GetAt(0) == '/')
{
cstrName.Delete(0);
}
//
// The second of the pair in the RelsTypeList iterator is the rels type
//
switch (iterRels->second)
{
case RelsPrintTicket:
{
hr = AddPrintTicket(cstrName, eContentType);
bPrintTicketSent = TRUE;
}
break;
case RelsAnnotations:
case RelsDigitalSignatureDefinitions:
case RelsDiscardControl:
case RelsDocumentStructure:
case RelsRequiredResource:
case RelsRestrictedFont:
case RelsStoryFragments:
case RelsCoreProperties:
case RelsDigitalSignature:
case RelsDigitalSignatureCertificate:
case RelsDigitalSignatureOrigin:
case RelsThumbnail:
{
//
// We are not interested in the content so intialise the current
// file in the XPS archive and send it on
//
if (SUCCEEDED(hr = m_xpsArchive.InitialiseFile(cstrName)))
{
hr = m_xpsArchive.SendCurrentFile();
}
}
break;
default:
{
ERR("Unrecognised rels part\n");
hr = E_FAIL;
}
break;
}
//
// Close the current file ready for the next
//
m_xpsArchive.CloseCurrent();
}
}
else if (hr == E_ELEMENT_NOT_FOUND)
{
//
// There is no PrintTicket
//
hr = S_OK;
}
//
// No print ticket has been sent so just inform the print ticket
// manager that a suitable ticket needs to be set for this level
//
if (bPrintTicketSent == FALSE)
{
switch (eContentType)
{
case ContentFixedPage:
{
hr = m_pPtManager->SetTicket(kPTPageScope, NULL);
}
break;
case ContentFixedDocument:
{
hr = m_pPtManager->SetTicket(kPTDocumentScope, NULL);
}
break;
case ContentFixedDocumentSequence:
{
hr = m_pPtManager->SetTicket(kPTJobScope, NULL);
}
break;
default:
{
hr = ERROR_NOT_SUPPORTED;
}
break;
}
}
}
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::AddPrintTicket
Routine Description:
This routine retrieves the PrintTicket information and updates the PrintTicket
manager at the appropriate scope
Arguments:
szPTPartName - The part name for the PrintTicket
eContentType - The type of the containing part. This must be either an FDS, FD or FP.
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::AddPrintTicket(
__in PCSTR szPTPartName,
__in CONST EContentType eContentType
)
{
HRESULT hr = S_OK;
//
// Validate the parameters
//
if (SUCCEEDED(hr = CHECK_POINTER(szPTPartName, E_POINTER)))
{
if (eContentType != ContentFixedDocumentSequence &&
eContentType != ContentFixedDocument &&
eContentType != ContentFixedPage)
{
hr = E_INVALIDARG;
}
}
//
// Extract the PrintTicket from the current file in the XPS archive
// and pass to the PrinTicket manager at the appropriate scope
//
CComPtr<ISequentialStream> pFileReader(NULL);
CComPtr<IXMLDOMDocument2> pPT(NULL);
VARIANT_BOOL fLoaded = VARIANT_FALSE;
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = m_xpsArchive.GetFileStream(szPTPartName, &pFileReader)) &&
SUCCEEDED(hr = pPT.CoCreateInstance(CLSID_DOMDocument60)) &&
SUCCEEDED(hr = pPT->load(CComVariant(pFileReader), &fLoaded)))
{
if (fLoaded == VARIANT_TRUE)
{
//
// Determine the scope from the parent parts content type
//
EPrintTicketScope ePTScope = kPTPageScope;
if (eContentType == ContentFixedDocumentSequence)
{
ePTScope = kPTJobScope;
}
else if (eContentType == ContentFixedDocument)
{
ePTScope = kPTDocumentScope;
}
if (SUCCEEDED(hr = m_pPtManager->SetTicket(ePTScope, pPT)))
{
//
// Make sure the PrintTicket is passed on
//
hr = m_xpsArchive.SendCurrentFile();
}
}
else
{
ERR("Failed to load PT\n");
hr = E_FAIL;
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CXPSProcessor::AddPrintTicket
Routine Description:
This routine intialises the appropriate read and write streams for a fixed
page processor and calls the processor to do the work
Arguments:
szFPPartName - The name of the FixedPage part
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CXPSProcessor::ProcessFixedPage(
__in PCSTR szFPPartName
)
{
HRESULT hr = S_OK;
//
// Retrieve the file stream and pass to the page scaling handler
//
CComPtr<ISequentialStream> pFileReader(NULL);
CXPSWriteFile* pXpsWriteFile = new CXPSWriteFile(szFPPartName);
IXMLDOMDocument2* pPT = NULL;
if (SUCCEEDED(hr = CHECK_POINTER(pXpsWriteFile, E_OUTOFMEMORY)) &&
SUCCEEDED(hr = CHECK_POINTER(m_pPageProcessor, E_PENDING)) &&
SUCCEEDED(hr = CHECK_POINTER(szFPPartName, E_PENDING)) &&
SUCCEEDED(hr = m_xpsArchive.GetFileStream(szFPPartName, &pFileReader)) &&
SUCCEEDED(hr = m_pPtManager->GetTicket(kPTPageScope, &pPT)) &&
SUCCEEDED(hr = CHECK_POINTER(pPT, E_FAIL)) &&
SUCCEEDED(hr = m_pPageProcessor->ProcessFixedPage(pPT, pFileReader, pXpsWriteFile)))
{
//
// Send the new fixed page
//
ULONG cb = 0;
PVOID pv = NULL;
if (SUCCEEDED(hr = pXpsWriteFile->GetBuffer(&pv, &cb)))
{
hr = m_xpsArchive.SendFile(szFPPartName, pv, cb, CompDeflated);
}
}
else if (hr == HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
{
//
// The page processor does not want to do any work - just send the page
//
hr = m_xpsArchive.SendCurrentFile();
}
//
// Close the curent file ready for the next
//
m_xpsArchive.CloseCurrent();
if (pXpsWriteFile != NULL)
{
delete pXpsWriteFile;
pXpsWriteFile = NULL;
}
ERR_ON_HR(hr);
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -