#include #include #include "MemoryUtils.h" #include "File.h" #include "StringExt.h" #include "List.h" #include "GlobalParams.h" #include "UnicodeMap.h" #include "../../DesktopEditor/graphics/TemporaryCS.h" #include "CharTypes.h" //------------------------------------------------------------------------------------------------------------------------------- #define maxExtCode 16 namespace PdfReader { struct UnicodeMapExt { Unicode nUnicode; char arrCode[maxExtCode]; unsigned int unBytesCount; }; //------------------------------------------------------------------------------------------------------------------------------- UnicodeMap *UnicodeMap::Parse(StringExt *seEncodingName, GlobalParams *pGlobalParams) { FILE *pFile = NULL; if (pGlobalParams && !(pFile = pGlobalParams->GetUnicodeMapFile(seEncodingName))) { // TO DO: Error "Couldn't find UnicodeMap file for the encoding" return NULL; } UnicodeMap *pMap = new UnicodeMap(seEncodingName->Copy()); int nSize = 8; pMap->m_pRanges = (UnicodeMapRange *)MemUtilsMallocArray(nSize, sizeof(UnicodeMapRange)); int nEMapsSize = 0; int nLineNum = 1; char sBuffer[256]; while (GetLine(sBuffer, sizeof(sBuffer), pFile)) { char *sToken1, *sToken2, *sToken3; if ((sToken1 = strtok(sBuffer, " \t\r\n")) && (sToken2 = strtok(NULL, " \t\r\n"))) { if (!(sToken3 = strtok(NULL, " \t\r\n"))) { sToken3 = sToken2; sToken2 = sToken1; } int nBytesCount = strlen(sToken3) / 2; if (nBytesCount <= 4) { if (pMap->m_nLen == nSize) { nSize *= 2; pMap->m_pRanges = (UnicodeMapRange *)MemUtilsReallocArray(pMap->m_pRanges, nSize, sizeof(UnicodeMapRange)); } UnicodeMapRange *pRange = &pMap->m_pRanges[pMap->m_nLen]; sscanf(sToken1, "%x", &pRange->nStart); sscanf(sToken2, "%x", &pRange->nEnd); sscanf(sToken3, "%x", &pRange->unCode); pRange->nBytesCount = nBytesCount; ++pMap->m_nLen; } else if (sToken2 == sToken1) { if (pMap->m_nEMapsLen == nEMapsSize) { nEMapsSize += 16; pMap->m_pEMaps = (UnicodeMapExt *)MemUtilsReallocArray(pMap->m_pEMaps, nEMapsSize, sizeof(UnicodeMapExt)); } UnicodeMapExt *pEMap = &pMap->m_pEMaps[pMap->m_nEMapsLen]; sscanf(sToken1, "%x", &pEMap->nUnicode); for (int nIndex = 0; nIndex < nBytesCount; ++nIndex) { int nValue = 0; sscanf(sToken3 + nIndex * 2, "%2x", &nValue); pEMap->arrCode[nIndex] = (char)nValue; } pEMap->unBytesCount = nBytesCount; ++pMap->m_nEMapsLen; } else { // TO DO: Error "Bad line in unicodeMap file for encoding" } } else { // TO DO: Error "Bad line in unicodeMap file for encoding" } ++nLineNum; } fclose(pFile); return pMap; } UnicodeMap::UnicodeMap(StringExt *seEncodingName) { m_seEncodingName = seEncodingName; m_bUnicodeOut = false; m_eType = unicodeMapUser; m_pRanges = NULL; m_nLen = 0; m_pEMaps = NULL; m_nEMapsLen = 0; m_nRefCount = 1; m_oCS.InitializeCriticalSection(); } UnicodeMap::UnicodeMap(char *sEncodingName, bool bUnicodeOut, UnicodeMapRange *pRanges, int nLen) { m_seEncodingName = new StringExt(sEncodingName); m_bUnicodeOut = bUnicodeOut; m_eType = unicodeMapResident; m_pRanges = pRanges; m_nLen = nLen; m_pEMaps = NULL; m_nEMapsLen = 0; m_nRefCount = 1; m_oCS.InitializeCriticalSection(); } UnicodeMap::UnicodeMap(char *sEncodingName, bool bUnicodeOut, UnicodeMapFunc pFunction) { m_seEncodingName = new StringExt(sEncodingName); m_bUnicodeOut = bUnicodeOut; m_eType = unicodeMapFunc; m_pFunction = pFunction; m_pEMaps = NULL; m_nEMapsLen = 0; m_nRefCount = 1; m_oCS.InitializeCriticalSection(); } UnicodeMap::~UnicodeMap() { if (m_seEncodingName) delete m_seEncodingName; if (m_eType == unicodeMapUser && m_pRanges) { MemUtilsFree(m_pRanges); } if (m_pEMaps) { MemUtilsFree(m_pEMaps); } m_oCS.DeleteCriticalSection(); } void UnicodeMap::AddRef() { CTemporaryCS *pCS = new CTemporaryCS(&m_oCS); ++m_nRefCount; RELEASEOBJECT(pCS); } void UnicodeMap::Release() { CTemporaryCS *pCS = new CTemporaryCS(&m_oCS); bool bDone = (--m_nRefCount == 0); RELEASEOBJECT(pCS); if (bDone) { delete this; } } bool UnicodeMap::Match(StringExt *seEncodingName) { return (!m_seEncodingName->Compare(seEncodingName)); } int UnicodeMap::MapUnicode(Unicode nUnicode, char *sBuffer, int nBufferSize) { if (m_eType == unicodeMapFunc) { return (*m_pFunction)(nUnicode, sBuffer, nBufferSize); } int nFirst = 0; int nLast = m_nLen; if (nUnicode >= m_pRanges[nFirst].nStart) { // m_pRanges[nFirst].nStart <= nUnicode < m_pRanges[nLast].nStart while (nLast - nFirst > 1) { int nMiddle = (nFirst + nLast) / 2; if (nUnicode >= m_pRanges[nMiddle].nStart) { nFirst = nMiddle; } else if (nUnicode < m_pRanges[nMiddle].nStart) { nLast = nMiddle; } } if (nUnicode <= m_pRanges[nFirst].nEnd) { int nLen = m_pRanges[nFirst].nBytesCount; if (nLen > nBufferSize) { return 0; } unsigned int unCode = m_pRanges[nFirst].unCode + (nUnicode - m_pRanges[nFirst].nStart); for (int nIndex = nLen - 1; nIndex >= 0; --nIndex) { sBuffer[nIndex] = (char)(unCode & 0xff); unCode >>= 8; } return nLen; } } for (int nIndex = 0; nIndex < m_nEMapsLen; ++nIndex) { if (m_pEMaps[nIndex].nUnicode == nUnicode) { int nLen = m_pEMaps[nIndex].unBytesCount; for (int nJ = 0; nJ < nLen; ++nJ) { sBuffer[nJ] = m_pEMaps[nIndex].arrCode[nJ]; } return nLen; } } return 0; } //------------------------------------------------------------------------------------------------------------------------------- UnicodeMapCache::UnicodeMapCache() { for (int nIndex = 0; nIndex < unicodeMapCacheSize; ++nIndex) { m_ppCache[nIndex] = NULL; } } UnicodeMapCache::~UnicodeMapCache() { for (int nIndex = 0; nIndex < unicodeMapCacheSize; ++nIndex) { if (m_ppCache[nIndex]) { m_ppCache[nIndex]->Release(); } } } UnicodeMap *UnicodeMapCache::GetUnicodeMap(StringExt *seEncodingName, GlobalParams *pGlobalParams) { if (m_ppCache[0] && m_ppCache[0]->Match(seEncodingName)) { m_ppCache[0]->AddRef(); return m_ppCache[0]; } UnicodeMap *pMap = NULL; for (int nIndex = 1; nIndex < unicodeMapCacheSize; ++nIndex) { if (m_ppCache[nIndex] && m_ppCache[nIndex]->Match(seEncodingName)) { pMap = m_ppCache[nIndex]; for (int nJ = nIndex; nJ >= 1; --nJ) { m_ppCache[nJ] = m_ppCache[nJ - 1]; } m_ppCache[0] = pMap; pMap->AddRef(); return pMap; } } if ((pMap = UnicodeMap::Parse(seEncodingName, pGlobalParams))) { if (m_ppCache[unicodeMapCacheSize - 1]) { m_ppCache[unicodeMapCacheSize - 1]->Release(); } for (int nJ = unicodeMapCacheSize - 1; nJ >= 1; --nJ) { m_ppCache[nJ] = m_ppCache[nJ - 1]; } m_ppCache[0] = pMap; pMap->AddRef(); return pMap; } return NULL; } }