#include "stdafx.h" #include #include #include #include #include "MemoryUtils.h" #include "File.h" #include "StringExt.h" #include "GlobalParams.h" #include "PSLexer.h" #include "CMap.h" //------------------------------------------------------------------------------------------------------------------------------- struct CMapVectorEntry { BOOL bIsVector; CID nCID; CMapVectorEntry *pVector; }; //------------------------------------------------------------------------------------------------------------------------------- static int GetCharFromFile(void *pFile) { return fgetc((FILE *)pFile); } //------------------------------------------------------------------------------------------------------------------------------- CMap *CMap::Parse(CMapCache *pCache, StringExt *seCollection, StringExt *seCMapName, GlobalParams *pGlobalParams, wchar_t *wsFilePath) { FILE *pFile = NULL; char sToken1[256], sToken2[256], sToken3[256]; int nLen1, nLen2, nLen3; if ( NULL != wsFilePath ) { if ( !(pFile = _wfopen( wsFilePath, _T("r") )) ) return NULL; } else { if ( pGlobalParams && !( pFile = pGlobalParams->FindCMapFile( seCollection, seCMapName ) ) ) { // Проверяем на Identity CMap. if ( !seCMapName->Compare("Identity") || !seCMapName->Compare("Identity-H") ) { return new CMap( pGlobalParams, seCollection->Copy(), seCMapName->Copy(), 0 ); } if ( !seCMapName->Compare("Identity-V") ) { return new CMap( pGlobalParams, seCollection->Copy(), seCMapName->Copy(), 1 ); } // TO DO: Error "Couldn't find CMap file for collection" return NULL; } } CMap *pCMap = new CMap( pGlobalParams, seCollection->Copy(), seCMapName->Copy()); PSLexer *Lexer = new PSLexer(&GetCharFromFile, pFile); Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1); while ( Lexer->GetToken( sToken2, sizeof(sToken2), &nLen2) ) { if ( !strcmp( sToken2, "usecmap") ) { if ( sToken1[0] == '/' ) { pCMap->UseCMap( pCache, sToken1 + 1); } Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1); } else if ( !strcmp( sToken1, "/WMode") ) { pCMap->m_nWMode = atoi(sToken2); Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1); } else if ( !strcmp( sToken2, "begincodespacerange") ) { while ( Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1) ) { if ( !strcmp(sToken1, "endcodespacerange") ) { break; } if ( !Lexer->GetToken( sToken2, sizeof(sToken2), &nLen2) || !strcmp( sToken2, "endcodespacerange") ) { // TO DO: Error "Illegal entry in codespacerange block in CMap" break; } if ( sToken1[0] == '<' && sToken2[0] == '<' && nLen1 == nLen2 && nLen1 >= 4 && (nLen1 & 1) == 0) { unsigned int unStart = 0, unEnd = 0; sToken1[nLen1 - 1] = sToken2[nLen1 - 1] = '\0'; sscanf( sToken1 + 1, "%x", &unStart); sscanf( sToken2 + 1, "%x", &unEnd); nLen1 = (nLen1 - 2) / 2; pCMap->AddCodeSpace( pCMap->m_pVector, unStart, unEnd, nLen1); } } Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1); } else if ( !strcmp( sToken2, "begincidchar") ) { while ( Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1) ) { if ( !strcmp( sToken1, "endcidchar") ) { break; } if ( !Lexer->GetToken( sToken2, sizeof(sToken2), &nLen2) || !strcmp( sToken2, "endcidchar") ) { // TO DO: Error "Illegal entry in cidchar block in CMap" break; } if ( !( sToken1[0] == '<' && sToken1[nLen1 - 1] == '>' && nLen1 >= 4 && (nLen1 & 1) == 0) ) { // TO DO: Error "Illegal entry in cidchar block in CMap" continue; } sToken1[nLen1 - 1] = '\0'; unsigned int unCode = 0; if ( sscanf( sToken1 + 1, "%x", &unCode) != 1 ) { // TO DO: Error "Illegal entry in cidchar block in CMap" continue; } nLen1 = (nLen1 - 2) / 2; pCMap->AddCIDs( unCode, unCode, nLen1, (CID)atoi(sToken2)); } Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1); } else if ( !strcmp( sToken2, "begincidrange") ) { while ( Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1) ) { if ( !strcmp( sToken1, "endcidrange") ) { break; } if ( !Lexer->GetToken( sToken2, sizeof(sToken2), &nLen2) || !strcmp( sToken2, "endcidrange") || !Lexer->GetToken( sToken3, sizeof(sToken3), &nLen3) || !strcmp( sToken3, "endcidrange") ) { // TO DO: Error "Illegal entry in cidrange block in CMap" break; } if ( sToken1[0] == '<' && sToken2[0] == '<' && nLen1 == nLen2 && nLen1 >= 4 && (nLen1 & 1) == 0 ) { unsigned int unStart = 0, unEnd = 0; sToken1[nLen1 - 1] = sToken2[nLen1 - 1] = '\0'; sscanf( sToken1 + 1, "%x", &unStart); sscanf( sToken2 + 1, "%x", &unEnd); nLen1 = (nLen1 - 2) / 2; pCMap->AddCIDs( unStart, unEnd, nLen1, (CID)atoi(sToken3)); } } Lexer->GetToken( sToken1, sizeof(sToken1), &nLen1); } else { strcpy( sToken1, sToken2); } } delete Lexer; fclose(pFile); return pCMap; } CMap::CMap(GlobalParams *pGlobalParams, StringExt *seCollection, StringExt *seCMapName) { m_pGlobalParams = pGlobalParams; m_seCollection = seCollection; m_seCMapName = seCMapName; m_nWMode = 0; m_pVector = (CMapVectorEntry *)MemUtilsMallocArray( 256, sizeof(CMapVectorEntry) ); for ( int nIndex = 0; nIndex < 256; ++nIndex ) { m_pVector[nIndex].bIsVector = FALSE; m_pVector[nIndex].nCID = 0; } m_nRef = 1; InitializeCriticalSection( &m_oCS ); } CMap::CMap(GlobalParams *pGlobalParams, StringExt *seCollection, StringExt *seCMapName, int nWMode) { m_pGlobalParams = pGlobalParams; m_seCollection = seCollection; m_seCMapName = seCMapName; m_nWMode = nWMode; m_pVector = NULL; m_nRef = 1; InitializeCriticalSection( &m_oCS ); } void CMap::UseCMap(CMapCache *pCache, char *sUseName) { StringExt *pUseNameStr = new StringExt(sUseName); if ( !pUseNameStr ) return; CMap *pSubCMap = pCache->GetCMap( m_seCollection, pUseNameStr, m_pGlobalParams ); delete pUseNameStr; if ( !pSubCMap ) return; CopyVector( m_pVector, pSubCMap->m_pVector); pSubCMap->Release(); } void CMap::CopyVector(CMapVectorEntry *pDest, CMapVectorEntry *pSrc) { for ( int nSrcIndex = 0; nSrcIndex < 256; ++nSrcIndex ) { if ( pSrc[nSrcIndex].bIsVector ) { if ( !pDest[nSrcIndex].bIsVector ) { pDest[nSrcIndex].bIsVector = TRUE; pDest[nSrcIndex].pVector = (CMapVectorEntry *)MemUtilsMallocArray(256, sizeof(CMapVectorEntry)); for ( int pDstIndex = 0; pDstIndex < 256; ++pDstIndex ) { pDest[nSrcIndex].pVector[pDstIndex].bIsVector = FALSE; pDest[nSrcIndex].pVector[pDstIndex].nCID = 0; } } CopyVector( pDest[nSrcIndex].pVector, pSrc[nSrcIndex].pVector); } else { if ( pDest[nSrcIndex].bIsVector ) { // TO DO: Error "Collision in usecmap" } else { pDest[nSrcIndex].nCID = pSrc[nSrcIndex].nCID; } } } } void CMap::AddCodeSpace(CMapVectorEntry *pVector, unsigned int unStart, unsigned int unEnd, unsigned int unBytesCount) { if ( unBytesCount > 1 ) { int nStartByte = (unStart >> (8 * (unBytesCount - 1))) & 0xff; int nEndByte = (unEnd >> (8 * (unBytesCount - 1))) & 0xff; unsigned int unStart2 = unStart & ((1 << (8 * (unBytesCount - 1))) - 1); unsigned int unEnd2 = unEnd & ((1 << (8 * (unBytesCount - 1))) - 1); for ( int nI = nStartByte; nI <= nEndByte; ++nI ) { if ( !pVector[nI].bIsVector ) { pVector[nI].bIsVector = TRUE; pVector[nI].pVector = (CMapVectorEntry *)MemUtilsMallocArray(256, sizeof(CMapVectorEntry)); for ( int nJ = 0; nJ < 256; ++nJ ) { pVector[nI].pVector[nJ].bIsVector = FALSE; pVector[nI].pVector[nJ].nCID = 0; } } AddCodeSpace( pVector[nI].pVector, unStart2, unEnd2, unBytesCount - 1); } } } void CMap::AddCIDs(unsigned int unStart, unsigned int unEnd, unsigned int unBytesCount, CID nFirstCID) { CMapVectorEntry *pVector = m_pVector; for ( unsigned int nIndex = unBytesCount - 1; nIndex >= 1; --nIndex ) { int nByte = (unStart >> (8 * nIndex)) & 0xff; if ( !pVector[nByte].bIsVector ) { // TO DO: Error "Invalid CID in CMap" return; } pVector = pVector[nByte].pVector; } CID nCID = nFirstCID; for ( int nByte = (int)(unStart & 0xff); nByte <= (int)(unEnd & 0xff); ++nByte ) { if ( pVector[nByte].bIsVector ) { // TO DO: Error "Invalid CID in CMap" } else { pVector[nByte].nCID = nCID; } ++nCID; } } CMap::~CMap() { if ( m_seCollection ) delete m_seCollection; if ( m_seCMapName ) delete m_seCMapName; if ( m_pVector ) { FreeCMapVector(m_pVector); } DeleteCriticalSection( &m_oCS ); } void CMap::FreeCMapVector(CMapVectorEntry *pVector) { for ( int nIndex = 0; nIndex < 256; ++nIndex ) { if ( pVector[nIndex].bIsVector ) { FreeCMapVector( pVector[nIndex].pVector); } } MemUtilsFree(pVector); } void CMap::AddRef() { CTemporaryCS *pCS = new CTemporaryCS( &m_oCS ); ++m_nRef; RELEASEOBJECT( pCS ); } void CMap::Release() { CTemporaryCS *pCS = new CTemporaryCS( &m_oCS ); BOOL bDelete = (--m_nRef == 0); RELEASEOBJECT( pCS ); if ( bDelete ) { delete this; } } BOOL CMap::Match(StringExt *seCollection, StringExt *seCMapName) { return !m_seCollection->Compare(seCollection) && !m_seCMapName->Compare(seCMapName); } CID CMap::GetCID(char *sChar, int nLen, int *pnUsed) { CMapVectorEntry *pVector; if ( !( pVector = m_pVector ) ) { // Identity CMap *pnUsed = 2; if ( nLen < 2 ) { return 0; } return ((sChar[0] & 0xff) << 8) + (sChar[1] & 0xff); } int nUsedCount = 0; while (1) { if ( nUsedCount >= nLen ) { *pnUsed = nUsedCount; return 0; } int nIndex = sChar[nUsedCount++] & 0xff; if ( !pVector[nIndex].bIsVector ) { *pnUsed = nUsedCount; return pVector[nIndex].nCID; } pVector = pVector[nIndex].pVector; } } void CMap::ToXml(CString sFilePath) { USES_CONVERSION; XmlUtils::CXmlWriter oWriter; oWriter.WriteNodeBegin( _T("PDF-CMap"), TRUE ); oWriter.WriteAttribute( _T("collection"), A2W( m_seCollection->GetBuffer() ) ); oWriter.WriteAttribute( _T("name"), A2W( m_seCMapName->GetBuffer() ) ); oWriter.WriteNodeEnd( _T("PDF-CMap"), TRUE, FALSE ); if ( !m_seCMapName->Compare("Identity") || !m_seCMapName->Compare("Identity-H") || !m_seCMapName->Compare("Identity-V") ) WriteVectorToXml( &oWriter, m_pVector ); oWriter.WriteNodeEnd( _T("PDF-CMap"), FALSE, TRUE ); oWriter.SaveToFile( sFilePath ); } void CMap::WriteVectorToXml(XmlUtils::CXmlWriter *pWriter, CMapVectorEntry *pVector) { if ( NULL == pVector ) return; for ( int nIndex = 0; nIndex < 256; nIndex++ ) { if ( 0 != pVector[nIndex].nCID || FALSE != pVector[nIndex].bIsVector ) { if ( pVector[nIndex].bIsVector ) { pWriter->WriteNodeBegin( _T("Vector"), TRUE ); pWriter->WriteAttribute( _T("index"), nIndex ); pWriter->WriteAttribute( _T("isvector"), 1 ); pWriter->WriteAttribute( _T("cid"), (int)pVector[nIndex].nCID ); pWriter->WriteNodeEnd( _T("Vector"), TRUE, FALSE ); WriteVectorToXml( pWriter, pVector[nIndex].pVector ); pWriter->WriteNodeEnd( _T("Vector"), FALSE, TRUE ); } else { pWriter->WriteNodeBegin( _T("Vector"), TRUE ); pWriter->WriteAttribute( _T("index"), nIndex ); pWriter->WriteAttribute( _T("isvector"), 0 ); pWriter->WriteAttribute( _T("cid"), (int)pVector[nIndex].nCID ); pWriter->WriteNodeEnd( _T("Vector"), TRUE, TRUE ); } } } } //------------------------------------------------------------------------------------------------------------------------------- CMapCache::CMapCache() { for ( int nIndex = 0; nIndex < CMapCacheSize; ++nIndex ) { m_ppCache[nIndex] = NULL; } } CMapCache::~CMapCache() { for ( int nIndex = 0; nIndex < CMapCacheSize; ++nIndex ) { if ( m_ppCache[nIndex] ) { m_ppCache[nIndex]->Release(); } } } CMap *CMapCache::GetCMap(StringExt *seCollection, StringExt *seCMapName, GlobalParams* pGlobalParams, wchar_t *wsFilePath) { CMap *pCMap = NULL; if ( m_ppCache[0] && m_ppCache[0]->Match( seCollection, seCMapName) ) { m_ppCache[0]->AddRef(); return m_ppCache[0]; } for ( int nIndex = 1; nIndex < CMapCacheSize; ++nIndex ) { if ( m_ppCache[nIndex] && m_ppCache[nIndex]->Match( seCollection, seCMapName) ) { pCMap = m_ppCache[nIndex]; for ( int nJ = nIndex; nJ >= 1; --nJ ) { m_ppCache[nJ] = m_ppCache[nJ - 1]; } m_ppCache[0] = pCMap; pCMap->AddRef(); return pCMap; } } if ( ( pCMap = CMap::Parse(this, seCollection, seCMapName, pGlobalParams, wsFilePath) ) ) { if ( m_ppCache[CMapCacheSize - 1] ) { m_ppCache[CMapCacheSize - 1]->Release(); } for ( int nJ = CMapCacheSize - 1; nJ >= 1; --nJ ) { m_ppCache[nJ] = m_ppCache[nJ - 1]; } m_ppCache[0] = pCMap; pCMap->AddRef(); return pCMap; } return NULL; }